Browse Source

Video autoplay

master
morethanwords 4 years ago
parent
commit
8ea5c3a283
  1. 62
      src/components/wrappers.ts
  2. 76
      src/lib/mediaPlayer.ts
  3. 23
      src/scss/partials/_chatBubble.scss

62
src/components/wrappers.ts

@ -22,6 +22,8 @@ import { renderImageFromUrl } from './misc'; @@ -22,6 +22,8 @@ import { renderImageFromUrl } from './misc';
import PollElement from './poll';
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}: {
doc: MyDocument,
container?: HTMLDivElement,
@ -35,22 +37,28 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -35,22 +37,28 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
noInfo?: true,
group?: string,
}) {
const isAlbumItem = !(boxWidth && boxHeight);
const canAutoplay = doc.type != 'video' || (doc.size <= MAX_VIDEO_AUTOPLAY_SIZE && !isAlbumItem);
let spanTime: HTMLElement;
if(!noInfo) {
if(doc.type != 'round') {
let span: HTMLSpanElement, spanPlay: HTMLSpanElement;
span = document.createElement('span');
span.classList.add('video-time');
container.append(span);
spanTime = document.createElement('span');
spanTime.classList.add('video-time');
container.append(spanTime);
if(doc.type != 'gif') {
span.innerText = (doc.duration + '').toHHMMSS(false);
spanPlay = document.createElement('span');
spanPlay.classList.add('video-play', 'tgico-largeplay', 'btn-circle', 'position-center');
container.append(spanPlay);
spanTime.innerText = (doc.duration + '').toHHMMSS(false);
if(canAutoplay) {
spanTime.classList.add('tgico', 'can-autoplay');
} else {
const spanPlay = document.createElement('span');
spanPlay.classList.add('video-play', 'tgico-largeplay', 'btn-circle', 'position-center');
container.append(spanPlay);
}
} else {
span.innerText = 'GIF';
spanTime.innerText = 'GIF';
}
}
}
@ -132,7 +140,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -132,7 +140,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
let img: HTMLImageElement;
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);
}
@ -199,18 +207,18 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -199,18 +207,18 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
}, {once: true}); */
await promise;
if(middleware && !middleware()) {
return;
}
} else if(doc.supportsStreaming) {
preloader = new ProgressivePreloader(null, false, false, 'prepend');
preloader.attach(container, false, null);
video.addEventListener('canplay', () => {
video.addEventListener(isSafari ? 'timeupdate' : 'canplay', () => {
preloader.detach();
}, {once: true});
}
if(middleware && !middleware()) {
return;
}
//console.log('loaded doc:', doc, doc.url, container);
const deferred = deferredPromise<void>();
@ -224,7 +232,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -224,7 +232,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
/* if(!video.paused) {
video.pause();
} */
if(doc.type == 'gif' && group) {
if(doc.type != 'round' && group) {
animationIntersector.addAnimation(video, group);
}
@ -235,6 +243,12 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -235,6 +243,12 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
}, {once: true});
//}
if(doc.type == 'video') {
video.addEventListener('timeupdate', () => {
spanTime.innerText = (video.duration - video.currentTime + '').toHHMMSS(false);
});
}
video.addEventListener('error', (e) => {
deferred.resolve();
/* console.error('video error', e, video.src);
@ -253,15 +267,15 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -253,15 +267,15 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
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.loop = true;
//video.play();
video.autoplay = true;
} else if(doc.type == 'round') {
video.dataset.ckin = 'circle';
video.dataset.overlay = '1';
new VideoPlayer(video);
}
return deferred;

76
src/lib/mediaPlayer.ts

@ -318,15 +318,15 @@ export default class VideoPlayer { @@ -318,15 +318,15 @@ export default class VideoPlayer {
const html = this.buildControls();
player.insertAdjacentHTML('beforeend', html);
let updateInterval = 0;
let elapsed = 0;
let prevTime = 0;
let timeDuration: HTMLElement;
if(skin === 'default') {
const toggle = player.querySelectorAll('.toggle') as NodeListOf<HTMLElement>;
const fullScreenButton = player.querySelector('.fullscreen') as HTMLElement;
var timeElapsed = player.querySelector('#time-elapsed');
var timeDuration = player.querySelector('#time-duration') as HTMLElement;
const timeElapsed = player.querySelector('#time-elapsed');
timeDuration = player.querySelector('#time-duration') as HTMLElement;
timeDuration.innerHTML = String(video.duration | 0).toHHMMSS();
const volumeDiv = document.createElement('div');
@ -451,10 +451,6 @@ export default class VideoPlayer { @@ -451,10 +451,6 @@ export default class VideoPlayer {
/* video.addEventListener('play', () => {
}); */
video.addEventListener('pause', () => {
clearInterval(updateInterval);
});
video.addEventListener('dblclick', () => {
if(isTouchSupported) {
return;
@ -470,16 +466,20 @@ export default class VideoPlayer { @@ -470,16 +466,20 @@ export default class VideoPlayer {
'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange'.split(' ').forEach(eventName => {
player.addEventListener(eventName, this.onFullScreen, false);
});
video.addEventListener('timeupdate', () => {
timeElapsed.innerHTML = String(video.currentTime | 0).toHHMMSS();
});
} else if(skin === 'circle') {
const wrapper = document.createElement('div');
wrapper.classList.add('circle-time-left');
video.parentNode.insertBefore(wrapper, video);
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;
var circumference = 2 * Math.PI * radius;
var timeDuration = player.querySelector('.circle-time') as HTMLElement;
const circumference = 2 * Math.PI * radius;
timeDuration = player.querySelector('.circle-time') as HTMLElement;
const iconVolume = player.querySelector('.iconVolume') as HTMLDivElement;
circle.style.strokeDasharray = circumference + ' ' + circumference;
circle.style.strokeDashoffset = '' + circumference;
@ -505,6 +505,28 @@ export default class VideoPlayer { @@ -505,6 +505,28 @@ export default class VideoPlayer {
video.addEventListener('pause', () => {
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', () => {
@ -522,14 +544,6 @@ export default class VideoPlayer { @@ -522,14 +544,6 @@ export default class VideoPlayer {
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) {
@ -547,32 +561,6 @@ export default class VideoPlayer { @@ -547,32 +561,6 @@ export default class VideoPlayer {
//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() {
const skin = this.skin;
if(skin === 'default') {

23
src/scss/partials/_chatBubble.scss

@ -519,6 +519,10 @@ $bubble-margin: .25rem; @@ -519,6 +519,10 @@ $bubble-margin: .25rem;
display: none;
}
}
.preloader-container {
z-index: 1;
}
}
&:not(.sticker) {
@ -537,6 +541,12 @@ $bubble-margin: .25rem; @@ -537,6 +541,12 @@ $bubble-margin: .25rem;
height: 100%;
}
html.is-safari &:not(.round) {
img:not(.emoji), video {
border-radius: inherit;
}
}
&.is-album {
.attachment {
max-width: unquote('min(451px, 100%)');
@ -1000,7 +1010,7 @@ $bubble-margin: .25rem; @@ -1000,7 +1010,7 @@ $bubble-margin: .25rem;
}
}
span.video-time {
.video-time {
position: absolute;
top: 3px;
left: 3px;
@ -1014,9 +1024,18 @@ $bubble-margin: .25rem; @@ -1014,9 +1024,18 @@ $bubble-margin: .25rem;
align-items: center;
cursor: pointer;
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);
color: #fff;
text-align: center;

Loading…
Cancel
Save