import { horizontalMenu, putPreloader, renderImageFromUrl, ripple } from "../../components/misc"; //import Scrollable from '../../components/scrollable'; import Scrollable from '../../components/scrollable_new'; import { $rootScope, findUpClassName } from "../utils"; import appMessagesManager from "./appMessagesManager"; import appPhotosManager from "./appPhotosManager"; import appPeersManager from "./appPeersManager"; import appUsersManager from "./appUsersManager"; import appProfileManager from "./appProfileManager"; import { RichTextProcessor } from "../richtextprocessor"; import { logger, LogLevels } from "../polyfill"; import appImManager from "./appImManager"; import appMediaViewer from "./appMediaViewer"; import LazyLoadQueue from "../../components/lazyLoadQueue"; import { wrapDocument, wrapAudio, wrapSticker } from "../../components/wrappers"; import AppSearch, { SearchGroup } from "../../components/appSearch"; import AvatarElement from "../../components/avatar"; import appForward from "../../components/appForward"; import { mediaSizes } from "../config"; import SidebarSlider, { SliderTab } from "../../components/slider"; import appStickersManager, { MTStickerSet, MTStickerSetCovered, MTStickerSetMultiCovered } from "./appStickersManager"; import animationIntersector from "../../components/animationIntersector"; import PopupStickers from "../../components/popupStickers"; import SearchInput from "../../components/searchInput"; import appPollsManager from "./appPollsManager"; import { roundPercents } from "../../components/poll"; import appDialogsManager from "./appDialogsManager"; const testScroll = false; let setText = (text: string, el: HTMLDivElement) => { window.requestAnimationFrame(() => { if(el.childElementCount > 1) { el.firstElementChild.remove(); } let p = document.createElement('p'); p.innerHTML = text; el.prepend(p); el.style.display = ''; }); }; class AppStickersTab implements SliderTab { private container = document.getElementById('stickers-container') as HTMLDivElement; private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement; private backBtn = this.container.querySelector('.sidebar-close-button') as HTMLButtonElement; //private input = this.container.querySelector('#stickers-search') as HTMLInputElement; private searchInput: SearchInput; private setsDiv = this.contentDiv.firstElementChild as HTMLDivElement; private scrollable: Scrollable; private lazyLoadQueue: LazyLoadQueue; constructor() { this.scrollable = new Scrollable(this.contentDiv, 'y', 'STICKERS-SEARCH', undefined, undefined, 2); this.scrollable.setVirtualContainer(this.setsDiv); this.lazyLoadQueue = new LazyLoadQueue(); this.searchInput = new SearchInput('Search Stickers', (value) => { this.search(value); }); this.backBtn.parentElement.append(this.searchInput.container); this.setsDiv.addEventListener('click', (e) => { const sticker = findUpClassName(e.target, 'sticker-set-sticker'); if(sticker) { const docID = sticker.dataset.docID; appImManager.chatInputC.sendMessageWithDocument(docID); return; } const target = findUpClassName(e.target, 'sticker-set'); if(!target) return; const id = target.dataset.stickerSet as string; const access_hash = target.dataset.stickerSet as string; const button = findUpClassName(e.target, 'sticker-set-button') as HTMLElement; if(button) { e.preventDefault(); e.cancelBubble = true; button.setAttribute('disabled', 'true'); appStickersManager.getStickerSet({id, access_hash}).then(full => { appStickersManager.toggleStickerSet(full.set).then(changed => { if(changed) { button.innerText = full.set.installed_date ? 'Added' : 'Add'; button.classList.toggle('gray', !!full.set.installed_date); } }).finally(() => { //button.style.width = set.installed_date ? '68px' : '52px'; button.removeAttribute('disabled'); }); }); } else { appStickersManager.getStickerSet({id, access_hash}).then(full => { new PopupStickers(full.set).show(); }); } }); } public onCloseAfterTimeout() { this.setsDiv.innerHTML = ''; this.searchInput.value = ''; animationIntersector.checkAnimations(undefined, 'STICKERS-SEARCH'); } public renderSet(set: MTStickerSet) { console.log('renderSet:', set); const div = document.createElement('div'); div.classList.add('sticker-set'); const header = document.createElement('div'); header.classList.add('sticker-set-header'); const details = document.createElement('div'); details.classList.add('sticker-set-details'); details.innerHTML = `
${RichTextProcessor.wrapEmojiText(set.title)}
${set.count} stickers
`; const button = document.createElement('button'); button.classList.add('btn-primary', 'sticker-set-button'); button.innerText = set.installed_date ? 'Added' : 'Add'; // button.style.width = set.installed_date ? '68px' : '52px'; if(set.installed_date) { button.classList.add('gray'); } //ripple(button); header.append(details, button); const stickersDiv = document.createElement('div'); stickersDiv.classList.add('sticker-set-stickers'); const count = Math.min(5, set.count); for(let i = 0; i < count; ++i) { const stickerDiv = document.createElement('div'); stickerDiv.classList.add('sticker-set-sticker'); stickersDiv.append(stickerDiv); } appStickersManager.getStickerSet(set).then(set => { console.log('renderSet got set:', set); for(let i = 0; i < count; ++i) { const div = stickersDiv.children[i] as HTMLDivElement; wrapSticker({ doc: set.documents[i], div, lazyLoadQueue: this.lazyLoadQueue, group: 'STICKERS-SEARCH', /* play: false, loop: false, */ play: true, loop: true, width: 68, height: 68 }); } }); /* const onMouseOver = () => { const animations: AnimationItem['animation'][] = []; for(let i = 0; i < count; ++i) { const stickerDiv = stickersDiv.children[i] as HTMLElement; const animationItem = animationIntersector.getAnimation(stickerDiv); if(!animationItem) continue; const animation = animationItem.animation; animations.push(animation); animation.loop = true; animation.play(); } div.addEventListener('mouseout', () => { animations.forEach(animation => { animation.loop = false; }); div.addEventListener('mouseover', onMouseOver, {once: true}); }, {once: true}); }; div.addEventListener('mouseover', onMouseOver, {once: true}); */ div.dataset.stickerSet = set.id; div.dataset.access_hash = set.access_hash; div.dataset.title = set.title; div.append(header, stickersDiv); this.scrollable.append(div); } public init() { appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.stickers); appSidebarRight.toggleSidebar(true).then(() => { this.renderFeatured(); }); } public renderFeatured() { return appStickersManager.getFeaturedStickers().then(coveredSets => { if(this.searchInput.value) { return; } coveredSets = this.filterRendered('', coveredSets); coveredSets.forEach(set => { this.renderSet(set.set); }); }); } private filterRendered(query: string, coveredSets: (MTStickerSetCovered | MTStickerSetMultiCovered)[]) { coveredSets = coveredSets.slice(); const children = Array.from(this.setsDiv.children) as HTMLElement[]; children.forEachReverse(el => { const id = el.dataset.stickerSet; const index = coveredSets.findIndex(covered => covered.set.id == id); if(index !== -1) { coveredSets.splice(index, 1); } else if(!query || !el.dataset.title.toLowerCase().includes(query.toLowerCase())) { el.remove(); } }); animationIntersector.checkAnimations(undefined, 'STICKERS-SEARCH'); return coveredSets; } public search(query: string) { if(!query) { return this.renderFeatured(); } return appStickersManager.searchStickerSets(query, false).then(coveredSets => { if(this.searchInput.value != query) { return; } //console.log('search result:', coveredSets); coveredSets = this.filterRendered(query, coveredSets); coveredSets.forEach(set => { this.renderSet(set.set); }); }); } } class AppPollResultsTab implements SliderTab { private container = document.getElementById('poll-results-container') as HTMLDivElement; private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement; private resultsDiv = this.contentDiv.firstElementChild as HTMLDivElement; private scrollable: Scrollable; private pollID: string; private mid: number; constructor() { this.scrollable = new Scrollable(this.contentDiv, 'y', 'POLL-RESULTS', undefined, undefined, 2); } public cleanup() { this.resultsDiv.innerHTML = ''; this.pollID = ''; this.mid = 0; } public onCloseAfterTimeout() { this.cleanup(); } public init(pollID: string, mid: number) { if(this.pollID == pollID && this.mid == mid) return; this.cleanup(); this.pollID = pollID; this.mid = mid; appSidebarRight.selectTab(AppSidebarRight.SLIDERITEMSIDS.pollResults); const poll = appPollsManager.getPoll(pollID); const title = document.createElement('h3'); title.innerHTML = poll.poll.rQuestion; const percents = poll.results.results.map(v => v.voters / poll.results.total_voters * 100); roundPercents(percents); const fragment = document.createDocumentFragment(); poll.results.results.forEach((result, idx) => { if(!result.voters) return; const hr = document.createElement('hr'); const answer = poll.poll.answers[idx]; // Head const answerEl = document.createElement('div'); answerEl.classList.add('poll-results-answer'); const answerTitle = document.createElement('div'); answerTitle.innerHTML = RichTextProcessor.wrapEmojiText(answer.text); const answerPercents = document.createElement('div'); answerPercents.innerText = Math.round(percents[idx]) + '%'; answerEl.append(answerTitle, answerPercents); // Humans const list = document.createElement('ul'); list.classList.add('poll-results-voters'); appDialogsManager.setListClickListener(list); list.style.minHeight = Math.min(result.voters, 4) * 50 + 'px'; fragment.append(hr, answerEl, list); let offset: string, limit = 4, loading = false, left = result.voters - 4; const load = () => { if(loading) return; loading = true; appPollsManager.getVotes(mid, answer.option, offset, limit).then(votesList => { votesList.votes.forEach(vote => { const {dom} = appDialogsManager.addDialog(vote.user_id, list, false, false, undefined, false); dom.lastMessageSpan.parentElement.remove(); }); if(offset) { left -= votesList.votes.length; (showMore.lastElementChild as HTMLElement).innerText = `Show ${Math.min(20, left)} more voter${left > 1 ? 's' : ''}`; } offset = votesList.next_offset; limit = 20; if(!left || !votesList.votes.length) { showMore.remove(); } }).finally(() => { loading = false; }); }; load(); if(left <= 0) return; const showMore = document.createElement('div'); showMore.classList.add('poll-results-more', 'show-more'); showMore.addEventListener('click', load); showMore.innerHTML = `
Show ${Math.min(20, left)} more voter${left > 1 ? 's' : ''}
`; ripple(showMore); fragment.append(showMore); }); this.resultsDiv.append(title, fragment); appSidebarRight.toggleSidebar(true).then(() => { /* appPollsManager.getVotes(mid).then(votes => { console.log('gOt VotEs', votes); }); */ }); } } const stickersTab = new AppStickersTab(); const pollResultsTab = new AppPollResultsTab(); export class AppSidebarRight extends SidebarSlider { public static SLIDERITEMSIDS = { search: 1, forward: 2, stickers: 3, pollResults: 4, }; public profileContainer: HTMLDivElement; public profileContentEl: HTMLDivElement; public contentContainer: HTMLDivElement; public profileElements: { avatar: AvatarElement, name: HTMLDivElement, subtitle: HTMLDivElement, bio: HTMLDivElement, username: HTMLDivElement, phone: HTMLDivElement, notificationsRow: HTMLDivElement, notificationsCheckbox: HTMLInputElement, notificationsStatus: HTMLParagraphElement } = {} as any; public sharedMedia: { [type: string]: HTMLDivElement } = {}; private loadSidebarMediaPromises: {[type: string]: Promise} = {}; private loadedAllMedia: {[type: string]: boolean} = {}; public sharedMediaTypes = [ //'members', 'inputMessagesFilterContacts', 'inputMessagesFilterPhotoVideo', 'inputMessagesFilterDocument', 'inputMessagesFilterUrl', 'inputMessagesFilterMusic' ]; public sharedMediaType: AppSidebarRight['sharedMediaTypes'][number] = ''; private sharedMediaSelected: HTMLDivElement = null; private lazyLoadQueue = new LazyLoadQueue(); public historiesStorage: { [peerID: number]: { [type: string]: number[] } } = {}; public usedFromHistory: { [type: string]: number } = {}; private log = logger('SR', LogLevels.error); private peerID = 0; public scroll: Scrollable = null; private profileTabs: HTMLUListElement; private prevTabID = -1; private mediaDivsByIDs: { [mid: number]: HTMLDivElement } = {}; public urlsToRevoke: string[] = []; private searchContainer: HTMLDivElement;; public searchCloseBtn: HTMLButtonElement; private searchInput: SearchInput; public privateSearch: AppSearch; private loadMutex: Promise = Promise.resolve(); public stickersTab: AppStickersTab; public pollResultsTab: AppPollResultsTab; constructor() { super(document.getElementById('column-right') as HTMLElement, { [AppSidebarRight.SLIDERITEMSIDS.stickers]: stickersTab, [AppSidebarRight.SLIDERITEMSIDS.pollResults]: pollResultsTab, }); //this._selectTab(3); this.stickersTab = stickersTab; this.pollResultsTab = pollResultsTab; this.profileContainer = this.sidebarEl.querySelector('.profile-container'); this.profileContentEl = this.sidebarEl.querySelector('.profile-content'); this.contentContainer = this.sidebarEl.querySelector('.content-container'); this.profileElements = { avatar: this.profileContentEl.querySelector('.profile-avatar'), name: this.profileContentEl.querySelector('.profile-name'), subtitle: this.profileContentEl.querySelector('.profile-subtitle'), bio: this.profileContentEl.querySelector('.profile-row-bio'), username: this.profileContentEl.querySelector('.profile-row-username'), phone: this.profileContentEl.querySelector('.profile-row-phone'), notificationsRow: this.profileContentEl.querySelector('.profile-row-notifications'), notificationsCheckbox: this.profileContentEl.querySelector('#profile-notifications'), notificationsStatus: this.profileContentEl.querySelector('.profile-row-notifications > p') }; this.sharedMedia = { contentMembers: this.profileContentEl.querySelector('#content-members'), contentMedia: this.profileContentEl.querySelector('#content-media'), contentDocuments: this.profileContentEl.querySelector('#content-docs'), contentLinks: this.profileContentEl.querySelector('#content-links'), contentAudio: this.profileContentEl.querySelector('#content-audio'), }; this.searchContainer = this.sidebarEl.querySelector('#search-private-container'); this.searchCloseBtn = this.searchContainer.querySelector('.sidebar-close-button'); this.searchInput = new SearchInput('Search'); this.searchCloseBtn.parentElement.append(this.searchInput.container); this.privateSearch = new AppSearch(this.searchContainer.querySelector('.chats-container'), this.searchInput, { messages: new SearchGroup('Private Search', 'messages') }); let container = this.profileContentEl.querySelector('.content-container .tabs-container') as HTMLDivElement; this.profileTabs = this.profileContentEl.querySelector('.profile-tabs'); this.scroll = new Scrollable(this.profileContainer, 'y', 'SR', undefined, 400); this.scroll.onScrolledBottom = () => { if(this.sharedMediaSelected && this.sharedMediaSelected.childElementCount/* && false */) { this.log('onScrolledBottom will load media'); this.loadSidebarMedia(true); } }; //this.scroll.attachSentinels(undefined, 400); horizontalMenu(this.profileTabs, container, (id, tabContent) => { if(this.prevTabID == id) return; this.sharedMediaType = this.sharedMediaTypes[id]; this.sharedMediaSelected = tabContent.firstElementChild as HTMLDivElement; if(this.prevTabID != -1 && this.profileTabs.offsetTop) { this.scroll.scrollTop -= this.profileTabs.offsetTop; } /* this.log('setVirtualContainer', id, this.sharedMediaSelected, this.sharedMediaSelected.childElementCount); this.scroll.setVirtualContainer(this.sharedMediaSelected); */ if(this.prevTabID != -1 && !this.sharedMediaSelected.childElementCount) { // quick brown fix //this.contentContainer.classList.remove('loaded'); this.loadSidebarMedia(true); } this.prevTabID = id; }); let sidebarCloseBtn = this.sidebarEl.querySelector('.sidebar-close-button') as HTMLButtonElement; sidebarCloseBtn.addEventListener('click', () => { this.toggleSidebar(false); }); this.searchCloseBtn.addEventListener('click', () => { this.searchContainer.classList.remove('active'); this.privateSearch.reset(); }); this.sharedMedia.contentMedia.addEventListener('click', (e) => { let target = e.target as HTMLDivElement; let messageID = +target.dataset.mid; if(!messageID) { this.log.warn('no messageID by click on target:', target); return; } let message = appMessagesManager.getMessage(messageID); let ids = Object.keys(this.mediaDivsByIDs).map(k => +k).sort((a, b) => a - b); let idx = ids.findIndex(i => i == messageID); let targets = ids.map(id => ({element: this.mediaDivsByIDs[id].firstElementChild as HTMLElement, mid: id})); appMediaViewer.openMedia(message, target, false, this.sidebarEl, targets.slice(idx + 1).reverse(), targets.slice(0, idx).reverse(), true); }); this.profileElements.notificationsCheckbox.addEventListener('change', () => { //let checked = this.profileElements.notificationsCheckbox.checked; appImManager.mutePeer(this.peerID); }); } public beginSearch() { this.toggleSidebar(true); this.searchContainer.classList.add('active'); this.privateSearch.beginSearch(this.peerID); } public toggleSidebar(enable?: boolean) { /////this.log('sidebarEl', this.sidebarEl, enable, isElementInViewport(this.sidebarEl)); const active = this.sidebarEl.classList.contains('active'); let willChange: boolean; if(enable !== undefined) { if(enable) { if(!active) { willChange = true; } } else if(active) { willChange = true; } } else { willChange = true; } if(!willChange) return Promise.resolve(); //console.log('sidebar selectTab', enable, willChange); if(mediaSizes.isMobile) { appImManager.selectTab(active ? 1 : 2); return Promise.resolve(); } const set = () => { this.sidebarEl.classList.toggle('active', enable); }; return new Promise((resolve, reject) => { const hidden: {element: HTMLDivElement, height: number}[] = []; const observer = new IntersectionObserver((entries) => { for(const entry of entries) { const bubble = entry.target as HTMLDivElement; if(!entry.isIntersecting) { hidden.push({element: bubble, height: bubble.scrollHeight}); } } for(const item of hidden) { item.element.style.minHeight = item.height + 'px'; (item.element.firstElementChild as HTMLElement).style.display = 'none'; item.element.style.width = '1px'; } //console.log('hidden', hidden); observer.disconnect(); set(); setTimeout(() => { for(const item of hidden) { item.element.style.minHeight = ''; item.element.style.width = ''; (item.element.firstElementChild as HTMLElement).style.display = ''; } if(active) { appForward.close(); this.searchCloseBtn.click(); } resolve(); }, 200); }); const length = Object.keys(appImManager.bubbles).length; if(length) { for(const i in appImManager.bubbles) { observer.observe(appImManager.bubbles[i]); } } else { set(); setTimeout(resolve, 200); } }); } public filterMessagesByType(ids: number[], type: string) { let messages: any[] = []; for(let mid of ids) { let message = appMessagesManager.getMessage(mid); if(message.media) messages.push(message); } let filtered: any[] = []; switch(type) { case 'inputMessagesFilterPhotoVideo': { for(let message of messages) { let media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document); if(!media) { //this.log('no media!', message); continue; } if(media._ == 'document' && media.type != 'video'/* && media.type != 'gif' */) { //this.log('broken video', media); continue; } filtered.push(message); } break; } case 'inputMessagesFilterDocument': { for(let message of messages) { if(!message.media.document || message.media.document.type == 'voice' || message.media.document.type == 'audio') { continue; } let doc = message.media.document; if(doc.attributes) { if(doc.attributes.find((a: any) => a._ == "documentAttributeSticker")) { continue; } } filtered.push(message); } break; } case 'inputMessagesFilterUrl': { for(let message of messages) { if(!message.media.webpage || message.media.webpage._ == 'webPageEmpty') { continue; } filtered.push(message); } break; } case 'inputMessagesFilterMusic': { for(let message of messages) { if(!message.media.document || message.media.document.type != 'audio') { continue; } filtered.push(message); } break; } default: break; } return filtered; } public async performSearchResult(messages: any[], type: string) { const peerID = this.peerID; const elemsToAppend: HTMLElement[] = []; const promises: Promise[] = []; let sharedMediaDiv: HTMLDivElement; // https://core.telegram.org/type/MessagesFilter switch(type) { case 'inputMessagesFilterPhotoVideo': { sharedMediaDiv = this.sharedMedia.contentMedia; for(const message of messages) { const media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document); const div = document.createElement('div'); div.classList.add('media-item'); //console.log(message, photo); const isPhoto = media._ == 'photo'; const photo = isPhoto ? appPhotosManager.getPhoto(media.id) : null; let isDownloaded: boolean; if(photo) { isDownloaded = photo.downloaded > 0; } else { const cachedThumb = appPhotosManager.getDocumentCachedThumb(media.id); isDownloaded = cachedThumb?.downloaded > 0; } //this.log('inputMessagesFilterPhotoVideo', message, media); if(!isPhoto) { const span = document.createElement('span'); span.classList.add('video-time'); div.append(span); if(media.type != 'gif') { span.innerText = (media.duration + '').toHHMMSS(false); /* const spanPlay = document.createElement('span'); spanPlay.classList.add('video-play', 'tgico-largeplay', 'btn-circle', 'position-center'); div.append(spanPlay); */ } else { span.innerText = 'GIF'; } } const load = () => appPhotosManager.preloadPhoto(isPhoto ? media.id : media, appPhotosManager.choosePhotoSize(media, 200, 200)) .then(() => { if($rootScope.selectedPeerID != peerID) { this.log.warn('peer changed'); return; } const url = (photo && photo.url) || appPhotosManager.getDocumentCachedThumb(media.id).url; if(url) { //if(needBlur) return; const p = renderImageFromUrl(img, url); if(needBlur) { p.then(() => { //void img.offsetLeft; // reflow img.style.opacity = ''; }); } } }); let thumb: HTMLImageElement; const sizes = media.sizes || media.thumbs; const willHaveThumb = !isDownloaded && sizes && sizes[0].bytes; if(willHaveThumb) { thumb = new Image(); thumb.classList.add('media-image', 'thumbnail'); thumb.dataset.mid = '' + message.mid; appPhotosManager.setAttachmentPreview(sizes[0].bytes, thumb, false, false); div.append(thumb); } const needBlur = !isDownloaded || !willHaveThumb; const img = new Image(); img.dataset.mid = '' + message.mid; img.classList.add('media-image'); if(needBlur) img.style.opacity = '0'; div.append(img); if(isDownloaded || willHaveThumb) { const promise = new Promise((resolve, reject) => { (thumb || img).addEventListener('load', () => { clearTimeout(timeout); resolve(); }); const timeout = setTimeout(() => { this.log('did not loaded', thumb, media, isDownloaded, sizes); reject(); }, 1e3); }); promises.push(promise); } if(isDownloaded) load(); else this.lazyLoadQueue.push({div, load}); elemsToAppend.push(div); this.mediaDivsByIDs[message.mid] = div; } break; } case 'inputMessagesFilterDocument': { sharedMediaDiv = this.sharedMedia.contentDocuments; for(let message of messages) { let div = wrapDocument(message.media.document, true, false, message.mid); elemsToAppend.push(div); } break; } case 'inputMessagesFilterUrl': { sharedMediaDiv = this.sharedMedia.contentLinks; for(let message of messages) { let webpage = message.media.webpage; let div = document.createElement('div'); let previewDiv = document.createElement('div'); previewDiv.classList.add('preview'); //this.log('wrapping webpage', webpage); previewDiv.innerText = (webpage.title || webpage.description || webpage.url || webpage.display_url).slice(0, 1); previewDiv.classList.add('empty'); if(webpage.photo) { let load = () => appPhotosManager.preloadPhoto(webpage.photo.id, appPhotosManager.choosePhotoSize(webpage.photo, 60, 60)) .then(() => { if($rootScope.selectedPeerID != peerID) { this.log.warn('peer changed'); return; } previewDiv.classList.remove('empty'); previewDiv.innerText = ''; renderImageFromUrl(previewDiv, webpage.photo.url); }); this.lazyLoadQueue.push({div: previewDiv, load}); } let title = webpage.rTitle || ''; let subtitle = webpage.rDescription || ''; let url = RichTextProcessor.wrapRichText(webpage.url || ''); if(!title) { //title = new URL(webpage.url).hostname; title = webpage.display_url.split('/', 1)[0]; } div.append(previewDiv); div.insertAdjacentHTML('beforeend', `
${title}
${subtitle}
${url}
`); if(div.innerText.trim().length) { elemsToAppend.push(div); } } break; } case 'inputMessagesFilterMusic': { sharedMediaDiv = this.sharedMedia.contentAudio; for(let message of messages) { let div = wrapAudio(message.media.document, true, message.mid); elemsToAppend.push(div); } break; } default: console.warn('death is my friend', messages); break; } if(this.loadMutex) { promises.push(this.loadMutex); } if(elemsToAppend.length) { if(promises.length) { await Promise.all(promises); if(this.peerID != peerID) { this.log.warn('peer changed'); return; } } sharedMediaDiv.append(...elemsToAppend); } if(sharedMediaDiv) { let parent = sharedMediaDiv.parentElement; if(parent.lastElementChild.classList.contains('preloader')) { parent.lastElementChild.remove(); //this.contentContainer.classList.add('loaded'); } } } public loadSidebarMedia(single = false) { if(testScroll/* || 1 == 1 */) { return; } this.log('loadSidebarMedia', single, this.peerID, this.loadSidebarMediaPromises); let peerID = this.peerID; let typesToLoad = single ? [this.sharedMediaType] : this.sharedMediaTypes; typesToLoad = typesToLoad.filter(type => !this.loadedAllMedia[type]); if(!typesToLoad.length) return; let loadCount = (appPhotosManager.windowH / 130 | 0) * 3; // that's good for all types let historyStorage = this.historiesStorage[peerID] ?? (this.historiesStorage[peerID] = {}); let promises = typesToLoad.map(type => { if(this.loadSidebarMediaPromises[type]) return this.loadSidebarMediaPromises[type]; let history = historyStorage[type] ?? (historyStorage[type] = []); // render from cache if(history.length && this.usedFromHistory[type] < history.length) { let messages: any[] = []; let used = this.usedFromHistory[type]; do { let ids = history.slice(used, used + loadCount); this.log('loadSidebarMedia: will render from cache', used, history, ids, loadCount); used += ids.length; messages.push(...this.filterMessagesByType(ids, type)); } while(messages.length < loadCount && used < history.length); // если перебор if(messages.length > loadCount) { let diff = messages.length - loadCount; messages = messages.slice(0, messages.length - diff); used -= diff; } this.usedFromHistory[type] = used; if(messages.length) { return this.performSearchResult(messages, type); } return Promise.resolve(); } // заливать новую картинку сюда только после полной отправки! let maxID = history[history.length - 1] || 0; let ids = !maxID && appMessagesManager.historiesStorage[peerID] ? appMessagesManager.historiesStorage[peerID].history.slice() : []; maxID = !maxID && ids.length ? ids[ids.length - 1] : maxID; this.log('loadSidebarMedia: search house of glass pre', type, ids, maxID); //let loadCount = history.length ? 50 : 15; return this.loadSidebarMediaPromises[type] = appMessagesManager.getSearch(peerID, '', {_: type}, maxID, loadCount) .then(value => { ids = ids.concat(value.history); history.push(...ids); this.log('loadSidebarMedia: search house of glass', type, value, ids); if($rootScope.selectedPeerID != peerID) { this.log.warn('peer changed'); return; } if(value.history.length < loadCount) { this.loadedAllMedia[type] = true; } this.usedFromHistory[type] = history.length; if(ids.length) { return this.performSearchResult(this.filterMessagesByType(ids, type), type); } }, (err) => { this.log.error('load error:', err); }).then(() => { this.loadSidebarMediaPromises[type] = null; }); }); return Promise.all(promises); } public cleanup() { this.loadSidebarMediaPromises = {}; this.loadedAllMedia = {}; this.prevTabID = -1; this.mediaDivsByIDs = {}; this.lazyLoadQueue.clear(); this.sharedMediaTypes.forEach(type => { this.usedFromHistory[type] = 0; }); this.sharedMediaType = 'inputMessagesFilterPhotoVideo'; } public cleanupHTML() { //this.contentContainer.classList.remove('loaded'); //this.profileContentEl.parentElement.scrollTop = 0; this.profileElements.bio.style.display = 'none'; this.profileElements.phone.style.display = 'none'; this.profileElements.username.style.display = 'none'; this.profileElements.notificationsRow.style.display = ''; this.profileElements.notificationsCheckbox.checked = true; this.profileElements.notificationsStatus.innerText = 'Enabled'; if(this.urlsToRevoke.length) { this.urlsToRevoke.forEach(url => { URL.revokeObjectURL(url); }); this.urlsToRevoke.length = 0; } Object.keys(this.sharedMedia).forEach(key => { this.sharedMedia[key].innerHTML = ''; if(!this.historiesStorage[this.peerID] || !this.historiesStorage[this.peerID][key]) { let parent = this.sharedMedia[key].parentElement; if(!parent.querySelector('.preloader')) { putPreloader(parent, true); } } }); if(testScroll) { for(let i = 0; i < 30; ++i) { //div.insertAdjacentHTML('beforeend', `
`); let div = document.createElement('div'); div.classList.add('media-item'); div.dataset.id = '' + (i / 3 | 0); div.innerText = '' + (i / 3 | 0); this.sharedMedia.contentMedia.append(div); } (this.profileTabs.children[1] as HTMLLIElement).click(); // set media } (this.profileTabs.firstElementChild.children[1] as HTMLLIElement).click(); // set media } public setLoadMutex(promise: Promise) { this.loadMutex = promise; } public setPeer(peerID: number) { this.peerID = peerID; this.cleanup(); } public fillProfileElements() { let peerID = this.peerID = $rootScope.selectedPeerID; this.cleanupHTML(); this.profileElements.avatar.setAttribute('peer', '' + peerID); // username if(peerID != $rootScope.myID) { let username = appPeersManager.getPeerUsername(peerID); if(username) { setText(appPeersManager.getPeerUsername(peerID), this.profileElements.username); } let dialog = appMessagesManager.getDialogByPeerID(peerID)[0]; if(dialog) { let muted = false; if(dialog.notify_settings && dialog.notify_settings.mute_until) { muted = new Date(dialog.notify_settings.mute_until * 1000) > new Date(); } appImManager.setMutedState(muted); } } else { window.requestAnimationFrame(() => { this.profileElements.notificationsRow.style.display = 'none'; }); } //let membersLi = this.profileTabs.firstElementChild.children[0] as HTMLLIElement; if(peerID > 0) { //membersLi.style.display = 'none'; let user = appUsersManager.getUser(peerID); if(user.phone && peerID != $rootScope.myID) { setText(user.rPhone, this.profileElements.phone); } appProfileManager.getProfile(peerID, true).then(userFull => { if(this.peerID != peerID) { this.log.warn('peer changed'); return; } if(userFull.rAbout && peerID != $rootScope.myID) { setText(userFull.rAbout, this.profileElements.bio); } //this.log('userFull', userFull); }); } else { //membersLi.style.display = appPeersManager.isBroadcast(peerID) ? 'none' : ''; let chat = appPeersManager.getPeer(peerID); appProfileManager.getChatFull(chat.id).then((chatFull: any) => { if(this.peerID != peerID) { this.log.warn('peer changed'); return; } //this.log('chatInfo res 2:', chatFull); if(chatFull.about) { setText(RichTextProcessor.wrapRichText(chatFull.about), this.profileElements.bio); } }); } } } const appSidebarRight = new AppSidebarRight(); // @ts-ignore if(process.env.NODE_ENV != 'production') { (window as any).appSidebarRight = appSidebarRight; } export default appSidebarRight;