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:
@@ -74,8 +74,8 @@
|
|||||||
"thehandy": "^1.0.3",
|
"thehandy": "^1.0.3",
|
||||||
"universal-cookie": "^4.0.4",
|
"universal-cookie": "^4.0.4",
|
||||||
"video.js": "^7.20.3",
|
"video.js": "^7.20.3",
|
||||||
"videojs-landscape-fullscreen": "^11.33.0",
|
"videojs-mobile-ui": "^0.8.0",
|
||||||
"videojs-seek-buttons": "^2.2.0",
|
"videojs-seek-buttons": "^3.0.1",
|
||||||
"videojs-vtt.js": "^0.15.4",
|
"videojs-vtt.js": "^0.15.4",
|
||||||
"vite": "^2.9.13",
|
"vite": "^2.9.13",
|
||||||
"vite-plugin-compression": "^0.3.5",
|
"vite-plugin-compression": "^0.3.5",
|
||||||
@@ -103,7 +103,8 @@
|
|||||||
"@types/react-router-dom": "5.1.7",
|
"@types/react-router-dom": "5.1.7",
|
||||||
"@types/react-router-hash-link": "^1.2.1",
|
"@types/react-router-hash-link": "^1.2.1",
|
||||||
"@types/react-slick": "^0.23.8",
|
"@types/react-slick": "^0.23.8",
|
||||||
"@types/video.js": "^7.3.28",
|
"@types/video.js": "^7.3.49",
|
||||||
|
"@types/videojs-mobile-ui": "^0.5.0",
|
||||||
"@types/videojs-seek-buttons": "^2.1.0",
|
"@types/videojs-seek-buttons": "^2.1.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||||
"@typescript-eslint/parser": "^4.33.0",
|
"@typescript-eslint/parser": "^4.33.0",
|
||||||
|
|||||||
47
ui/v2.5/src/@types/landscape-fullscreen.d.ts
vendored
47
ui/v2.5/src/@types/landscape-fullscreen.d.ts
vendored
@@ -1,47 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
|
||||||
|
|
||||||
declare module "videojs-landscape-fullscreen" {
|
|
||||||
import videojs from "video.js";
|
|
||||||
|
|
||||||
function landscapeFullscreen(options?: {
|
|
||||||
fullscreen: landscapeFullscreen.Options;
|
|
||||||
}): void;
|
|
||||||
|
|
||||||
namespace landscapeFullscreen {
|
|
||||||
const VERSION: typeof videojs.VERSION;
|
|
||||||
|
|
||||||
interface Options {
|
|
||||||
/**
|
|
||||||
* Enter fullscreen mode on rotating the device to landscape.
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
enterOnRotate?: boolean;
|
|
||||||
/**
|
|
||||||
* Exit fullscreen mode on rotating the device to portrait.
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
exitOnRotate?: boolean;
|
|
||||||
/**
|
|
||||||
* Always enter fullscreen in landscape mode even when device is in portrait mode (works on Chromium, Firefox, and IE >= 11).
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
alwaysInLandscapeMode?: boolean;
|
|
||||||
/**
|
|
||||||
* Whether to use fake fullscreen on iOS (needed for displaying player controls instead of system controls).
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
iOS?: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export = landscapeFullscreen;
|
|
||||||
|
|
||||||
declare module "video.js" {
|
|
||||||
interface VideoJsPlayer {
|
|
||||||
landscapeFullscreen: typeof landscapeFullscreen;
|
|
||||||
}
|
|
||||||
interface VideoJsPlayerPluginOptions {
|
|
||||||
landscapeFullscreen?: { fullscreen: landscapeFullscreen.Options };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,15 +7,14 @@ import React, {
|
|||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from "video.js";
|
import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from "video.js";
|
||||||
|
import "videojs-mobile-ui";
|
||||||
import "videojs-seek-buttons";
|
import "videojs-seek-buttons";
|
||||||
import "videojs-landscape-fullscreen";
|
|
||||||
import "./live";
|
import "./live";
|
||||||
import "./PlaylistButtons";
|
import "./PlaylistButtons";
|
||||||
import "./source-selector";
|
import "./source-selector";
|
||||||
import "./persist-volume";
|
import "./persist-volume";
|
||||||
import "./markers";
|
import "./markers";
|
||||||
import "./vtt-thumbnails";
|
import "./vtt-thumbnails";
|
||||||
import "./big-buttons";
|
|
||||||
import "./track-activity";
|
import "./track-activity";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import {
|
import {
|
||||||
@@ -36,6 +35,18 @@ import { VIDEO_PLAYER_ID } from "./util";
|
|||||||
import { IUIConfig } from "src/core/config";
|
import { IUIConfig } from "src/core/config";
|
||||||
|
|
||||||
function handleHotkeys(player: VideoJsPlayer, event: videojs.KeyboardEvent) {
|
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) {
|
function seekPercent(percent: number) {
|
||||||
const duration = player.duration();
|
const duration = player.duration();
|
||||||
const time = duration * percent;
|
const time = duration * percent;
|
||||||
@@ -50,6 +61,21 @@ function handleHotkeys(player: VideoJsPlayer, event: videojs.KeyboardEvent) {
|
|||||||
player.currentTime(time);
|
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) {
|
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -67,12 +93,6 @@ function handleHotkeys(player: VideoJsPlayer, event: videojs.KeyboardEvent) {
|
|||||||
if (player.isFullscreen()) player.exitFullscreen();
|
if (player.isFullscreen()) player.exitFullscreen();
|
||||||
else player.requestFullscreen();
|
else player.requestFullscreen();
|
||||||
break;
|
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
|
case 38: // up arrow
|
||||||
player.volume(player.volume() + 0.1);
|
player.volume(player.volume() + 0.1);
|
||||||
break;
|
break;
|
||||||
@@ -263,7 +283,6 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
|
|||||||
markers: {},
|
markers: {},
|
||||||
sourceSelector: {},
|
sourceSelector: {},
|
||||||
persistVolume: {},
|
persistVolume: {},
|
||||||
bigButtons: {},
|
|
||||||
seekButtons: {
|
seekButtons: {
|
||||||
forward: 10,
|
forward: 10,
|
||||||
back: 10,
|
back: 10,
|
||||||
@@ -421,20 +440,21 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
|
|||||||
interactiveClient.pause();
|
interactiveClient.pause();
|
||||||
interactiveReady.current = false;
|
interactiveReady.current = false;
|
||||||
|
|
||||||
const alwaysStartFromBeginning =
|
|
||||||
uiConfig?.alwaysStartFromBeginning ?? false;
|
|
||||||
const isLandscape = file.height && file.width && file.width > file.height;
|
const isLandscape = file.height && file.width && file.width > file.height;
|
||||||
|
const mobileUiOptions = {
|
||||||
if (isLandscape) {
|
|
||||||
player.landscapeFullscreen({
|
|
||||||
fullscreen: {
|
fullscreen: {
|
||||||
enterOnRotate: true,
|
enterOnRotate: true,
|
||||||
exitOnRotate: true,
|
exitOnRotate: true,
|
||||||
alwaysInLandscapeMode: true,
|
lockOnRotate: true,
|
||||||
iOS: false,
|
lockToLandscapeOnEnter: isLandscape,
|
||||||
},
|
},
|
||||||
});
|
touchControls: {
|
||||||
}
|
seekSeconds: 10,
|
||||||
|
tapTimeout: 500,
|
||||||
|
disableOnEnd: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
player.mobileUi(mobileUiOptions);
|
||||||
|
|
||||||
const { duration } = file;
|
const { duration } = file;
|
||||||
const sourceSelector = player.sourceSelector();
|
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() {
|
function getDefaultLanguageCode() {
|
||||||
let languageCode = window.navigator.language;
|
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 =
|
auto.current =
|
||||||
autoplay ||
|
autoplay ||
|
||||||
(interfaceConfig?.autostartVideo ?? false) ||
|
(interfaceConfig?.autostartVideo ?? false) ||
|
||||||
_initialTimestamp > 0;
|
_initialTimestamp > 0;
|
||||||
|
|
||||||
let startPositition = _initialTimestamp;
|
const alwaysStartFromBeginning =
|
||||||
|
uiConfig?.alwaysStartFromBeginning ?? false;
|
||||||
|
|
||||||
|
let startPosition = _initialTimestamp;
|
||||||
if (
|
if (
|
||||||
!startPositition &&
|
!startPosition &&
|
||||||
!(alwaysStartFromBeginning || sessionInitialised) &&
|
!(alwaysStartFromBeginning || sessionInitialised) &&
|
||||||
file.duration > scene.resume_time!
|
file.duration > scene.resume_time!
|
||||||
) {
|
) {
|
||||||
startPositition = scene.resume_time!;
|
startPosition = scene.resume_time!;
|
||||||
}
|
}
|
||||||
|
|
||||||
initialTimestamp.current = startPositition;
|
initialTimestamp.current = startPosition;
|
||||||
setTime(startPositition);
|
setTime(startPosition);
|
||||||
setSessionInitialised(true);
|
setSessionInitialised(true);
|
||||||
|
|
||||||
player.load();
|
player.load();
|
||||||
@@ -556,6 +564,26 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
|
|||||||
_initialTimestamp,
|
_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(() => {
|
useEffect(() => {
|
||||||
const player = playerRef.current;
|
const player = playerRef.current;
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
|
|||||||
@@ -211,6 +211,8 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = ({
|
|||||||
|
|
||||||
mouseDown.current = false;
|
mouseDown.current = false;
|
||||||
|
|
||||||
|
contentEl.current!.classList.remove("dragging");
|
||||||
|
|
||||||
let newPosition = position.current;
|
let newPosition = position.current;
|
||||||
const midpointOffset = slider.clientWidth / 2;
|
const midpointOffset = slider.clientWidth / 2;
|
||||||
const delta = Math.abs(event.clientX - startMouseEvent.current!.clientX);
|
const delta = Math.abs(event.clientX - startMouseEvent.current!.clientX);
|
||||||
@@ -256,6 +258,8 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = ({
|
|||||||
onScroll();
|
onScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contentEl.current!.classList.add("dragging");
|
||||||
|
|
||||||
// negative dragging right (past), positive left (future)
|
// negative dragging right (past), positive left (future)
|
||||||
const delta = event.clientX - lastMouseEvent.current!.clientX;
|
const delta = event.clientX - lastMouseEvent.current!.clientX;
|
||||||
|
|
||||||
@@ -338,7 +342,6 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div className="scrubber-wrapper">
|
<div className="scrubber-wrapper">
|
||||||
<Button
|
<Button
|
||||||
variant="link"
|
|
||||||
className="scrubber-button"
|
className="scrubber-button"
|
||||||
id="scrubber-back"
|
id="scrubber-back"
|
||||||
onClick={() => goBack()}
|
onClick={() => goBack()}
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
import videojs, { VideoJsPlayer } from "video.js";
|
|
||||||
|
|
||||||
// prettier-ignore
|
|
||||||
const BigPlayButton = videojs.getComponent("BigPlayButton") as unknown as typeof videojs.BigPlayButton;
|
|
||||||
|
|
||||||
class BigPlayPauseButton extends BigPlayButton {
|
|
||||||
handleClick(event: videojs.EventTarget.Event) {
|
|
||||||
if (this.player().paused()) {
|
|
||||||
super.handleClick(event);
|
|
||||||
} else {
|
|
||||||
this.player().pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildCSSClass() {
|
|
||||||
return "vjs-control vjs-button vjs-big-play-pause-button";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BigButtonGroup extends videojs.getComponent("Component") {
|
|
||||||
constructor(player: VideoJsPlayer) {
|
|
||||||
super(player);
|
|
||||||
|
|
||||||
this.addChild("seekButton", {
|
|
||||||
direction: "back",
|
|
||||||
seconds: 10,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.addChild("BigPlayPauseButton");
|
|
||||||
|
|
||||||
this.addChild("seekButton", {
|
|
||||||
direction: "forward",
|
|
||||||
seconds: 10,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
createEl() {
|
|
||||||
return super.createEl("div", {
|
|
||||||
className: "vjs-big-button-group",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BigButtonsPlugin extends videojs.getPlugin("plugin") {
|
|
||||||
constructor(player: VideoJsPlayer) {
|
|
||||||
super(player);
|
|
||||||
|
|
||||||
player.ready(() => {
|
|
||||||
player.addChild("BigButtonGroup");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register the plugin with video.js.
|
|
||||||
videojs.registerComponent("BigButtonGroup", BigButtonGroup);
|
|
||||||
videojs.registerComponent("BigPlayPauseButton", BigPlayPauseButton);
|
|
||||||
videojs.registerPlugin("bigButtons", BigButtonsPlugin);
|
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
|
||||||
declare module "video.js" {
|
|
||||||
interface VideoJsPlayer {
|
|
||||||
bigButtons: () => BigButtonsPlugin;
|
|
||||||
}
|
|
||||||
interface VideoJsPlayerPluginOptions {
|
|
||||||
bigButtons?: {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BigButtonsPlugin;
|
|
||||||
@@ -48,7 +48,13 @@ class MarkersPlugin extends videojs.getPlugin("plugin") {
|
|||||||
const marker = this.markers[i];
|
const marker = this.markers[i];
|
||||||
const markerDiv = this.markerDivs[i];
|
const markerDiv = this.markerDivs[i];
|
||||||
|
|
||||||
markerDiv.style.left = `${(marker.time / duration) * 100}%`;
|
if (duration) {
|
||||||
|
// marker is 6px wide - adjust by 3px to align to center not left side
|
||||||
|
markerDiv.style.left = `calc(${
|
||||||
|
(marker.time / duration) * 100
|
||||||
|
}% - 3px)`;
|
||||||
|
markerDiv.style.visibility = "visible";
|
||||||
|
}
|
||||||
if (seekBar) seekBar.appendChild(markerDiv);
|
if (seekBar) seekBar.appendChild(markerDiv);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -58,6 +64,7 @@ class MarkersPlugin extends videojs.getPlugin("plugin") {
|
|||||||
if (!this.markerTooltip) return;
|
if (!this.markerTooltip) return;
|
||||||
|
|
||||||
this.markerTooltip.innerText = title;
|
this.markerTooltip.innerText = title;
|
||||||
|
this.markerTooltip.style.right = `${-this.markerTooltip.clientWidth / 2}px`;
|
||||||
this.markerTooltip.style.visibility = "visible";
|
this.markerTooltip.style.visibility = "visible";
|
||||||
|
|
||||||
// hide default tooltip
|
// hide default tooltip
|
||||||
@@ -76,7 +83,11 @@ class MarkersPlugin extends videojs.getPlugin("plugin") {
|
|||||||
markerDiv.className = "vjs-marker";
|
markerDiv.className = "vjs-marker";
|
||||||
|
|
||||||
const duration = this.player.duration();
|
const duration = this.player.duration();
|
||||||
markerDiv.style.position = `${(marker.time / duration) * 100}%`;
|
if (duration) {
|
||||||
|
// marker is 6px wide - adjust by 3px to align to center not left side
|
||||||
|
markerDiv.style.left = `calc(${(marker.time / duration) * 100}% - 3px)`;
|
||||||
|
markerDiv.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
|
||||||
// bind click event to seek to marker time
|
// bind click event to seek to marker time
|
||||||
markerDiv.addEventListener("click", () =>
|
markerDiv.addEventListener("click", () =>
|
||||||
@@ -122,7 +133,7 @@ class MarkersPlugin extends videojs.getPlugin("plugin") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearMarkers() {
|
clearMarkers() {
|
||||||
this.removeMarkers(this.markers);
|
this.removeMarkers([...this.markers]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
@import "video.js/dist/video-js.css";
|
||||||
|
@import "videojs-mobile-ui/dist/videojs-mobile-ui.css";
|
||||||
|
@import "videojs-seek-buttons/dist/videojs-seek-buttons.css";
|
||||||
|
|
||||||
$scrubberHeight: 120px;
|
$scrubberHeight: 120px;
|
||||||
$menuHeight: 4rem;
|
$menuHeight: 4rem;
|
||||||
$sceneTabWidth: 450px;
|
$sceneTabWidth: 450px;
|
||||||
@@ -52,6 +56,10 @@ $sceneTabWidth: 450px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vjs-touch-overlay .vjs-play-control {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.vjs-control-bar {
|
.vjs-control-bar {
|
||||||
background: none;
|
background: none;
|
||||||
|
|
||||||
@@ -67,13 +75,16 @@ $sceneTabWidth: 450px;
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
content: "";
|
content: "";
|
||||||
height: 10rem;
|
height: 10rem;
|
||||||
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vjs-time-control {
|
.vjs-time-control {
|
||||||
display: block;
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@@ -92,17 +103,22 @@ $sceneTabWidth: 450px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.vjs-progress-control {
|
.vjs-progress-control {
|
||||||
bottom: 3rem;
|
bottom: 2.5em;
|
||||||
margin-left: 1%;
|
height: 3em;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 98%;
|
width: 100%;
|
||||||
|
|
||||||
.vjs-play-progress .vjs-time-tooltip,
|
.vjs-progress-holder {
|
||||||
&:hover .vjs-play-progress .vjs-time-tooltip {
|
margin: 0 1rem;
|
||||||
visibility: hidden;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* stylelint-disable declaration-no-important */
|
||||||
|
.vjs-play-progress .vjs-time-tooltip {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
/* stylelint-enable declaration-no-important */
|
||||||
|
|
||||||
.vjs-volume-control {
|
.vjs-volume-control {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
@@ -117,7 +133,7 @@ $sceneTabWidth: 450px;
|
|||||||
.vjs-vtt-thumbnail-display {
|
.vjs-vtt-thumbnail-display {
|
||||||
border: 2px solid white;
|
border: 2px solid white;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
bottom: 90px;
|
bottom: 6em;
|
||||||
box-shadow: 0 0 7px rgba(0, 0, 0, 0.6);
|
box-shadow: 0 0 7px rgba(0, 0, 0, 0.6);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@@ -155,7 +171,7 @@ $sceneTabWidth: 450px;
|
|||||||
|
|
||||||
.vjs-source-selector {
|
.vjs-source-selector {
|
||||||
.vjs-menu li {
|
.vjs-menu li {
|
||||||
font-size: 12px;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vjs-button > .vjs-icon-placeholder::before {
|
.vjs-button > .vjs-icon-placeholder::before {
|
||||||
@@ -171,36 +187,31 @@ $sceneTabWidth: 450px;
|
|||||||
left: 0;
|
left: 0;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
-webkit-transition: opacity 0.2s ease;
|
|
||||||
-moz-transition: opacity 0.2s ease;
|
|
||||||
transition: opacity 0.2s ease;
|
transition: opacity 0.2s ease;
|
||||||
|
visibility: hidden;
|
||||||
width: 6px;
|
width: 6px;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
-webkit-transform: scale(1.3, 1.3);
|
|
||||||
-moz-transform: scale(1.3, 1.3);
|
|
||||||
-o-transform: scale(1.3, 1.3);
|
|
||||||
-ms-transform: scale(1.3, 1.3);
|
|
||||||
transform: scale(1.3, 1.3);
|
transform: scale(1.3, 1.3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vjs-marker-tooltip {
|
.vjs-marker-tooltip {
|
||||||
|
background-color: #fff;
|
||||||
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
border-radius: 0.3em;
|
border-radius: 0.3em;
|
||||||
color: white;
|
color: #000;
|
||||||
display: block;
|
|
||||||
float: right;
|
float: right;
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
font-size: 10px;
|
font-size: 0.6em;
|
||||||
height: 50px;
|
|
||||||
padding: 6px 8px 8px 8px;
|
padding: 6px 8px 8px 8px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -80px;
|
top: -3.4em;
|
||||||
top: -5.4em;
|
visibility: hidden;
|
||||||
width: 160px;
|
white-space: nowrap;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,9 +255,8 @@ $sceneTabWidth: 450px;
|
|||||||
content: "\f103";
|
content: "\f103";
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide the regular play/pause button on touch screens
|
.vjs-vtt-thumbnail-display {
|
||||||
.vjs-play-control {
|
bottom: 2.8em;
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide the regular seek buttons on touch screens
|
// hide the regular seek buttons on touch screens
|
||||||
@@ -259,10 +269,19 @@ $sceneTabWidth: 450px;
|
|||||||
// make controls a little more compact on smaller screens
|
// make controls a little more compact on smaller screens
|
||||||
@media (max-width: 576px) {
|
@media (max-width: 576px) {
|
||||||
.vjs-control-bar {
|
.vjs-control-bar {
|
||||||
.vjs-control:not(.vjs-progress-control) {
|
.vjs-control {
|
||||||
width: 2.5em;
|
width: 2.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vjs-progress-control {
|
||||||
|
height: 2em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-playback-rate {
|
||||||
|
width: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
.vjs-button > .vjs-icon-placeholder::before,
|
.vjs-button > .vjs-icon-placeholder::before,
|
||||||
.vjs-skip-button::before {
|
.vjs-skip-button::before {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
@@ -270,9 +289,27 @@ $sceneTabWidth: 450px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vjs-menu-button-popup .vjs-menu {
|
||||||
|
width: 8em;
|
||||||
|
|
||||||
|
.vjs-menu-content {
|
||||||
|
max-height: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-playback-rate .vjs-playback-rate-value {
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 2.97;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-source-selector {
|
||||||
|
.vjs-menu li {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.vjs-time-control {
|
.vjs-time-control {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 4em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.vjs-big-button-group .vjs-button {
|
.vjs-big-button-group .vjs-button {
|
||||||
@@ -283,10 +320,6 @@ $sceneTabWidth: 450px;
|
|||||||
.vjs-current-time {
|
.vjs-current-time {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vjs-vtt-thumbnail-display {
|
|
||||||
bottom: 40px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,73 +334,8 @@ $sceneTabWidth: 450px;
|
|||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1199px) {
|
|
||||||
.scene-tabs {
|
|
||||||
padding-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-player-container {
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
.scene-tabs {
|
|
||||||
flex: 0 0 $sceneTabWidth;
|
|
||||||
max-width: $sceneTabWidth;
|
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
&.collapsed {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-content {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-height: 15rem;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-divider {
|
|
||||||
flex: 0 0 15px;
|
|
||||||
max-width: 15px;
|
|
||||||
|
|
||||||
button {
|
|
||||||
background-color: transparent;
|
|
||||||
border: 0;
|
|
||||||
color: $link-color;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 10px;
|
|
||||||
font-weight: 800;
|
|
||||||
height: 100%;
|
|
||||||
line-height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&:active:not(:hover),
|
|
||||||
&:focus:not(:hover) {
|
|
||||||
background-color: transparent;
|
|
||||||
border: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-player-container {
|
|
||||||
flex: 0 0 calc(100% - #{$sceneTabWidth} - 15px);
|
|
||||||
max-width: calc(100% - #{$sceneTabWidth} - 15px);
|
|
||||||
padding-left: 0;
|
|
||||||
|
|
||||||
&.expanded {
|
|
||||||
flex: 0 0 calc(100% - 15px);
|
|
||||||
max-width: calc(100% - 15px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.scrubber-wrapper {
|
.scrubber-wrapper {
|
||||||
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -387,26 +355,26 @@ $sceneTabWidth: 450px;
|
|||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
color: $link-color;
|
color: $link-color;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 20px;
|
font-size: 1.3rem;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: $scrubberHeight;
|
line-height: $scrubberHeight;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 1.5%;
|
width: 1.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrubber-content {
|
.scrubber-content {
|
||||||
cursor: grab;
|
cursor: pointer;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
flex-grow: 1;
|
||||||
height: $scrubberHeight;
|
height: $scrubberHeight;
|
||||||
margin: 0 0.5%;
|
margin: 0 7px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
position: relative;
|
position: relative;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
width: 96%;
|
|
||||||
|
|
||||||
&.dragging {
|
&.dragging {
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
@@ -492,7 +460,6 @@ $sceneTabWidth: 450px;
|
|||||||
|
|
||||||
.scrubber-item {
|
.scrubber-item {
|
||||||
color: white;
|
color: white;
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -506,3 +473,74 @@ $sceneTabWidth: 450px;
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1199px) {
|
||||||
|
.scene-tabs {
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene-player-container {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrubber-wrapper {
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
.scene-tabs {
|
||||||
|
flex: 0 0 $sceneTabWidth;
|
||||||
|
max-width: $sceneTabWidth;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
&.collapsed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 15rem;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene-divider {
|
||||||
|
flex: 0 0 15px;
|
||||||
|
max-width: 15px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0;
|
||||||
|
color: $link-color;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 800;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:active:not(:hover),
|
||||||
|
&:focus:not(:hover) {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene-player-container {
|
||||||
|
flex: 0 0 calc(100% - #{$sceneTabWidth} - 15px);
|
||||||
|
max-width: calc(100% - #{$sceneTabWidth} - 15px);
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
flex: 0 0 calc(100% - 15px);
|
||||||
|
max-width: calc(100% - 15px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,7 +68,13 @@ const typePolicies: TypePolicies = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Scene: {
|
||||||
|
fields: {
|
||||||
|
scene_markers: {
|
||||||
|
merge: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
Tag: {
|
Tag: {
|
||||||
fields: {
|
fields: {
|
||||||
parents: {
|
parents: {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
* Added tag description filter criterion. ([#3011](https://github.com/stashapp/stash/pull/3011))
|
* Added tag description filter criterion. ([#3011](https://github.com/stashapp/stash/pull/3011))
|
||||||
|
|
||||||
### 🎨 Improvements
|
### 🎨 Improvements
|
||||||
|
* Jump back/forward buttons on mobile have been replaced with double-tap gestures on mobile. ([#3120](https://github.com/stashapp/stash/pull/3120))
|
||||||
|
* Added shift- and ctrl-keybinds for seeking for shorter and longer intervals, respectively. ([#3120](https://github.com/stashapp/stash/pull/3120))
|
||||||
* Added Estonian and Russian Language translations. Added in-progress Languages for Persian, Ukrainian, Bengali, Thai, Romainian, Hungarian, and Czech.([#3024] (https://github.com/stashapp/stash/pull/3024))
|
* Added Estonian and Russian Language translations. Added in-progress Languages for Persian, Ukrainian, Bengali, Thai, Romainian, Hungarian, and Czech.([#3024] (https://github.com/stashapp/stash/pull/3024))
|
||||||
* Also show imperial units for performer height and weight. ([#3097](https://github.com/stashapp/stash/pull/3097))
|
* Also show imperial units for performer height and weight. ([#3097](https://github.com/stashapp/stash/pull/3097))
|
||||||
* Limit number of items in selector drop-downs to 200. ([#3062](https://github.com/stashapp/stash/pull/3062))
|
* Limit number of items in selector drop-downs to 200. ([#3062](https://github.com/stashapp/stash/pull/3062))
|
||||||
|
|||||||
@@ -64,6 +64,12 @@
|
|||||||
| `p n` | Play next scene in queue |
|
| `p n` | Play next scene in queue |
|
||||||
| `p p` | Play previous scene in queue |
|
| `p p` | Play previous scene in queue |
|
||||||
| `p r` | Play random scene in queue |
|
| `p r` | Play random scene in queue |
|
||||||
|
| `←` | Seek backwards by 10 seconds |
|
||||||
|
| `→` | Seek forwards by 10 seconds |
|
||||||
|
| `Shift + ←` | Seek backwards by 5 seconds |
|
||||||
|
| `Shift + →` | Seek forwards by 5 seconds |
|
||||||
|
| `Ctrl/Alt + ←` | Seek backwards by 1 minute |
|
||||||
|
| `Ctrl/Alt + →` | Seek forwards by 1 minute |
|
||||||
| `{1-9}` | Seek to 10-90% duration |
|
| `{1-9}` | Seek to 10-90% duration |
|
||||||
| `[` | Scrub backwards 10% duration |
|
| `[` | Scrub backwards 10% duration |
|
||||||
| `]` | Scrub forwards 10% duration |
|
| `]` | Scrub forwards 10% duration |
|
||||||
|
|||||||
@@ -26,8 +26,6 @@
|
|||||||
@import "src/components/Dialogs/IdentifyDialog/styles.scss";
|
@import "src/components/Dialogs/IdentifyDialog/styles.scss";
|
||||||
@import "src/components/Dialogs/styles.scss";
|
@import "src/components/Dialogs/styles.scss";
|
||||||
@import "../node_modules/flag-icon-css/css/flag-icon.min.css";
|
@import "../node_modules/flag-icon-css/css/flag-icon.min.css";
|
||||||
@import "video.js/dist/video-js.css";
|
|
||||||
@import "videojs-seek-buttons/dist/videojs-seek-buttons.css";
|
|
||||||
|
|
||||||
/* stylelint-disable */
|
/* stylelint-disable */
|
||||||
#root {
|
#root {
|
||||||
|
|||||||
@@ -1576,10 +1576,17 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz"
|
resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz"
|
||||||
integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
|
integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
|
||||||
|
|
||||||
"@types/video.js@*", "@types/video.js@^7.3.28":
|
"@types/video.js@*", "@types/video.js@^7.3.49":
|
||||||
version "7.3.28"
|
version "7.3.49"
|
||||||
resolved "https://registry.yarnpkg.com/@types/video.js/-/video.js-7.3.28.tgz#9acb8c46db3984d556ee7321483ef834bf0a43a2"
|
resolved "https://registry.yarnpkg.com/@types/video.js/-/video.js-7.3.49.tgz#33fbc421a02827c90935afbf7dcaac77170b6cda"
|
||||||
integrity sha512-vUxgGAQN+tAOx6OVu8wiSKGfvXJXvX++B5xKJTRpWfPHOV8y1VcJxqhIMb9nLfhIz0Pw3R69pWq2DzlOoxOn8Q==
|
integrity sha512-GtBMH+rm7yyw5DAK7ycQeEd35x/EYoLK/49op+CqDDoNUm9XJEVOfb+EARKKe4TwP5jkaikjWqf5RFjmw8yHoQ==
|
||||||
|
|
||||||
|
"@types/videojs-mobile-ui@^0.5.0":
|
||||||
|
version "0.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/videojs-mobile-ui/-/videojs-mobile-ui-0.5.0.tgz#66934b140fd437fda361986f8e7e87b01dc39138"
|
||||||
|
integrity sha512-wqeapTB35qpLfERxvL5mZGoexf5bA2TreDpFgc3zyCdr7Acf86VItvo9oTclFeUc11wOo7W7/4ueZZAEYmlTaA==
|
||||||
|
dependencies:
|
||||||
|
"@types/video.js" "*"
|
||||||
|
|
||||||
"@types/videojs-seek-buttons@^2.1.0":
|
"@types/videojs-seek-buttons@^2.1.0":
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
@@ -6673,16 +6680,11 @@ requires-port@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||||
|
|
||||||
resize-observer-polyfill@^1.5.0:
|
resize-observer-polyfill@^1.5.0, resize-observer-polyfill@^1.5.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz"
|
resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz"
|
||||||
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
||||||
|
|
||||||
resize-observer-polyfill@^1.5.1:
|
|
||||||
version "1.5.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
|
||||||
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
|
||||||
|
|
||||||
resolve-from@5.0.0, resolve-from@^5.0.0:
|
resolve-from@5.0.0, resolve-from@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz"
|
resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz"
|
||||||
@@ -7910,20 +7912,19 @@ videojs-font@3.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-3.2.0.tgz#212c9d3f4e4ec3fa7345167d64316add35e92232"
|
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-3.2.0.tgz#212c9d3f4e4ec3fa7345167d64316add35e92232"
|
||||||
integrity sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==
|
integrity sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==
|
||||||
|
|
||||||
videojs-landscape-fullscreen@^11.33.0:
|
videojs-mobile-ui@^0.8.0:
|
||||||
version "11.33.0"
|
version "0.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/videojs-landscape-fullscreen/-/videojs-landscape-fullscreen-11.33.0.tgz#4033100b3a97399c994426e825662860dfc232e0"
|
resolved "https://registry.yarnpkg.com/videojs-mobile-ui/-/videojs-mobile-ui-0.8.0.tgz#40a1c6f9302071b9bbe95937c934114600916ac5"
|
||||||
integrity sha512-Eex5ovlvIipHHif9LEhVL63zxxmOEQQi6Bt1P+EaA0QpjJAPF+CocWfhMItfGF1GcFQeP1ZFGCPTGw60n7vyUg==
|
integrity sha512-Jd+u/ctjUkbZlT1cAA0umTu0LQwSZSFG+02cJxShuwq27B6rfrRALETK/gsuTc7U27lB9fbwcF7HBMaNxW62nA==
|
||||||
dependencies:
|
dependencies:
|
||||||
global "^4.4.0"
|
global "^4.4.0"
|
||||||
|
|
||||||
videojs-seek-buttons@^2.2.0:
|
videojs-seek-buttons@^3.0.1:
|
||||||
version "2.2.0"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/videojs-seek-buttons/-/videojs-seek-buttons-2.2.0.tgz#50b8da1178a5718ee5a7649fbb90a64a518103f7"
|
resolved "https://registry.yarnpkg.com/videojs-seek-buttons/-/videojs-seek-buttons-3.0.1.tgz#cc2adc23a6372e8aa6c2e9fd0fe7e7831a46747f"
|
||||||
integrity sha512-yjCA6ntq+8fRKgZi/H6QJlghQWgA1x9oSRl6wfLODAcujhynDXetwMgRKGgl4NlV5af2bKY6erNtJ0kOBko/nQ==
|
integrity sha512-scVWOqCMqHajlbwYZIzJ5nBYkDXTAhEpWjfcdCu8ykksA1barrKnEKdQvS84TtDWOx6UXDD/e/x0acYEZCDMEQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
global "^4.4.0"
|
global "^4.4.0"
|
||||||
video.js "^6 || ^7"
|
|
||||||
|
|
||||||
videojs-vtt.js@^0.15.4:
|
videojs-vtt.js@^0.15.4:
|
||||||
version "0.15.4"
|
version "0.15.4"
|
||||||
|
|||||||
Reference in New Issue
Block a user