1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-11-09 18:25:58 +01:00

Rework custom video controls.

Move custom video controls into its own function.  Remove some
DOM traversals, avoid querySelector.  Remove dead code.
This commit is contained in:
Juliusz Chroboczek 2020-11-28 01:53:29 +01:00
parent 907a712d6a
commit a2e322edcb
2 changed files with 106 additions and 109 deletions

View file

@ -209,21 +209,13 @@
<div id="videocontrols-template" class="invisible">
<div class="video-controls vc-overlay">
<span class="volume" title="Volume">
<i class="fas fa-volume-up" data-type="bt-volume" aria-hidden="true"></i>
<i class="fas fa-volume-up" aria-hidden="true"></i>
</span>
<span class="pip" title="Picture In Picture">
<i class="fas fa-clone" data-type="bt-pip" aria-hidden="true"></i>
<i class="fas fa-clone" aria-hidden="true"></i>
</span>
<span class="fullscreen" title="Fullscreen">
<i class="fas fa-expand-alt" data-type="bt-fullscreen" aria-hidden="true"></i>
</span>
</div>
</div>
<div id="top-videocontrols-template" class="invisible">
<div class="top-video-controls">
<span class="expand invisible" title="Maximize">
<i class="fas fa-external-link" data-type="bt-expand" aria-hidden="true"></i>
<i class="fas fa-expand-alt" aria-hidden="true"></i>
</span>
</div>
</div>

View file

