Volume controls for video
This commit is contained in:
parent
a0c2004c6d
commit
f87cfba0dc
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -36,7 +36,7 @@
|
|||
@media only screen and (max-width: 720px){.bubble .message.audio-message .audio{height:59px;padding-left:47px}}
|
||||
@media only screen and (max-width: 720px){.bubble .message.audio-message .audio-details{margin-top:-1px}}
|
||||
@media only screen and (max-width: 720px){.bubble .message.audio-message .audio-ico{margin-top:1px;margin-left:2px}}
|
||||
@media only screen and (max-width: 720px){.bubble .message.audio-message .media-progress{width:unset}}
|
||||
@media only screen and (max-width: 720px){.bubble .message.audio-message .progress-line{width:unset}}
|
||||
@media only screen and (max-width: 720px){.bubble .message.document-message .document{padding-left:44px}}
|
||||
@media only screen and (max-width: 720px){.bubble.is-in.is-reply.emoji-big .reply,.bubble.is-in.is-reply.sticker .reply{left:calc(100% + 1px)}}
|
||||
@media only screen and (max-width: 720px){.bubble.is-in{margin-right:auto}.bubble.is-out{margin-left:auto}}
|
||||
|
|
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
public/sw.js.gz
BIN
public/sw.js.gz
Binary file not shown.
|
@ -16,7 +16,7 @@ export function logger(prefix: string, level = LogLevels.log | LogLevels.warn |
|
|||
level = LogLevels.error;
|
||||
}
|
||||
|
||||
level = LogLevels.log | LogLevels.warn | LogLevels.error | LogLevels.debug
|
||||
//level = LogLevels.log | LogLevels.warn | LogLevels.error | LogLevels.debug
|
||||
|
||||
function Log(...args: any[]) {
|
||||
return level & LogLevels.log && console.log(dT(), '[' + prefix + ']:', ...args);
|
||||
|
@ -38,13 +38,13 @@ export function logger(prefix: string, level = LogLevels.log | LogLevels.warn |
|
|||
return level & LogLevels.log && console.trace(dT(), '[' + prefix + ']:', ...args);
|
||||
};
|
||||
|
||||
Log.debug = function(...args: any[]) {
|
||||
return level & LogLevels.debug && console.log(dT(), '[' + prefix + ']:', ...args);
|
||||
};
|
||||
|
||||
/* Log.debug = function(...args: any[]) {
|
||||
return level & LogLevels.debug && console.debug(dT(), '[' + prefix + ']:', ...args);
|
||||
return level & LogLevels.debug && console.log(dT(), '[' + prefix + ']:', ...args);
|
||||
}; */
|
||||
|
||||
Log.debug = function(...args: any[]) {
|
||||
return level & LogLevels.debug && console.debug(dT(), '[' + prefix + ']:', ...args);
|
||||
};
|
||||
|
||||
return Log;
|
||||
};
|
|
@ -1,9 +1,11 @@
|
|||
import { cancelEvent } from "./utils";
|
||||
|
||||
export class ProgressLine {
|
||||
public container: HTMLDivElement;
|
||||
protected filled: HTMLDivElement;
|
||||
protected seek: HTMLInputElement;
|
||||
|
||||
protected duration = 100;
|
||||
protected duration = 1;
|
||||
protected mousedown = false;
|
||||
|
||||
private events: Partial<{
|
||||
|
@ -13,22 +15,26 @@ export class ProgressLine {
|
|||
onScrub: (scrubTime: number) => void
|
||||
}> = {};
|
||||
|
||||
constructor() {
|
||||
constructor(initialValue = 0) {
|
||||
this.container = document.createElement('div');
|
||||
this.container.classList.add('media-progress');
|
||||
this.container.classList.add('progress-line');
|
||||
|
||||
this.filled = document.createElement('div');
|
||||
this.filled.classList.add('media-progress__filled');
|
||||
this.filled.classList.add('progress-line__filled');
|
||||
|
||||
const seek = this.seek = document.createElement('input');
|
||||
seek.classList.add('media-progress__seek');
|
||||
seek.value = '0';
|
||||
seek.classList.add('progress-line__seek');
|
||||
seek.value = '' + initialValue;
|
||||
seek.setAttribute('min', '0');
|
||||
seek.setAttribute('max', '0');
|
||||
//seek.setAttribute('max', '0');
|
||||
seek.type = 'range';
|
||||
seek.step = '0.1';
|
||||
seek.max = '' + (this.duration * 1000);
|
||||
|
||||
if(initialValue > 0) {
|
||||
this.setProgress(initialValue);
|
||||
}
|
||||
|
||||
//this.setListeners();
|
||||
|
||||
this.container.append(this.filled, seek);
|
||||
|
@ -45,28 +51,37 @@ export class ProgressLine {
|
|||
onMouseDown = (e: MouseEvent) => {
|
||||
this.scrub(e);
|
||||
this.mousedown = true;
|
||||
this.events?.onMouseDown(e);
|
||||
this.events?.onMouseDown && this.events.onMouseDown(e);
|
||||
};
|
||||
|
||||
onMouseUp = (e: MouseEvent) => {
|
||||
this.mousedown = false;
|
||||
this.events?.onMouseUp(e);
|
||||
this.events?.onMouseUp && this.events.onMouseUp(e);
|
||||
};
|
||||
|
||||
protected setListeners() {
|
||||
public setListeners() {
|
||||
this.container.addEventListener('mousemove', this.onMouseMove);
|
||||
this.container.addEventListener('mousedown', this.onMouseDown);
|
||||
this.container.addEventListener('mouseup', this.onMouseUp);
|
||||
}
|
||||
|
||||
protected scrub(e: MouseEvent) {
|
||||
const scrubTime = e.offsetX / this.container.offsetWidth * this.duration;
|
||||
public setProgress(scrubTime: number) {
|
||||
this.setFilled(scrubTime);
|
||||
this.seek.value = '' + (scrubTime * 1000);
|
||||
}
|
||||
|
||||
public setFilled(scrubTime: number) {
|
||||
let scaleX = scrubTime / this.duration;
|
||||
scaleX = Math.max(0, Math.min(1, scaleX));
|
||||
this.filled.style.transform = 'scaleX(' + scaleX + ')';
|
||||
}
|
||||
|
||||
//this.events?.onScrub(scrubTime);
|
||||
protected scrub(e: MouseEvent) {
|
||||
const scrubTime = e.offsetX / this.container.offsetWidth * this.duration;
|
||||
|
||||
this.setFilled(scrubTime);
|
||||
|
||||
this.events?.onScrub && this.events.onScrub(scrubTime);
|
||||
return scrubTime;
|
||||
}
|
||||
|
||||
|
@ -90,7 +105,7 @@ export class MediaProgressLine extends ProgressLine {
|
|||
|
||||
if(streamable) {
|
||||
this.filledLoad = document.createElement('div');
|
||||
this.filledLoad.classList.add('media-progress__filled', 'media-progress__loaded');
|
||||
this.filledLoad.classList.add('progress-line__filled', 'progress-line__loaded');
|
||||
this.container.prepend(this.filledLoad);
|
||||
//this.setLoadProgress();
|
||||
}
|
||||
|
@ -197,15 +212,13 @@ export class MediaProgressLine extends ProgressLine {
|
|||
}
|
||||
}
|
||||
|
||||
protected setProgress() {
|
||||
public setProgress() {
|
||||
const currentTime = this.media.currentTime;
|
||||
|
||||
const scaleX = (currentTime / this.duration);
|
||||
this.filled.style.transform = 'scaleX(' + scaleX + ')';
|
||||
this.seek.value = '' + currentTime * 1000;
|
||||
super.setProgress(currentTime);
|
||||
}
|
||||
|
||||
protected setListeners() {
|
||||
public setListeners() {
|
||||
super.setListeners();
|
||||
this.media.addEventListener('ended', this.onEnded);
|
||||
this.media.addEventListener('play', this.onPlay);
|
||||
|
@ -230,6 +243,7 @@ export class MediaProgressLine extends ProgressLine {
|
|||
}
|
||||
}
|
||||
|
||||
let lastVolume = 1, muted = !lastVolume;
|
||||
export default class VideoPlayer {
|
||||
public wrapper: HTMLDivElement;
|
||||
public progress: MediaProgressLine;
|
||||
|
@ -274,7 +288,66 @@ export default class VideoPlayer {
|
|||
var timeElapsed = player.querySelector('#time-elapsed');
|
||||
var timeDuration = player.querySelector('#time-duration') as HTMLElement;
|
||||
timeDuration.innerHTML = String(video.duration | 0).toHHMMSS();
|
||||
|
||||
|
||||
const volumeDiv = document.createElement('div');
|
||||
volumeDiv.classList.add('player-volume');
|
||||
|
||||
volumeDiv.innerHTML = `
|
||||
<svg class="player-volume__icon" focusable="false" viewBox="0 0 24 24" aria-hidden="true"></svg>
|
||||
`;
|
||||
const volumeSvg = volumeDiv.firstElementChild as SVGSVGElement;
|
||||
|
||||
volumeSvg.addEventListener('click', (e) => {
|
||||
cancelEvent(e);
|
||||
|
||||
if(!lastVolume) {
|
||||
muted = true;
|
||||
lastVolume = 1;
|
||||
}
|
||||
|
||||
const realVolume = !muted ? 0 : lastVolume;
|
||||
setVolume(realVolume);
|
||||
volumeProgress.setProgress(realVolume);
|
||||
muted = !muted;
|
||||
});
|
||||
|
||||
const setVolume = (volume: number) => {
|
||||
let d: string;
|
||||
if(volume > .5) {
|
||||
d = `M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z`;
|
||||
} else if(!volume) {
|
||||
d = `M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z`;
|
||||
} else if(volume > 0 && volume < .25) {
|
||||
d = `M7 9v6h4l5 5V4l-5 5H7z`;
|
||||
} else {
|
||||
d = `M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z`;
|
||||
}
|
||||
|
||||
try {
|
||||
volumeSvg.innerHTML = `<path d="${d}"></path>`;
|
||||
} catch(err) {}
|
||||
|
||||
video.volume = volume;
|
||||
};
|
||||
|
||||
const fakeVolume = muted ? 0 : lastVolume;
|
||||
video.volume = fakeVolume;
|
||||
setVolume(fakeVolume);
|
||||
|
||||
const volumeProgress = new ProgressLine(muted ? 0 : fakeVolume);
|
||||
volumeProgress.setListeners();
|
||||
volumeProgress.setHandlers({
|
||||
onScrub: currentTime => {
|
||||
const value = Math.max(Math.min(currentTime, 1), 0);
|
||||
console.log('scrub', currentTime, value);
|
||||
setVolume(lastVolume = value);
|
||||
}
|
||||
});
|
||||
volumeDiv.append(volumeProgress.container);
|
||||
|
||||
const leftControls = player.querySelector('.left-controls');
|
||||
leftControls.insertBefore(volumeDiv, timeElapsed.parentElement);
|
||||
|
||||
Array.from(toggle).forEach((button) => {
|
||||
return button.addEventListener('click', () => {
|
||||
this.togglePlay();
|
||||
|
@ -402,9 +475,8 @@ export default class VideoPlayer {
|
|||
|
||||
private buildControls() {
|
||||
const skin = this.skin;
|
||||
const html: string[] = [];
|
||||
if(skin === 'default') {
|
||||
html.push(`
|
||||
return `
|
||||
<button class="${skin}__button--big toggle tgico-largeplay" title="Toggle Play"></button>
|
||||
<div class="${skin}__gradient-bottom ckin__controls"></div>
|
||||
<div class="${skin}__controls ckin__controls">
|
||||
|
@ -421,14 +493,14 @@ export default class VideoPlayer {
|
|||
<button class="${skin}__button fullscreen tgico-fullscreen" title="Full Screen"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
</div>`;
|
||||
} else if(skin === 'circle') {
|
||||
html.push('<svg class="progress-ring" width="200px" height="200px">',
|
||||
'<circle class="progress-ring__circle" stroke="white" stroke-opacity="0.3" stroke-width="3.5" cx="100" cy="100" r="93" fill="transparent" transform="rotate(-90, 100, 100)"/>',
|
||||
'</svg>');
|
||||
return `
|
||||
<svg class="progress-ring" width="200px" height="200px">
|
||||
<circle class="progress-ring__circle" stroke="white" stroke-opacity="0.3" stroke-width="3.5" cx="100" cy="100" r="93" fill="transparent" transform="rotate(-90, 100, 100)"/>
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
|
||||
return html.join('');
|
||||
}
|
||||
|
||||
public updateButton(toggle: NodeListOf<HTMLElement>) {
|
||||
|
|
|
@ -754,7 +754,7 @@ $bubble-margin: .25rem;
|
|||
}
|
||||
}
|
||||
|
||||
.media-progress {
|
||||
.progress-line {
|
||||
/* width: calc(100% + 50px); */
|
||||
width: 191px;
|
||||
margin: 9px 0 9px;
|
||||
|
@ -1202,7 +1202,7 @@ $bubble-margin: .25rem;
|
|||
}
|
||||
|
||||
.message.audio-message {
|
||||
.media-progress {
|
||||
.progress-line {
|
||||
&__seek {
|
||||
background: rgba(193, 207, 220, 0.39);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,27 @@
|
|||
.ckin {
|
||||
&__player {
|
||||
letter-spacing: 0.02em;
|
||||
|
||||
&.ckin__fullscreen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 10000000;
|
||||
background: #000;
|
||||
border-radius: 0 !important;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
|
||||
video {
|
||||
max-height: none;
|
||||
max-width: none;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__overlay {
|
||||
|
@ -16,27 +37,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.ckin__player.ckin__fullscreen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 10000000;
|
||||
background: #000;
|
||||
border-radius: 0 !important;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
|
||||
video {
|
||||
max-height: none;
|
||||
max-width: none;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.default {
|
||||
border: 0 solid rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
|
||||
|
@ -120,73 +120,105 @@
|
|||
direction: ltr;
|
||||
border-radius: 0 0 5px 5px;
|
||||
z-index: 6;
|
||||
}
|
||||
}
|
||||
|
||||
.default__gradient-bottom {
|
||||
height: 49px;
|
||||
// padding-top: 49px;
|
||||
padding-top: 93px;
|
||||
bottom: 0;
|
||||
z-index: 2;
|
||||
background-position: bottom;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
background-repeat: repeat-x;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADGCAYAAAAT+OqFAAAAdklEQVQoz42QQQ7AIAgEF/T/D+kbq/RWAlnQyyazA4aoAB4FsBSA/bFjuF1EOL7VbrIrBuusmrt4ZZORfb6ehbWdnRHEIiITaEUKa5EJqUakRSaEYBJSCY2dEstQY7AuxahwXFrvZmWl2rh4JZ07z9dLtesfNj5q0FU3A5ObbwAAAABJRU5ErkJggg==);
|
||||
transition: all .3s;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.default.is-playing .default__gradient-bottom {
|
||||
transform: translateY(50px);
|
||||
}
|
||||
|
||||
html.no-touch .default.is-playing:hover .default__gradient-bottom {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
|
||||
.default.is-playing:before {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translate(-50%, -50%) scale(1.3);
|
||||
}
|
||||
|
||||
.default.is-playing .default__button--big {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.default.is-playing .default__controls {
|
||||
transform: translateY(52px);
|
||||
}
|
||||
|
||||
html.no-touch .default.is-playing:hover .default__controls {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.default {
|
||||
.media-progress {
|
||||
margin: 0 16px;
|
||||
height: 5px;
|
||||
transition: height 0.3s;
|
||||
background: rgba(255, 255, 255, 0.38);
|
||||
border-radius: 4px;
|
||||
overflow: visible;
|
||||
|
||||
&__filled {
|
||||
background: #63a2e3;
|
||||
transform-origin: left;
|
||||
border-radius: 4px;
|
||||
.progress-line {
|
||||
margin: 0 16px;
|
||||
height: 5px;
|
||||
transform: scaleX(0);
|
||||
background: rgba(255, 255, 255, 0.38);
|
||||
border-radius: 4px;
|
||||
overflow: visible;
|
||||
|
||||
&__filled {
|
||||
background: #63a2e3;
|
||||
transform-origin: left;
|
||||
border-radius: 4px;
|
||||
height: 5px;
|
||||
transform: scaleX(0);
|
||||
}
|
||||
|
||||
&__loaded {
|
||||
background: rgba(255, 255, 255, 0.38);
|
||||
left: 11px;
|
||||
width: calc(100% - 11px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__gradient-bottom {
|
||||
height: 49px;
|
||||
// padding-top: 49px;
|
||||
padding-top: 93px;
|
||||
bottom: 0;
|
||||
z-index: 2;
|
||||
background-position: bottom;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
background-repeat: repeat-x;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADGCAYAAAAT+OqFAAAAdklEQVQoz42QQQ7AIAgEF/T/D+kbq/RWAlnQyyazA4aoAB4FsBSA/bFjuF1EOL7VbrIrBuusmrt4ZZORfb6ehbWdnRHEIiITaEUKa5EJqUakRSaEYBJSCY2dEstQY7AuxahwXFrvZmWl2rh4JZ07z9dLtesfNj5q0FU3A5ObbwAAAABJRU5ErkJggg==);
|
||||
transition: all .3s;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.is-playing {
|
||||
.default__gradient-bottom {
|
||||
transform: translateY(50px);
|
||||
}
|
||||
|
||||
&__loaded {
|
||||
background: rgba(255, 255, 255, 0.38);
|
||||
left: 11px;
|
||||
width: calc(100% - 11px);
|
||||
html.no-touch &:hover {
|
||||
.default__gradient-bottom {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
|
||||
.default__controls {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
&:before {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translate(-50%, -50%) scale(1.3);
|
||||
}
|
||||
|
||||
.default__button--big {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.default__controls {
|
||||
transform: translateY(52px);
|
||||
}
|
||||
}
|
||||
|
||||
.player-volume {
|
||||
margin: -3px 12px 0 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&__icon {
|
||||
fill: #fff;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.progress-line {
|
||||
margin: 0;
|
||||
width: 50px;
|
||||
|
||||
&__filled {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-thumb {
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
border-radius: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,7 +232,7 @@ video::-webkit-media-controls-enclosure {
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
.media-progress {
|
||||
.progress-line {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
|
|
|
@ -466,7 +466,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.media-progress {
|
||||
.progress-line {
|
||||
margin: 11px 0 8px;
|
||||
|
||||
&__filled {
|
||||
|
|
Loading…
Reference in New Issue
Block a user