From 13c4b541cd6dcfdf20aa4492e2e664a5b9c6c832 Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Tue, 26 Jan 2021 00:47:04 +0200 Subject: [PATCH] Media viewer fixes --- src/components/appMediaViewer.ts | 124 ++++++++++++-------- src/components/sidebarLeft/tabs/settings.ts | 9 +- src/helpers/dom.ts | 10 +- src/lib/appManagers/appPhotosManager.ts | 19 +-- src/scss/partials/_mediaViewer.scss | 12 +- src/scss/partials/_preloader.scss | 4 + 6 files changed, 109 insertions(+), 69 deletions(-) diff --git a/src/components/appMediaViewer.ts b/src/components/appMediaViewer.ts index cc9c79ca..739f9441 100644 --- a/src/components/appMediaViewer.ts +++ b/src/components/appMediaViewer.ts @@ -774,8 +774,10 @@ class AppMediaViewerBase = Promise.resolve(); + if(useContainerAsTarget) { + const cacheContext = appPhotosManager.getCacheContext(media); + if(cacheContext.downloaded) { + const img = new Image(); + img.src = cacheContext.url; + container.append(img); + } else { + const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(media); + if(gotThumb) { + thumbPromise = gotThumb.loadPromise; + container.append(gotThumb.image); + } + } } - const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight); + const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight, mediaSizes.isMobile ? false : true); // need after setAttachmentSize /* if(useContainerAsTarget) { @@ -910,55 +923,55 @@ class AppMediaViewerBase { + const set = () => 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 moverVideo = mover.querySelector('video'); if(moverVideo) { moverVideo.remove(); } - + //video.src = ''; - + 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(); } }); - + if(isSafari) { // test stream // video.controls = true; video.autoplay = true; } - + if(media.type == 'gif') { video.muted = true; video.autoplay = true; video.loop = true; } - + if(!video.parentElement) { div.append(video); } - + 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'; - + // fix for simultaneous play appMediaPlaybackController.pause(); appMediaPlaybackController.willBePlayedMedia = null; @@ -967,25 +980,25 @@ class AppMediaViewerBase { if(video.readyState < video.HAVE_FUTURE_DATA) { preloader.attach(mover, true); } - + /* canPlayThrough.then(() => { preloader.detach(); }); */ }); - + const attachCanPlay = () => { video.addEventListener('canplay', () => { //this.log('video waited and progress loaded'); @@ -993,22 +1006,22 @@ class AppMediaViewerBase { 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(); - + preloader.attach(mover, true); - + // поставлю класс для плеера, чтобы убрать большую иконку пока прелоадер на месте video.parentElement.classList.add('is-buffering'); } }); - + attachCanPlay(); } @@ -1023,13 +1036,13 @@ class AppMediaViewerBase).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) { @@ -1040,25 +1053,27 @@ class AppMediaViewerBase { + const set = () => 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); - + onAnimationEnd.then(() => { if(!media.url) { this.preloader.attach(mover, true, cancellablePromise); @@ -1072,12 +1087,12 @@ class AppMediaViewerBase { + this.updateMediaSource(target, url, 'img'); - renderImageFromUrl(image, url, () => { - if(div.firstElementChild?.tagName === 'IMG') { - div.firstElementChild.remove(); - } - - div.append(image); - }); + if(haveImage) { + window.requestAnimationFrame(() => { + haveImage.remove(); + }); + } + + div.append(image); + }); + } } - + this.preloader.detach(); }).catch(err => { this.log.error(err); }); - + return cancellablePromise; }; - + this.lazyLoadQueue.unshift({load}); }); + + setMoverPromise = thumbPromise.then(set); } return this.setMoverPromise = setMoverPromise.catch(() => { diff --git a/src/components/sidebarLeft/tabs/settings.ts b/src/components/sidebarLeft/tabs/settings.ts index a106a5cb..e865e1ba 100644 --- a/src/components/sidebarLeft/tabs/settings.ts +++ b/src/components/sidebarLeft/tabs/settings.ts @@ -5,7 +5,7 @@ import appSidebarLeft, { AppSidebarLeft } from ".."; import appUsersManager from "../../../lib/appManagers/appUsersManager"; import ButtonMenuToggle from "../../buttonMenuToggle"; import Button from "../../button"; -import AppMediaViewer from "../../appMediaViewer"; +//import AppMediaViewer from "../../appMediaViewerNew"; export default class AppSettingsTab extends SliderSuperTab { private avatarElem: AvatarElement; @@ -44,12 +44,15 @@ export default class AppSettingsTab extends SliderSuperTab { this.avatarElem.classList.add('profile-avatar', 'avatar-120'); /* const div = document.createElement('div'); - div.style.cssText = 'border-radius: 8px; overflow: hidden; width: 396px; height: 264px; flex: 0 0 auto; position: relative; margin: 10rem 0 10rem auto;'; + //div.style.cssText = 'border-radius: 8px; overflow: hidden; width: 396px; height: 264px; flex: 0 0 auto; position: relative; margin: 10rem 0 10rem auto;'; + //div.style.width = '135px'; + //div.style.height = '100px'; + div.style.cssText = 'border-radius: 8px; overflow: hidden; width: 396px; height: 264px; flex: 0 0 auto; position: relative; margin: 10rem auto 10rem 0;'; div.style.width = '135px'; div.style.height = '100px'; const img = document.createElement('img'); - img.src = 'assets/img/PinnedMessages.png'; + img.src = 'assets/img/pepe.jpg'; img.classList.add('media-photo'); img.style.cssText = 'max-width: 100%;max-height: 100%;'; diff --git a/src/helpers/dom.ts b/src/helpers/dom.ts index d7877979..b7c4c721 100644 --- a/src/helpers/dom.ts +++ b/src/helpers/dom.ts @@ -410,13 +410,13 @@ export function fillPropertyValue(str: string) { return splitted; } -export function calcImageInBox(imageW: number, imageH: number, boxW: number, boxH: number, noZoom?: boolean) { - if(imageW < boxW && imageH < boxH) { +export function calcImageInBox(imageW: number, imageH: number, boxW: number, boxH: number, noZoom = true) { + if(imageW < boxW && imageH < boxH && noZoom) { return {w: imageW, h: imageH}; } - var boxedImageW = boxW; - var boxedImageH = boxH; + let boxedImageW = boxW; + let boxedImageH = boxH; if((imageW / imageH) > (boxW / boxH)) { boxedImageH = (imageH * boxW / imageW) | 0; @@ -441,6 +441,8 @@ export function calcImageInBox(imageW: number, imageH: number, boxW: number, box return {w: boxedImageW, h: boxedImageH}; } +MOUNT_CLASS_TO && (MOUNT_CLASS_TO.calcImageInBox = calcImageInBox); + export function positionElementByIndex(element: HTMLElement, container: HTMLElement, pos: number) { const prevPos = element.parentElement === container ? whichChild(element) : -1; diff --git a/src/lib/appManagers/appPhotosManager.ts b/src/lib/appManagers/appPhotosManager.ts index 14fcdea2..5955c859 100644 --- a/src/lib/appManagers/appPhotosManager.ts +++ b/src/lib/appManagers/appPhotosManager.ts @@ -38,13 +38,14 @@ export class AppPhotosManager { public static Df = bytesFromHex('ffd9'); constructor() { - window.addEventListener('resize', (e) => { - this.windowW = document.body.scrollWidth; - this.windowH = document.body.scrollHeight; - }); - - this.windowW = document.body.scrollWidth; - this.windowH = document.body.scrollHeight; + // @ts-ignore + const w: any = 'visualViewport' in window ? window.visualViewport : window; + const set = () => { + this.windowW = w.width || w.innerWidth; + this.windowH = w.height || w.innerHeight; + }; + w.addEventListener('resize', set); + set(); } public savePhoto(photo: Photo, context?: ReferenceContext) { @@ -208,7 +209,7 @@ export class AppPhotosManager { return {image, loadPromise}; } - public setAttachmentSize(photo: MyPhoto | MyDocument, element: HTMLElement | SVGForeignObjectElement, boxWidth: number, boxHeight: number) { + public setAttachmentSize(photo: MyPhoto | MyDocument, element: HTMLElement | SVGForeignObjectElement, boxWidth: number, boxHeight: number, noZoom = true) { const photoSize = this.choosePhotoSize(photo, boxWidth, boxHeight); //console.log('setAttachmentSize', photo, photo.sizes[0].bytes, div); @@ -222,7 +223,7 @@ export class AppPhotosManager { height = 'h' in photoSize ? photoSize.h : 100; } - const {w, h} = calcImageInBox(width, height, boxWidth, boxHeight); + const {w, h} = calcImageInBox(width, height, boxWidth, boxHeight, noZoom); if(element instanceof SVGForeignObjectElement) { element.setAttributeNS(null, 'width', '' + w); element.setAttributeNS(null, 'height', '' + h); diff --git a/src/scss/partials/_mediaViewer.scss b/src/scss/partials/_mediaViewer.scss index f1a86b06..74798967 100644 --- a/src/scss/partials/_mediaViewer.scss +++ b/src/scss/partials/_mediaViewer.scss @@ -218,18 +218,21 @@ transform-origin: top left; //transform-origin: bottom right; overflow: hidden; + transform: translateZ(0) scale3d(1, 1, 1); + border-radius: 0; + -webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%); // fix border-radius overflow // эти значения должны быть такими же, как при установке maxWidth и maxHeight в openMedia! //max-width: 100%; - max-width: calc(100% - 16px); + //max-width: calc(1vw - 16px); //max-height: 100%; - max-height: calc(100% - 100px); + //max-height: calc((var(--vh, 1vh) * 100) - 100px); // эти значения должны быть такими же, как при установке maxWidth и maxHeight в openMedia! @include respond-to(handhelds) { overflow: visible; //max-height: 100% !important; - max-width: 100% !important; + //max-width: 100vw !important; } .ckin__player { @@ -291,10 +294,13 @@ left: 50% !important; top: 50% !important; transform: translate3d(-50%, -50%, 0) !important; + max-width: calc(100vw - 16px); + max-height: calc((var(--vh, 1vh) * 100) - 100px); @include respond-to(handhelds) { width: 100% !important; height: 100% !important; + max-width: 100vw !important; //height: calc(100% - 100px) !important; /* height: calc(100% - 50px) !important; top: calc(50% + 25px) !important; diff --git a/src/scss/partials/_preloader.scss b/src/scss/partials/_preloader.scss index 982ca051..4f332940 100644 --- a/src/scss/partials/_preloader.scss +++ b/src/scss/partials/_preloader.scss @@ -89,6 +89,10 @@ $transition: .2s ease-in-out; //animation: dashNew 1.5s ease-in-out infinite; stroke-dasharray: 112.36, 149.82; } + + &.preloader-streamable .preloader-path-new { + stroke-dasharray: 88.95, 118.61; + } } .preloader-close, .preloader-download {