mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user