diff --git a/src/components/appMediaViewer.ts b/src/components/appMediaViewer.ts index a60fe0a11..4f752ae80 100644 --- a/src/components/appMediaViewer.ts +++ b/src/components/appMediaViewer.ts @@ -194,39 +194,43 @@ class AppMediaViewerBase { - if(VideoPlayer.isFullScreen()) { - return; - } - //console.log(xDiff, yDiff); + const swipeHandler = new SwipeHandler({ + element: this.wholeDiv, + onSwipe: (xDiff, yDiff) => { + if(VideoPlayer.isFullScreen()) { + return; + } + //console.log(xDiff, yDiff); - const percents = Math.abs(xDiff) / appPhotosManager.windowW; - if(percents > .2 || xDiff > 125) { - //console.log('will swipe', xDiff); + const percents = Math.abs(xDiff) / appPhotosManager.windowW; + if(percents > .2 || xDiff > 125) { + //console.log('will swipe', xDiff); - if(xDiff < 0) { - this.buttons.prev.click(); - } else { - this.buttons.next.click(); + if(xDiff < 0) { + this.buttons.prev.click(); + } else { + this.buttons.next.click(); + } + + return true; + } + + const percentsY = Math.abs(yDiff) / appPhotosManager.windowH; + if(percentsY > .2 || yDiff > 125) { + this.buttons.close.click(); + return true; + } + + return false; + }, + verifyTouchTarget: (evt) => { + // * Fix for seek input + if((evt.target as HTMLElement).tagName === 'INPUT' || findUpClassName(evt.target, 'media-viewer-caption')) { + return false; } return true; } - - const percentsY = Math.abs(yDiff) / appPhotosManager.windowH; - if(percentsY > .2 || yDiff > 125) { - this.buttons.close.click(); - return true; - } - - return false; - }, (evt) => { - // * Fix for seek input - if((evt.target as HTMLElement).tagName === 'INPUT' || findUpClassName(evt.target, 'media-viewer-caption')) { - return false; - } - - return true; }); } } diff --git a/src/components/appMediaViewerNew.ts b/src/components/appMediaViewerNew.ts index 4aa6e4aad..4ec9c2575 100644 --- a/src/components/appMediaViewerNew.ts +++ b/src/components/appMediaViewerNew.ts @@ -1,1416 +1,1418 @@ -import { deferredPromise } from "../helpers/cancellablePromise"; -import mediaSizes from "../helpers/mediaSizes"; -import { isTouchSupported } from "../helpers/touchSupport"; -import { isSafari } from "../helpers/userAgent"; -import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager"; -import appImManager from "../lib/appManagers/appImManager"; -import appMessagesManager from "../lib/appManagers/appMessagesManager"; -import appPeersManager from "../lib/appManagers/appPeersManager"; -import appPhotosManager from "../lib/appManagers/appPhotosManager"; -import { logger } from "../lib/logger"; -import VideoPlayer from "../lib/mediaPlayer"; -import { RichTextProcessor } from "../lib/richtextprocessor"; -import rootScope from "../lib/rootScope"; -import { cancelEvent, fillPropertyValue, generatePathData } from "../helpers/dom"; -import animationIntersector from "./animationIntersector"; -import appMediaPlaybackController from "./appMediaPlaybackController"; -import AvatarElement from "./avatar"; -import ButtonIcon from "./buttonIcon"; -import { ButtonMenuItemOptions } from "./buttonMenu"; -import ButtonMenuToggle from "./buttonMenuToggle"; -import { LazyLoadQueueBase } from "./lazyLoadQueue"; -import PopupForward from "./popups/forward"; -import ProgressivePreloader from "./preloader"; -import Scrollable from "./scrollable"; -import appSidebarRight, { AppSidebarRight } from "./sidebarRight"; -import SwipeHandler from "./swipeHandler"; -import { months, ONE_DAY } from "../helpers/date"; -import { SearchSuperContext } from "./appSearchSuper."; -import { Message, PhotoSize } from "../layer"; -import { forEachReverse } from "../helpers/array"; -import AppSharedMediaTab from "./sidebarRight/tabs/sharedMedia"; -import findUpClassName from "../helpers/dom/findUpClassName"; -import renderImageFromUrl from "../helpers/dom/renderImageFromUrl"; +// import { deferredPromise } from "../helpers/cancellablePromise"; +// import mediaSizes from "../helpers/mediaSizes"; +// import { isTouchSupported } from "../helpers/touchSupport"; +// import { isSafari } from "../helpers/userAgent"; +// import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager"; +// import appImManager from "../lib/appManagers/appImManager"; +// import appMessagesManager from "../lib/appManagers/appMessagesManager"; +// import appPeersManager from "../lib/appManagers/appPeersManager"; +// import appPhotosManager from "../lib/appManagers/appPhotosManager"; +// import { logger } from "../lib/logger"; +// import VideoPlayer from "../lib/mediaPlayer"; +// import { RichTextProcessor } from "../lib/richtextprocessor"; +// import rootScope from "../lib/rootScope"; +// import { cancelEvent, fillPropertyValue, generatePathData } from "../helpers/dom"; +// import animationIntersector from "./animationIntersector"; +// import appMediaPlaybackController from "./appMediaPlaybackController"; +// import AvatarElement from "./avatar"; +// import ButtonIcon from "./buttonIcon"; +// import { ButtonMenuItemOptions } from "./buttonMenu"; +// import ButtonMenuToggle from "./buttonMenuToggle"; +// import { LazyLoadQueueBase } from "./lazyLoadQueue"; +// import PopupForward from "./popups/forward"; +// import ProgressivePreloader from "./preloader"; +// import Scrollable from "./scrollable"; +// import appSidebarRight, { AppSidebarRight } from "./sidebarRight"; +// import SwipeHandler from "./swipeHandler"; +// import { months, ONE_DAY } from "../helpers/date"; +// import { SearchSuperContext } from "./appSearchSuper."; +// import { Message, PhotoSize } from "../layer"; +// import { forEachReverse } from "../helpers/array"; +// import AppSharedMediaTab from "./sidebarRight/tabs/sharedMedia"; +// import findUpClassName from "../helpers/dom/findUpClassName"; +// import renderImageFromUrl from "../helpers/dom/renderImageFromUrl"; -// TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию -// TODO: картинки "обрезаются" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода) -// TODO: видео в мобильной вёрстке, если показываются элементы управления: если свайпнуть в сторону, то элементы вернутся на место, т.е. прыгнут - это не ок, надо бы замаскировать +// // TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию +// // TODO: картинки "обрезаются" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода) +// // TODO: видео в мобильной вёрстке, если показываются элементы управления: если свайпнуть в сторону, то элементы вернутся на место, т.е. прыгнут - это не ок, надо бы замаскировать -const MEDIA_VIEWER_CLASSNAME = 'media-viewer'; +// const MEDIA_VIEWER_CLASSNAME = 'media-viewer'; -function transition(t: number) { - return 1 - ((1 - t) ** 3.5); -} +// function transition(t: number) { +// return 1 - ((1 - t) ** 3.5); +// } -class AppMediaViewerBase { - public wholeDiv: HTMLElement; - protected overlaysDiv: HTMLElement; - protected author: {[k in 'container' | 'avatarEl' | 'nameEl' | 'date']: HTMLElement} = {} as any; - protected content: {[k in 'main' | 'container' | 'media' | 'mover' | ContentAdditionType]: HTMLElement} = {} as any; - protected mover: HTMLCanvasElement; - public buttons: {[k in 'download' | 'close' | 'prev' | 'next' | 'mobile-close' | ButtonsAdditionType]: HTMLElement} = {} as any; +// class AppMediaViewerBase { +// public wholeDiv: HTMLElement; +// protected overlaysDiv: HTMLElement; +// protected author: {[k in 'container' | 'avatarEl' | 'nameEl' | 'date']: HTMLElement} = {} as any; +// protected content: {[k in 'main' | 'container' | 'media' | 'mover' | ContentAdditionType]: HTMLElement} = {} as any; +// protected mover: HTMLCanvasElement; +// public buttons: {[k in 'download' | 'close' | 'prev' | 'next' | 'mobile-close' | ButtonsAdditionType]: HTMLElement} = {} as any; - protected tempId = 0; - protected preloader: ProgressivePreloader = null; - protected preloaderStreamable: ProgressivePreloader = null; +// protected tempId = 0; +// protected preloader: ProgressivePreloader = null; +// protected preloaderStreamable: ProgressivePreloader = null; - protected lastTarget: HTMLElement = null; - protected prevTargets: TargetType[] = []; - protected nextTargets: TargetType[] = []; - //protected targetContainer: HTMLElement = null; - //protected loadMore: () => void = null; +// protected lastTarget: HTMLElement = null; +// protected prevTargets: TargetType[] = []; +// protected nextTargets: TargetType[] = []; +// //protected targetContainer: HTMLElement = null; +// //protected loadMore: () => void = null; - public log: ReturnType; +// public log: ReturnType; - protected isFirstOpen = true; - protected loadMediaPromiseUp: Promise = null; - protected loadMediaPromiseDown: Promise = null; - protected loadedAllMediaUp = false; - protected loadedAllMediaDown = false; +// 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; +// protected reverse = false; // reverse means next = higher msgid +// protected needLoadMore = true; - protected pageEl = document.getElementById('page-chats') as HTMLDivElement; +// protected pageEl = document.getElementById('page-chats') as HTMLDivElement; - protected setMoverPromise: Promise; - protected setMoverAnimationPromise: Promise; +// protected setMoverPromise: Promise; +// protected setMoverAnimationPromise: Promise; - protected lazyLoadQueue: LazyLoadQueueBase; +// protected lazyLoadQueue: LazyLoadQueueBase; - protected highlightSwitchersTimeout: number; +// protected highlightSwitchersTimeout: number; - protected onDownloadClick: (e: MouseEvent) => void; - protected onPrevClick: (target: TargetType) => void; - protected onNextClick: (target: TargetType) => void; - protected loadMoreMedia: (older: boolean) => Promise; +// protected onDownloadClick: (e: MouseEvent) => void; +// protected onPrevClick: (target: TargetType) => void; +// protected onNextClick: (target: TargetType) => void; +// protected loadMoreMedia: (older: boolean) => Promise; - protected animatingContext: { - width: number, - height: number, - startWidth: number, - startHeight: number, - media: HTMLImageElement | HTMLVideoElement, - diffX: number, - diffY: number, - startTime: number, - borderRadius: number[] - }; +// protected animatingContext: { +// width: number, +// height: number, +// startWidth: number, +// startHeight: number, +// media: HTMLImageElement | HTMLVideoElement, +// diffX: number, +// diffY: number, +// startTime: number, +// borderRadius: number[] +// }; - constructor(topButtons: Array['buttons']>) { - this.log = logger('AMV'); - this.preloader = new ProgressivePreloader(); - this.preloaderStreamable = new ProgressivePreloader({ - cancelable: false, - streamable: true - }); - this.preloader.construct(); - this.preloaderStreamable.construct(); - this.lazyLoadQueue = new LazyLoadQueueBase(); +// constructor(topButtons: Array['buttons']>) { +// this.log = logger('AMV'); +// this.preloader = new ProgressivePreloader(); +// this.preloaderStreamable = new ProgressivePreloader({ +// cancelable: false, +// streamable: true +// }); +// this.preloader.construct(); +// this.preloaderStreamable.construct(); +// this.lazyLoadQueue = new LazyLoadQueueBase(); - this.wholeDiv = document.createElement('div'); - this.wholeDiv.classList.add(MEDIA_VIEWER_CLASSNAME + '-whole'); +// this.wholeDiv = document.createElement('div'); +// this.wholeDiv.classList.add(MEDIA_VIEWER_CLASSNAME + '-whole'); - this.overlaysDiv = document.createElement('div'); - this.overlaysDiv.classList.add('overlays'); +// this.overlaysDiv = document.createElement('div'); +// this.overlaysDiv.classList.add('overlays'); - const mainDiv = document.createElement('div'); - mainDiv.classList.add(MEDIA_VIEWER_CLASSNAME); +// const mainDiv = document.createElement('div'); +// mainDiv.classList.add(MEDIA_VIEWER_CLASSNAME); - // * author - this.author.container = document.createElement('div'); - this.author.container.classList.add(MEDIA_VIEWER_CLASSNAME + '-author', 'no-select'); +// // * author +// this.author.container = document.createElement('div'); +// this.author.container.classList.add(MEDIA_VIEWER_CLASSNAME + '-author', 'no-select'); - this.author.avatarEl = new AvatarElement(); - this.author.avatarEl.classList.add(MEDIA_VIEWER_CLASSNAME + '-userpic', 'avatar-44'); +// this.author.avatarEl = new AvatarElement(); +// this.author.avatarEl.classList.add(MEDIA_VIEWER_CLASSNAME + '-userpic', 'avatar-44'); - this.author.nameEl = document.createElement('div'); - this.author.nameEl.classList.add(MEDIA_VIEWER_CLASSNAME + '-name'); +// this.author.nameEl = document.createElement('div'); +// this.author.nameEl.classList.add(MEDIA_VIEWER_CLASSNAME + '-name'); - this.author.date = document.createElement('div'); - this.author.date.classList.add(MEDIA_VIEWER_CLASSNAME + '-date'); +// this.author.date = document.createElement('div'); +// this.author.date.classList.add(MEDIA_VIEWER_CLASSNAME + '-date'); - this.author.container.append(this.author.avatarEl, this.author.nameEl, this.author.date); +// this.author.container.append(this.author.avatarEl, this.author.nameEl, this.author.date); - // * buttons - const buttonsDiv = document.createElement('div'); - buttonsDiv.classList.add(MEDIA_VIEWER_CLASSNAME + '-buttons'); +// // * buttons +// const buttonsDiv = document.createElement('div'); +// buttonsDiv.classList.add(MEDIA_VIEWER_CLASSNAME + '-buttons'); - topButtons.concat(['download', 'close']).forEach(name => { - const button = ButtonIcon(name); - this.buttons[name] = button; - buttonsDiv.append(button); - }); +// topButtons.concat(['download', 'close']).forEach(name => { +// const button = ButtonIcon(name); +// this.buttons[name] = button; +// buttonsDiv.append(button); +// }); - // * content - this.content.main = document.createElement('div'); - this.content.main.classList.add(MEDIA_VIEWER_CLASSNAME + '-content'); +// // * content +// this.content.main = document.createElement('div'); +// this.content.main.classList.add(MEDIA_VIEWER_CLASSNAME + '-content'); - this.content.container = document.createElement('div'); - this.content.container.classList.add(MEDIA_VIEWER_CLASSNAME + '-container'); +// this.content.container = document.createElement('div'); +// this.content.container.classList.add(MEDIA_VIEWER_CLASSNAME + '-container'); - this.content.media = document.createElement('div'); - this.content.media.classList.add(MEDIA_VIEWER_CLASSNAME + '-media'); +// this.content.media = document.createElement('div'); +// this.content.media.classList.add(MEDIA_VIEWER_CLASSNAME + '-media'); - this.content.container.append(this.content.media); +// this.content.container.append(this.content.media); - this.content.main.append(this.content.container); - mainDiv.append(this.author.container, buttonsDiv, this.content.main); - this.overlaysDiv.append(mainDiv); - // * overlays end +// this.content.main.append(this.content.container); +// mainDiv.append(this.author.container, buttonsDiv, this.content.main); +// this.overlaysDiv.append(mainDiv); +// // * overlays end - this.buttons["mobile-close"] = ButtonIcon('close', {onlyMobile: true}); +// this.buttons["mobile-close"] = ButtonIcon('close', {onlyMobile: true}); - this.buttons.prev = document.createElement('div'); - this.buttons.prev.className = `${MEDIA_VIEWER_CLASSNAME}-switcher ${MEDIA_VIEWER_CLASSNAME}-switcher-left`; - this.buttons.prev.innerHTML = ``; +// this.buttons.prev = document.createElement('div'); +// this.buttons.prev.className = `${MEDIA_VIEWER_CLASSNAME}-switcher ${MEDIA_VIEWER_CLASSNAME}-switcher-left`; +// this.buttons.prev.innerHTML = ``; - this.buttons.next = document.createElement('div'); - this.buttons.next.className = `${MEDIA_VIEWER_CLASSNAME}-switcher ${MEDIA_VIEWER_CLASSNAME}-switcher-right`; - this.buttons.next.innerHTML = ``; +// this.buttons.next = document.createElement('div'); +// this.buttons.next.className = `${MEDIA_VIEWER_CLASSNAME}-switcher ${MEDIA_VIEWER_CLASSNAME}-switcher-right`; +// this.buttons.next.innerHTML = ``; - this.wholeDiv.append(this.overlaysDiv, this.buttons['mobile-close'], this.buttons.prev, this.buttons.next); +// this.wholeDiv.append(this.overlaysDiv, this.buttons['mobile-close'], this.buttons.prev, this.buttons.next); - // * constructing html end +// // * constructing html end - this.setNewMover(); - } +// this.setNewMover(); +// } - protected setListeners() { - this.buttons.download.addEventListener('click', this.onDownloadClick); - [this.buttons.close, this.buttons["mobile-close"], this.preloaderStreamable.preloader].forEach(el => { - el.addEventListener('click', this.close.bind(this)); - }); +// protected setListeners() { +// this.buttons.download.addEventListener('click', this.onDownloadClick); +// [this.buttons.close, this.buttons["mobile-close"], this.preloaderStreamable.preloader].forEach(el => { +// el.addEventListener('click', this.close.bind(this)); +// }); - this.buttons.prev.addEventListener('click', (e) => { - cancelEvent(e); - if(this.setMoverPromise) return; +// this.buttons.prev.addEventListener('click', (e) => { +// cancelEvent(e); +// if(this.setMoverPromise) return; - const target = this.prevTargets.pop(); - if(target) { - this.onPrevClick(target); - } else { - this.buttons.prev.style.display = 'none'; - } - }); +// const target = this.prevTargets.pop(); +// if(target) { +// this.onPrevClick(target); +// } else { +// this.buttons.prev.style.display = 'none'; +// } +// }); - this.buttons.next.addEventListener('click', (e) => { - cancelEvent(e); - if(this.setMoverPromise) return; +// this.buttons.next.addEventListener('click', (e) => { +// cancelEvent(e); +// if(this.setMoverPromise) return; - let target = this.nextTargets.shift(); - if(target) { - this.onNextClick(target); - } else { - this.buttons.next.style.display = 'none'; - } - }); +// let target = this.nextTargets.shift(); +// if(target) { +// this.onNextClick(target); +// } else { +// this.buttons.next.style.display = 'none'; +// } +// }); - this.wholeDiv.addEventListener('click', this.onClick); +// this.wholeDiv.addEventListener('click', this.onClick); - if(isTouchSupported) { - const swipeHandler = new SwipeHandler(this.wholeDiv, (xDiff, yDiff) => { - if(VideoPlayer.isFullScreen()) { - return; - } - //console.log(xDiff, yDiff); +// if(isTouchSupported) { +// const swipeHandler = new SwipeHandler(this.wholeDiv, (xDiff, yDiff) => { +// if(VideoPlayer.isFullScreen()) { +// return; +// } +// //console.log(xDiff, yDiff); - const percents = Math.abs(xDiff) / appPhotosManager.windowW; - if(percents > .2 || xDiff > 125) { - //console.log('will swipe', xDiff); +// const percents = Math.abs(xDiff) / appPhotosManager.windowW; +// if(percents > .2 || xDiff > 125) { +// //console.log('will swipe', xDiff); - if(xDiff < 0) { - this.buttons.prev.click(); - } else { - this.buttons.next.click(); - } +// if(xDiff < 0) { +// this.buttons.prev.click(); +// } else { +// this.buttons.next.click(); +// } - return true; - } +// return true; +// } - const percentsY = Math.abs(yDiff) / appPhotosManager.windowH; - if(percentsY > .2 || yDiff > 125) { - this.buttons.close.click(); - return true; - } +// const percentsY = Math.abs(yDiff) / appPhotosManager.windowH; +// if(percentsY > .2 || yDiff > 125) { +// this.buttons.close.click(); +// return true; +// } - return false; - }, (evt) => { - // * Fix for seek input - if((evt.target as HTMLElement).tagName === 'INPUT' || findUpClassName(evt.target, 'media-viewer-caption')) { - return false; - } +// return false; +// }, (evt) => { +// // * Fix for seek input +// if((evt.target as HTMLElement).tagName === 'INPUT' || findUpClassName(evt.target, 'media-viewer-caption')) { +// return false; +// } - return true; - }); - } - } +// return true; +// }); +// } +// } - protected setBtnMenuToggle(buttons: ButtonMenuItemOptions[]) { - const btnMenuToggle = ButtonMenuToggle({onlyMobile: true}, 'bottom-left', buttons); - this.wholeDiv.append(btnMenuToggle); - } +// protected setBtnMenuToggle(buttons: ButtonMenuItemOptions[]) { +// const btnMenuToggle = ButtonMenuToggle({onlyMobile: true}, 'bottom-left', buttons); +// this.wholeDiv.append(btnMenuToggle); +// } - public close(e?: MouseEvent) { - if(e) { - cancelEvent(e); - } +// public close(e?: MouseEvent) { +// if(e) { +// cancelEvent(e); +// } - if(this.setMoverAnimationPromise) return; +// if(this.setMoverAnimationPromise) return; - this.lazyLoadQueue.clear(); +// this.lazyLoadQueue.clear(); - const promise = this.setMoverToTarget(this.lastTarget, true).then(({onAnimationEnd}) => onAnimationEnd); +// const promise = this.setMoverToTarget(this.lastTarget, true).then(({onAnimationEnd}) => onAnimationEnd); - this.lastTarget = null; - this.prevTargets = []; - this.nextTargets = []; - this.loadedAllMediaUp = this.loadedAllMediaDown = false; - this.loadMediaPromiseUp = this.loadMediaPromiseDown = null; - this.setMoverPromise = null; - this.tempId = -1; +// this.lastTarget = null; +// this.prevTargets = []; +// this.nextTargets = []; +// this.loadedAllMediaUp = this.loadedAllMediaDown = false; +// this.loadMediaPromiseUp = this.loadMediaPromiseDown = null; +// this.setMoverPromise = null; +// this.tempId = -1; - /* if(appSidebarRight.historyTabIDs.slice(-1)[0] === AppSidebarRight.SLIDERITEMSIDS.forward) { - promise.then(() => { - appSidebarRight.forwardTab.closeBtn.click(); - }); - } */ +// /* if(appSidebarRight.historyTabIDs.slice(-1)[0] === AppSidebarRight.SLIDERITEMSIDS.forward) { +// promise.then(() => { +// appSidebarRight.forwardTab.closeBtn.click(); +// }); +// } */ - window.removeEventListener('keydown', this.onKeyDown); +// window.removeEventListener('keydown', this.onKeyDown); - promise.finally(() => { - this.wholeDiv.remove(); - rootScope.overlayIsActive = false; - animationIntersector.checkAnimations(false); - }); +// promise.finally(() => { +// this.wholeDiv.remove(); +// rootScope.overlayIsActive = false; +// animationIntersector.checkAnimations(false); +// }); - return promise; - } +// return promise; +// } - onClick = (e: MouseEvent) => { - if(this.setMoverAnimationPromise) return; +// onClick = (e: MouseEvent) => { +// if(this.setMoverAnimationPromise) return; - const target = e.target as HTMLElement; - if(target.tagName === 'A') return; - cancelEvent(e); +// const target = e.target as HTMLElement; +// if(target.tagName === 'A') return; +// cancelEvent(e); - if(isTouchSupported) { - if(this.highlightSwitchersTimeout) { - clearTimeout(this.highlightSwitchersTimeout); - } else { - this.wholeDiv.classList.add('highlight-switchers'); - } +// if(isTouchSupported) { +// if(this.highlightSwitchersTimeout) { +// clearTimeout(this.highlightSwitchersTimeout); +// } else { +// this.wholeDiv.classList.add('highlight-switchers'); +// } - this.highlightSwitchersTimeout = window.setTimeout(() => { - this.wholeDiv.classList.remove('highlight-switchers'); - this.highlightSwitchersTimeout = 0; - }, 3e3); +// this.highlightSwitchersTimeout = window.setTimeout(() => { +// this.wholeDiv.classList.remove('highlight-switchers'); +// this.highlightSwitchersTimeout = 0; +// }, 3e3); - return; - } +// return; +// } - let mover: HTMLElement = null; - ['media-viewer-mover', 'media-viewer-buttons', 'media-viewer-author', 'media-viewer-caption'].find(s => { - try { - mover = findUpClassName(target, s); - if(mover) return true; - } catch(err) {return false;} - }); +// let mover: HTMLElement = null; +// ['media-viewer-mover', 'media-viewer-buttons', 'media-viewer-author', 'media-viewer-caption'].find(s => { +// try { +// mover = findUpClassName(target, s); +// if(mover) return true; +// } catch(err) {return false;} +// }); - if(/* target === this.mediaViewerDiv */!mover || target.tagName === 'IMG' || target.tagName === 'image') { - this.buttons.close.click(); - } - }; +// if(/* target === this.mediaViewerDiv */!mover || target.tagName === 'IMG' || target.tagName === 'image') { +// this.buttons.close.click(); +// } +// }; - onKeyDown = (e: KeyboardEvent) => { - //this.log('onKeyDown', e); +// onKeyDown = (e: KeyboardEvent) => { +// //this.log('onKeyDown', e); - if(e.key === 'Escape') { - this.close(); - } else if(e.key === 'ArrowRight') { - this.buttons.next.click(); - } else if(e.key === 'ArrowLeft') { - this.buttons.prev.click(); - } - }; +// if(e.key === 'Escape') { +// this.close(); +// } else if(e.key === 'ArrowRight') { +// this.buttons.next.click(); +// } else if(e.key === 'ArrowLeft') { +// this.buttons.prev.click(); +// } +// }; - protected async setMoverToTarget(target: HTMLElement, closing = false, fromRight = 0) { - const mover = this.mover; +// protected async setMoverToTarget(target: HTMLElement, closing = false, fromRight = 0) { +// const mover = this.mover; - if(!target) { - target = this.content.media; - } +// if(!target) { +// target = this.content.media; +// } - if(!closing) { - mover.innerHTML = ''; - //mover.append(this.buttons.prev, this.buttons.next); - } +// if(!closing) { +// mover.innerHTML = ''; +// //mover.append(this.buttons.prev, this.buttons.next); +// } - this.removeCenterFromMover(mover); +// this.removeCenterFromMover(mover); - const wasActive = fromRight !== 0; +// const wasActive = fromRight !== 0; - const delay = rootScope.settings.animationsEnabled ? (wasActive ? 350 : 200) : 0; - //let delay = wasActive ? 350 : 10000; +// const delay = rootScope.settings.animationsEnabled ? (wasActive ? 350 : 200) : 0; +// //let delay = wasActive ? 350 : 10000; - /* if(wasActive) { - this.moveTheMover(mover); - mover = this.setNewMover(); - } */ +// /* if(wasActive) { +// this.moveTheMover(mover); +// mover = this.setNewMover(); +// } */ - /* if(DEBUG) { - this.log('setMoverToTarget', target, closing, wasActive, fromRight); - } */ +// /* if(DEBUG) { +// this.log('setMoverToTarget', target, closing, wasActive, fromRight); +// } */ - let realParent: HTMLElement; +// let realParent: HTMLElement; - let rect: DOMRect; - if(target) { - if(target instanceof AvatarElement) { - realParent = target; - rect = target.getBoundingClientRect(); - } else { - realParent = target.parentElement as HTMLElement; - rect = target.getBoundingClientRect(); - } - } +// let rect: DOMRect; +// if(target) { +// if(target instanceof AvatarElement) { +// realParent = target; +// rect = target.getBoundingClientRect(); +// } else { +// realParent = target.parentElement as HTMLElement; +// rect = target.getBoundingClientRect(); +// } +// } - const containerRect = this.content.media.getBoundingClientRect(); +// const containerRect = this.content.media.getBoundingClientRect(); - let transform = ''; - let left: number; - let top: number; +// let transform = ''; +// let left: number; +// let top: number; - if(wasActive) { - left = fromRight === 1 ? appPhotosManager.windowW : -containerRect.width; - top = containerRect.top; - } else { - left = rect.left; - top = rect.top; - } +// if(wasActive) { +// left = fromRight === 1 ? appPhotosManager.windowW : -containerRect.width; +// top = containerRect.top; +// } else { +// left = rect.left; +// top = rect.top; +// } - transform += `translate3d(${left}px,${top}px,0) `; +// transform += `translate3d(${left}px,${top}px,0) `; - /* if(wasActive) { - left = fromRight === 1 ? appPhotosManager.windowW / 2 : -(containerRect.width + appPhotosManager.windowW / 2); - transform += `translate(${left}px,-50%) `; - } else { - left = rect.left - (appPhotosManager.windowW / 2); - top = rect.top - (appPhotosManager.windowH / 2); - transform += `translate(${left}px,${top}px) `; - } */ +// /* if(wasActive) { +// left = fromRight === 1 ? appPhotosManager.windowW / 2 : -(containerRect.width + appPhotosManager.windowW / 2); +// transform += `translate(${left}px,-50%) `; +// } else { +// left = rect.left - (appPhotosManager.windowW / 2); +// top = rect.top - (appPhotosManager.windowH / 2); +// transform += `translate(${left}px,${top}px) `; +// } */ - //mover.style.width = containerRect.width + 'px'; - //mover.style.height = containerRect.height + 'px'; +// //mover.style.width = containerRect.width + 'px'; +// //mover.style.height = containerRect.height + 'px'; - const scaleX = rect.width / containerRect.width; - const scaleY = rect.height / containerRect.height; +// const scaleX = rect.width / containerRect.width; +// const scaleY = rect.height / containerRect.height; - let borderRadius: any = window.getComputedStyle(realParent).getPropertyValue('border-radius'); - const brSplitted = fillPropertyValue(borderRadius) as string[]; - borderRadius = brSplitted.map(v => parseInt(v)); +// let borderRadius: any = window.getComputedStyle(realParent).getPropertyValue('border-radius'); +// const brSplitted = fillPropertyValue(borderRadius) as string[]; +// borderRadius = brSplitted.map(v => parseInt(v)); - //let borderRadius = '0px 0px 0px 0px'; +// //let borderRadius = '0px 0px 0px 0px'; - mover.style.transform = transform; +// mover.style.transform = transform; - /* if(wasActive) { - this.log('setMoverToTarget', mover.style.transform); - } */ +// /* if(wasActive) { +// this.log('setMoverToTarget', mover.style.transform); +// } */ - let path: SVGPathElement; - const isOut = target.classList.contains('is-out'); +// let path: SVGPathElement; +// const isOut = target.classList.contains('is-out'); - const deferred = this.setMoverAnimationPromise = deferredPromise(); - const ret = {onAnimationEnd: deferred}; +// const deferred = this.setMoverAnimationPromise = deferredPromise(); +// const ret = {onAnimationEnd: deferred}; - this.setMoverAnimationPromise.then(() => { - this.setMoverAnimationPromise = null; - }); +// this.setMoverAnimationPromise.then(() => { +// this.setMoverAnimationPromise = null; +// }); - if(!closing) { - let mediaElement: HTMLImageElement | HTMLVideoElement; +// if(!closing) { +// let mediaElement: HTMLImageElement | HTMLVideoElement; - if(target.tagName === 'DIV' || target.tagName === 'AVATAR-ELEMENT') { // useContainerAsTarget - if(target.firstElementChild) { - mediaElement = target.firstElementChild as HTMLImageElement; - } - /* mediaElement = new Image(); - src = target.style.backgroundImage.slice(5, -2); */ +// if(target.tagName === 'DIV' || target.tagName === 'AVATAR-ELEMENT') { // useContainerAsTarget +// if(target.firstElementChild) { +// mediaElement = target.firstElementChild as HTMLImageElement; +// } +// /* mediaElement = new Image(); +// src = target.style.backgroundImage.slice(5, -2); */ - } else if(target instanceof HTMLImageElement) { - mediaElement = target; - } else if(target instanceof HTMLVideoElement) { - mediaElement = target; - } +// } else if(target instanceof HTMLImageElement) { +// mediaElement = target; +// } else if(target instanceof HTMLVideoElement) { +// mediaElement = target; +// } - const naturalWidth = (mediaElement as HTMLImageElement).naturalWidth || (mediaElement as HTMLVideoElement).videoWidth; - const naturalHeight = (mediaElement as HTMLImageElement).naturalHeight || (mediaElement as HTMLVideoElement).videoHeight; +// const naturalWidth = (mediaElement as HTMLImageElement).naturalWidth || (mediaElement as HTMLVideoElement).videoWidth; +// const naturalHeight = (mediaElement as HTMLImageElement).naturalHeight || (mediaElement as HTMLVideoElement).videoHeight; - const context = this.animatingContext = { - width: this.mover.width, - height: this.mover.height, - startWidth: rect.width, - startHeight: rect.height, - diffX: 0, - diffY: 0, - media: mediaElement, - startTime: Date.now(), - borderRadius - }; +// const context = this.animatingContext = { +// width: this.mover.width, +// height: this.mover.height, +// startWidth: rect.width, +// startHeight: rect.height, +// diffX: 0, +// diffY: 0, +// media: mediaElement, +// startTime: Date.now(), +// borderRadius +// }; - let left = rect.left, top = rect.top; - if(mediaElement.width !== naturalWidth) { - const diff = context.diffX = (naturalWidth - mediaElement.width) / 2; - left -= diff; - } +// let left = rect.left, top = rect.top; +// if(mediaElement.width !== naturalWidth) { +// const diff = context.diffX = (naturalWidth - mediaElement.width) / 2; +// left -= diff; +// } - if(mediaElement.height !== naturalHeight) { - const diff = context.diffY = (naturalHeight - mediaElement.height) / 2; - top -= diff; - } +// if(mediaElement.height !== naturalHeight) { +// const diff = context.diffY = (naturalHeight - mediaElement.height) / 2; +// top -= diff; +// } - transform = `translate3d(${left}px,${top}px,0) `; +// transform = `translate3d(${left}px,${top}px,0) `; - mover.style.transform = transform; +// mover.style.transform = transform; - mover.style.display = ''; +// mover.style.display = ''; - this.beginMagic(context, delay); - //this.renderMedia(context, 0); +// this.beginMagic(context, delay); +// //this.renderMedia(context, 0); - window.requestAnimationFrame(() => { - mover.classList.add(wasActive ? 'moving' : 'active'); - }); - } else { - /* if(mover.classList.contains('center')) { - mover.classList.remove('center'); - void mover.offsetLeft; // reflow - } */ +// window.requestAnimationFrame(() => { +// mover.classList.add(wasActive ? 'moving' : 'active'); +// }); +// } else { +// /* if(mover.classList.contains('center')) { +// mover.classList.remove('center'); +// void mover.offsetLeft; // reflow +// } */ - if(target.classList.contains('media-viewer-media')) { - mover.classList.add('hiding'); - } +// if(target.classList.contains('media-viewer-media')) { +// mover.classList.add('hiding'); +// } - setTimeout(() => { - this.wholeDiv.classList.remove('active'); - }, 0); +// setTimeout(() => { +// this.wholeDiv.classList.remove('active'); +// }, 0); - setTimeout(() => { - mover.style.borderRadius = borderRadius; +// setTimeout(() => { +// mover.style.borderRadius = borderRadius; - if(mover.firstElementChild) { - (mover.firstElementChild as HTMLElement).style.borderRadius = borderRadius; - } - }, delay / 2); +// if(mover.firstElementChild) { +// (mover.firstElementChild as HTMLElement).style.borderRadius = borderRadius; +// } +// }, delay / 2); - setTimeout(() => { - mover.innerHTML = ''; - mover.classList.remove('moving', 'active', 'hiding'); - mover.style.cssText = 'display: none;'; +// setTimeout(() => { +// mover.innerHTML = ''; +// mover.classList.remove('moving', 'active', 'hiding'); +// mover.style.cssText = 'display: none;'; - deferred.resolve(); - }, delay); +// deferred.resolve(); +// }, delay); - return ret; - } +// return ret; +// } - //await new Promise((resolve) => setTimeout(resolve, 0)); - //await new Promise((resolve) => window.requestAnimationFrame(resolve)); - // * одного RAF'а недостаточно, иногда анимация с одним не срабатывает (преимущественно на мобильных) - await new Promise((resolve) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve))); +// //await new Promise((resolve) => setTimeout(resolve, 0)); +// //await new Promise((resolve) => window.requestAnimationFrame(resolve)); +// // * одного RAF'а недостаточно, иногда анимация с одним не срабатывает (преимущественно на мобильных) +// await new Promise((resolve) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve))); - // чтобы проверить установленную позицию - раскомментировать - throw ''; +// // чтобы проверить установленную позицию - раскомментировать +// throw ''; - //await new Promise((resolve) => setTimeout(resolve, 5e3)); +// //await new Promise((resolve) => setTimeout(resolve, 5e3)); - mover.style.transform = `translate3d(${containerRect.left}px,${containerRect.top}px,0)`; - //mover.style.transform = `translate(-50%,-50%) scale(1,1)`; +// mover.style.transform = `translate3d(${containerRect.left}px,${containerRect.top}px,0)`; +// //mover.style.transform = `translate(-50%,-50%) scale(1,1)`; - //throw ''; +// //throw ''; - mover.dataset.timeout = '' + setTimeout(() => { - mover.classList.remove('moving'); +// mover.dataset.timeout = '' + setTimeout(() => { +// mover.classList.remove('moving'); - // эти строки нужны для установки центральной позиции, в случае ресайза это будет нужно - mover.classList.add('center', 'no-transition'); - /* mover.style.left = mover.style.top = '50%'; - mover.style.transform = 'translate(-50%, -50%)'; - void mover.offsetLeft; // reflow */ +// // эти строки нужны для установки центральной позиции, в случае ресайза это будет нужно +// mover.classList.add('center', 'no-transition'); +// /* mover.style.left = mover.style.top = '50%'; +// mover.style.transform = 'translate(-50%, -50%)'; +// void mover.offsetLeft; // reflow */ - // это уже нужно для будущих анимаций - mover.classList.add('active'); - delete mover.dataset.timeout; +// // это уже нужно для будущих анимаций +// mover.classList.add('active'); +// delete mover.dataset.timeout; - deferred.resolve(); - }, delay); +// deferred.resolve(); +// }, delay); - return ret; - } +// return ret; +// } - protected beginMagic(context: AppMediaViewer['animatingContext'], delay: number) { - const start = Date.now(); +// protected beginMagic(context: AppMediaViewer['animatingContext'], delay: number) { +// const start = Date.now(); - const step = () => { - const diff = Date.now() - start; +// const step = () => { +// const diff = Date.now() - start; - let progress = delay ? Math.min(1, diff / delay) : 1; +// let progress = delay ? Math.min(1, diff / delay) : 1; - this.renderMedia(context, progress); +// this.renderMedia(context, progress); - if(diff < delay) window.requestAnimationFrame(step); - }; +// if(diff < delay) window.requestAnimationFrame(step); +// }; - window.requestAnimationFrame(step); - //step(); +// window.requestAnimationFrame(step); +// //step(); - this.renderMedia(context, 0); - } +// this.renderMedia(context, 0); +// } - protected renderMedia(context: AppMediaViewer['animatingContext'], percents: number) { - const ctx = this.mover.getContext('2d'); +// protected renderMedia(context: AppMediaViewer['animatingContext'], percents: number) { +// const ctx = this.mover.getContext('2d'); - //percents = transition(percents); - const width = context.startWidth + (context.width - context.startWidth) * percents; - const height = context.startHeight + (context.height - context.startHeight) * percents; - const x = context.diffX - (context.diffX * percents); - const y = context.diffY - (context.diffY * percents); +// //percents = transition(percents); +// const width = context.startWidth + (context.width - context.startWidth) * percents; +// const height = context.startHeight + (context.height - context.startHeight) * percents; +// const x = context.diffX - (context.diffX * percents); +// const y = context.diffY - (context.diffY * percents); - const borderRadius = context.borderRadius.map(v => v - v * percents); - const [brTl, brTr, brBr, brBl] = borderRadius; +// const borderRadius = context.borderRadius.map(v => v - v * percents); +// const [brTl, brTr, brBr, brBl] = borderRadius; - /* ctx.clearRect(0, 0, context.width, context.height); - ctx.closePath(); */ +// /* ctx.clearRect(0, 0, context.width, context.height); +// ctx.closePath(); */ - ctx.save(); +// ctx.save(); - ctx.beginPath(); - ctx.moveTo(x + brTl, y); - ctx.lineTo(x + width - brTr, y); - ctx.quadraticCurveTo(x + width, y, x + width, y + brTr); - ctx.lineTo(x + width, y + height - brBr); - ctx.quadraticCurveTo(x + width, y + height, x + width - brBr, y + height); - ctx.lineTo(x + brBl, y + height); - ctx.quadraticCurveTo(x, y + height, x, y + height - brBl); - ctx.lineTo(x, y + brTl); - ctx.quadraticCurveTo(x, y, x + brTl, y); - ctx.closePath(); +// ctx.beginPath(); +// ctx.moveTo(x + brTl, y); +// ctx.lineTo(x + width - brTr, y); +// ctx.quadraticCurveTo(x + width, y, x + width, y + brTr); +// ctx.lineTo(x + width, y + height - brBr); +// ctx.quadraticCurveTo(x + width, y + height, x + width - brBr, y + height); +// ctx.lineTo(x + brBl, y + height); +// ctx.quadraticCurveTo(x, y + height, x, y + height - brBl); +// ctx.lineTo(x, y + brTl); +// ctx.quadraticCurveTo(x, y, x + brTl, y); +// ctx.closePath(); - ctx.clip(); - ctx.drawImage(context.media, x, y, width, height); - ctx.restore(); - } +// ctx.clip(); +// ctx.drawImage(context.media, x, y, width, height); +// ctx.restore(); +// } - protected setFullAspect(aspecter: HTMLDivElement, containerRect: DOMRect, rect: DOMRect) { - /* let media = aspecter.firstElementChild; - let proportion: number; - if(media instanceof HTMLImageElement) { - proportion = media.naturalWidth / media.naturalHeight; - } else if(media instanceof HTMLVideoElement) { - proportion = media.videoWidth / media.videoHeight; - } */ - const proportion = containerRect.width / containerRect.height; +// protected setFullAspect(aspecter: HTMLDivElement, containerRect: DOMRect, rect: DOMRect) { +// /* let media = aspecter.firstElementChild; +// let proportion: number; +// if(media instanceof HTMLImageElement) { +// proportion = media.naturalWidth / media.naturalHeight; +// } else if(media instanceof HTMLVideoElement) { +// proportion = media.videoWidth / media.videoHeight; +// } */ +// const proportion = containerRect.width / containerRect.height; - let {width, height} = rect; - /* if(proportion === 1) { - aspecter.style.cssText = ''; - } else { */ - if(proportion > 0) { - width = height * proportion; - } else { - height = width * proportion; - } +// let {width, height} = rect; +// /* if(proportion === 1) { +// aspecter.style.cssText = ''; +// } else { */ +// if(proportion > 0) { +// width = height * proportion; +// } else { +// height = width * proportion; +// } - //this.log('will set style aspecter:', `width: ${width}px; height: ${height}px; transform: scale(${containerRect.width / width}, ${containerRect.height / height});`); +// //this.log('will set style aspecter:', `width: ${width}px; height: ${height}px; transform: scale(${containerRect.width / width}, ${containerRect.height / height});`); - aspecter.style.cssText = `width: ${width}px; height: ${height}px; transform: scale3d(${containerRect.width / width}, ${containerRect.height / height}, 1);`; - //} - } +// aspecter.style.cssText = `width: ${width}px; height: ${height}px; transform: scale3d(${containerRect.width / width}, ${containerRect.height / height}, 1);`; +// //} +// } - protected sizeTailPath(path: SVGPathElement, rect: DOMRect, scaleX: number, delay: number, upscale: boolean, isOut: boolean, borderRadius: string) { - const start = Date.now(); - const {width, height} = rect; - delay = delay / 2; +// protected sizeTailPath(path: SVGPathElement, rect: DOMRect, scaleX: number, delay: number, upscale: boolean, isOut: boolean, borderRadius: string) { +// const start = Date.now(); +// const {width, height} = rect; +// delay = delay / 2; - const br = borderRadius.split(' ').map(v => parseInt(v)); +// const br = borderRadius.split(' ').map(v => parseInt(v)); - const step = () => { - const diff = Date.now() - start; +// const step = () => { +// const diff = Date.now() - start; - let progress = delay ? diff / delay : 1; - if(progress > 1) progress = 1; - if(upscale) progress = 1 - progress; +// let progress = delay ? diff / delay : 1; +// if(progress > 1) progress = 1; +// if(upscale) progress = 1 - progress; - const _br: [number, number, number, number] = br.map(v => v * progress) as any; +// const _br: [number, number, number, number] = br.map(v => v * progress) as any; - let d: string; - if(isOut) d = generatePathData(0, 0, width - (9 / scaleX * progress), height, ..._br); - else d = generatePathData(9 / scaleX * progress, 0, width/* width - (9 / scaleX * progress) */, height, ..._br); - path.setAttributeNS(null, 'd', d); +// let d: string; +// if(isOut) d = generatePathData(0, 0, width - (9 / scaleX * progress), height, ..._br); +// else d = generatePathData(9 / scaleX * progress, 0, width/* width - (9 / scaleX * progress) */, height, ..._br); +// path.setAttributeNS(null, 'd', d); - if(diff < delay) window.requestAnimationFrame(step); - }; +// if(diff < delay) window.requestAnimationFrame(step); +// }; - //window.requestAnimationFrame(step); - step(); - } +// //window.requestAnimationFrame(step); +// step(); +// } - protected removeCenterFromMover(mover: HTMLElement) { - if(mover.classList.contains('center')) { - //const rect = mover.getBoundingClientRect(); - const rect = this.content.media.getBoundingClientRect(); - mover.style.transform = `translate3d(${rect.left}px,${rect.top}px,0)`; - mover.classList.remove('center'); - void mover.offsetLeft; // reflow - mover.classList.remove('no-transition'); - } - } +// protected removeCenterFromMover(mover: HTMLElement) { +// if(mover.classList.contains('center')) { +// //const rect = mover.getBoundingClientRect(); +// const rect = this.content.media.getBoundingClientRect(); +// mover.style.transform = `translate3d(${rect.left}px,${rect.top}px,0)`; +// mover.classList.remove('center'); +// void mover.offsetLeft; // reflow +// mover.classList.remove('no-transition'); +// } +// } - protected moveTheMover(mover: HTMLElement, toLeft = true) { - const windowW = appPhotosManager.windowW; +// protected moveTheMover(mover: HTMLElement, toLeft = true) { +// const windowW = appPhotosManager.windowW; - this.removeCenterFromMover(mover); +// this.removeCenterFromMover(mover); - //mover.classList.remove('active'); - mover.classList.add('moving'); +// //mover.classList.remove('active'); +// mover.classList.add('moving'); - if(mover.dataset.timeout) { // и это тоже всё из-за скейла видео, так бы это не нужно было - clearTimeout(+mover.dataset.timeout); - } +// if(mover.dataset.timeout) { // и это тоже всё из-за скейла видео, так бы это не нужно было +// clearTimeout(+mover.dataset.timeout); +// } - const rect = mover.getBoundingClientRect(); +// const rect = mover.getBoundingClientRect(); - const newTransform = mover.style.transform.replace(/translate3d\((.+?),/, (match, p1) => { - const x = toLeft ? -rect.width : windowW; - //const x = toLeft ? -(rect.right + (rect.width / 2)) : windowW / 2; +// const newTransform = mover.style.transform.replace(/translate3d\((.+?),/, (match, p1) => { +// const x = toLeft ? -rect.width : windowW; +// //const x = toLeft ? -(rect.right + (rect.width / 2)) : windowW / 2; - return match.replace(p1, x + 'px'); - }); +// return match.replace(p1, x + 'px'); +// }); - ////////this.log('set newTransform:', newTransform, mover.style.transform, toLeft); - mover.style.transform = newTransform; +// ////////this.log('set newTransform:', newTransform, mover.style.transform, toLeft); +// mover.style.transform = newTransform; - setTimeout(() => { - mover.remove(); - }, 350); - } +// setTimeout(() => { +// mover.remove(); +// }, 350); +// } - protected setNewMover() { - const newMover = document.createElement('canvas'); - newMover.classList.add('media-viewer-canvas'); +// protected setNewMover() { +// const newMover = document.createElement('canvas'); +// newMover.classList.add('media-viewer-canvas'); - if(this.mover) { - const oldMover = this.mover; - oldMover.parentElement.append(newMover); - } else { - this.wholeDiv.append(newMover); - } +// if(this.mover) { +// const oldMover = this.mover; +// oldMover.parentElement.append(newMover); +// } else { +// this.wholeDiv.append(newMover); +// } - return this.mover = newMover; - } +// return this.mover = newMover; +// } - /* public isElementVisible(container: HTMLElement, target: HTMLElement) { - const rect = container.getBoundingClientRect(); - const targetRect = target.getBoundingClientRect(); +// /* public isElementVisible(container: HTMLElement, target: HTMLElement) { +// const rect = container.getBoundingClientRect(); +// const targetRect = target.getBoundingClientRect(); - return targetRect.bottom > rect.top && targetRect.top < rect.bottom; - } */ +// return targetRect.bottom > rect.top && targetRect.top < rect.bottom; +// } */ - protected updateMediaSource(target: HTMLElement, url: string, tagName: 'video' | 'img') { - //if(target instanceof SVGSVGElement) { - const el = target.querySelector(tagName) as HTMLElement; - renderImageFromUrl(el, url); - /* } else { +// protected updateMediaSource(target: HTMLElement, url: string, tagName: 'video' | 'img') { +// //if(target instanceof SVGSVGElement) { +// const el = target.querySelector(tagName) as HTMLElement; +// renderImageFromUrl(el, url); +// /* } else { - } */ - } +// } */ +// } - protected setAuthorInfo(fromId: number, timestamp: number) { - const date = new Date(); - const time = new Date(timestamp * 1000); - const now = date.getTime() / 1000; +// protected setAuthorInfo(fromId: number, timestamp: number) { +// const date = new Date(); +// const time = new Date(timestamp * 1000); +// const now = date.getTime() / 1000; - const timeStr = time.getHours() + ':' + ('0' + time.getMinutes()).slice(-2); - let dateStr: string; - if((now - timestamp) < ONE_DAY && date.getDate() === time.getDate()) { // if the same day - dateStr = 'Today'; - } else if((now - timestamp) < (ONE_DAY * 2) && (date.getDate() - 1) === time.getDate()) { // yesterday - dateStr = 'Yesterday'; - } else if(date.getFullYear() !== time.getFullYear()) { // different year - dateStr = months[time.getMonth()].slice(0, 3) + ' ' + time.getDate() + ', ' + time.getFullYear(); - } else { - dateStr = months[time.getMonth()].slice(0, 3) + ' ' + time.getDate(); - } +// const timeStr = time.getHours() + ':' + ('0' + time.getMinutes()).slice(-2); +// let dateStr: string; +// if((now - timestamp) < ONE_DAY && date.getDate() === time.getDate()) { // if the same day +// dateStr = 'Today'; +// } else if((now - timestamp) < (ONE_DAY * 2) && (date.getDate() - 1) === time.getDate()) { // yesterday +// dateStr = 'Yesterday'; +// } else if(date.getFullYear() !== time.getFullYear()) { // different year +// dateStr = months[time.getMonth()].slice(0, 3) + ' ' + time.getDate() + ', ' + time.getFullYear(); +// } else { +// dateStr = months[time.getMonth()].slice(0, 3) + ' ' + time.getDate(); +// } - this.author.date.innerText = dateStr + ' at ' + timeStr; +// this.author.date.innerText = dateStr + ' at ' + timeStr; - const name = appPeersManager.getPeerTitle(fromId); - this.author.nameEl.innerHTML = name; +// const name = appPeersManager.getPeerTitle(fromId); +// this.author.nameEl.innerHTML = name; - let oldAvatar = this.author.avatarEl; - this.author.avatarEl = (this.author.avatarEl.cloneNode() as AvatarElement); - this.author.avatarEl.setAttribute('peer', '' + fromId); - oldAvatar.parentElement.replaceChild(this.author.avatarEl, oldAvatar); - } +// let oldAvatar = this.author.avatarEl; +// this.author.avatarEl = (this.author.avatarEl.cloneNode() as AvatarElement); +// this.author.avatarEl.setAttribute('peer', '' + fromId); +// oldAvatar.parentElement.replaceChild(this.author.avatarEl, oldAvatar); +// } - protected async _openMedia(media: any, timestamp: number, fromId: number, fromRight: number, target?: HTMLElement, reverse = false, - prevTargets: TargetType[] = [], nextTargets: TargetType[] = [], needLoadMore = true) { - if(this.setMoverPromise) return this.setMoverPromise; +// protected async _openMedia(media: any, timestamp: number, fromId: number, fromRight: number, target?: HTMLElement, reverse = false, +// prevTargets: TargetType[] = [], nextTargets: TargetType[] = [], needLoadMore = true) { +// if(this.setMoverPromise) return this.setMoverPromise; - /* if(DEBUG) { - this.log('openMedia:', media, fromId, prevTargets, nextTargets); - } */ +// /* if(DEBUG) { +// this.log('openMedia:', media, fromId, prevTargets, nextTargets); +// } */ - this.setAuthorInfo(fromId, timestamp); +// this.setAuthorInfo(fromId, timestamp); - const isVideo = (media as MyDocument).type === 'video' || (media as MyDocument).type === 'gif'; +// const isVideo = (media as MyDocument).type === 'video' || (media as MyDocument).type === 'gif'; - if(this.isFirstOpen) { - //this.targetContainer = targetContainer; - this.prevTargets = prevTargets; - this.nextTargets = nextTargets; - this.reverse = reverse; - this.needLoadMore = needLoadMore; - this.isFirstOpen = false; - //this.loadMore = loadMore; +// if(this.isFirstOpen) { +// //this.targetContainer = targetContainer; +// this.prevTargets = prevTargets; +// this.nextTargets = nextTargets; +// this.reverse = reverse; +// this.needLoadMore = needLoadMore; +// this.isFirstOpen = false; +// //this.loadMore = loadMore; - /* if(appSidebarRight.historyTabIDs.slice(-1)[0] === AppSidebarRight.SLIDERITEMSIDS.forward) { - appSidebarRight.forwardTab.closeBtn.click(); - await new Promise((resolve) => setTimeout(resolve, 200)); - } */ - } +// /* if(appSidebarRight.historyTabIDs.slice(-1)[0] === AppSidebarRight.SLIDERITEMSIDS.forward) { +// appSidebarRight.forwardTab.closeBtn.click(); +// await new Promise((resolve) => setTimeout(resolve, 200)); +// } */ +// } - /* if(this.nextTargets.length < 10 && this.loadMore) { - this.loadMore(); - } */ +// /* if(this.nextTargets.length < 10 && this.loadMore) { +// this.loadMore(); +// } */ - //if(prevTarget && (!prevTarget.parentElement || !this.isElementVisible(this.targetContainer, prevTarget))) prevTarget = null; - //if(nextTarget && (!nextTarget.parentElement || !this.isElementVisible(this.targetContainer, nextTarget))) nextTarget = null; +// //if(prevTarget && (!prevTarget.parentElement || !this.isElementVisible(this.targetContainer, prevTarget))) prevTarget = null; +// //if(nextTarget && (!nextTarget.parentElement || !this.isElementVisible(this.targetContainer, nextTarget))) nextTarget = null; - this.buttons.prev.classList.toggle('hide', !this.prevTargets.length); - this.buttons.next.classList.toggle('hide', !this.nextTargets.length); +// this.buttons.prev.classList.toggle('hide', !this.prevTargets.length); +// this.buttons.next.classList.toggle('hide', !this.nextTargets.length); - const container = this.content.media; - const useContainerAsTarget = !target; - if(useContainerAsTarget) target = container; +// const container = this.content.media; +// const useContainerAsTarget = !target; +// if(useContainerAsTarget) target = container; - this.lastTarget = target; - const tempId = ++this.tempId; +// this.lastTarget = target; +// const tempId = ++this.tempId; - if(this.needLoadMore) { - if(this.nextTargets.length < 20) { - this.loadMoreMedia(!this.reverse); - } +// if(this.needLoadMore) { +// if(this.nextTargets.length < 20) { +// this.loadMoreMedia(!this.reverse); +// } - if(this.prevTargets.length < 20) { - this.loadMoreMedia(this.reverse); - } - } +// if(this.prevTargets.length < 20) { +// this.loadMoreMedia(this.reverse); +// } +// } - if(container.firstElementChild) { - container.innerHTML = ''; - } +// if(container.firstElementChild) { +// container.innerHTML = ''; +// } - // ok set +// // ok set - const wasActive = fromRight !== 0; - if(wasActive) { - this.moveTheMover(this.mover, fromRight === 1); - this.setNewMover(); - } else { - window.addEventListener('keydown', this.onKeyDown); - const mainColumns = this.pageEl.querySelector('#main-columns'); - this.pageEl.insertBefore(this.wholeDiv, mainColumns); - void this.wholeDiv.offsetLeft; // reflow - this.wholeDiv.classList.add('active'); - rootScope.overlayIsActive = true; - animationIntersector.checkAnimations(true); - } +// const wasActive = fromRight !== 0; +// if(wasActive) { +// this.moveTheMover(this.mover, fromRight === 1); +// this.setNewMover(); +// } else { +// window.addEventListener('keydown', this.onKeyDown); +// const mainColumns = this.pageEl.querySelector('#main-columns'); +// this.pageEl.insertBefore(this.wholeDiv, mainColumns); +// void this.wholeDiv.offsetLeft; // reflow +// this.wholeDiv.classList.add('active'); +// rootScope.overlayIsActive = true; +// animationIntersector.checkAnimations(true); +// } - ////////this.log('wasActive:', wasActive); +// ////////this.log('wasActive:', wasActive); - const mover = this.mover; +// const mover = this.mover; - //const maxWidth = appPhotosManager.windowW - 16; - const maxWidth = mediaSizes.isMobile ? this.pageEl.scrollWidth : this.pageEl.scrollWidth - 16; - const maxHeight = appPhotosManager.windowH - 100; - const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(media); - if(gotThumb) { - container.append(gotThumb.image); - } - const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight); +// //const maxWidth = appPhotosManager.windowW - 16; +// const maxWidth = mediaSizes.isMobile ? this.pageEl.scrollWidth : this.pageEl.scrollWidth - 16; +// const maxHeight = appPhotosManager.windowH - 100; +// const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(media); +// if(gotThumb) { +// container.append(gotThumb.image); +// } +// const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight); - this.mover.width = (size as PhotoSize.photoSize).w; - this.mover.height = (size as PhotoSize.photoSize).h; +// this.mover.width = (size as PhotoSize.photoSize).w; +// this.mover.height = (size as PhotoSize.photoSize).h; - // need after setAttachmentSize - /* if(useContainerAsTarget) { - target = target.querySelector('img, video') || target; - } */ +// // need after setAttachmentSize +// /* if(useContainerAsTarget) { +// target = target.querySelector('img, video') || target; +// } */ - //return; +// //return; - const preloader = media.supportsStreaming ? this.preloaderStreamable : this.preloader; +// const preloader = media.supportsStreaming ? this.preloaderStreamable : this.preloader; - let setMoverPromise: Promise; - if(isVideo) { - ////////this.log('will wrap video', media, size); +// let setMoverPromise: Promise; +// if(isVideo) { +// ////////this.log('will wrap video', media, size); - // потому что для safari нужно создать элемент из event'а - const video = document.createElement('video'); +// // потому что для safari нужно создать элемент из event'а +// const video = document.createElement('video'); - setMoverPromise = this.setMoverToTarget(target, false, fromRight).then(({onAnimationEnd}) => { - //return; // set and don't move - //if(wasActive) return; - //return; +// setMoverPromise = this.setMoverToTarget(target, false, fromRight).then(({onAnimationEnd}) => { +// //return; // set and don't move +// //if(wasActive) return; +// //return; - const div = mover.firstElementChild && mover.firstElementChild.classList.contains('media-viewer-aspecter') ? mover.firstElementChild : mover; - //const video = mover.querySelector('video') || document.createElement('video'); +// const div = mover.firstElementChild && mover.firstElementChild.classList.contains('media-viewer-aspecter') ? mover.firstElementChild : mover; +// //const video = mover.querySelector('video') || document.createElement('video'); - const moverVideo = mover.querySelector('video'); - if(moverVideo) { - moverVideo.remove(); - } +// const moverVideo = mover.querySelector('video'); +// if(moverVideo) { +// moverVideo.remove(); +// } - //video.src = ''; +// //video.src = ''; - video.setAttribute('playsinline', 'true'); +// video.setAttribute('playsinline', 'true'); - // * fix for playing video if viewer is closed (https://contest.com/javascript-web-bonus/entry1425#issue11629) - video.addEventListener('timeupdate', () => { - if(this.tempId !== tempId) { - video.pause(); - } - }); +// // * fix for playing video if viewer is closed (https://contest.com/javascript-web-bonus/entry1425#issue11629) +// video.addEventListener('timeupdate', () => { +// if(this.tempId !== tempId) { +// video.pause(); +// } +// }); - if(isSafari) { - // test stream - // video.controls = true; - video.autoplay = true; - } +// if(isSafari) { +// // test stream +// // video.controls = true; +// video.autoplay = true; +// } - if(media.type === 'gif') { - video.muted = true; - video.autoplay = true; - video.loop = true; - } +// if(media.type === 'gif') { +// video.muted = true; +// video.autoplay = true; +// video.loop = true; +// } - if(!video.parentElement) { - div.append(video); - } +// if(!video.parentElement) { +// div.append(video); +// } - const canPlayThrough = new Promise((resolve) => { - video.addEventListener('canplay', resolve, {once: true}); - }); +// const canPlayThrough = new Promise((resolve) => { +// video.addEventListener('canplay', resolve, {once: true}); +// }); - const createPlayer = () => { - if(media.type !== 'gif') { - video.dataset.ckin = 'default'; - video.dataset.overlay = '1'; +// const createPlayer = () => { +// if(media.type !== 'gif') { +// video.dataset.ckin = 'default'; +// video.dataset.overlay = '1'; - // fix for simultaneous play - appMediaPlaybackController.pause(); - appMediaPlaybackController.willBePlayedMedia = null; +// // fix for simultaneous play +// appMediaPlaybackController.pause(); +// appMediaPlaybackController.willBePlayedMedia = null; - Promise.all([canPlayThrough, onAnimationEnd]).then(() => { - if(this.tempId !== tempId) { - return; - } +// Promise.all([canPlayThrough, onAnimationEnd]).then(() => { +// if(this.tempId !== tempId) { +// return; +// } - const player = new VideoPlayer(video, true, media.supportsStreaming); - /* div.append(video); - mover.append(player.wrapper); */ - }); - } - }; +// const player = new VideoPlayer(video, true, media.supportsStreaming); +// /* div.append(video); +// mover.append(player.wrapper); */ +// }); +// } +// }; - if(media.supportsStreaming) { - onAnimationEnd.then(() => { - if(video.readyState < video.HAVE_FUTURE_DATA) { - preloader.attach(mover, true); - } +// if(media.supportsStreaming) { +// onAnimationEnd.then(() => { +// if(video.readyState < video.HAVE_FUTURE_DATA) { +// preloader.attach(mover, true); +// } - /* canPlayThrough.then(() => { - preloader.detach(); - }); */ - }); +// /* canPlayThrough.then(() => { +// preloader.detach(); +// }); */ +// }); - const attachCanPlay = () => { - video.addEventListener('canplay', () => { - //this.log('video waited and progress loaded'); - preloader.detach(); - video.parentElement.classList.remove('is-buffering'); - }, {once: true}); - }; +// const attachCanPlay = () => { +// video.addEventListener('canplay', () => { +// //this.log('video waited and progress loaded'); +// preloader.detach(); +// video.parentElement.classList.remove('is-buffering'); +// }, {once: true}); +// }; - video.addEventListener('waiting', (e) => { - const loading = video.networkState === video.NETWORK_LOADING; - const isntEnoughData = video.readyState < video.HAVE_FUTURE_DATA; +// video.addEventListener('waiting', (e) => { +// const loading = video.networkState === video.NETWORK_LOADING; +// const isntEnoughData = video.readyState < video.HAVE_FUTURE_DATA; - //this.log('video waiting for progress', loading, isntEnoughData); - if(loading && isntEnoughData) { - attachCanPlay(); +// //this.log('video waiting for progress', loading, isntEnoughData); +// if(loading && isntEnoughData) { +// attachCanPlay(); - preloader.attach(mover, true); +// preloader.attach(mover, true); - // поставлю класс для плеера, чтобы убрать большую иконку пока прелоадер на месте - video.parentElement.classList.add('is-buffering'); - } - }); +// // поставлю класс для плеера, чтобы убрать большую иконку пока прелоадер на месте +// video.parentElement.classList.add('is-buffering'); +// } +// }); - attachCanPlay(); - } +// attachCanPlay(); +// } - //if(!video.src || media.url !== video.src) { - const load = () => { - const promise = media.supportsStreaming ? Promise.resolve() : appDocsManager.downloadDoc(media); +// //if(!video.src || media.url !== video.src) { +// const load = () => { +// const promise = media.supportsStreaming ? Promise.resolve() : appDocsManager.downloadDoc(media); - if(!media.supportsStreaming) { - onAnimationEnd.then(() => { - if(!media.url) { - preloader.attach(mover, true, promise); - } - }); - } +// if(!media.supportsStreaming) { +// onAnimationEnd.then(() => { +// if(!media.url) { +// preloader.attach(mover, true, promise); +// } +// }); +// } - (promise as Promise).then(async() => { - if(this.tempId !== tempId) { - this.log.warn('media viewer changed video'); - return; - } +// (promise as Promise).then(async() => { +// if(this.tempId !== tempId) { +// this.log.warn('media viewer changed video'); +// return; +// } - const url = media.url; - if(target instanceof SVGSVGElement/* && (video.parentElement || !isSafari) */) { // if video exists - //if(!video.parentElement) { - div.firstElementChild.lastElementChild.append(video); - //} +// const url = media.url; +// if(target instanceof SVGSVGElement/* && (video.parentElement || !isSafari) */) { // if video exists +// //if(!video.parentElement) { +// div.firstElementChild.lastElementChild.append(video); +// //} - this.updateMediaSource(mover, url, 'video'); - } else { - renderImageFromUrl(video, url); - } +// this.updateMediaSource(mover, url, 'video'); +// } else { +// renderImageFromUrl(video, url); +// } - createPlayer(); - }); +// createPlayer(); +// }); - return promise; - }; +// return promise; +// }; - this.lazyLoadQueue.unshift({load}); - //} else createPlayer(); - }); - } else { - setMoverPromise = this.setMoverToTarget(target, false, fromRight).then(({onAnimationEnd}) => { - //return; // set and don't move - //if(wasActive) return; - //return; +// this.lazyLoadQueue.unshift({load}); +// //} else createPlayer(); +// }); +// } else { +// setMoverPromise = this.setMoverToTarget(target, false, fromRight).then(({onAnimationEnd}) => { +// //return; // set and don't move +// //if(wasActive) return; +// //return; - const load = () => { - const cancellablePromise = appPhotosManager.preloadPhoto(media.id, size); +// const load = () => { +// const cancellablePromise = appPhotosManager.preloadPhoto(media.id, size); - onAnimationEnd.then(() => { - if(!media.url) { - this.preloader.attach(mover, true, cancellablePromise); - } - }); +// onAnimationEnd.then(() => { +// if(!media.url) { +// this.preloader.attach(mover, true, cancellablePromise); +// } +// }); - Promise.all([onAnimationEnd, cancellablePromise]).then(() => { - if(this.tempId !== tempId) { - this.log.warn('media viewer changed photo'); - return; - } +// Promise.all([onAnimationEnd, cancellablePromise]).then(() => { +// if(this.tempId !== tempId) { +// this.log.warn('media viewer changed photo'); +// return; +// } - ///////this.log('indochina', blob); +// ///////this.log('indochina', blob); - const url = media.url; - if(target instanceof SVGSVGElement) { - this.updateMediaSource(target, url, 'img'); - this.updateMediaSource(mover, url, 'img'); +// const url = media.url; +// if(target instanceof SVGSVGElement) { +// this.updateMediaSource(target, url, 'img'); +// this.updateMediaSource(mover, url, 'img'); - if(mediaSizes.isMobile) { - const imgs = mover.querySelectorAll('img'); - if(imgs && imgs.length) { - imgs.forEach(img => { - img.classList.remove('thumbnail'); // может здесь это вообще не нужно - }); - } - } - } else { - const div = mover.firstElementChild && mover.firstElementChild.classList.contains('media-viewer-aspecter') ? mover.firstElementChild : mover; - let image = new Image(); +// if(mediaSizes.isMobile) { +// const imgs = mover.querySelectorAll('img'); +// if(imgs && imgs.length) { +// imgs.forEach(img => { +// img.classList.remove('thumbnail'); // может здесь это вообще не нужно +// }); +// } +// } +// } else { +// const div = mover.firstElementChild && mover.firstElementChild.classList.contains('media-viewer-aspecter') ? mover.firstElementChild : mover; +// let image = new Image(); - //this.log('will renderImageFromUrl:', image, div, target); +// //this.log('will renderImageFromUrl:', image, div, target); - renderImageFromUrl(image, url, () => { - if(div.firstElementChild?.tagName === 'IMG') { - div.firstElementChild.remove(); - } +// renderImageFromUrl(image, url, () => { +// if(div.firstElementChild?.tagName === 'IMG') { +// div.firstElementChild.remove(); +// } - div.append(image); - }); - } +// div.append(image); +// }); +// } - this.preloader.detach(); - }).catch(err => { - this.log.error(err); - }); +// this.preloader.detach(); +// }).catch(err => { +// this.log.error(err); +// }); - return cancellablePromise; - }; +// return cancellablePromise; +// }; - //this.lazyLoadQueue.unshift({load}); - }); - } +// //this.lazyLoadQueue.unshift({load}); +// }); +// } - return this.setMoverPromise = setMoverPromise.catch(() => { - this.setMoverAnimationPromise = null; - }).finally(() => { - this.setMoverPromise = null; - }); - } -} +// return this.setMoverPromise = setMoverPromise.catch(() => { +// this.setMoverAnimationPromise = null; +// }).finally(() => { +// this.setMoverPromise = null; +// }); +// } +// } -type AppMediaViewerTargetType = { - element: HTMLElement, - mid: number, - peerId: number -}; -export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delete' | 'forward', AppMediaViewerTargetType> { - public currentMessageId = 0; - public currentPeerId = 0; - public searchContext: SearchSuperContext; +// type AppMediaViewerTargetType = { +// element: HTMLElement, +// mid: number, +// peerId: number +// }; +// export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delete' | 'forward', AppMediaViewerTargetType> { +// public currentMessageId = 0; +// public currentPeerId = 0; +// public searchContext: SearchSuperContext; - constructor() { - super(['delete', 'forward']); +// constructor() { +// super(['delete', 'forward']); - /* const stub = document.createElement('div'); - stub.classList.add(MEDIA_VIEWER_CLASSNAME + '-stub'); - this.content.main.prepend(stub); */ +// /* 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' */); +// this.content.caption = document.createElement('div'); +// this.content.caption.classList.add(MEDIA_VIEWER_CLASSNAME + '-caption'/* , 'media-viewer-stub' */); - new Scrollable(this.content.caption); +// new Scrollable(this.content.caption); - //this.content.main.append(this.content.caption); - this.wholeDiv.append(this.content.caption); +// //this.content.main.append(this.content.caption); +// this.wholeDiv.append(this.content.caption); - this.setBtnMenuToggle([{ - icon: 'forward', - text: 'Forward', - onClick: this.onForwardClick - }, { - icon: 'download', - text: 'MediaViewer.Context.Download', - onClick: this.onDownloadClick - }, { - icon: 'delete danger btn-disabled', - text: 'Delete', - onClick: () => {} - }]); +// this.setBtnMenuToggle([{ +// icon: 'forward', +// text: 'Forward', +// onClick: this.onForwardClick +// }, { +// icon: 'download', +// text: 'MediaViewer.Context.Download', +// onClick: this.onDownloadClick +// }, { +// icon: 'delete danger btn-disabled', +// text: 'Delete', +// onClick: () => {} +// }]); - // * constructing html end +// // * constructing html end - this.setListeners(); - } +// this.setListeners(); +// } - protected setListeners() { - super.setListeners(); - this.buttons.forward.addEventListener('click', this.onForwardClick); - this.author.container.addEventListener('click', this.onAuthorClick); - } +// protected setListeners() { +// super.setListeners(); +// this.buttons.forward.addEventListener('click', this.onForwardClick); +// this.author.container.addEventListener('click', this.onAuthorClick); +// } - /* public close(e?: MouseEvent) { - const good = !this.setMoverAnimationPromise; - const promise = super.close(e); +// /* public close(e?: MouseEvent) { +// const good = !this.setMoverAnimationPromise; +// const promise = super.close(e); - if(good) { // clear - this.currentMessageId = 0; - this.peerId = 0; - } +// if(good) { // clear +// this.currentMessageId = 0; +// this.peerId = 0; +// } - return promise; - } */ +// return promise; +// } */ - onPrevClick = (target: AppMediaViewerTargetType) => { - this.nextTargets.unshift({element: this.lastTarget, mid: this.currentMessageId, peerId: this.currentPeerId}); - this.openMedia(appMessagesManager.getMessageByPeer(target.peerId, target.mid), target.element, -1); - }; +// onPrevClick = (target: AppMediaViewerTargetType) => { +// this.nextTargets.unshift({element: this.lastTarget, mid: this.currentMessageId, peerId: this.currentPeerId}); +// this.openMedia(appMessagesManager.getMessageByPeer(target.peerId, target.mid), target.element, -1); +// }; - onNextClick = (target: AppMediaViewerTargetType) => { - this.prevTargets.push({element: this.lastTarget, mid: this.currentMessageId, peerId: this.currentPeerId}); - this.openMedia(appMessagesManager.getMessageByPeer(target.peerId, target.mid), target.element, 1); - }; +// onNextClick = (target: AppMediaViewerTargetType) => { +// this.prevTargets.push({element: this.lastTarget, mid: this.currentMessageId, peerId: this.currentPeerId}); +// this.openMedia(appMessagesManager.getMessageByPeer(target.peerId, target.mid), target.element, 1); +// }; - onForwardClick = () => { - if(this.currentMessageId) { - //appSidebarRight.forwardTab.open([this.currentMessageId]); - new PopupForward(this.currentPeerId, [this.currentMessageId], () => { - return this.close(); - }); - } - }; +// onForwardClick = () => { +// if(this.currentMessageId) { +// //appSidebarRight.forwardTab.open([this.currentMessageId]); +// new PopupForward(this.currentPeerId, [this.currentMessageId], () => { +// return this.close(); +// }); +// } +// }; - onAuthorClick = (e: MouseEvent) => { - if(this.currentMessageId && this.currentMessageId !== Number.MAX_SAFE_INTEGER) { - const mid = this.currentMessageId; - const peerId = this.currentPeerId; - const threadId = this.searchContext.threadId; - this.close(e) - //.then(() => mediaSizes.isMobile ? appSidebarRight.sharedMediaTab.closeBtn.click() : Promise.resolve()) - .then(() => { - if(mediaSizes.isMobile) { - const tab = appSidebarRight.getTab(AppSharedMediaTab); - if(tab) { - tab.close(); - } - } +// onAuthorClick = (e: MouseEvent) => { +// if(this.currentMessageId && this.currentMessageId !== Number.MAX_SAFE_INTEGER) { +// const mid = this.currentMessageId; +// const peerId = this.currentPeerId; +// const threadId = this.searchContext.threadId; +// this.close(e) +// //.then(() => mediaSizes.isMobile ? appSidebarRight.sharedMediaTab.closeBtn.click() : Promise.resolve()) +// .then(() => { +// if(mediaSizes.isMobile) { +// const tab = appSidebarRight.getTab(AppSharedMediaTab); +// if(tab) { +// tab.close(); +// } +// } - const message = appMessagesManager.getMessageByPeer(peerId, mid); - appImManager.setInnerPeer(message.peerId, mid, threadId ? 'discussion' : undefined, threadId); - }); - } - }; +// const message = appMessagesManager.getMessageByPeer(peerId, mid); +// appImManager.setInnerPeer(message.peerId, mid, threadId ? 'discussion' : undefined, threadId); +// }); +// } +// }; - onDownloadClick = () => { - const message = appMessagesManager.getMessageByPeer(this.currentPeerId, this.currentMessageId); - if(message.media.photo) { - appPhotosManager.savePhotoFile(message.media.photo, appImManager.chat.bubbles.lazyLoadQueue.queueId); - } else { - let document: MyDocument = null; +// onDownloadClick = () => { +// const message = appMessagesManager.getMessageByPeer(this.currentPeerId, this.currentMessageId); +// if(message.media.photo) { +// appPhotosManager.savePhotoFile(message.media.photo, appImManager.chat.bubbles.lazyLoadQueue.queueId); +// } else { +// let document: MyDocument = null; - if(message.media.webpage) document = message.media.webpage.document; - else document = message.media.document; +// if(message.media.webpage) document = message.media.webpage.document; +// else document = message.media.document; - if(document) { - //console.log('will save document:', document); - appDocsManager.saveDocFile(document, appImManager.chat.bubbles.lazyLoadQueue.queueId); - } - } - }; +// if(document) { +// //console.log('will save document:', document); +// appDocsManager.saveDocFile(document, appImManager.chat.bubbles.lazyLoadQueue.queueId); +// } +// } +// }; - // нет смысла делать проверку для reverse и loadMediaPromise - protected loadMoreMedia = (older = true) => { - //if(!older && this.reverse) return; +// // нет смысла делать проверку для reverse и loadMediaPromise +// protected loadMoreMedia = (older = true) => { +// //if(!older && this.reverse) return; - if(older && this.loadedAllMediaDown) return Promise.resolve(); - else if(!older && this.loadedAllMediaUp) return Promise.resolve(); +// if(older && this.loadedAllMediaDown) return Promise.resolve(); +// else if(!older && this.loadedAllMediaUp) return Promise.resolve(); - if(older && this.loadMediaPromiseDown) return this.loadMediaPromiseDown; - else if(!older && this.loadMediaPromiseUp) return this.loadMediaPromiseUp; +// if(older && this.loadMediaPromiseDown) return this.loadMediaPromiseDown; +// else if(!older && this.loadMediaPromiseUp) return this.loadMediaPromiseUp; - const loadCount = 50; - const backLimit = older ? 0 : loadCount; - let maxId = this.currentMessageId; +// const loadCount = 50; +// const backLimit = older ? 0 : loadCount; +// let maxId = this.currentMessageId; - let anchor: AppMediaViewerTargetType; - if(older) { - anchor = this.reverse ? this.prevTargets[0] : this.nextTargets[this.nextTargets.length - 1]; - } else { - anchor = this.reverse ? this.nextTargets[this.nextTargets.length - 1] : this.prevTargets[0]; - } +// let anchor: AppMediaViewerTargetType; +// if(older) { +// anchor = this.reverse ? this.prevTargets[0] : this.nextTargets[this.nextTargets.length - 1]; +// } else { +// anchor = this.reverse ? this.nextTargets[this.nextTargets.length - 1] : this.prevTargets[0]; +// } - if(anchor) maxId = anchor.mid; - if(!older) maxId = appMessagesManager.incrementMessageId(maxId, 1); +// if(anchor) maxId = anchor.mid; +// if(!older) maxId = appMessagesManager.incrementMessageId(maxId, 1); - const promise = appMessagesManager.getSearch({ - peerId: this.searchContext.peerId, - query: this.searchContext.query, - inputFilter: { - _: this.searchContext.inputFilter - }, - maxId, - limit: backLimit ? 0 : loadCount, - backLimit, - threadId: this.searchContext.threadId, - folderId: this.searchContext.folderId, - nextRate: this.searchContext.nextRate, - minDate: this.searchContext.minDate, - maxDate: this.searchContext.maxDate - }).then(value => { - /* if(DEBUG) { - this.log('loaded more media by maxId:', maxId, value, older, this.reverse); - } */ +// const promise = appMessagesManager.getSearch({ +// peerId: this.searchContext.peerId, +// query: this.searchContext.query, +// inputFilter: { +// _: this.searchContext.inputFilter +// }, +// maxId, +// limit: backLimit ? 0 : loadCount, +// backLimit, +// threadId: this.searchContext.threadId, +// folderId: this.searchContext.folderId, +// nextRate: this.searchContext.nextRate, +// minDate: this.searchContext.minDate, +// maxDate: this.searchContext.maxDate +// }).then(value => { +// /* if(DEBUG) { +// this.log('loaded more media by maxId:', maxId, value, older, this.reverse); +// } */ - if(value.next_rate) { - this.searchContext.nextRate = value.next_rate; - } +// if(value.next_rate) { +// this.searchContext.nextRate = value.next_rate; +// } - if(value.history.length < loadCount) { - /* if(this.reverse) { - if(older) this.loadedAllMediaUp = true; - else this.loadedAllMediaDown = true; - } else { */ - if(older) this.loadedAllMediaDown = true; - else this.loadedAllMediaUp = true; - //} - } +// if(value.history.length < loadCount) { +// /* if(this.reverse) { +// if(older) this.loadedAllMediaUp = true; +// else this.loadedAllMediaDown = true; +// } else { */ +// if(older) this.loadedAllMediaDown = true; +// else this.loadedAllMediaUp = true; +// //} +// } - const method: any = older ? value.history.forEach.bind(value.history) : forEachReverse.bind(null, value.history); - method((message: Message.message) => { - const {mid, peerId} = message; - const media = this.getMediaFromMessage(message); +// const method: any = older ? value.history.forEach.bind(value.history) : forEachReverse.bind(null, value.history); +// method((message: Message.message) => { +// const {mid, peerId} = message; +// const media = this.getMediaFromMessage(message); - if(!media) return; - //if(media._ === 'document' && media.type !== 'video') return; +// if(!media) return; +// //if(media._ === 'document' && media.type !== 'video') return; - const t = {element: null as HTMLElement, mid, peerId}; - if(older) { - if(this.reverse) this.prevTargets.unshift(t); - else this.nextTargets.push(t); - } else { - if(this.reverse) this.nextTargets.push(t); - else this.prevTargets.unshift(t); - } - }); +// const t = {element: null as HTMLElement, mid, peerId}; +// if(older) { +// if(this.reverse) this.prevTargets.unshift(t); +// else this.nextTargets.push(t); +// } else { +// if(this.reverse) this.nextTargets.push(t); +// else this.prevTargets.unshift(t); +// } +// }); - this.buttons.prev.classList.toggle('hide', !this.prevTargets.length); - this.buttons.next.classList.toggle('hide', !this.nextTargets.length); - }, () => {}).then(() => { - if(older) this.loadMediaPromiseDown = null; - else this.loadMediaPromiseUp = null; - }); +// this.buttons.prev.classList.toggle('hide', !this.prevTargets.length); +// this.buttons.next.classList.toggle('hide', !this.nextTargets.length); +// }, () => {}).then(() => { +// if(older) this.loadMediaPromiseDown = null; +// else this.loadMediaPromiseUp = null; +// }); - if(older) this.loadMediaPromiseDown = promise; - else this.loadMediaPromiseUp = promise; +// if(older) this.loadMediaPromiseDown = promise; +// else this.loadMediaPromiseUp = promise; - return promise; - }; +// return promise; +// }; - private getMediaFromMessage(message: any) { - return message.action ? message.action.photo : message.media.photo - || message.media.document - || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo)); - } +// private getMediaFromMessage(message: any) { +// return message.action ? message.action.photo : message.media.photo +// || message.media.document +// || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo)); +// } - private setCaption(message: any) { - const caption = message.message; - this.content.caption.classList.toggle('hide', !caption); - if(caption) { - this.content.caption.firstElementChild.innerHTML = RichTextProcessor.wrapRichText(caption, { - entities: message.totalEntities - }); - } else { - this.content.caption.firstElementChild.innerHTML = ''; - } - } +// private setCaption(message: any) { +// const caption = message.message; +// this.content.caption.classList.toggle('hide', !caption); +// if(caption) { +// this.content.caption.firstElementChild.innerHTML = RichTextProcessor.wrapRichText(caption, { +// entities: message.totalEntities +// }); +// } else { +// this.content.caption.firstElementChild.innerHTML = ''; +// } +// } - public setSearchContext(context: SearchSuperContext) { - this.searchContext = context; +// public setSearchContext(context: SearchSuperContext) { +// this.searchContext = context; - if(this.searchContext.folderId !== undefined) { - this.loadedAllMediaUp = true; +// if(this.searchContext.folderId !== undefined) { +// this.loadedAllMediaUp = true; - if(this.searchContext.nextRate === undefined) { - this.loadedAllMediaDown = true; - } - } +// if(this.searchContext.nextRate === undefined) { +// this.loadedAllMediaDown = true; +// } +// } - return this; - } +// return this; +// } - public async openMedia(message: any, target?: HTMLElement, fromRight = 0, reverse = false, - prevTargets: AppMediaViewer['prevTargets'] = [], nextTargets: AppMediaViewer['prevTargets'] = [], needLoadMore = true) { - if(this.setMoverPromise) return this.setMoverPromise; +// public async openMedia(message: any, target?: HTMLElement, fromRight = 0, reverse = false, +// prevTargets: AppMediaViewer['prevTargets'] = [], nextTargets: AppMediaViewer['prevTargets'] = [], needLoadMore = true) { +// if(this.setMoverPromise) return this.setMoverPromise; - const mid = message.mid; - const fromId = message.fromId; - const media = this.getMediaFromMessage(message); +// const mid = message.mid; +// const fromId = message.fromId; +// const media = this.getMediaFromMessage(message); - this.currentMessageId = mid; - this.currentPeerId = message.peerId; - const promise = super._openMedia(media, message.date, fromId, fromRight, target, reverse, prevTargets, nextTargets, needLoadMore); - this.setCaption(message); +// this.currentMessageId = mid; +// this.currentPeerId = message.peerId; +// const promise = super._openMedia(media, message.date, fromId, fromRight, target, reverse, prevTargets, nextTargets, needLoadMore); +// this.setCaption(message); - return promise; - } -} +// return promise; +// } +// } -type AppMediaViewerAvatarTargetType = {element: HTMLElement, photoId: string}; -export class AppMediaViewerAvatar extends AppMediaViewerBase<'', 'delete', AppMediaViewerAvatarTargetType> { - public currentPhotoId: string; - public peerId: number; +// type AppMediaViewerAvatarTargetType = {element: HTMLElement, photoId: string}; +// export class AppMediaViewerAvatar extends AppMediaViewerBase<'', 'delete', AppMediaViewerAvatarTargetType> { +// public currentPhotoId: string; +// public peerId: number; - constructor(peerId: number) { - super(['delete']); +// constructor(peerId: number) { +// super(['delete']); - this.peerId = peerId; +// this.peerId = peerId; - this.setBtnMenuToggle([{ - icon: 'download', - text: 'MediaViewer.Context.Download', - onClick: this.onDownloadClick - }, { - icon: 'delete danger btn-disabled', - text: 'Delete', - onClick: () => {} - }]); +// this.setBtnMenuToggle([{ +// icon: 'download', +// text: 'MediaViewer.Context.Download', +// onClick: this.onDownloadClick +// }, { +// icon: 'delete danger btn-disabled', +// text: 'Delete', +// onClick: () => {} +// }]); - // * constructing html end +// // * constructing html end - this.setListeners(); - } +// this.setListeners(); +// } - onPrevClick = (target: AppMediaViewerAvatarTargetType) => { - this.nextTargets.unshift({element: this.lastTarget, photoId: this.currentPhotoId}); - this.openMedia(target.photoId, target.element, -1); - }; +// onPrevClick = (target: AppMediaViewerAvatarTargetType) => { +// this.nextTargets.unshift({element: this.lastTarget, photoId: this.currentPhotoId}); +// this.openMedia(target.photoId, target.element, -1); +// }; - onNextClick = (target: AppMediaViewerAvatarTargetType) => { - this.prevTargets.push({element: this.lastTarget, photoId: this.currentPhotoId}); - this.openMedia(target.photoId, target.element, 1); - }; +// onNextClick = (target: AppMediaViewerAvatarTargetType) => { +// this.prevTargets.push({element: this.lastTarget, photoId: this.currentPhotoId}); +// this.openMedia(target.photoId, target.element, 1); +// }; - onDownloadClick = () => { - appPhotosManager.savePhotoFile(appPhotosManager.getPhoto(this.currentPhotoId), appImManager.chat.bubbles.lazyLoadQueue.queueId); - }; +// 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; +// 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 peerId = this.peerId; +// const loadCount = 50; - const maxId = this.nextTargets.length ? this.nextTargets[this.nextTargets.length - 1].photoId : this.currentPhotoId; +// 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; - } +// 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(DEBUG) { +// // this.log('loaded more media by maxId:', /* maxId, */value, older, this.reverse); +// // } - if(value.photos.length < loadCount) { - this.loadedAllMediaDown = true; - } +// 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}); - }); +// 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; - }); +// 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; - }; +// return this.loadMediaPromiseDown = promise; +// }; - public async openMedia(photoId: string, target?: HTMLElement, fromRight = 0) { - if(this.setMoverPromise) return this.setMoverPromise; +// public async openMedia(photoId: string, target?: HTMLElement, fromRight = 0) { +// if(this.setMoverPromise) return this.setMoverPromise; - const photo = appPhotosManager.getPhoto(photoId); +// const photo = appPhotosManager.getPhoto(photoId); - this.currentPhotoId = photo.id; +// this.currentPhotoId = photo.id; - return super._openMedia(photo, photo.date, this.peerId, fromRight, target, false); - } -} +// return super._openMedia(photo, photo.date, this.peerId, fromRight, target, false); +// } +// } + +export const z = 1; diff --git a/src/components/appSearchSuper..ts b/src/components/appSearchSuper..ts index 1564d8830..2a775a257 100644 --- a/src/components/appSearchSuper..ts +++ b/src/components/appSearchSuper..ts @@ -1,6 +1,6 @@ import { formatDateAccordingToToday, months } from "../helpers/date"; import { positionElementByIndex } from "../helpers/dom"; -import { copy, getObjectKeysAndSort } from "../helpers/object"; +import { copy, getObjectKeysAndSort, safeAssign } from "../helpers/object"; import { escapeRegExp, limitSymbols } from "../helpers/string"; import appChatsManager from "../lib/appManagers/appChatsManager"; import appDialogsManager from "../lib/appManagers/appDialogsManager"; @@ -25,11 +25,11 @@ import useHeavyAnimationCheck, { getHeavyAnimationPromise } from "../hooks/useHe import { isSafari } from "../helpers/userAgent"; import { LangPackKey, i18n } from "../lib/langPack"; import findUpClassName from "../helpers/dom/findUpClassName"; -import renderImageFromUrl from "../helpers/dom/renderImageFromUrl"; +import { getMiddleware } from "../helpers/middleware"; //const testScroll = false; -export type SearchSuperType = MyInputMessagesFilter/* | 'chats' */; +export type SearchSuperType = MyInputMessagesFilter/* | 'members' */; export type SearchSuperContext = { peerId: number, inputFilter: MyInputMessagesFilter, @@ -43,10 +43,20 @@ export type SearchSuperContext = { maxDate?: number }; +export type SearchSuperMediaType = 'members' | 'media' | 'files' | 'links' | 'music' | 'chats' | 'voice'; +export type SearchSuperMediaTab = { + inputFilter: SearchSuperType, + name: LangPackKey, + type: SearchSuperMediaType, + contentTab?: HTMLElement, + menuTab?: HTMLElement, + scroll?: {scrollTop: number, scrollHeight: number} +}; + export default class AppSearchSuper { public tabs: {[t in SearchSuperType]: HTMLDivElement} = {} as any; - public type: SearchSuperType; + public mediaTab: SearchSuperMediaTab; public tabSelected: HTMLElement; public container: HTMLElement; @@ -56,7 +66,7 @@ export default class AppSearchSuper { private prevTabId = -1; private lazyLoadQueue = new LazyLoadQueue(); - private cleanupObj = {cleaned: false}; + public middleware = getMiddleware(); public historyStorage: Partial<{[type in SearchSuperType]: {mid: number, peerId: number}[]}> = {}; public usedFromHistory: Partial<{[type in SearchSuperType]: number}> = {}; @@ -84,9 +94,19 @@ export default class AppSearchSuper { private searchGroupMedia: SearchGroup; - public goingHard: Partial<{[type in MyInputMessagesFilter]: {scrollTop: number, scrollHeight: number}}> = {}; + public mediaTabsMap: Map = new Map(); + + // * arguments + public mediaTabs: SearchSuperMediaTab[]; + public scrollable: Scrollable; + public searchGroups?: {[group in SearchGroupType]: SearchGroup}; + public asChatList? = false; + public groupByMonth? = true; + public hideEmptyTabs? = true; + + constructor(options: Pick) { + safeAssign(this, options); - constructor(public types: {inputFilter: SearchSuperType, name: LangPackKey, type: string}[], public scrollable: Scrollable, public searchGroups?: {[group in SearchGroupType]: SearchGroup}, public asChatList = false, public groupByMonth = true) { this.container = document.createElement('div'); this.container.classList.add('search-super'); @@ -101,13 +121,13 @@ export default class AppSearchSuper { navScrollable.container.append(nav); - for(const type of types) { + for(const mediaTab of this.mediaTabs) { const menuTab = document.createElement('div'); menuTab.classList.add('menu-horizontal-div-item'); const span = document.createElement('span'); const i = document.createElement('i'); - span.append(i18n(type.name)); + span.append(i18n(mediaTab.name)); span.append(i); menuTab.append(span); @@ -115,38 +135,29 @@ export default class AppSearchSuper { ripple(menuTab); this.tabsMenu.append(menuTab); + + this.mediaTabsMap.set(mediaTab.type, mediaTab); + + mediaTab.menuTab = menuTab; } this.tabsContainer = document.createElement('div'); this.tabsContainer.classList.add('search-super-tabs-container', 'tabs-container'); - for(const type of types) { + for(const mediaTab of this.mediaTabs) { const container = document.createElement('div'); - container.classList.add('search-super-container-' + type.type/* , 'scrollable', 'scrollable-y' */); + container.classList.add('search-super-container-' + mediaTab.type); const content = document.createElement('div'); - content.classList.add('search-super-content-' + type.type/* , 'scrollable', 'scrollable-y' */); - - //content.style.overflowY = 'hidden'; - /* container.style.overflow = 'visible'; - const v = 236; - content.style.top = (v * -1) + 'px'; - content.style.paddingTop = v + 'px'; - content.style.height = `calc(100% + ${v}px)`; - content.style.maxHeight = `calc(100% + ${v}px)`; - content.addEventListener('scroll', (e) => { - const scrollTop = content.scrollTop; - if(scrollTop <= v) { - //this.scrollable.scrollTop = scrollTop; - (this.container.previousElementSibling as HTMLElement).style.transform = `translateY(-${scrollTop}px)`; - } - }); */ + content.classList.add('search-super-content-' + mediaTab.type); container.append(content); this.tabsContainer.append(container); - this.tabs[type.inputFilter] = content; + this.tabs[mediaTab.inputFilter] = content; + + mediaTab.contentTab = content; } this.container.append(navScrollableContainer, this.tabsContainer); @@ -169,24 +180,24 @@ export default class AppSearchSuper { if(this.prevTabId !== -1) { this.onTransitionStart(); } + + this.mediaTab.scroll = {scrollTop: this.scrollable.scrollTop, scrollHeight: this.scrollable.scrollHeight}; - this.goingHard[this.type] = {scrollTop: this.scrollable.scrollTop, scrollHeight: this.scrollable.scrollHeight}; - - const newType = this.types[id].inputFilter; + const newMediaTab = this.mediaTabs[id]; this.tabSelected = tabContent.firstElementChild as HTMLDivElement; - if(this.goingHard[newType] === undefined) { + if(newMediaTab.scroll === undefined) { const rect = this.container.getBoundingClientRect(); const rect2 = this.container.parentElement.getBoundingClientRect(); const diff = rect.y - rect2.y; if(this.scrollable.scrollTop > diff) { - this.goingHard[newType] = {scrollTop: diff, scrollHeight: 0}; + newMediaTab.scroll = {scrollTop: diff, scrollHeight: 0}; } } - if(this.goingHard[newType]) { - const diff = this.goingHard[this.type].scrollTop - this.goingHard[newType].scrollTop; + if(newMediaTab.scroll) { + const diff = this.mediaTab.scroll.scrollTop - newMediaTab.scroll.scrollTop; //console.log('what you gonna do', this.goingHard, diff); if(diff/* && diff < 0 */) { @@ -194,7 +205,7 @@ export default class AppSearchSuper { } } - this.type = newType; + this.mediaTab = newMediaTab; /* if(this.prevTabId !== -1 && nav.offsetTop) { this.scrollable.scrollTop -= nav.offsetTop; @@ -213,9 +224,9 @@ export default class AppSearchSuper { this.scrollable.onScroll(); //console.log('what y', this.tabSelected.style.transform); - if(this.goingHard[this.type] !== undefined) { + if(this.mediaTab.scroll !== undefined) { this.tabSelected.style.transform = ''; - this.scrollable.scrollTop = this.goingHard[this.type].scrollTop; + this.scrollable.scrollTop = this.mediaTab.scroll.scrollTop; } this.onTransitionEnd(); @@ -241,11 +252,11 @@ export default class AppSearchSuper { const message = appMessagesManager.getMessageByPeer(peerId, mid); new AppMediaViewer() - .setSearchContext(this.copySearchContext(this.type)) + .setSearchContext(this.copySearchContext(this.mediaTab.inputFilter)) .openMedia(message, target, 0, false, targets.slice(0, idx), targets.slice(idx + 1)); }); - this.type = this.types[0].inputFilter; + this.mediaTab = this.mediaTabs[0]; useHeavyAnimationCheck(() => { this.lazyLoadQueue.lock(); @@ -381,7 +392,7 @@ export default class AppSearchSuper { const elemsToAppend: {element: HTMLElement, message: any}[] = []; const sharedMediaDiv: HTMLElement = this.tabs[type]; const promises: Promise[] = []; - const middleware = this.getMiddleware(); + const middleware = this.middleware.get(); await getHeavyAnimationPromise(); @@ -538,23 +549,22 @@ export default class AppSearchSuper { //this.log('wrapping webpage', webpage); - previewDiv.innerHTML = RichTextProcessor.getAbbreviation(webpage.title || webpage.display_url || webpage.description || webpage.url, true); - previewDiv.classList.add('empty'); if(webpage.photo) { - let load = () => appPhotosManager.preloadPhoto(webpage.photo.id, appPhotosManager.choosePhotoSize(webpage.photo, 60, 60)) - .then(() => { - if(!middleware()) { - //this.log.warn('peer changed'); - return; - } - - previewDiv.classList.remove('empty'); - - previewDiv.innerText = ''; - renderImageFromUrl(previewDiv, webpage.photo.url); + const res = wrapPhoto({ + container: previewDiv, + message: null, + photo: webpage.photo, + boxWidth: 0, + boxHeight: 0, + withoutPreloader: true, + lazyLoadQueue: this.lazyLoadQueue, + middleware, + size: appPhotosManager.choosePhotoSize(webpage.photo, 60, 60, false), + loadPromises: promises }); - - this.lazyLoadQueue.push({div: previewDiv, load}); + } else { + previewDiv.classList.add('empty'); + previewDiv.innerHTML = RichTextProcessor.getAbbreviation(webpage.title || webpage.display_url || webpage.description || webpage.url, true); } let title = webpage.rTitle || ''; @@ -624,16 +634,16 @@ export default class AppSearchSuper { //} } - private afterPerforming(length: number, tab: HTMLElement) { - if(tab) { - const parent = tab.parentElement; + private afterPerforming(length: number, contentTab: HTMLElement) { + if(contentTab) { + const parent = contentTab.parentElement; Array.from(parent.children).slice(1).forEach(child => { child.remove(); }); //this.contentContainer.classList.add('loaded'); - if(!length && !tab.childElementCount) { + if(!length && !contentTab.childElementCount) { const div = document.createElement('div'); div.innerText = 'Nothing interesting here yet...'; div.classList.add('position-center', 'text-center', 'content-empty', 'no-select'); @@ -645,7 +655,7 @@ export default class AppSearchSuper { private loadChats() { const renderedPeerIds: Set = new Set(); - const middleware = this.getMiddleware(); + const middleware = this.middleware.get(); for(let i in this.searchGroups) { const group = this.searchGroups[i as SearchGroupType]; @@ -807,6 +817,135 @@ export default class AppSearchSuper { ]); } else return Promise.resolve(); } + + private loadType(mediaTab: SearchSuperMediaTab, justLoad: boolean, loadCount: number, middleware: () => boolean) { + const type = mediaTab.inputFilter; + + if(this.loadPromises[type]) { + return this.loadPromises[type]; + } + + const history = this.historyStorage[type] ?? (this.historyStorage[type] = []); + + if(type === 'inputMessagesFilterEmpty' && !history.length) { + if(!this.loadedChats) { + this.loadChats(); + this.loadedChats = true; + } + + if(!this.searchContext.query.trim() && !this.searchContext.peerId && !this.searchContext.minDate) { + this.loaded[type] = true; + return Promise.resolve(); + } + } + + const logStr = 'load [' + type + ']: '; + + // render from cache + if(history.length && this.usedFromHistory[type] < history.length && !justLoad) { + let messages: any[] = []; + let used = Math.max(0, this.usedFromHistory[type]); + let slicedLength = 0; + + do { + let ids = history.slice(used, used + loadCount); + //this.log(logStr + 'will render from cache', used, history, ids, loadCount); + used += ids.length; + slicedLength += ids.length; + + messages.push(...this.filterMessagesByType(ids.map(m => appMessagesManager.getMessageByPeer(m.peerId, m.mid)), type)); + } while(slicedLength < loadCount && used < history.length); + + // если перебор + /* if(slicedLength > 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).finally(() => { + setTimeout(() => { + this.scrollable.checkForTriggers(); + }, 0); + }); + //} + + return Promise.resolve(); + } + + let maxId = history.length ? history[history.length - 1].mid : 0; + + //this.log(logStr + 'search house of glass pre', type, maxId); + + //let loadCount = history.length ? 50 : 15; + return this.loadPromises[type] = appMessagesManager.getSearch({ + peerId: this.searchContext.peerId, + query: this.searchContext.query, + inputFilter: {_: type}, + maxId, + limit: loadCount, + nextRate: this.nextRates[type] ?? (this.nextRates[type] = 0), + threadId: this.searchContext.threadId, + folderId: this.searchContext.folderId, + minDate: this.searchContext.minDate, + maxDate: this.searchContext.maxDate + }).then(value => { + history.push(...value.history.map(m => ({mid: m.mid, peerId: m.peerId}))); + + this.log(logStr + 'search house of glass', type, value); + + if(!middleware()) { + //this.log.warn('peer changed'); + return; + } + + // ! Фикс случая, когда не загружаются документы при открытой панели разработчиков (происходит из-за того, что не совпадают критерии отбора документов в getSearch) + if(value.history.length < loadCount) { + //if((value.count || history.length === value.count) && history.length >= value.count) { + //this.log(logStr + 'loaded all media', value, loadCount); + this.loaded[type] = true; + } + + this.nextRates[type] = value.next_rate; + + if(justLoad) { + return Promise.resolve(); + } + + this.usedFromHistory[type] = history.length; + + if(!this.loaded[type]) { + (this.loadPromises[type] || Promise.resolve()).then(() => { + setTimeout(() => { + if(!middleware()) return; + //this.log('will preload more'); + if(this.mediaTab === mediaTab) { + const promise = this.load(true, true); + if(promise) { + promise.then(() => { + if(!middleware()) return; + //this.log('preloaded more'); + setTimeout(() => { + this.scrollable.checkForTriggers(); + }, 0); + }); + } + } + }, 0); + }); + } + + //if(value.history.length) { + return this.performSearchResult(this.filterMessagesByType(value.history, type), type); + //} + }).catch(err => { + this.log.error('load error:', err); + }).finally(() => { + this.loadPromises[type] = null; + }); + } public load(single = false, justLoad = false) { // if(testScroll/* || 1 === 1 */) { @@ -818,141 +957,21 @@ export default class AppSearchSuper { const peerId = this.searchContext.peerId; this.log('load', single, peerId, this.loadPromises); - let typesToLoad = single ? [this.type] : this.types.filter(t => t.inputFilter !== this.type).map(t => t.inputFilter); - typesToLoad = typesToLoad.filter(type => !this.loaded[type] - || (this.historyStorage[type] && this.usedFromHistory[type] < this.historyStorage[type].length)); + let toLoad = single ? [this.mediaTab] : this.mediaTabs.filter(t => t !== this.mediaTab); + toLoad = toLoad.filter(mediaTab => { + const inputFilter = mediaTab.inputFilter; + return !this.loaded[inputFilter] || (this.historyStorage[inputFilter] && this.usedFromHistory[inputFilter] < this.historyStorage[inputFilter].length); + }); - if(!typesToLoad.length) return; + if(!toLoad.length) { + return; + } const loadCount = justLoad ? 50 : Math.round((appPhotosManager.windowH / 130 | 0) * 3 * 1.25); // that's good for all types - - const historyStorage = this.historyStorage ?? (this.historyStorage = {}); + const middleware = this.middleware.get(); - const middleware = this.getMiddleware(); - - const promises: Promise[] = typesToLoad.map(type => { - if(this.loadPromises[type]) return this.loadPromises[type]; - - const history = historyStorage[type] ?? (historyStorage[type] = []); - - if(type === 'inputMessagesFilterEmpty' && !history.length) { - if(!this.loadedChats) { - this.loadChats(); - this.loadedChats = true; - } - - if(!this.searchContext.query.trim() && !this.searchContext.peerId && !this.searchContext.minDate) { - this.loaded[type] = true; - return Promise.resolve(); - } - } - - const logStr = 'load [' + type + ']: '; - - // render from cache - if(history.length && this.usedFromHistory[type] < history.length && !justLoad) { - let messages: any[] = []; - let used = Math.max(0, this.usedFromHistory[type]); - let slicedLength = 0; - - do { - let ids = history.slice(used, used + loadCount); - //this.log(logStr + 'will render from cache', used, history, ids, loadCount); - used += ids.length; - slicedLength += ids.length; - - messages.push(...this.filterMessagesByType(ids.map(m => appMessagesManager.getMessageByPeer(m.peerId, m.mid)), type)); - } while(slicedLength < loadCount && used < history.length); - - // если перебор - /* if(slicedLength > 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).finally(() => { - setTimeout(() => { - this.scrollable.checkForTriggers(); - }, 0); - }); - //} - - return Promise.resolve(); - } - - let maxId = history.length ? history[history.length - 1].mid : 0; - - //this.log(logStr + 'search house of glass pre', type, maxId); - - //let loadCount = history.length ? 50 : 15; - return this.loadPromises[type] = appMessagesManager.getSearch({ - peerId, - query: this.searchContext.query, - inputFilter: {_: type}, - maxId, - limit: loadCount, - nextRate: this.nextRates[type] ?? (this.nextRates[type] = 0), - threadId: this.searchContext.threadId, - folderId: this.searchContext.folderId, - minDate: this.searchContext.minDate, - maxDate: this.searchContext.maxDate - }).then(value => { - history.push(...value.history.map(m => ({mid: m.mid, peerId: m.peerId}))); - - this.log(logStr + 'search house of glass', type, value); - - if(!middleware()) { - //this.log.warn('peer changed'); - return; - } - - // ! Фикс случая, когда не загружаются документы при открытой панели разработчиков (происходит из-за того, что не совпадают критерии отбора документов в getSearch) - if(value.history.length < loadCount) { - //if((value.count || history.length === value.count) && history.length >= value.count) { - //this.log(logStr + 'loaded all media', value, loadCount); - this.loaded[type] = true; - } - - this.nextRates[type] = value.next_rate; - - if(justLoad) { - return Promise.resolve(); - } - - this.usedFromHistory[type] = history.length; - - if(!this.loaded[type]) { - (this.loadPromises[type] || Promise.resolve()).then(() => { - setTimeout(() => { - if(!middleware()) return; - //this.log('will preload more'); - if(this.type === type) { - const promise = this.load(true, true); - if(promise) { - promise.then(() => { - if(!middleware()) return; - //this.log('preloaded more'); - setTimeout(() => { - this.scrollable.checkForTriggers(); - }, 0); - }); - } - } - }, 0); - }); - } - - //if(value.history.length) { - return this.performSearchResult(this.filterMessagesByType(value.history, type), type); - //} - }).catch(err => { - this.log.error('load error:', err); - }).finally(() => { - this.loadPromises[type] = null; - }); + const promises: Promise[] = toLoad.map(mediaTab => { + return this.loadType(mediaTab, justLoad, loadCount, middleware) }); return Promise.all(promises).catch(err => { @@ -1006,13 +1025,18 @@ export default class AppSearchSuper { this.lazyLoadQueue.clear(); - this.types.forEach(type => { - this.usedFromHistory[type.inputFilter] = -1; + this.mediaTabs.forEach(mediaTab => { + this.usedFromHistory[mediaTab.inputFilter] = -1; }); - this.cleanupObj.cleaned = true; - this.cleanupObj = {cleaned: false}; - this.goingHard = {}; + this.middleware.clean(); + this.cleanScrollPositions(); + } + + public cleanScrollPositions() { + this.mediaTabs.forEach(mediaTab => { + mediaTab.scroll = undefined; + }); } public cleanupHTML() { @@ -1023,15 +1047,15 @@ export default class AppSearchSuper { this.urlsToRevoke.length = 0; } - (Object.keys(this.tabs) as SearchSuperType[]).forEach(type => { - this.tabs[type].innerHTML = ''; + this.mediaTabs.forEach((tab) => { + tab.contentTab.innerHTML = ''; - if(type === 'inputMessagesFilterEmpty') { + if(tab.type === 'chats') { return; } - if(!this.historyStorage || !this.historyStorage[type]) { - const parent = this.tabs[type].parentElement; + if(!this.historyStorage[tab.inputFilter]) { + const parent = tab.contentTab.parentElement; //if(!testScroll) { if(!parent.querySelector('.preloader')) { putPreloader(parent, true); @@ -1044,7 +1068,7 @@ export default class AppSearchSuper { } } }); - + this.monthContainers = {}; this.searchGroupMedia.clear(); this.scrollable.scrollTop = 0; @@ -1061,14 +1085,6 @@ export default class AppSearchSuper { } */ } - // * will change .cleaned in cleanup() and new instance will be created - public getMiddleware() { - const cleanupObj = this.cleanupObj; - return () => { - return !cleanupObj.cleaned; - }; - } - private copySearchContext(newInputFilter: MyInputMessagesFilter) { const context = copy(this.searchContext); context.inputFilter = newInputFilter; @@ -1088,7 +1104,7 @@ export default class AppSearchSuper { this.searchContext = { peerId: peerId || 0, query: query || '', - inputFilter: this.type, + inputFilter: this.mediaTab.inputFilter, threadId, folderId, minDate, diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 451e77e96..f7cd24824 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -829,7 +829,7 @@ export default class ChatBubbles { //appSidebarRight.forwardTab.open([mid]); return; } else if(target.classList.contains('peer-title') || target.classList.contains('name')) { - target = findUpClassName(target, 'name'); + target = findUpClassName(target, 'name') || target; const peerId = +target.dataset.peerId; const savedFrom = target.dataset.savedFrom; if(savedFrom) { diff --git a/src/components/sidebarLeft/index.ts b/src/components/sidebarLeft/index.ts index 44f00b69f..f15ebe1fd 100644 --- a/src/components/sidebarLeft/index.ts +++ b/src/components/sidebarLeft/index.ts @@ -193,31 +193,37 @@ export class AppSidebarLeft extends SidebarSlider { recent: new SearchGroup('Recent', 'contacts', true, 'search-group-recent', true, true, close) }; - const searchSuper = this.searchSuper = new AppSearchSuper([{ - inputFilter: 'inputMessagesFilterEmpty', - name: 'FilterChats', - type: 'chats' - }, { - inputFilter: 'inputMessagesFilterPhotoVideo', - name: 'SharedMediaTab2', - type: 'media' - }, { - inputFilter: 'inputMessagesFilterUrl', - name: 'SharedLinksTab2', - type: 'links' - }, { - inputFilter: 'inputMessagesFilterDocument', - name: 'SharedFilesTab2', - type: 'files' - }, { - inputFilter: 'inputMessagesFilterMusic', - name: 'SharedMusicTab2', - type: 'music' - }, { - inputFilter: 'inputMessagesFilterVoice', - name: 'SharedVoiceTab2', - type: 'voice' - }], scrollable, this.searchGroups, true); + const searchSuper = this.searchSuper = new AppSearchSuper({ + mediaTabs: [{ + inputFilter: 'inputMessagesFilterEmpty', + name: 'FilterChats', + type: 'chats' + }, { + inputFilter: 'inputMessagesFilterPhotoVideo', + name: 'SharedMediaTab2', + type: 'media' + }, { + inputFilter: 'inputMessagesFilterUrl', + name: 'SharedLinksTab2', + type: 'links' + }, { + inputFilter: 'inputMessagesFilterDocument', + name: 'SharedFilesTab2', + type: 'files' + }, { + inputFilter: 'inputMessagesFilterMusic', + name: 'SharedMusicTab2', + type: 'music' + }, { + inputFilter: 'inputMessagesFilterVoice', + name: 'SharedVoiceTab2', + type: 'voice' + }], + scrollable, + searchGroups: this.searchGroups, + asChatList: true, + hideEmptyTabs: false + }); searchContainer.prepend(searchSuper.nav.parentElement.parentElement); scrollable.container.append(searchSuper.container); @@ -347,7 +353,7 @@ export class AppSidebarLeft extends SidebarSlider { } if(!selectedPeerId && value.trim()) { - const middleware = searchSuper.getMiddleware(); + const middleware = searchSuper.middleware.get(); Promise.all([ appMessagesManager.getConversationsAll(value).then(dialogs => dialogs.map(d => d.peerId)), appUsersManager.getContacts(value, true) diff --git a/src/components/sidebarRight/tabs/sharedMedia.ts b/src/components/sidebarRight/tabs/sharedMedia.ts index 0e112c9f2..370d33cff 100644 --- a/src/components/sidebarRight/tabs/sharedMedia.ts +++ b/src/components/sidebarRight/tabs/sharedMedia.ts @@ -10,7 +10,7 @@ import AppSearchSuper, { SearchSuperType } from "../../appSearchSuper."; import AvatarElement from "../../avatar"; import SidebarSlider, { SliderSuperTab } from "../../slider"; import CheckboxField from "../../checkboxField"; -import { attachClickEvent, replaceContent } from "../../../helpers/dom"; +import { attachClickEvent, replaceContent, whichChild } from "../../../helpers/dom"; import appSidebarRight from ".."; import { TransitionSlider } from "../../transition"; import appNotificationsManager from "../../../lib/appManagers/appNotificationsManager"; @@ -32,6 +32,7 @@ import { safeAssign } from "../../../helpers/object"; import { forEachReverse } from "../../../helpers/array"; import appPhotosManager from "../../../lib/appManagers/appPhotosManager"; import renderImageFromUrl from "../../../helpers/dom/renderImageFromUrl"; +import SwipeHandler from "../../swipeHandler"; let setText = (text: string, row: Row) => { fastRaf(() => { @@ -175,7 +176,13 @@ class PeerProfileAvatars { this.container.append(this.avatars, this.info, this.tabs); + let cancel = false; attachClickEvent(this.container, (_e) => { + if(cancel) { + cancel = false; + return; + } + const rect = this.container.getBoundingClientRect(); const e = (_e as TouchEvent).touches ? (_e as TouchEvent).touches[0] : _e as MouseEvent; @@ -184,7 +191,57 @@ class PeerProfileAvatars { const centerX = rect.right - (rect.width / 2); const toRight = x > centerX; - this.listLoader.go(toRight ? 1 : -1); + // this.avatars.classList.remove('no-transition'); + // fastRaf(() => { + this.listLoader.go(toRight ? 1 : -1); + // }); + }); + + let width = 0, x = 0, lastDiffX = 0, lastIndex = 0, minX = 0; + const swipeHandler = new SwipeHandler({ + element: this.avatars, + onSwipe: (xDiff, yDiff) => { + lastDiffX = xDiff; + let lastX = x + xDiff * -2; + if(lastX > 0) lastX = 0; + else if(lastX < minX) lastX = minX; + + this.avatars.style.transform = `translate3d(${lastX}px, 0, -1px) scale(2)`; + //console.log(xDiff, yDiff); + return false; + }, + verifyTouchTarget: (e) => { + if(this.tabs.classList.contains('hide')) { + return false; + } + + return true; + }, + onFirstSwipe: () => { + const rect = this.avatars.getBoundingClientRect(); + width = rect.width; + minX = -width * (this.tabs.childElementCount - 1); + + /* lastIndex = whichChild(this.tabs.querySelector('.active')); + x = -width * lastIndex; */ + x = rect.left - this.container.getBoundingClientRect().left; + + this.avatars.style.transform = `translate3d(${x}px, 0, -1px) scale(2)`; + + this.avatars.classList.add('no-transition'); + void this.avatars.offsetLeft; // reflow + }, + onReset: () => { + const addIndex = Math.ceil(Math.abs(lastDiffX) / (width / 2)) * (lastDiffX >= 0 ? 1 : -1); + cancel = true; + + //console.log(addIndex); + + this.avatars.classList.remove('no-transition'); + fastRaf(() => { + this.listLoader.go(addIndex); + }); + } }); } @@ -211,7 +268,7 @@ class PeerProfileAvatars { onJump: (item, older) => { const id = this.listLoader.index; //const nextId = Math.max(0, id); - this.avatars.style.transform = `translateX(-${100 * id}%)`; + this.avatars.style.transform = `translate3d(-${200 * id}%, 0, -1px) scale(2)`; const activeTab = this.tabs.querySelector('.active'); if(activeTab) activeTab.classList.remove('active'); @@ -235,6 +292,8 @@ class PeerProfileAvatars { if(this.tabs.childElementCount === 1) { tab.classList.add('active'); } + + this.tabs.classList.toggle('hide', this.tabs.childElementCount <= 1); } public processItem = (photoId: string) => { @@ -242,16 +301,19 @@ class PeerProfileAvatars { avatar.classList.add(PeerProfileAvatars.BASE_CLASS + '-avatar'); const photo = appPhotosManager.getPhoto(photoId); + const img = new Image(); + img.classList.add(PeerProfileAvatars.BASE_CLASS + '-avatar-image'); + img.draggable = false; + if(photo) { appPhotosManager.preloadPhoto(photo, appPhotosManager.choosePhotoSize(photo, 420, 420, false)).then(() => { - const img = new Image(); renderImageFromUrl(img, photo.url, () => { avatar.append(img); }); }); } else { const photo = appPeersManager.getPeerPhoto(this.peerId); - appProfileManager.putAvatar(avatar, this.peerId, photo, 'photo_big'); + appProfileManager.putAvatar(avatar, this.peerId, photo, 'photo_big', img); } this.avatars.append(avatar); @@ -636,19 +698,10 @@ export default class AppSharedMediaTab extends SliderSuperTab { transition(+isSharedMedia); if(!isSharedMedia) { - this.searchSuper.goingHard = {}; + this.searchSuper.cleanScrollPositions(); } }; - this.scrollable.container.addEventListener('scroll', () => { - if(this.profile.avatars) { - const scrollTop = this.scrollable.scrollTop; - const y = scrollTop / 2; - this.profile.avatars.avatars.style.transform = `translateY(${y}px)`; - //this.profile.avatars.tabs.style.transform = `translateY(${scrollTop}px)`; - } - }); - const transition = TransitionSlider(transitionContainer, 'slide-fade', 400, null, false); transition(0); @@ -686,25 +739,30 @@ export default class AppSharedMediaTab extends SliderSuperTab { //this.container.prepend(this.closeBtn.parentElement); - this.searchSuper = new AppSearchSuper([{ - inputFilter: 'inputMessagesFilterPhotoVideo', - name: 'SharedMediaTab2', - type: 'media' - }, { - inputFilter: 'inputMessagesFilterDocument', - name: 'SharedFilesTab2', - type: 'files' - }, { - inputFilter: 'inputMessagesFilterUrl', - name: 'SharedLinksTab2', - type: 'links' - }, { - inputFilter: 'inputMessagesFilterMusic', - name: 'SharedMusicTab2', - type: 'music' - }], this.scrollable/* , undefined, undefined, false */); - - this.profile.element.append(this.searchSuper.container); + this.searchSuper = new AppSearchSuper({ + mediaTabs: [{ + inputFilter: 'inputMessagesFilterEmpty', + name: 'PeerMedia.Members', + type: 'members' + }, { + inputFilter: 'inputMessagesFilterPhotoVideo', + name: 'SharedMediaTab2', + type: 'media' + }, { + inputFilter: 'inputMessagesFilterDocument', + name: 'SharedFilesTab2', + type: 'files' + }, { + inputFilter: 'inputMessagesFilterUrl', + name: 'SharedLinksTab2', + type: 'links' + }, { + inputFilter: 'inputMessagesFilterMusic', + name: 'SharedMusicTab2', + type: 'music' + }], + scrollable: this.scrollable + }); } public renderNewMessages(peerId: number, mids: number[]) { @@ -713,7 +771,7 @@ export default class AppSharedMediaTab extends SliderSuperTab { if(!this.historiesStorage[peerId]) return; mids = mids.slice().reverse(); // ! because it will be ascend sorted array - for(const type of this.searchSuper.types) { + for(const type of this.searchSuper.mediaTabs) { const inputFilter = type.inputFilter; const filtered = this.searchSuper.filterMessagesByType(mids.map(mid => appMessagesManager.getMessageByPeer(peerId, mid)), inputFilter); if(filtered.length) { @@ -737,7 +795,7 @@ export default class AppSharedMediaTab extends SliderSuperTab { if(!this.historiesStorage[peerId]) return; for(const mid of mids) { - for(const type of this.searchSuper.types) { + for(const type of this.searchSuper.mediaTabs) { const inputFilter = type.inputFilter; if(!this.historiesStorage[peerId][inputFilter]) continue; @@ -773,6 +831,10 @@ export default class AppSharedMediaTab extends SliderSuperTab { this.editBtn.style.display = 'none'; this.searchSuper.cleanupHTML(); this.searchSuper.selectTab(0, false); + + if(!this.searchSuper.container.parentElement) { + this.profile.element.append(this.searchSuper.container); + } } public setLoadMutex(promise: Promise) { @@ -800,6 +862,8 @@ export default class AppSharedMediaTab extends SliderSuperTab { } public fillProfileElements() { + this.cleanupHTML(); + this.profile.fillProfileElements(); if(this.peerId > 0) { diff --git a/src/components/slider.ts b/src/components/slider.ts index c84939faf..3f44ad4ab 100644 --- a/src/components/slider.ts +++ b/src/components/slider.ts @@ -112,6 +112,7 @@ export default class SidebarSlider { } this.removeTabFromHistory(tab); + appNavigationController.removeByType(this.navigationType, true); } } diff --git a/src/components/swipeHandler.ts b/src/components/swipeHandler.ts index 3332350a8..8663f1e86 100644 --- a/src/components/swipeHandler.ts +++ b/src/components/swipeHandler.ts @@ -1,34 +1,108 @@ -export default class SwipeHandler { - private xDown: number; - private yDown: number; +import { cancelEvent } from "../helpers/dom"; +import { safeAssign } from "../helpers/object"; +import { isTouchSupported } from "../helpers/touchSupport"; - constructor(element: HTMLElement, private onSwipe: (xDiff: number, yDiff: number) => boolean, private verifyTouchTarget?: (evt: TouchEvent) => boolean) { - element.addEventListener('touchstart', this.handleTouchStart, false); - element.addEventListener('touchmove', this.handleTouchMove, false); +const getEvent = (e: TouchEvent | MouseEvent) => { + return (e as TouchEvent).touches ? (e as TouchEvent).touches[0] : e as MouseEvent; +}; + +const attachGlobalListenerTo = window; + +export default class SwipeHandler { + private element: HTMLElement; + private onSwipe: (xDiff: number, yDiff: number) => boolean; + private verifyTouchTarget: (evt: Touch | MouseEvent) => boolean; + private onFirstSwipe: () => void; + private onReset: () => void; + + private hadMove = false; + private xDown: number = null; + private yDown: number = null; + + constructor(options: { + element: SwipeHandler['element'], + onSwipe: SwipeHandler['onSwipe'], + verifyTouchTarget?: SwipeHandler['verifyTouchTarget'], + onFirstSwipe?: SwipeHandler['onFirstSwipe'], + onReset?: SwipeHandler['onReset'], + }) { + safeAssign(this, options); + + if(!isTouchSupported) { + this.element.addEventListener('mousedown', this.handleStart, false); + attachGlobalListenerTo.addEventListener('mouseup', this.reset); + } else { + this.element.addEventListener('touchstart', this.handleStart, false); + attachGlobalListenerTo.addEventListener('touchend', this.reset); + } } - handleTouchStart = (evt: TouchEvent) => { - if(this.verifyTouchTarget && !this.verifyTouchTarget(evt)) { - this.xDown = this.yDown = null; - return; + reset = (e?: Event) => { + /* if(e) { + cancelEvent(e); + } */ + + if(isTouchSupported) { + attachGlobalListenerTo.removeEventListener('touchmove', this.handleMove, {capture: true}); + } else { + attachGlobalListenerTo.removeEventListener('mousemove', this.handleMove); + this.element.style.cursor = ''; } - const firstTouch = evt.touches[0]; - this.xDown = firstTouch.clientX; - this.yDown = firstTouch.clientY; + if(this.onReset && this.hadMove) { + this.onReset(); + } + + this.xDown = this.yDown = null; + this.hadMove = false; }; - handleTouchMove = (evt: TouchEvent) => { - if(this.xDown === null || this.yDown === null) { - return; + handleStart = (_e: TouchEvent | MouseEvent) => { + const e = getEvent(_e); + if(this.verifyTouchTarget && !this.verifyTouchTarget(e)) { + return this.reset(); } - const xUp = evt.touches[0].clientX; - const yUp = evt.touches[0].clientY; + this.xDown = e.clientX; + this.yDown = e.clientY; + + if(isTouchSupported) { + attachGlobalListenerTo.addEventListener('touchmove', this.handleMove, {passive: false, capture: true}); + } else { + attachGlobalListenerTo.addEventListener('mousemove', this.handleMove, false); + } + }; + + handleMove = (_e: TouchEvent | MouseEvent) => { + if(this.xDown === null || this.yDown === null) { + return this.reset(); + } + + cancelEvent(_e); + + const e = getEvent(_e); + const xUp = e.clientX; + const yUp = e.clientY; const xDiff = this.xDown - xUp; const yDiff = this.yDown - yUp; + if(!this.hadMove) { + if(!xDiff && !yDiff) { + return; + } + + this.hadMove = true; + + if(!isTouchSupported) { + this.element.style.cursor = 'grabbing'; + } + + if(this.onFirstSwipe) { + this.onFirstSwipe(); + } + } + // if(Math.abs(xDiff) > Math.abs(yDiff)) { /*most significant*/ // if(xDiff > 0) { /* left swipe */ @@ -45,8 +119,7 @@ export default class SwipeHandler { /* reset values */ if(this.onSwipe(xDiff, yDiff)) { - this.xDown = null; - this.yDown = null; + this.reset(); } }; -} \ No newline at end of file +} diff --git a/src/config/app.ts b/src/config/app.ts index 6deca7705..ee1d7e967 100644 --- a/src/config/app.ts +++ b/src/config/app.ts @@ -2,7 +2,7 @@ const App = { id: 1025907, hash: '452b0359b988148995f22ff0f4229750', version: '0.4.0', - langPackVersion: '0.0.9', + langPackVersion: '0.1.0', langPack: 'macos', langPackCode: 'en', domains: [] as string[], diff --git a/src/helpers/middleware.ts b/src/helpers/middleware.ts new file mode 100644 index 000000000..869fab524 --- /dev/null +++ b/src/helpers/middleware.ts @@ -0,0 +1,16 @@ +// * will change .cleaned and new instance will be created +export const getMiddleware = () => { + let cleanupObj = {cleaned: false}; + return { + clean: () => { + cleanupObj.cleaned = true; + cleanupObj = {cleaned: false}; + }, + get: () => { + const _cleanupObj = cleanupObj; + return () => { + return !_cleanupObj.cleaned; + }; + } + }; +}; diff --git a/src/index.hbs b/src/index.hbs index abc2cdae3..16fdc1cb7 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -82,7 +82,7 @@