@ -1002,19 +1002,17 @@ function muteLocalTracks(mute) {
}
/**
* setMedia adds a new media element corresponding to stream c.
*
* @param {Stream} c
* @param {boolean} isUp
* - indicates whether the stream goes in the up direction
* @param {HTMLVideoElement} [video]
* - the video element to add. If null, a new element with custom
* controls will be created.
*/
function setMedia(c, isUp, video) {
let peersdiv = document.getElementById('peers');
let local_media;
for(let id in serverConnection.up) {
if (id === c.id) {
local_media = serverConnection.up[id];
}
}
let div = document.getElementById('peer-' + c.id);
if(!div) {
@ -1026,21 +1024,28 @@ function setMedia(c, isUp, video) {
let media = /** @type {HTMLVideoElement} */
(document.getElementById('media-' + c.id));
if(!media) {
if(media) {
if(video) {
throw new Error("Duplicate video");
}
} else {
if(video) {
media = video;
} else {
media = document.createElement('video');
media.controls = false;
if(isUp)
media.muted = true;
media.srcObject = c.stream;
}
media.classList.add('media');
media.autoplay = true;
/** @ts-ignore */
media.playsinline = true;
media.id = 'media-' + c.id;
div.appendChild(media);
if(!video)
addCustomControls(media, div, c);
}
let label = document.getElementById('label-' + c.id);
@ -1051,129 +1056,129 @@ function setMedia(c, isUp, video) {
div.appendChild(label);
}
if(!video) {
let template = document.getElementById('videocontrols-template')
.firstElementChild;
let top_template = document.getElementById('top-videocontrols-template')
.firstElementChild;
let top_controls = document.getElementById('topcontrols-' + c.id);
if(template && !top_controls) {
top_controls = /** @type{HTMLElement} */(top_template.cloneNode(true));
top_controls.id = 'topcontrols-' + c.id;
div.appendChild(top_controls);
}
let controls = document.getElementById('controls-' + c.id);
if(template && !controls) {
controls = /** @type{HTMLElement} */(template.cloneNode(true));
controls.id = 'controls-' + c.id;
div.appendChild(controls);
let volume = controls.querySelector(".fa-volume-up");
if(media.muted) {
if (volume) {
volume.classList.remove("fa-volume-up");
volume.classList.add("fa-volume-off");
}
}
if (local_media && local_media.kind === "local")
volume.parentElement.remove();
}
media.srcObject = c.stream;
}
setLabel(c);
setMediaStatus(c);
showVideo();
resizePeers();
registerControlEvent(div.id);
}
/**
* @param {HTMLVideoElement} video
* @param {Element} elt
*/
async function videoPIP(video) {
/** @ts-ignore */
if (video.requestPictureInPicture) {
/** @ts-ignore */
await video.requestPictureInPicture();
function cloneHTMLElement(elt) {
if(!(elt instanceof HTMLElement))
throw new Error('Unexpected element type');
return /** @type{HTMLElement} */(elt.cloneNode(true));
}
/**
* @param {HTMLVideoElement} media
* @param {HTMLElement} container
* @param {Stream} c
*/
function addCustomControls(media, container, c) {
media.controls = false;
let controls = document.getElementById('controls-' + c.id);
if(controls) {
console.warn('Attempted to add duplicate controls');
return;
}
let template =
document.getElementById('videocontrols-template').firstElementChild;
controls = cloneHTMLElement(template);
controls.id = 'controls-' + c.id;
let volume = getVideoButton(controls, 'volume');
if(c.kind === 'local') {
volume.remove();
} else {
displayWarning("Video PIP Mode not supported!");
setVolumeButton(
/** @type{HTMLElement} */(volume.firstElementChild),
media.muted,
);
}
container.appendChild(controls);
registerControlHandlers(media, container);
}
/**
* @param {HTMLElement} container
* @param {string} name
*/
function getVideoButton(container, name) {
return /** @type {HTMLElement} */(container.getElementsByClassName(name)[0]);
}
/**
* @param {HTMLElement} button
* @param {boolean} muted
*/
function setVolumeButton(button, muted) {
if(!muted) {
button.classList.remove("fa-volume-off");
button.classList.add("fa-volume-up");
} else {
button.classList.remove("fa-volume-up");
button.classList.add("fa-volume-off");
}
}
/**
* @param {HTMLElement} target
* @param {HTMLVideoElement} media
* @param {HTMLElement} container
*/
function getParentVideo(target) {
// target is the <i> element, parent the div <div><span><i/></span></div>
let control = target.parentElement.parentElement;
let id = control.id.split('-')[1];
let media = /** @type {HTMLVideoElement} */
(document.getElementById('media-' + id));
if (!media) {
displayError("Cannot find media!");
}
return media;
}
/**
* @param {string} peerid
*/
function registerControlEvent(peerid) {
let peer = document.getElementById(peerid);
//Add event listener when a video component is added to the DOM
let volume = /** @type {HTMLElement} */(peer.querySelector("span.volume"));
function registerControlHandlers(media, container) {
let volume = getVideoButton(container, 'volume');
if (volume) {
volume.onclick = function(event) {
event.preventDefault();
let volume = /** @type{HTMLElement} */(event.target);
let video = getParentVideo(volume);
if(volume.className.indexOf("fa-volume-off") !== -1) {
volume.classList.remove("fa-volume-off");
volume.classList.add("fa-volume-up");
video.muted = false;
} else {
volume.classList.remove("fa-volume-up");
volume.classList.add("fa-volume-off");
// mute video sound
video.muted = true;
}
media.muted = !media.muted;
setVolumeButton(
/** @type{HTMLElement} */(event.target),
media.muted,
);
};
}
let pip = /** @type {HTMLElement} */(peer.querySelector("span.pip"));
let pip = getVideoButton(container, 'pip');
if(pip) {
/** @ts-ignore */
if(HTMLVideoElement.prototype.requestPictureInPicture) {
pip.onclick = function(event) {
event.preventDefault();
let pip = /** @type{HTMLElement} */(event.target);
let video = getParentVideo(pip);
videoPIP(video);
pip.onclick = function(e) {
e.preventDefault();
/** @ts-ignore */
if(media.requestPictureInPicture) {
/** @ts-ignore */
media.requestPictureInPicture();
} else {
displayWarning('Picture in Picture not supported.');
}
};
} else {
pip.style.display = 'none';
}
}
let fs = /** @type {HTMLElement} */(peer.querySelector("span.fullscreen"));
let fs = getVideoButton(container, 'fullscreen');
if(fs) {
fs.onclick = function(event) {
event.preventDefault();
let fs = /** @type {HTMLElement} */(event.target);
let video = getParentVideo(fs);
if(video.requestFullscreen) {
video.requestFullscreen();
} else {
displayWarning("Video Fullscreen not supported!");
}
};
if(HTMLVideoElement.prototype.requestFullscreen) {
fs.onclick = function(e) {
e.preventDefault();
if(media.requestFullscreen) {
media.requestFullscreen();
} else {
displayWarning('Full screen not supported!');
}
};
} else {
fs.style.display = 'none';
}
}
}
/**
* @param {string} id
*/