Scene player presentation improvements (#5145)

* Show controls before video plays
* Allow interaction with controls while displaying error
* Source selector improvements

Don't auto-play next source if manually selected.
Don't remove errored sources

* Show errored sources in different style
This commit is contained in:
WithoutPants 2024-08-28 10:10:47 +10:00 committed by GitHub
parent c69d72b243
commit 294e2090d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 70 additions and 6 deletions

View File

@ -2,6 +2,7 @@ import videojs, { VideoJsPlayer } from "video.js";
export interface ISource extends videojs.Tech.SourceObject {
label?: string;
errored?: boolean;
}
class SourceMenuItem extends videojs.getComponent("MenuItem") {
@ -81,6 +82,22 @@ class SourceMenuButton extends videojs.getComponent("MenuButton") {
return this.items;
}
setSelectedSource(source: ISource) {
this.selectedSource = source;
if (this.items === undefined) return;
for (const item of this.items) {
item.selected(item.source === this.selectedSource);
}
}
markSourceErrored(source: ISource) {
const item = this.items.find((i) => i.source.src === source.src);
if (item === undefined) return;
item.addClass("vjs-source-menu-item-error");
}
}
class SourceSelectorPlugin extends videojs.getPlugin("plugin") {
@ -90,6 +107,9 @@ class SourceSelectorPlugin extends videojs.getPlugin("plugin") {
private cleanupTextTracks: HTMLTrackElement[] = [];
private manualTextTracks: HTMLTrackElement[] = [];
// don't auto play next source if user manually selected a source
private manuallySelected = false;
constructor(player: VideoJsPlayer) {
super(player);
@ -99,6 +119,8 @@ class SourceSelectorPlugin extends videojs.getPlugin("plugin") {
this.selectedIndex = this.sources.findIndex((src) => src === source);
if (this.selectedIndex === -1) return;
this.manuallySelected = true;
const loadSrc = this.sources[this.selectedIndex];
const currentTime = player.currentTime();
@ -154,14 +176,26 @@ class SourceSelectorPlugin extends videojs.getPlugin("plugin") {
const currentSource = player.currentSource() as ISource;
console.log(`Source '${currentSource.label}' is unsupported`);
if (this.sources.length > 1) {
if (this.selectedIndex === -1) return;
// mark current source as errored
currentSource.errored = true;
this.menu.markSourceErrored(currentSource);
this.sources.splice(this.selectedIndex, 1);
const newSource = this.sources[0];
// don't auto play next source if user manually selected a source
if (this.manuallySelected) {
return;
}
// TODO - make auto play next source configurable
// try the next source in the list
if (
this.selectedIndex !== -1 &&
this.selectedIndex + 1 < this.sources.length
) {
this.selectedIndex += 1;
const newSource = this.sources[this.selectedIndex];
console.log(`Trying next source in playlist: '${newSource.label}'`);
this.menu.setSources(this.sources);
this.selectedIndex = 0;
this.menu.setSelectedSource(newSource);
player.src(newSource);
player.load();
player.play();

View File

@ -39,6 +39,28 @@ $sceneTabWidth: 450px;
position: absolute;
width: 100%;
&:not(.vjs-has-started) .vjs-control-bar {
display: flex;
}
// show controls even when an error is displayed
/* stylelint-disable declaration-no-important */
&.vjs-error .vjs-control-bar {
display: flex !important;
}
/* stylelint-enable declaration-no-important */
// allow interaction with the controls when error is displayed
.vjs-error-display,
.vjs-error-display .vjs-modal-dialog-content {
position: static;
}
// hide spinner when error is displayed
&.vjs-error .vjs-loading-spinner {
display: none;
}
.vjs-button {
outline: none;
}
@ -197,6 +219,14 @@ $sceneTabWidth: 450px;
content: "\f110";
font-family: VideoJS;
}
.vjs-menu-item.vjs-source-menu-item-error:not(.vjs-selected) {
color: $text-muted;
}
.vjs-menu-item.vjs-source-menu-item-error {
font-style: italic;
}
}
.vjs-vr-selector {