Video autoplay
This commit is contained in:
parent
1796dff9ce
commit
8ea5c3a283
@ -22,6 +22,8 @@ import { renderImageFromUrl } from './misc';
|
|||||||
import PollElement from './poll';
|
import PollElement from './poll';
|
||||||
import ProgressivePreloader from './preloader';
|
import ProgressivePreloader from './preloader';
|
||||||
|
|
||||||
|
const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB
|
||||||
|
|
||||||
export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue, noInfo, group}: {
|
export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue, noInfo, group}: {
|
||||||
doc: MyDocument,
|
doc: MyDocument,
|
||||||
container?: HTMLDivElement,
|
container?: HTMLDivElement,
|
||||||
@ -35,22 +37,28 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
|||||||
noInfo?: true,
|
noInfo?: true,
|
||||||
group?: string,
|
group?: string,
|
||||||
}) {
|
}) {
|
||||||
|
const isAlbumItem = !(boxWidth && boxHeight);
|
||||||
|
const canAutoplay = doc.type != 'video' || (doc.size <= MAX_VIDEO_AUTOPLAY_SIZE && !isAlbumItem);
|
||||||
|
let spanTime: HTMLElement;
|
||||||
|
|
||||||
if(!noInfo) {
|
if(!noInfo) {
|
||||||
if(doc.type != 'round') {
|
if(doc.type != 'round') {
|
||||||
let span: HTMLSpanElement, spanPlay: HTMLSpanElement;
|
spanTime = document.createElement('span');
|
||||||
|
spanTime.classList.add('video-time');
|
||||||
span = document.createElement('span');
|
container.append(spanTime);
|
||||||
span.classList.add('video-time');
|
|
||||||
container.append(span);
|
|
||||||
|
|
||||||
if(doc.type != 'gif') {
|
if(doc.type != 'gif') {
|
||||||
span.innerText = (doc.duration + '').toHHMMSS(false);
|
spanTime.innerText = (doc.duration + '').toHHMMSS(false);
|
||||||
|
|
||||||
spanPlay = document.createElement('span');
|
if(canAutoplay) {
|
||||||
spanPlay.classList.add('video-play', 'tgico-largeplay', 'btn-circle', 'position-center');
|
spanTime.classList.add('tgico', 'can-autoplay');
|
||||||
container.append(spanPlay);
|
} else {
|
||||||
|
const spanPlay = document.createElement('span');
|
||||||
|
spanPlay.classList.add('video-play', 'tgico-largeplay', 'btn-circle', 'position-center');
|
||||||
|
container.append(spanPlay);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
span.innerText = 'GIF';
|
spanTime.innerText = 'GIF';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,7 +140,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
|||||||
|
|
||||||
let img: HTMLImageElement;
|
let img: HTMLImageElement;
|
||||||
if(message) {
|
if(message) {
|
||||||
if(doc.type == 'video' && doc.thumbs?.length) {
|
if(!canAutoplay && doc.thumbs?.length) {
|
||||||
return wrapPhoto(doc, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware);
|
return wrapPhoto(doc, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,18 +207,18 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
|||||||
}, {once: true}); */
|
}, {once: true}); */
|
||||||
|
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
|
if(middleware && !middleware()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else if(doc.supportsStreaming) {
|
} else if(doc.supportsStreaming) {
|
||||||
preloader = new ProgressivePreloader(null, false, false, 'prepend');
|
preloader = new ProgressivePreloader(null, false, false, 'prepend');
|
||||||
preloader.attach(container, false, null);
|
preloader.attach(container, false, null);
|
||||||
video.addEventListener('canplay', () => {
|
video.addEventListener(isSafari ? 'timeupdate' : 'canplay', () => {
|
||||||
preloader.detach();
|
preloader.detach();
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(middleware && !middleware()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log('loaded doc:', doc, doc.url, container);
|
//console.log('loaded doc:', doc, doc.url, container);
|
||||||
|
|
||||||
const deferred = deferredPromise<void>();
|
const deferred = deferredPromise<void>();
|
||||||
@ -224,7 +232,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
|||||||
/* if(!video.paused) {
|
/* if(!video.paused) {
|
||||||
video.pause();
|
video.pause();
|
||||||
} */
|
} */
|
||||||
if(doc.type == 'gif' && group) {
|
if(doc.type != 'round' && group) {
|
||||||
animationIntersector.addAnimation(video, group);
|
animationIntersector.addAnimation(video, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +243,12 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
|||||||
}, {once: true});
|
}, {once: true});
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
if(doc.type == 'video') {
|
||||||
|
video.addEventListener('timeupdate', () => {
|
||||||
|
spanTime.innerText = (video.duration - video.currentTime + '').toHHMMSS(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
video.addEventListener('error', (e) => {
|
video.addEventListener('error', (e) => {
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
/* console.error('video error', e, video.src);
|
/* console.error('video error', e, video.src);
|
||||||
@ -253,15 +267,15 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
|||||||
container.append(video);
|
container.append(video);
|
||||||
} */
|
} */
|
||||||
|
|
||||||
if(doc.type == 'gif'/* || true */) {
|
if(doc.type == 'round') {
|
||||||
|
video.dataset.ckin = 'circle';
|
||||||
|
video.dataset.overlay = '1';
|
||||||
|
new VideoPlayer(video);
|
||||||
|
} else {
|
||||||
video.muted = true;
|
video.muted = true;
|
||||||
video.loop = true;
|
video.loop = true;
|
||||||
//video.play();
|
//video.play();
|
||||||
video.autoplay = true;
|
video.autoplay = true;
|
||||||
} else if(doc.type == 'round') {
|
|
||||||
video.dataset.ckin = 'circle';
|
|
||||||
video.dataset.overlay = '1';
|
|
||||||
new VideoPlayer(video);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return deferred;
|
return deferred;
|
||||||
|
@ -318,15 +318,15 @@ export default class VideoPlayer {
|
|||||||
|
|
||||||
const html = this.buildControls();
|
const html = this.buildControls();
|
||||||
player.insertAdjacentHTML('beforeend', html);
|
player.insertAdjacentHTML('beforeend', html);
|
||||||
let updateInterval = 0;
|
|
||||||
let elapsed = 0;
|
let elapsed = 0;
|
||||||
let prevTime = 0;
|
let prevTime = 0;
|
||||||
|
let timeDuration: HTMLElement;
|
||||||
|
|
||||||
if(skin === 'default') {
|
if(skin === 'default') {
|
||||||
const toggle = player.querySelectorAll('.toggle') as NodeListOf<HTMLElement>;
|
const toggle = player.querySelectorAll('.toggle') as NodeListOf<HTMLElement>;
|
||||||
const fullScreenButton = player.querySelector('.fullscreen') as HTMLElement;
|
const fullScreenButton = player.querySelector('.fullscreen') as HTMLElement;
|
||||||
var timeElapsed = player.querySelector('#time-elapsed');
|
const timeElapsed = player.querySelector('#time-elapsed');
|
||||||
var timeDuration = player.querySelector('#time-duration') as HTMLElement;
|
timeDuration = player.querySelector('#time-duration') as HTMLElement;
|
||||||
timeDuration.innerHTML = String(video.duration | 0).toHHMMSS();
|
timeDuration.innerHTML = String(video.duration | 0).toHHMMSS();
|
||||||
|
|
||||||
const volumeDiv = document.createElement('div');
|
const volumeDiv = document.createElement('div');
|
||||||
@ -451,10 +451,6 @@ export default class VideoPlayer {
|
|||||||
/* video.addEventListener('play', () => {
|
/* video.addEventListener('play', () => {
|
||||||
}); */
|
}); */
|
||||||
|
|
||||||
video.addEventListener('pause', () => {
|
|
||||||
clearInterval(updateInterval);
|
|
||||||
});
|
|
||||||
|
|
||||||
video.addEventListener('dblclick', () => {
|
video.addEventListener('dblclick', () => {
|
||||||
if(isTouchSupported) {
|
if(isTouchSupported) {
|
||||||
return;
|
return;
|
||||||
@ -470,16 +466,20 @@ export default class VideoPlayer {
|
|||||||
'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange'.split(' ').forEach(eventName => {
|
'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange'.split(' ').forEach(eventName => {
|
||||||
player.addEventListener(eventName, this.onFullScreen, false);
|
player.addEventListener(eventName, this.onFullScreen, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
video.addEventListener('timeupdate', () => {
|
||||||
|
timeElapsed.innerHTML = String(video.currentTime | 0).toHHMMSS();
|
||||||
|
});
|
||||||
} else if(skin === 'circle') {
|
} else if(skin === 'circle') {
|
||||||
const wrapper = document.createElement('div');
|
const wrapper = document.createElement('div');
|
||||||
wrapper.classList.add('circle-time-left');
|
wrapper.classList.add('circle-time-left');
|
||||||
video.parentNode.insertBefore(wrapper, video);
|
video.parentNode.insertBefore(wrapper, video);
|
||||||
wrapper.innerHTML = '<div class="circle-time"></div><div class="iconVolume tgico-nosound"></div>';
|
wrapper.innerHTML = '<div class="circle-time"></div><div class="iconVolume tgico-nosound"></div>';
|
||||||
|
|
||||||
var circle = player.querySelector('.progress-ring__circle') as SVGCircleElement;
|
const circle = player.querySelector('.progress-ring__circle') as SVGCircleElement;
|
||||||
const radius = circle.r.baseVal.value;
|
const radius = circle.r.baseVal.value;
|
||||||
var circumference = 2 * Math.PI * radius;
|
const circumference = 2 * Math.PI * radius;
|
||||||
var timeDuration = player.querySelector('.circle-time') as HTMLElement;
|
timeDuration = player.querySelector('.circle-time') as HTMLElement;
|
||||||
const iconVolume = player.querySelector('.iconVolume') as HTMLDivElement;
|
const iconVolume = player.querySelector('.iconVolume') as HTMLDivElement;
|
||||||
circle.style.strokeDasharray = circumference + ' ' + circumference;
|
circle.style.strokeDasharray = circumference + ' ' + circumference;
|
||||||
circle.style.strokeDashoffset = '' + circumference;
|
circle.style.strokeDashoffset = '' + circumference;
|
||||||
@ -505,6 +505,28 @@ export default class VideoPlayer {
|
|||||||
video.addEventListener('pause', () => {
|
video.addEventListener('pause', () => {
|
||||||
iconVolume.style.display = '';
|
iconVolume.style.display = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let updateInterval = 0;
|
||||||
|
video.addEventListener('timeupdate', () => {
|
||||||
|
clearInterval(updateInterval);
|
||||||
|
|
||||||
|
let elapsed = 0;
|
||||||
|
let prevTime = 0;
|
||||||
|
|
||||||
|
updateInterval = window.setInterval(() => {
|
||||||
|
if(video.currentTime != prevTime) {
|
||||||
|
elapsed = video.currentTime; // Update if getCurrentTime was changed
|
||||||
|
prevTime = video.currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
const offset = circumference - elapsed / video.duration * circumference;
|
||||||
|
circle.style.strokeDashoffset = '' + offset;
|
||||||
|
if(video.paused) clearInterval(updateInterval);
|
||||||
|
}, 20);
|
||||||
|
|
||||||
|
const timeLeft = String((video.duration - video.currentTime) | 0).toHHMMSS();
|
||||||
|
if(timeLeft != '0') timeDuration.innerHTML = timeLeft;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
video.addEventListener('play', () => {
|
video.addEventListener('play', () => {
|
||||||
@ -522,14 +544,6 @@ export default class VideoPlayer {
|
|||||||
timeDuration.innerHTML = String(Math.round(video.duration)).toHHMMSS();
|
timeDuration.innerHTML = String(Math.round(video.duration)).toHHMMSS();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
video.addEventListener('timeupdate', () => {
|
|
||||||
if(skin == 'default') {
|
|
||||||
timeElapsed.innerHTML = String(video.currentTime | 0).toHHMMSS();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateInterval = this.handleProgress(timeDuration, circumference, circle, updateInterval);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public togglePlay(stop?: boolean) {
|
public togglePlay(stop?: boolean) {
|
||||||
@ -547,32 +561,6 @@ export default class VideoPlayer {
|
|||||||
//this.wrapper.classList.toggle('is-playing', !this.video.paused);
|
//this.wrapper.classList.toggle('is-playing', !this.video.paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleProgress(timeDuration: HTMLElement, circumference: number, circle: SVGCircleElement, updateInterval: number) {
|
|
||||||
const {video, skin} = this;
|
|
||||||
|
|
||||||
clearInterval(updateInterval);
|
|
||||||
let elapsed = 0;
|
|
||||||
let prevTime = 0;
|
|
||||||
|
|
||||||
if(skin === 'circle') {
|
|
||||||
updateInterval = window.setInterval(() => {
|
|
||||||
if(video.currentTime != prevTime) {
|
|
||||||
elapsed = video.currentTime; // Update if getCurrentTime was changed
|
|
||||||
prevTime = video.currentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
const offset = circumference - elapsed / video.duration * circumference;
|
|
||||||
circle.style.strokeDashoffset = '' + offset;
|
|
||||||
if(video.paused) clearInterval(updateInterval);
|
|
||||||
}, 20);
|
|
||||||
|
|
||||||
const timeLeft = String((video.duration - video.currentTime) | 0).toHHMMSS();
|
|
||||||
if(timeLeft != '0') timeDuration.innerHTML = timeLeft;
|
|
||||||
|
|
||||||
return updateInterval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildControls() {
|
private buildControls() {
|
||||||
const skin = this.skin;
|
const skin = this.skin;
|
||||||
if(skin === 'default') {
|
if(skin === 'default') {
|
||||||
|
@ -519,6 +519,10 @@ $bubble-margin: .25rem;
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preloader-container {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.sticker) {
|
&:not(.sticker) {
|
||||||
@ -537,6 +541,12 @@ $bubble-margin: .25rem;
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html.is-safari &:not(.round) {
|
||||||
|
img:not(.emoji), video {
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.is-album {
|
&.is-album {
|
||||||
.attachment {
|
.attachment {
|
||||||
max-width: unquote('min(451px, 100%)');
|
max-width: unquote('min(451px, 100%)');
|
||||||
@ -1000,7 +1010,7 @@ $bubble-margin: .25rem;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
span.video-time {
|
.video-time {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 3px;
|
top: 3px;
|
||||||
left: 3px;
|
left: 3px;
|
||||||
@ -1014,9 +1024,18 @@ $bubble-margin: .25rem;
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
|
&.can-autoplay:after {
|
||||||
|
content: $tgico-nosound;
|
||||||
|
|
||||||
|
// * same as .iconVolume
|
||||||
|
padding: 0 1px 0 3px;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
span.video-play {
|
.video-play {
|
||||||
background-color: var(--message-time-background);
|
background-color: var(--message-time-background);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
Loading…
Reference in New Issue
Block a user