Fix round videos
This commit is contained in:
parent
43cfa9ee12
commit
8dc136538a
@ -4,6 +4,7 @@ import appDocsManager, {MyDocument} from "../lib/appManagers/appDocsManager";
|
||||
import { CancellablePromise, deferredPromise } from "../helpers/cancellablePromise";
|
||||
import { isSafari } from "../helpers/userAgent";
|
||||
import { MOUNT_CLASS_TO } from "../lib/mtproto/mtproto_config";
|
||||
import { isInDOM } from "../helpers/dom";
|
||||
|
||||
// TODO: если удалить сообщение, и при этом аудио будет играть - оно не остановится, и можно будет по нему перейти вникуда
|
||||
|
||||
@ -177,6 +178,13 @@ class AppMediaPlaybackController {
|
||||
}
|
||||
|
||||
onPause = (e: Event) => {
|
||||
/* const target = e.target as HTMLMediaElement;
|
||||
if(!isInDOM(target)) {
|
||||
this.container.append(target);
|
||||
target.play();
|
||||
return;
|
||||
} */
|
||||
|
||||
rootScope.broadcast('audio_pause');
|
||||
};
|
||||
|
||||
|
@ -237,6 +237,8 @@ export default class ProgressivePreloader {
|
||||
}
|
||||
|
||||
public detach() {
|
||||
//return;
|
||||
|
||||
this.detached = true;
|
||||
|
||||
//return;
|
||||
|
@ -1,3 +1,4 @@
|
||||
import type Chat from './chat/chat';
|
||||
import { getEmojiToneIndex } from '../emoji';
|
||||
import { readBlobAsText } from '../helpers/blob';
|
||||
import { deferredPromise } from '../helpers/cancellablePromise';
|
||||
@ -7,7 +8,6 @@ import { formatBytes } from '../helpers/number';
|
||||
import { isAppleMobile, isSafari } from '../helpers/userAgent';
|
||||
import { PhotoSize } from '../layer';
|
||||
import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager";
|
||||
import { DownloadBlob } from '../lib/appManagers/appDownloadManager';
|
||||
import appMessagesManager from '../lib/appManagers/appMessagesManager';
|
||||
import appPhotosManager, { MyPhoto } from '../lib/appManagers/appPhotosManager';
|
||||
import LottieLoader from '../lib/lottieLoader';
|
||||
@ -27,9 +27,9 @@ import './middleEllipsis';
|
||||
import { nextRandomInt } from '../helpers/random';
|
||||
import RichTextProcessor from '../lib/richtextprocessor';
|
||||
import appImManager from '../lib/appManagers/appImManager';
|
||||
import Chat from './chat/chat';
|
||||
import { SearchSuperContext } from './appSearchSuper.';
|
||||
import rootScope from '../lib/rootScope';
|
||||
import { onVideoLoad } from '../helpers/files';
|
||||
|
||||
const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB
|
||||
|
||||
@ -108,28 +108,28 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
video.remove();
|
||||
} */
|
||||
|
||||
const video = document.createElement('video');
|
||||
const video = /* doc.type === 'round' ? appMediaPlaybackController.addMedia(message.peerId, doc, message.mid) as HTMLVideoElement : */document.createElement('video');
|
||||
video.classList.add('media-video');
|
||||
video.muted = true;
|
||||
video.setAttribute('playsinline', 'true');
|
||||
if(doc.type === 'round') {
|
||||
//video.muted = true;
|
||||
//video.classList.add('z-depth-1');
|
||||
const globalVideo = appMediaPlaybackController.addMedia(message.peerId, doc, message.mid);
|
||||
|
||||
video.classList.add('z-depth-1');
|
||||
|
||||
video.addEventListener('canplay', () => {
|
||||
if(globalVideo.currentTime > 0) {
|
||||
onVideoLoad(video).then(() => {
|
||||
if(globalVideo.currentTime !== globalVideo.duration) {
|
||||
video.currentTime = globalVideo.currentTime;
|
||||
}
|
||||
|
||||
if(!globalVideo.paused) {
|
||||
// с закоментированными настройками - хром выключал видео при скролле, для этого нужно было включить видео - выйти из диалога, зайти заново и проскроллить вверх
|
||||
/* video.autoplay = true;
|
||||
video.loop = false; */
|
||||
//video.autoplay = true;
|
||||
//video.loop = false;
|
||||
video.play();
|
||||
}
|
||||
}, {once: true});
|
||||
});
|
||||
|
||||
const clear = () => {
|
||||
//console.log('clearing video');
|
||||
@ -160,14 +160,18 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
|
||||
const onVideoPlay = (e: Event) => {
|
||||
//console.log('video play event', e);
|
||||
globalVideo.currentTime = video.currentTime;
|
||||
globalVideo.play();
|
||||
if(globalVideo.paused) {
|
||||
globalVideo.currentTime = video.currentTime;
|
||||
globalVideo.play();
|
||||
}
|
||||
};
|
||||
|
||||
// * this will fire when video unmounts
|
||||
const onVideoPause = (e: Event) => {
|
||||
//console.trace('video pause event', e);
|
||||
if(isInDOM(video)) {
|
||||
globalVideo.pause();
|
||||
globalVideo.currentTime = video.currentTime;
|
||||
} else {
|
||||
clear();
|
||||
}
|
||||
@ -229,22 +233,25 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
return;
|
||||
}
|
||||
|
||||
let loadPromise: Promise<any> = Promise.resolve();
|
||||
let preloader: ProgressivePreloader;
|
||||
if(message?.media?.preloader) { // means upload
|
||||
preloader = message.media.preloader as ProgressivePreloader;
|
||||
preloader.attach(container, false);
|
||||
} else if(!doc.downloaded && !doc.supportsStreaming) {
|
||||
const promise = appDocsManager.downloadDoc(doc, lazyLoadQueue?.queueId);
|
||||
const promise = loadPromise = appDocsManager.downloadDoc(doc, lazyLoadQueue?.queueId);
|
||||
preloader = new ProgressivePreloader({
|
||||
attachMethod: 'prepend'
|
||||
});
|
||||
preloader.attach(container, true, promise);
|
||||
|
||||
await promise;
|
||||
//if(doc.type !== 'round') {
|
||||
await promise;
|
||||
|
||||
if(middleware && !middleware()) {
|
||||
return;
|
||||
}
|
||||
if(middleware && !middleware()) {
|
||||
return;
|
||||
}
|
||||
//}
|
||||
} else if(doc.supportsStreaming) {
|
||||
preloader = new ProgressivePreloader({
|
||||
cancelable: false,
|
||||
@ -255,13 +262,17 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
preloader.detach();
|
||||
}, {once: true});
|
||||
}
|
||||
|
||||
/* if(doc.type === 'round') {
|
||||
return;
|
||||
} */
|
||||
|
||||
//console.log('loaded doc:', doc, doc.url, container);
|
||||
|
||||
const deferred = deferredPromise<void>();
|
||||
|
||||
//if(doc.type == 'gif'/* || true */) {
|
||||
video.addEventListener(isAppleMobile ? 'loadeddata' : 'canplay', () => {
|
||||
onVideoLoad(video).then(() => {
|
||||
/* if(!video.paused) {
|
||||
video.pause();
|
||||
} */
|
||||
@ -273,7 +284,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
//setTimeout(() => {
|
||||
deferred.resolve();
|
||||
//}, 5000);
|
||||
}, {once: true});
|
||||
});
|
||||
//}
|
||||
|
||||
if(doc.type === 'video') {
|
||||
@ -286,22 +297,24 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
renderImageFromUrl(video, doc.url);
|
||||
|
||||
if(doc.type === 'round') {
|
||||
video.dataset.ckin = 'circle';
|
||||
video.dataset.overlay = '1';
|
||||
new VideoPlayer(video);
|
||||
} else {
|
||||
if(doc.type !== 'round') {
|
||||
video.muted = true;
|
||||
video.loop = true;
|
||||
//video.play();
|
||||
video.autoplay = true;
|
||||
}
|
||||
|
||||
renderImageFromUrl(video, doc.url);
|
||||
|
||||
return deferred;
|
||||
return Promise.all([loadPromise, deferred]);
|
||||
};
|
||||
|
||||
if(doc.type === 'round') {
|
||||
video.dataset.ckin = 'circle';
|
||||
video.dataset.overlay = '1';
|
||||
new VideoPlayer(video, undefined, undefined, doc.duration);
|
||||
}
|
||||
|
||||
/* if(doc.size >= 20e6 && !doc.downloaded) {
|
||||
let downloadDiv = document.createElement('div');
|
||||
downloadDiv.classList.add('download');
|
||||
|
@ -11,6 +11,22 @@ interface AnimationInstance {
|
||||
type AnimationInstanceKey = any;
|
||||
const instances: Map<AnimationInstanceKey, AnimationInstance> = new Map();
|
||||
|
||||
export function createAnimationInstance(key: AnimationInstanceKey) {
|
||||
cancelAnimationByKey(key);
|
||||
|
||||
const instance: AnimationInstance = {
|
||||
isCancelled: false,
|
||||
deferred: deferredPromise<void>()
|
||||
};
|
||||
|
||||
instances.set(key, instance);
|
||||
instance.deferred.then(() => {
|
||||
instances.delete(key);
|
||||
});
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
export function getAnimationInstance(key: AnimationInstanceKey) {
|
||||
return instances.get(key);
|
||||
}
|
||||
@ -20,15 +36,12 @@ export function cancelAnimationByKey(key: AnimationInstanceKey) {
|
||||
if(instance) {
|
||||
instance.isCancelled = true;
|
||||
instance.deferred.resolve();
|
||||
instances.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
export function animateSingle(tick: Function, key: AnimationInstanceKey, instance?: AnimationInstance) {
|
||||
if(!instance) {
|
||||
cancelAnimationByKey(key);
|
||||
instance = { isCancelled: false, deferred: deferredPromise<void>() };
|
||||
instances.set(key, instance);
|
||||
instance = createAnimationInstance(key);
|
||||
}
|
||||
|
||||
fastRaf(() => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { pause } from "./schedulers";
|
||||
import { isAppleMobile } from "./userAgent";
|
||||
|
||||
export function preloadVideo(url: string): Promise<HTMLVideoElement> {
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -35,4 +36,15 @@ export async function createPosterForVideo(url: string): Promise<Blob | undefine
|
||||
pause(2000) as Promise<undefined>,
|
||||
createPosterFromVideo(video),
|
||||
]);
|
||||
}
|
||||
|
||||
export function onVideoLoad(video: HTMLVideoElement) {
|
||||
return new Promise<void>((resolve) => {
|
||||
if(video.readyState >= video.HAVE_METADATA) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
video.addEventListener(isAppleMobile ? 'loadeddata' : 'canplay', () => resolve(), {once: true});
|
||||
});
|
||||
}
|
@ -82,7 +82,7 @@ export default class CacheStorageController {
|
||||
reject();
|
||||
//console.warn('CACHESTORAGE TIMEOUT');
|
||||
rejected = true;
|
||||
}, 5e3);
|
||||
}, 15e3);
|
||||
|
||||
try {
|
||||
const cache = await this.openDatabase();
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { cancelEvent } from "../helpers/dom";
|
||||
import { attachClickEvent, cancelEvent } from "../helpers/dom";
|
||||
import appMediaPlaybackController from "../components/appMediaPlaybackController";
|
||||
import { isAppleMobile } from "../helpers/userAgent";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import RangeSelector from "../components/rangeSelector";
|
||||
import { animateSingle } from "../helpers/animation";
|
||||
import { onVideoLoad } from "../helpers/files";
|
||||
|
||||
type SUPEREVENT = MouseEvent | TouchEvent;
|
||||
|
||||
@ -167,7 +169,7 @@ export default class VideoPlayer {
|
||||
/* private videoParent: HTMLElement;
|
||||
private videoWhichChild: number; */
|
||||
|
||||
constructor(public video: HTMLVideoElement, play = false, streamable = false) {
|
||||
constructor(public video: HTMLVideoElement, play = false, streamable = false, duration?: number) {
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.classList.add('ckin__player');
|
||||
|
||||
@ -176,7 +178,7 @@ export default class VideoPlayer {
|
||||
|
||||
this.skin = video.dataset.ckin ?? 'default';
|
||||
|
||||
this.stylePlayer();
|
||||
this.stylePlayer(duration);
|
||||
|
||||
if(this.skin === 'default') {
|
||||
let controls = this.wrapper.querySelector('.default__controls.ckin__controls') as HTMLDivElement;
|
||||
@ -199,7 +201,7 @@ export default class VideoPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
private stylePlayer() {
|
||||
private stylePlayer(initDuration: number) {
|
||||
const {wrapper: player, video, skin} = this;
|
||||
|
||||
player.classList.add(skin);
|
||||
@ -365,11 +367,12 @@ export default class VideoPlayer {
|
||||
const circle = player.querySelector('.progress-ring__circle') as SVGCircleElement;
|
||||
const radius = circle.r.baseVal.value;
|
||||
const circumference = 2 * Math.PI * radius;
|
||||
timeDuration = player.querySelector('.circle-time') as HTMLElement;
|
||||
const iconVolume = player.querySelector('.iconVolume') as HTMLDivElement;
|
||||
timeDuration = wrapper.firstElementChild as HTMLElement;
|
||||
const iconVolume = wrapper.lastElementChild as HTMLElement;
|
||||
circle.style.strokeDasharray = circumference + ' ' + circumference;
|
||||
circle.style.strokeDashoffset = '' + circumference;
|
||||
circle.addEventListener('click', () => {
|
||||
attachClickEvent(circle as any, (e) => {
|
||||
cancelEvent(e);
|
||||
this.togglePlay();
|
||||
});
|
||||
|
||||
@ -377,24 +380,33 @@ export default class VideoPlayer {
|
||||
const offset = circumference - video.currentTime / video.duration * circumference;
|
||||
circle.style.strokeDashoffset = '' + offset;
|
||||
|
||||
if(video.paused) {
|
||||
clearInterval(updateInterval);
|
||||
}
|
||||
return !video.paused;
|
||||
};
|
||||
|
||||
const timeUpdate = () => {
|
||||
const timeLeft = String((video.duration - video.currentTime) | 0).toHHMMSS();
|
||||
if(timeLeft != '0') timeDuration.innerHTML = timeLeft;
|
||||
};
|
||||
|
||||
video.addEventListener('play', () => {
|
||||
iconVolume.style.display = 'none';
|
||||
updateInterval = window.setInterval(update, 20);
|
||||
|
||||
animateSingle(update, circle);
|
||||
update();
|
||||
});
|
||||
|
||||
video.addEventListener('pause', () => {
|
||||
iconVolume.style.display = '';
|
||||
});
|
||||
|
||||
let updateInterval = 0;
|
||||
video.addEventListener('timeupdate', () => {
|
||||
const timeLeft = String((video.duration - video.currentTime) | 0).toHHMMSS();
|
||||
if(timeLeft != '0') timeDuration.innerHTML = timeLeft;
|
||||
timeUpdate();
|
||||
});
|
||||
|
||||
onVideoLoad(video).then(() => {
|
||||
if(!video.currentTime || video.currentTime === video.duration) return;
|
||||
update();
|
||||
timeUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
@ -406,10 +418,10 @@ export default class VideoPlayer {
|
||||
this.wrapper.classList.remove('is-playing');
|
||||
});
|
||||
|
||||
if(video.duration > 0) {
|
||||
timeDuration.innerHTML = String(Math.round(video.duration)).toHHMMSS();
|
||||
if(video.duration || initDuration) {
|
||||
timeDuration.innerHTML = String(Math.round(video.duration || initDuration)).toHHMMSS();
|
||||
} else {
|
||||
video.addEventListener('loadeddata', () => {
|
||||
onVideoLoad(video).then(() => {
|
||||
timeDuration.innerHTML = String(Math.round(video.duration)).toHHMMSS();
|
||||
});
|
||||
}
|
||||
|
@ -78,8 +78,8 @@ avatar-element {
|
||||
}
|
||||
|
||||
&.emoji {
|
||||
width: calc(1.125rem / var(--multiplier));
|
||||
height: calc(1.125rem / var(--multiplier));
|
||||
width: calc(1.125rem / var(--multiplier)) !important;
|
||||
height: calc(1.125rem / var(--multiplier)) !important;
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
}
|
||||
|
@ -667,13 +667,6 @@ $bubble-margin: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.round {
|
||||
.attachment {
|
||||
max-height: 200px;
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.web {
|
||||
padding-top: 1px;
|
||||
margin: 4px 0 -5px 1px;
|
||||
|
Loading…
Reference in New Issue
Block a user