mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-01-11 22:40:31 +00:00
Merge branch 'development' of https://github.com/Stremio/stremio-web into feat/player-mute-shortcut-2
This commit is contained in:
commit
fc2d906a42
14 changed files with 161 additions and 169 deletions
|
|
@ -41,7 +41,7 @@
|
||||||
"react-i18next": "^15.1.3",
|
"react-i18next": "^15.1.3",
|
||||||
"react-is": "18.3.1",
|
"react-is": "18.3.1",
|
||||||
"spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6",
|
"spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6",
|
||||||
"stremio-translations": "github:Stremio/stremio-translations#01aaa201e419782b26b9f2cbe4430795021426e5",
|
"stremio-translations": "github:Stremio/stremio-translations#0e7fbd8522148f5727ac6adee3b2eb96132c10ac",
|
||||||
"url": "0.11.4",
|
"url": "0.11.4",
|
||||||
"use-long-press": "^3.2.0"
|
"use-long-press": "^3.2.0"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,8 @@ importers:
|
||||||
specifier: github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6
|
specifier: github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6
|
||||||
version: https://codeload.github.com/Stremio/spatial-navigation/tar.gz/64871b1422466f5f45d24ebc8bbd315b2ebab6a6
|
version: https://codeload.github.com/Stremio/spatial-navigation/tar.gz/64871b1422466f5f45d24ebc8bbd315b2ebab6a6
|
||||||
stremio-translations:
|
stremio-translations:
|
||||||
specifier: github:Stremio/stremio-translations#01aaa201e419782b26b9f2cbe4430795021426e5
|
specifier: github:Stremio/stremio-translations#0e7fbd8522148f5727ac6adee3b2eb96132c10ac
|
||||||
version: https://codeload.github.com/Stremio/stremio-translations/tar.gz/01aaa201e419782b26b9f2cbe4430795021426e5
|
version: https://codeload.github.com/Stremio/stremio-translations/tar.gz/0e7fbd8522148f5727ac6adee3b2eb96132c10ac
|
||||||
url:
|
url:
|
||||||
specifier: 0.11.4
|
specifier: 0.11.4
|
||||||
version: 0.11.4
|
version: 0.11.4
|
||||||
|
|
@ -4527,9 +4527,9 @@ packages:
|
||||||
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/01aaa201e419782b26b9f2cbe4430795021426e5:
|
stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/0e7fbd8522148f5727ac6adee3b2eb96132c10ac:
|
||||||
resolution: {tarball: https://codeload.github.com/Stremio/stremio-translations/tar.gz/01aaa201e419782b26b9f2cbe4430795021426e5}
|
resolution: {tarball: https://codeload.github.com/Stremio/stremio-translations/tar.gz/0e7fbd8522148f5727ac6adee3b2eb96132c10ac}
|
||||||
version: 1.44.13
|
version: 1.44.14
|
||||||
|
|
||||||
string-length@4.0.2:
|
string-length@4.0.2:
|
||||||
resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==}
|
resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==}
|
||||||
|
|
@ -10283,7 +10283,7 @@ snapshots:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
internal-slot: 1.1.0
|
internal-slot: 1.1.0
|
||||||
|
|
||||||
stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/01aaa201e419782b26b9f2cbe4430795021426e5: {}
|
stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/0e7fbd8522148f5727ac6adee3b2eb96132c10ac: {}
|
||||||
|
|
||||||
string-length@4.0.2:
|
string-length@4.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
import React, { createContext, useCallback, useContext, useEffect } from 'react';
|
import React, { createContext, useCallback, useContext, useEffect, useRef } from 'react';
|
||||||
import shortcuts from './shortcuts.json';
|
import shortcuts from './shortcuts.json';
|
||||||
|
|
||||||
const SHORTCUTS = shortcuts.map(({ shortcuts }) => shortcuts).flat();
|
const SHORTCUTS = shortcuts.map(({ shortcuts }) => shortcuts).flat();
|
||||||
|
|
||||||
export type ShortcutName = string;
|
export type ShortcutName = string;
|
||||||
export type ShortcutListener = () => void;
|
export type ShortcutListener = (combo: number) => void;
|
||||||
|
|
||||||
interface ShortcutsContext {
|
interface ShortcutsContext {
|
||||||
grouped: ShortcutGroup[],
|
grouped: ShortcutGroup[],
|
||||||
|
on: (name: ShortcutName, listener: ShortcutListener) => void,
|
||||||
|
off: (name: ShortcutName, listener: ShortcutListener) => void,
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShortcutsContext = createContext<ShortcutsContext>({} as ShortcutsContext);
|
const ShortcutsContext = createContext<ShortcutsContext>({} as ShortcutsContext);
|
||||||
|
|
@ -18,27 +20,38 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const ShortcutsProvider = ({ children, onShortcut }: Props) => {
|
const ShortcutsProvider = ({ children, onShortcut }: Props) => {
|
||||||
const onKeyDown = useCallback(({ ctrlKey, shiftKey, key }: KeyboardEvent) => {
|
const listeners = useRef<Map<ShortcutName, Set<ShortcutListener>>>(new Map());
|
||||||
|
|
||||||
|
const onKeyDown = useCallback(({ ctrlKey, shiftKey, code, key }: KeyboardEvent) => {
|
||||||
SHORTCUTS.forEach(({ name, combos }) => combos.forEach((keys) => {
|
SHORTCUTS.forEach(({ name, combos }) => combos.forEach((keys) => {
|
||||||
const modifers = (keys.includes('Ctrl') ? ctrlKey : true)
|
const modifers = (keys.includes('Ctrl') ? ctrlKey : true)
|
||||||
&& (keys.includes('Shift') ? shiftKey : true);
|
&& (keys.includes('Shift') ? shiftKey : true);
|
||||||
|
|
||||||
if (modifers && keys.includes(key.toUpperCase())) {
|
if (modifers && (keys.includes(code) || keys.includes(key.toUpperCase()))) {
|
||||||
|
const combo = combos.indexOf(keys);
|
||||||
|
listeners.current.get(name)?.forEach((listener) => listener(combo));
|
||||||
|
|
||||||
onShortcut(name as ShortcutName);
|
onShortcut(name as ShortcutName);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}, [onShortcut]);
|
}, [onShortcut]);
|
||||||
|
|
||||||
|
const on = (name: ShortcutName, listener: ShortcutListener) => {
|
||||||
|
!listeners.current.has(name) && listeners.current.set(name, new Set());
|
||||||
|
listeners.current.get(name)!.add(listener);
|
||||||
|
};
|
||||||
|
|
||||||
|
const off = (name: ShortcutName, listener: ShortcutListener) => {
|
||||||
|
listeners.current.get(name)?.delete(listener);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.addEventListener('keydown', onKeyDown);
|
document.addEventListener('keydown', onKeyDown);
|
||||||
|
return () => document.removeEventListener('keydown', onKeyDown);
|
||||||
return () => {
|
|
||||||
document.removeEventListener('keydown', onKeyDown);
|
|
||||||
};
|
|
||||||
}, [onKeyDown]);
|
}, [onKeyDown]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ShortcutsContext.Provider value={{ grouped: shortcuts }}>
|
<ShortcutsContext.Provider value={{ grouped: shortcuts, on, off }}>
|
||||||
{children}
|
{children}
|
||||||
</ShortcutsContext.Provider>
|
</ShortcutsContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
@ -50,5 +63,5 @@ const useShortcuts = () => {
|
||||||
|
|
||||||
export {
|
export {
|
||||||
ShortcutsProvider,
|
ShortcutsProvider,
|
||||||
useShortcuts
|
useShortcuts,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
import { ShortcutsProvider, useShortcuts } from './Shortcuts';
|
import { ShortcutsProvider, useShortcuts } from './Shortcuts';
|
||||||
|
import onShortcut from './onShortcut';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
ShortcutsProvider,
|
ShortcutsProvider,
|
||||||
useShortcuts,
|
useShortcuts,
|
||||||
|
onShortcut,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
15
src/common/Shortcuts/onShortcut.ts
Normal file
15
src/common/Shortcuts/onShortcut.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { DependencyList, useCallback, useEffect } from 'react';
|
||||||
|
import { ShortcutListener, ShortcutName, useShortcuts } from './Shortcuts';
|
||||||
|
|
||||||
|
const onShortcut = (name: ShortcutName, listener: ShortcutListener, deps: DependencyList) => {
|
||||||
|
const shortcuts = useShortcuts();
|
||||||
|
|
||||||
|
const listenerCallback = useCallback(listener, deps);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
shortcuts.on(name, listenerCallback);
|
||||||
|
return () => shortcuts.off(name, listenerCallback);
|
||||||
|
}, [listenerCallback]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default onShortcut;
|
||||||
|
|
@ -88,6 +88,16 @@
|
||||||
"name": "infoMenu",
|
"name": "infoMenu",
|
||||||
"label": "SETTINGS_SHORTCUT_MENU_INFO",
|
"label": "SETTINGS_SHORTCUT_MENU_INFO",
|
||||||
"combos": [["I"]]
|
"combos": [["I"]]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "speedMenu",
|
||||||
|
"label": "SETTINGS_SHORTCUT_MENU_PLAYBACK_SPEED",
|
||||||
|
"combos": [["R"]]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "statisticsMenu",
|
||||||
|
"label": "SETTINGS_SHORTCUT_MENU_STATISTICS",
|
||||||
|
"combos": [["D"]]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
&.error {
|
&.error {
|
||||||
.icon-container {
|
.icon-container {
|
||||||
.icon {
|
.icon {
|
||||||
color: var(--color-trakt);
|
color: var(--danger-accent-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ const { FileDropProvider, onFileDrop } = require('./FileDrop');
|
||||||
const { PlatformProvider, usePlatform } = require('./Platform');
|
const { PlatformProvider, usePlatform } = require('./Platform');
|
||||||
const { ToastProvider, useToast } = require('./Toast');
|
const { ToastProvider, useToast } = require('./Toast');
|
||||||
const { TooltipProvider, Tooltip } = require('./Tooltips');
|
const { TooltipProvider, Tooltip } = require('./Tooltips');
|
||||||
const { ShortcutsProvider, useShortcuts } = require('./Shortcuts');
|
const { ShortcutsProvider, useShortcuts, onShortcut } = require('./Shortcuts');
|
||||||
const comparatorWithPriorities = require('./comparatorWithPriorities');
|
const comparatorWithPriorities = require('./comparatorWithPriorities');
|
||||||
const CONSTANTS = require('./CONSTANTS');
|
const CONSTANTS = require('./CONSTANTS');
|
||||||
const { withCoreSuspender, useCoreSuspender } = require('./CoreSuspender');
|
const { withCoreSuspender, useCoreSuspender } = require('./CoreSuspender');
|
||||||
|
|
@ -38,6 +38,7 @@ module.exports = {
|
||||||
usePlatform,
|
usePlatform,
|
||||||
ShortcutsProvider,
|
ShortcutsProvider,
|
||||||
useShortcuts,
|
useShortcuts,
|
||||||
|
onShortcut,
|
||||||
ToastProvider,
|
ToastProvider,
|
||||||
useToast,
|
useToast,
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.error {
|
&.error {
|
||||||
border-color: var(--color-trakt);
|
border-color: var(--danger-accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.checked {
|
&.checked {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
border-radius: 2rem;
|
border-radius: 2rem;
|
||||||
height: @height;
|
height: @height;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
|
||||||
.icon-container {
|
.icon-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.error {
|
&.error {
|
||||||
border-color: var(--color-trakt);
|
border-color: var(--danger-accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ const langs = require('langs');
|
||||||
const { useTranslation } = require('react-i18next');
|
const { useTranslation } = require('react-i18next');
|
||||||
const { useRouteFocused } = require('stremio-router');
|
const { useRouteFocused } = require('stremio-router');
|
||||||
const { useServices } = require('stremio/services');
|
const { useServices } = require('stremio/services');
|
||||||
const { onFileDrop, useSettings, useProfile, useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender, CONSTANTS, useShell, usePlatform } = require('stremio/common');
|
const { onFileDrop, useSettings, useProfile, useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender, CONSTANTS, useShell, usePlatform, onShortcut } = require('stremio/common');
|
||||||
const { HorizontalNavBar, Transition, ContextMenu } = require('stremio/components');
|
const { HorizontalNavBar, Transition, ContextMenu } = require('stremio/components');
|
||||||
const BufferingLoader = require('./BufferingLoader');
|
const BufferingLoader = require('./BufferingLoader');
|
||||||
const VolumeChangeIndicator = require('./VolumeChangeIndicator');
|
const VolumeChangeIndicator = require('./VolumeChangeIndicator');
|
||||||
|
|
@ -597,121 +597,99 @@ const Player = ({ urlParams, queryParams }) => {
|
||||||
navigator.mediaSession.setActionHandler('nexttrack', nexVideoCallback);
|
navigator.mediaSession.setActionHandler('nexttrack', nexVideoCallback);
|
||||||
}, [player.nextVideo, onPlayRequested, onPauseRequested, onNextVideoRequested]);
|
}, [player.nextVideo, onPlayRequested, onPauseRequested, onNextVideoRequested]);
|
||||||
|
|
||||||
React.useLayoutEffect(() => {
|
onShortcut('playPause', () => {
|
||||||
const onKeyDown = (event) => {
|
if (!menusOpen && !nextVideoPopupOpen && video.state.paused !== null) {
|
||||||
switch (event.code) {
|
if (video.state.paused) {
|
||||||
case 'Space': {
|
onPlayRequested();
|
||||||
if (!menusOpen && !nextVideoPopupOpen && video.state.paused !== null) {
|
setSeeking(false);
|
||||||
if (video.state.paused) {
|
} else {
|
||||||
onPlayRequested();
|
onPauseRequested();
|
||||||
setSeeking(false);
|
|
||||||
} else {
|
|
||||||
onPauseRequested();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'ArrowRight': {
|
|
||||||
if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) {
|
|
||||||
const seekDuration = event.shiftKey ? settings.seekShortTimeDuration : settings.seekTimeDuration;
|
|
||||||
setSeeking(true);
|
|
||||||
onSeekRequested(video.state.time + seekDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'ArrowLeft': {
|
|
||||||
if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) {
|
|
||||||
const seekDuration = event.shiftKey ? settings.seekShortTimeDuration : settings.seekTimeDuration;
|
|
||||||
setSeeking(true);
|
|
||||||
onSeekRequested(video.state.time - seekDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'ArrowUp': {
|
|
||||||
if (!menusOpen && !nextVideoPopupOpen && video.state.volume !== null) {
|
|
||||||
onVolumeChangeRequested(Math.min(video.state.volume + 5, 200));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'ArrowDown': {
|
|
||||||
if (!menusOpen && !nextVideoPopupOpen && video.state.volume !== null) {
|
|
||||||
onVolumeChangeRequested(Math.max(video.state.volume - 5, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'KeyS': {
|
|
||||||
closeMenus();
|
|
||||||
if ((Array.isArray(video.state.subtitlesTracks) && video.state.subtitlesTracks.length > 0) ||
|
|
||||||
(Array.isArray(video.state.extraSubtitlesTracks) && video.state.extraSubtitlesTracks.length > 0)) {
|
|
||||||
toggleSubtitlesMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'KeyA': {
|
|
||||||
closeMenus();
|
|
||||||
if (Array.isArray(video.state.audioTracks) && video.state.audioTracks.length > 0) {
|
|
||||||
toggleAudioMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'KeyI': {
|
|
||||||
closeMenus();
|
|
||||||
if (player.metaItem !== null && player.metaItem.type === 'Ready') {
|
|
||||||
toggleSideDrawer();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'KeyR': {
|
|
||||||
closeMenus();
|
|
||||||
if (video.state.playbackSpeed !== null) {
|
|
||||||
toggleSpeedMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'KeyD': {
|
|
||||||
closeMenus();
|
|
||||||
if (streamingServer.statistics !== null && streamingServer.statistics.type !== 'Err' && player.selected && typeof player.selected.stream.infoHash === 'string' && typeof player.selected.stream.fileIdx === 'number') {
|
|
||||||
toggleStatisticsMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'KeyG': {
|
|
||||||
onDecreaseSubtitlesDelay();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'KeyH': {
|
|
||||||
onIncreaseSubtitlesDelay();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'KeyM': {
|
|
||||||
(typeof video.state.muted === 'boolean' && video.state.muted) ? onUnmuteRequested() : onMuteRequested();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'Minus': {
|
|
||||||
onUpdateSubtitlesSize(-1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'Equal': {
|
|
||||||
onUpdateSubtitlesSize(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'Escape': {
|
|
||||||
closeMenus();
|
|
||||||
!settings.escExitFullscreen && window.history.back();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}, [menusOpen, nextVideoPopupOpen, video.state.paused, onPlayRequested, onPauseRequested]);
|
||||||
|
|
||||||
|
onShortcut('seekForward', (combo) => {
|
||||||
|
if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) {
|
||||||
|
const seekDuration = combo === 1 ? settings.seekShortTimeDuration : settings.seekTimeDuration;
|
||||||
|
setSeeking(true);
|
||||||
|
onSeekRequested(video.state.time + seekDuration);
|
||||||
|
}
|
||||||
|
}, [menusOpen, nextVideoPopupOpen, video.state.time, onSeekRequested]);
|
||||||
|
|
||||||
|
onShortcut('seekBackward', (combo) => {
|
||||||
|
if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) {
|
||||||
|
const seekDuration = combo === 1 ? settings.seekShortTimeDuration : settings.seekTimeDuration;
|
||||||
|
setSeeking(true);
|
||||||
|
onSeekRequested(video.state.time - seekDuration);
|
||||||
|
}
|
||||||
|
}, [menusOpen, nextVideoPopupOpen, video.state.time, onSeekRequested]);
|
||||||
|
|
||||||
|
onShortcut('mute', () => {
|
||||||
|
video.state.muted === true ? onUnmuteRequested() : onMuteRequested();
|
||||||
|
}, [video.state.muted]);
|
||||||
|
|
||||||
|
onShortcut('volumeUp', () => {
|
||||||
|
if (!menusOpen && !nextVideoPopupOpen && video.state.volume !== null) {
|
||||||
|
onVolumeChangeRequested(Math.min(video.state.volume + 5, 200));
|
||||||
|
}
|
||||||
|
}, [menusOpen, nextVideoPopupOpen, video.state.volume]);
|
||||||
|
|
||||||
|
onShortcut('volumeDown', () => {
|
||||||
|
if (!menusOpen && !nextVideoPopupOpen && video.state.volume !== null) {
|
||||||
|
onVolumeChangeRequested(Math.min(video.state.volume - 5, 200));
|
||||||
|
}
|
||||||
|
}, [menusOpen, nextVideoPopupOpen, video.state.volume]);
|
||||||
|
|
||||||
|
onShortcut('subtitlesDelay', (combo) => {
|
||||||
|
combo === 1 ? onIncreaseSubtitlesDelay() : onDecreaseSubtitlesDelay();
|
||||||
|
}, [onIncreaseSubtitlesDelay, onDecreaseSubtitlesDelay]);
|
||||||
|
|
||||||
|
onShortcut('subtitlesSize', (combo) => {
|
||||||
|
combo === 1 ? onUpdateSubtitlesSize(-1) : onUpdateSubtitlesSize(1);
|
||||||
|
}, [onUpdateSubtitlesSize, onUpdateSubtitlesSize]);
|
||||||
|
|
||||||
|
onShortcut('subtitlesMenu', () => {
|
||||||
|
closeMenus();
|
||||||
|
if (video.state?.subtitlesTracks?.length > 0 || video.state?.extraSubtitlesTracks?.length > 0) {
|
||||||
|
toggleSubtitlesMenu();
|
||||||
|
}
|
||||||
|
}, [video.state.subtitlesTracks, video.state.extraSubtitlesTracks, toggleSubtitlesMenu]);
|
||||||
|
|
||||||
|
onShortcut('audioMenu', () => {
|
||||||
|
closeMenus();
|
||||||
|
if (video.state?.audioTracks?.length > 0) {
|
||||||
|
toggleAudioMenu();
|
||||||
|
}
|
||||||
|
}, [video.state.audioTracks, toggleAudioMenu]);
|
||||||
|
|
||||||
|
onShortcut('infoMenu', () => {
|
||||||
|
closeMenus();
|
||||||
|
if (player.metaItem?.type === 'Ready') {
|
||||||
|
toggleSideDrawer();
|
||||||
|
}
|
||||||
|
}, [player.metaItem, toggleSideDrawer]);
|
||||||
|
|
||||||
|
onShortcut('speedMenu', () => {
|
||||||
|
closeMenus();
|
||||||
|
if (video.state.playbackSpeed !== null) {
|
||||||
|
toggleSpeedMenu();
|
||||||
|
}
|
||||||
|
}, [video.state.playbackSpeed, toggleSpeedMenu]);
|
||||||
|
|
||||||
|
onShortcut('statisticsMenu', () => {
|
||||||
|
closeMenus();
|
||||||
|
const stream = player.selected?.stream;
|
||||||
|
if (streamingServer?.statistics?.type !== 'Err' && typeof stream === 'string' && typeof stream === 'number') {
|
||||||
|
toggleStatisticsMenu();
|
||||||
|
}
|
||||||
|
}, [player.selected, streamingServer.statistics, toggleStatisticsMenu]);
|
||||||
|
|
||||||
|
onShortcut('exit', () => {
|
||||||
|
closeMenus();
|
||||||
|
!settings.escExitFullscreen && window.history.back();
|
||||||
|
}, [settings.escExitFullscreen]);
|
||||||
|
|
||||||
|
React.useLayoutEffect(() => {
|
||||||
const onKeyUp = (event) => {
|
const onKeyUp = (event) => {
|
||||||
if (event.code === 'ArrowRight' || event.code === 'ArrowLeft') {
|
if (event.code === 'ArrowRight' || event.code === 'ArrowLeft') {
|
||||||
setSeeking(false);
|
setSeeking(false);
|
||||||
|
|
@ -729,43 +707,14 @@ const Player = ({ urlParams, queryParams }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (routeFocused) {
|
if (routeFocused) {
|
||||||
window.addEventListener('keydown', onKeyDown);
|
|
||||||
window.addEventListener('keyup', onKeyUp);
|
window.addEventListener('keyup', onKeyUp);
|
||||||
window.addEventListener('wheel', onWheel);
|
window.addEventListener('wheel', onWheel);
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('keydown', onKeyDown);
|
|
||||||
window.removeEventListener('keyup', onKeyUp);
|
window.removeEventListener('keyup', onKeyUp);
|
||||||
window.removeEventListener('wheel', onWheel);
|
window.removeEventListener('wheel', onWheel);
|
||||||
};
|
};
|
||||||
}, [
|
}, [routeFocused, menusOpen, video.state.volume]);
|
||||||
player.metaItem,
|
|
||||||
player.selected,
|
|
||||||
streamingServer.statistics,
|
|
||||||
settings.seekTimeDuration,
|
|
||||||
settings.seekShortTimeDuration,
|
|
||||||
settings.escExitFullscreen,
|
|
||||||
routeFocused,
|
|
||||||
menusOpen,
|
|
||||||
nextVideoPopupOpen,
|
|
||||||
video.state.paused,
|
|
||||||
video.state.time,
|
|
||||||
video.state.volume,
|
|
||||||
video.state.muted,
|
|
||||||
video.state.audioTracks,
|
|
||||||
video.state.subtitlesTracks,
|
|
||||||
video.state.extraSubtitlesTracks,
|
|
||||||
video.state.playbackSpeed,
|
|
||||||
toggleSubtitlesMenu,
|
|
||||||
toggleStatisticsMenu,
|
|
||||||
toggleSideDrawer,
|
|
||||||
onUnmuteRequested,
|
|
||||||
onMuteRequested,
|
|
||||||
overlayHidden,
|
|
||||||
onDecreaseSubtitlesDelay,
|
|
||||||
onIncreaseSubtitlesDelay,
|
|
||||||
onUpdateSubtitlesSize,
|
|
||||||
]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
video.events.on('error', onError);
|
video.events.on('error', onError);
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
.cancel {
|
.cancel {
|
||||||
&:hover {
|
&:hover {
|
||||||
.icon {
|
.icon {
|
||||||
color: var(--color-trakt);
|
color: var(--danger-accent-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.error {
|
&.error {
|
||||||
background-color: var(--color-trakt);
|
background-color: var(--danger-accent-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +92,7 @@
|
||||||
background-color: var(--overlay-color);
|
background-color: var(--overlay-color);
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
color: var(--color-trakt);
|
color: var(--danger-accent-color);
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue