Player mobile improvements (#3120)

* Add videojs-mobile-ui
* Prevent marker wrapping and fix alignment
* Fix marker update on delete
* Change hotkey modifier behaviour
* Update KeyboardShortcuts.md
This commit is contained in:
DingDongSoLong4
2022-11-23 06:55:24 +02:00
committed by GitHub
parent b175f1865f
commit 821587b166
12 changed files with 268 additions and 290 deletions

View File

@@ -7,15 +7,14 @@ import React, {
useState,
} from "react";
import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from "video.js";
import "videojs-mobile-ui";
import "videojs-seek-buttons";
import "videojs-landscape-fullscreen";
import "./live";
import "./PlaylistButtons";
import "./source-selector";
import "./persist-volume";
import "./markers";
import "./vtt-thumbnails";
import "./big-buttons";
import "./track-activity";
import cx from "classnames";
import {
@@ -36,6 +35,18 @@ import { VIDEO_PLAYER_ID } from "./util";
import { IUIConfig } from "src/core/config";
function handleHotkeys(player: VideoJsPlayer, event: videojs.KeyboardEvent) {
function seekStep(step: number) {
const time = player.currentTime() + step;
const duration = player.duration();
if (time < 0) {
player.currentTime(0);
} else if (time < duration) {
player.currentTime(time);
} else {
player.currentTime(duration);
}
}
function seekPercent(percent: number) {
const duration = player.duration();
const time = duration * percent;
@@ -50,6 +61,21 @@ function handleHotkeys(player: VideoJsPlayer, event: videojs.KeyboardEvent) {
player.currentTime(time);
}
let seekFactor = 10;
if (event.shiftKey) {
seekFactor = 5;
} else if (event.ctrlKey || event.altKey) {
seekFactor = 60;
}
switch (event.which) {
case 39: // right arrow
seekStep(seekFactor);
break;
case 37: // left arrow
seekStep(-seekFactor);
break;
}
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
return;
}
@@ -67,12 +93,6 @@ function handleHotkeys(player: VideoJsPlayer, event: videojs.KeyboardEvent) {
if (player.isFullscreen()) player.exitFullscreen();
else player.requestFullscreen();
break;
case 39: // right arrow
player.currentTime(Math.min(player.duration(), player.currentTime() + 5));
break;
case 37: // left arrow
player.currentTime(Math.max(0, player.currentTime() - 5));
break;
case 38: // up arrow
player.volume(player.volume() + 0.1);
break;
@@ -263,7 +283,6 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
markers: {},
sourceSelector: {},
persistVolume: {},
bigButtons: {},
seekButtons: {
forward: 10,
back: 10,
@@ -421,20 +440,21 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
interactiveClient.pause();
interactiveReady.current = false;
const alwaysStartFromBeginning =
uiConfig?.alwaysStartFromBeginning ?? false;
const isLandscape = file.height && file.width && file.width > file.height;
if (isLandscape) {
player.landscapeFullscreen({
fullscreen: {
enterOnRotate: true,
exitOnRotate: true,
alwaysInLandscapeMode: true,
iOS: false,
},
});
}
const mobileUiOptions = {
fullscreen: {
enterOnRotate: true,
exitOnRotate: true,
lockOnRotate: true,
lockToLandscapeOnEnter: isLandscape,
},
touchControls: {
seekSeconds: 10,
tapTimeout: 500,
disableOnEnd: false,
},
};
player.mobileUi(mobileUiOptions);
const { duration } = file;
const sourceSelector = player.sourceSelector();
@@ -455,15 +475,6 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
})
);
const markers = player.markers();
markers.clearMarkers();
for (const marker of scene.scene_markers) {
markers.addMarker({
title: getMarkerTitle(marker),
time: marker.seconds,
});
}
function getDefaultLanguageCode() {
let languageCode = window.navigator.language;
@@ -507,28 +518,25 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
}
}
if (scene.paths.screenshot) {
player.poster(scene.paths.screenshot);
} else {
player.poster("");
}
auto.current =
autoplay ||
(interfaceConfig?.autostartVideo ?? false) ||
_initialTimestamp > 0;
let startPositition = _initialTimestamp;
const alwaysStartFromBeginning =
uiConfig?.alwaysStartFromBeginning ?? false;
let startPosition = _initialTimestamp;
if (
!startPositition &&
!startPosition &&
!(alwaysStartFromBeginning || sessionInitialised) &&
file.duration > scene.resume_time!
) {
startPositition = scene.resume_time!;
startPosition = scene.resume_time!;
}
initialTimestamp.current = startPositition;
setTime(startPositition);
initialTimestamp.current = startPosition;
setTime(startPosition);
setSessionInitialised(true);
player.load();
@@ -556,6 +564,26 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
_initialTimestamp,
]);
useEffect(() => {
const player = playerRef.current;
if (!player || !scene) return;
const markers = player.markers();
markers.clearMarkers();
for (const marker of scene.scene_markers) {
markers.addMarker({
title: getMarkerTitle(marker),
time: marker.seconds,
});
}
if (scene.paths.screenshot) {
player.poster(scene.paths.screenshot);
} else {
player.poster("");
}
}, [scene]);
useEffect(() => {
const player = playerRef.current;
if (!player) return;