From 9f168465b50355d3798ddffd5d373067d00fc1ec Mon Sep 17 00:00:00 2001 From: morethanwords Date: Thu, 23 Sep 2021 19:22:30 +0400 Subject: [PATCH] Fix loading lists in media viewer --- src/components/appMediaViewer.ts | 179 +++++++++++------------ src/lib/appManagers/appPhotosManager.ts | 18 ++- src/lib/appManagers/appProfileManager.ts | 11 ++ 3 files changed, 104 insertions(+), 104 deletions(-) diff --git a/src/components/appMediaViewer.ts b/src/components/appMediaViewer.ts index b8761064..ad9ec56b 100644 --- a/src/components/appMediaViewer.ts +++ b/src/components/appMediaViewer.ts @@ -76,6 +76,7 @@ type MediaQueueLoaderOptions = { }; class MediaQueueLoader { + public target: Item = false as any; public prevTargets: Item[] = []; public nextTargets: Item[] = []; @@ -129,6 +130,10 @@ class MediaQueueLoader { } const promise = this.getLoadPromise(older, anchor, loadCount).then(items => { + if((older && this.loadMediaPromiseDown !== promise) || (!older && this.loadMediaPromiseUp !== promise)) { + return; + } + if(items.length < loadCount) { /* if(this.reverse) { if(older) this.loadedAllMediaUp = true; @@ -169,7 +174,6 @@ class MediaQueueLoader { } class MediaSearchQueueLoader extends MediaQueueLoader { - public currentMessageId = 0; public searchContext: SearchSuperContext; constructor(options: Omit, 'getLoadPromise'> = {}) { @@ -177,13 +181,14 @@ class MediaSearchQueueLoader extends ...options, getLoadPromise: (older, anchor, loadCount) => { const backLimit = older ? 0 : loadCount; - let maxId = this.currentMessageId; + let maxId = this.target?.mid; if(anchor) maxId = anchor.mid; if(!older) maxId = appMessagesIdsManager.incrementMessageId(maxId, 1); return appMessagesManager.getSearch({ ...this.searchContext, + peerId: anchor?.peerId, maxId, limit: backLimit ? 0 : loadCount, backLimit @@ -204,6 +209,40 @@ class MediaSearchQueueLoader extends public setSearchContext(context: SearchSuperContext) { this.searchContext = context; + + if(this.searchContext.folderId !== undefined) { + this.loadedAllMediaUp = true; + + if(this.searchContext.nextRate === undefined) { + this.loadedAllMediaDown = true; + } + } + } +} + +class MediaAvatarQueueLoader extends MediaQueueLoader { + private peerId: number; + + constructor(options: Omit, 'getLoadPromise'> & {peerId: number}) { + super({ + ...options, + getLoadPromise: (older, anchor, loadCount) => { + if(this.peerId < 0) return Promise.resolve([]); // ! это значит, что открыло аватар чата, но следующих фотографий нет. + + return appPhotosManager.getUserPhotos(this.peerId, anchor?.photoId, loadCount).then(value => { + const idx = value.photos.indexOf(this.target.photoId); + if(idx !== -1) { + value.photos.splice(idx, 1); + } + + return value.photos.map(photoId => { + return {element: null as HTMLElement, photoId} as any; + }); + }); + } + }); + + this.peerId = options.peerId; } } @@ -220,7 +259,6 @@ class AppMediaViewerBase; protected isFirstOpen = true; - protected loadMediaPromiseUp: Promise = null; - protected loadMediaPromiseDown: Promise = null; - protected loadedAllMediaUp = false; - protected loadedAllMediaDown = false; protected reverse = false; // reverse means next = higher msgid protected needLoadMore = true; @@ -249,7 +283,6 @@ class AppMediaViewerBase void; protected onPrevClick: (target: TargetType) => void; protected onNextClick: (target: TargetType) => void; - protected loadMoreMedia: (older: boolean) => Promise; protected videoPlayer: VideoPlayer; @@ -268,7 +301,16 @@ class AppMediaViewerBase['buttons']>) { + get target() { + return this.queueLoader.target; + } + + set target(value) { + this.queueLoader.target = value; + } + + constructor(protected queueLoader: MediaQueueLoader, + topButtons: Array['buttons']>) { this.log = logger('AMV'); this.preloader = new ProgressivePreloader(); this.preloaderStreamable = new ProgressivePreloader({ @@ -564,13 +606,12 @@ class AppMediaViewerBase onAnimationEnd); - this.target = null; - this.prevTargets = []; - this.nextTargets = []; - this.loadedAllMediaUp = this.loadedAllMediaDown = false; - this.loadMediaPromiseUp = this.loadMediaPromiseDown = null; + this.target = false as any; + this.prevTargets.length = 0; + this.nextTargets.length = 0; this.setMoverPromise = null; this.tempId = -1; + (window as any).appMediaViewer = undefined; if(this.zoomSwipeHandler) { this.zoomSwipeHandler.removeListeners(); @@ -1331,6 +1372,8 @@ class AppMediaViewerBase { - protected currentMessageId = 0; - protected currentPeerId = 0; - protected searchContext: SearchSuperContext; protected btnMenuDelete: HTMLElement; protected queueLoader: MediaSearchQueueLoader; - constructor() { - super(['delete', 'forward']); - - /* const stub = document.createElement('div'); - stub.classList.add(MEDIA_VIEWER_CLASSNAME + '-stub'); - this.content.main.prepend(stub); */ + get searchContext() { + return this.queueLoader.searchContext; + } - this.queueLoader = new MediaSearchQueueLoader({ - prevTargets: this.prevTargets, - nextTargets: this.nextTargets, + constructor() { + super(new MediaSearchQueueLoader({ generateItem: (item) => { const isForDocument = this.searchContext.inputFilter._ === 'inputMessagesFilterDocument'; const {mid, peerId} = item; @@ -1732,7 +1768,11 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet return {element: null as HTMLElement, mid, peerId}; } - }); + }), ['delete', 'forward']); + + /* const stub = document.createElement('div'); + stub.classList.add(MEDIA_VIEWER_CLASSNAME + '-stub'); + this.content.main.prepend(stub); */ this.content.caption = document.createElement('div'); this.content.caption.classList.add(MEDIA_VIEWER_CLASSNAME + '-caption'/* , 'media-viewer-stub' */); @@ -1837,17 +1877,19 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet }; onDeleteClick = () => { - new PopupDeleteMessages(this.currentPeerId, [this.currentMessageId], 'chat', () => { + const target = this.target; + new PopupDeleteMessages(target.peerId, [target.mid], 'chat', () => { this.target = {element: this.content.media} as any; this.close(); }); }; onForwardClick = () => { - if(this.currentMessageId) { - //appSidebarRight.forwardTab.open([this.currentMessageId]); + const target = this.target; + if(target.mid) { + //appSidebarRight.forwardTab.open([target.mid]); new PopupForward({ - [this.currentPeerId]: [this.currentMessageId] + [target.peerId]: [target.mid] }, () => { return this.close(); }); @@ -1855,9 +1897,8 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet }; onAuthorClick = (e: MouseEvent) => { - if(this.currentMessageId && this.currentMessageId !== Number.MAX_SAFE_INTEGER) { - const mid = this.currentMessageId; - const peerId = this.currentPeerId; + const {mid, peerId} = this.target; + if(mid && mid !== Number.MAX_SAFE_INTEGER) { const threadId = this.searchContext.threadId; this.close(e) //.then(() => mediaSizes.isMobile ? appSidebarRight.sharedMediaTab.closeBtn.click() : Promise.resolve()) @@ -1876,7 +1917,8 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet }; onDownloadClick = () => { - const message = appMessagesManager.getMessageByPeer(this.currentPeerId, this.currentMessageId); + const {peerId, mid} = this.target; + const message = appMessagesManager.getMessageByPeer(peerId, mid); if(message.media.photo) { appPhotosManager.savePhotoFile(message.media.photo, appImManager.chat.bubbles.lazyLoadQueue.queueId); } else { @@ -1892,11 +1934,6 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet } }; - // нет смысла делать проверку для reverse и loadMediaPromise - protected loadMoreMedia = (older = true) => { - return this.queueLoader.loadMoreMedia(older); - }; - private setCaption(message: Message.message) { const caption = message.message; let html = ''; @@ -1913,15 +1950,7 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet } public setSearchContext(context: SearchSuperContext) { - this.searchContext = context; - - if(this.searchContext.folderId !== undefined) { - this.loadedAllMediaUp = true; - - if(this.searchContext.nextRate === undefined) { - this.loadedAllMediaDown = true; - } - } + this.queueLoader.setSearchContext(context); return this; } @@ -1941,8 +1970,6 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet button.classList.toggle('hide', !canDeleteMessage); }); - this.currentMessageId = mid; - this.currentPeerId = message.peerId; this.setCaption(message); const promise = super._openMedia(media, message.date, fromId, fromRight, target, reverse, prevTargets, nextTargets, needLoadMore); this.target.mid = mid; @@ -1958,11 +1985,10 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet type AppMediaViewerAvatarTargetType = {element: HTMLElement, photoId: string}; export class AppMediaViewerAvatar extends AppMediaViewerBase<'', 'delete', AppMediaViewerAvatarTargetType> { - public currentPhotoId: string; public peerId: number; constructor(peerId: number) { - super([/* 'delete' */]); + super(new MediaAvatarQueueLoader({peerId}), [/* 'delete' */]); this.peerId = peerId; @@ -1990,54 +2016,13 @@ export class AppMediaViewerAvatar extends AppMediaViewerBase<'', 'delete', AppMe }; onDownloadClick = () => { - appPhotosManager.savePhotoFile(appPhotosManager.getPhoto(this.currentPhotoId), appImManager.chat.bubbles.lazyLoadQueue.queueId); - }; - - protected loadMoreMedia = (older = true) => { - if(this.peerId < 0) return Promise.resolve(); // ! это значит, что открыло аватар чата, но следующих фотографий нет. - if(this.loadedAllMediaDown) return Promise.resolve(); - if(this.loadMediaPromiseDown) return this.loadMediaPromiseDown; - - const peerId = this.peerId; - const loadCount = 50; - - const maxId = this.nextTargets.length ? this.nextTargets[this.nextTargets.length - 1].photoId : this.currentPhotoId; - - const promise = appPhotosManager.getUserPhotos(peerId, maxId, loadCount).then(value => { - if(this.peerId !== peerId) { - this.log.warn('peer changed'); - return; - } - - // if(DEBUG) { - // this.log('loaded more media by maxId:', /* maxId, */value, older, this.reverse); - // } - - if(value.photos.length < loadCount) { - this.loadedAllMediaDown = true; - } - - value.photos.forEach(photoId => { - if(this.currentPhotoId === photoId) return; - this.nextTargets.push({element: null as HTMLElement, photoId: photoId}); - }); - - this.buttons.prev.classList.toggle('hide', !this.prevTargets.length); - this.buttons.next.classList.toggle('hide', !this.nextTargets.length); - }, () => {}).then(() => { - this.loadMediaPromiseDown = null; - }); - - return this.loadMediaPromiseDown = promise; + appPhotosManager.savePhotoFile(appPhotosManager.getPhoto(this.target.photoId), appImManager.chat.bubbles.lazyLoadQueue.queueId); }; public async openMedia(photoId: string, target?: HTMLElement, fromRight = 0, prevTargets?: AppMediaViewerAvatarTargetType[], nextTargets?: AppMediaViewerAvatarTargetType[]) { if(this.setMoverPromise) return this.setMoverPromise; const photo = appPhotosManager.getPhoto(photoId); - - this.currentPhotoId = photo.id; - const ret = super._openMedia(photo, photo.date, this.peerId, fromRight, target, false, prevTargets, nextTargets); this.target.photoId = photo.id; diff --git a/src/lib/appManagers/appPhotosManager.ts b/src/lib/appManagers/appPhotosManager.ts index b04b097e..dd438d62 100644 --- a/src/lib/appManagers/appPhotosManager.ts +++ b/src/lib/appManagers/appPhotosManager.ts @@ -15,7 +15,7 @@ import { CancellablePromise } from "../../helpers/cancellablePromise"; import { getFileNameByLocation } from "../../helpers/fileName"; import { safeReplaceArrayInObject, isObject } from "../../helpers/object"; import { isSafari } from "../../helpers/userAgent"; -import { InputFileLocation, InputMedia, Photo, PhotoSize, PhotosPhotos } from "../../layer"; +import { InputFileLocation, InputMedia, InputPhoto, Photo, PhotoSize, PhotosPhotos } from "../../layer"; import apiManager from "../mtproto/mtprotoworker"; import referenceDatabase, { ReferenceContext } from "../mtproto/referenceDatabase"; import { MyDocument } from "./appDocsManager"; @@ -383,15 +383,19 @@ export class AppPhotosManager { return isObject(photoId) ? photoId as MyPhoto : this.photos[photoId as any as string]; } + public getInput(photo: MyPhoto): InputPhoto.inputPhoto { + return { + _: 'inputPhoto', + id: photo.id, + access_hash: photo.access_hash, + file_reference: photo.file_reference + }; + } + public getMediaInput(photo: MyPhoto): InputMedia.inputMediaPhoto { return { _: 'inputMediaPhoto', - id: { - _: 'inputPhoto', - id: photo.id, - access_hash: photo.access_hash, - file_reference: photo.file_reference - }, + id: this.getInput(photo), ttl_seconds: 0 }; } diff --git a/src/lib/appManagers/appProfileManager.ts b/src/lib/appManagers/appProfileManager.ts index a9a0f268..8c5601ae 100644 --- a/src/lib/appManagers/appProfileManager.ts +++ b/src/lib/appManagers/appProfileManager.ts @@ -488,6 +488,17 @@ export class AppProfileManager { }); } + public deletePhotos(photoIds: string[]) { + return apiManager.invokeApiSingle('photos.deletePhotos', { + id: photoIds.map(photoId => { + const photo = appPhotosManager.getPhoto(photoId); + return appPhotosManager.getInput(photo); + }) + }).then((deletedList) => { + + }); + } + public getChatMembersString(id: number) { const chat: Chat = appChatsManager.getChat(id); if(chat._ === 'chatForbidden') {