mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-01-11 22:40:31 +00:00
feat(shell): implement escape key fullscreen behavior
This commit is contained in:
parent
2da5a0c6d1
commit
e0d1662f86
9 changed files with 99 additions and 61 deletions
|
|
@ -14,12 +14,13 @@ const languages = require('./languages');
|
|||
const routesRegexp = require('./routesRegexp');
|
||||
const useAnimationFrame = require('./useAnimationFrame');
|
||||
const useBinaryState = require('./useBinaryState');
|
||||
const useFullscreen = require('./useFullscreen');
|
||||
const { default: useFullscreen } = require('./useFullscreen');
|
||||
const useLiveRef = require('./useLiveRef');
|
||||
const useModelState = require('./useModelState');
|
||||
const useNotifications = require('./useNotifications');
|
||||
const useOnScrollToBottom = require('./useOnScrollToBottom');
|
||||
const useProfile = require('./useProfile');
|
||||
const { default: useSettings } = require('./useSettings');
|
||||
const { default: useShell } = require('./useShell');
|
||||
const useStreamingServer = require('./useStreamingServer');
|
||||
const useTorrent = require('./useTorrent');
|
||||
|
|
@ -52,6 +53,7 @@ module.exports = {
|
|||
useNotifications,
|
||||
useOnScrollToBottom,
|
||||
useProfile,
|
||||
useSettings,
|
||||
useShell,
|
||||
useStreamingServer,
|
||||
useTorrent,
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (C) 2017-2023 Smart code 203358507
|
||||
|
||||
const React = require('react');
|
||||
|
||||
const useFullscreen = () => {
|
||||
const [fullscreen, setFullscreen] = React.useState(document.fullscreenElement === document.documentElement);
|
||||
const requestFullscreen = React.useCallback(() => {
|
||||
document.documentElement.requestFullscreen();
|
||||
}, []);
|
||||
const exitFullscreen = React.useCallback(() => {
|
||||
document.exitFullscreen();
|
||||
}, []);
|
||||
const toggleFullscreen = React.useCallback(() => {
|
||||
if (fullscreen) {
|
||||
exitFullscreen();
|
||||
} else {
|
||||
requestFullscreen();
|
||||
}
|
||||
}, [fullscreen]);
|
||||
React.useEffect(() => {
|
||||
const onFullscreenChange = () => {
|
||||
setFullscreen(document.fullscreenElement === document.documentElement);
|
||||
};
|
||||
document.addEventListener('fullscreenchange', onFullscreenChange);
|
||||
return () => {
|
||||
document.removeEventListener('fullscreenchange', onFullscreenChange);
|
||||
};
|
||||
}, []);
|
||||
return [fullscreen, requestFullscreen, exitFullscreen, toggleFullscreen];
|
||||
};
|
||||
|
||||
module.exports = useFullscreen;
|
||||
66
src/common/useFullscreen.ts
Normal file
66
src/common/useFullscreen.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (C) 2017-2023 Smart code 203358507
|
||||
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import useShell, { type WindowVisibilityState } from './useShell';
|
||||
import useSettings from './useSettings';
|
||||
|
||||
const useFullscreen = () => {
|
||||
const shell = useShell();
|
||||
const [settings] = useSettings();
|
||||
|
||||
const [fullscreen, setFullscreen] = useState(false);
|
||||
|
||||
const requestFullscreen = useCallback(() => {
|
||||
if (shell.active) {
|
||||
shell.send('win-set-visibility', { fullscreen: true });
|
||||
} else {
|
||||
document.documentElement.requestFullscreen();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const exitFullscreen = useCallback(() => {
|
||||
if (shell.active) {
|
||||
shell.send('win-set-visibility', { fullscreen: false });
|
||||
} else {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toggleFullscreen = useCallback(() => {
|
||||
fullscreen ? exitFullscreen() : requestFullscreen();
|
||||
}, [fullscreen]);
|
||||
|
||||
useEffect(() => {
|
||||
const onWindowVisibilityChanged = (state: WindowVisibilityState) => {
|
||||
setFullscreen(state.isFullscreen === true);
|
||||
};
|
||||
|
||||
const onFullscreenChange = () => {
|
||||
setFullscreen(document.fullscreenElement === document.documentElement);
|
||||
};
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.code === 'Escape' && settings.escExitFullscreen) {
|
||||
exitFullscreen();
|
||||
}
|
||||
|
||||
if ((event.code === 'F11' || event.code === 'KeyF') && shell.active) {
|
||||
toggleFullscreen();
|
||||
}
|
||||
};
|
||||
|
||||
shell.on('win-visibility-changed', onWindowVisibilityChanged);
|
||||
document.addEventListener('keydown', onKeyDown);
|
||||
document.addEventListener('fullscreenchange', onFullscreenChange);
|
||||
|
||||
return () => {
|
||||
shell.off('win-visibility-changed', onWindowVisibilityChanged);
|
||||
document.removeEventListener('keydown', onKeyDown);
|
||||
document.removeEventListener('fullscreenchange', onFullscreenChange);
|
||||
};
|
||||
}, [settings.escExitFullscreen]);
|
||||
|
||||
return [fullscreen, requestFullscreen, exitFullscreen, toggleFullscreen];
|
||||
};
|
||||
|
||||
export default useFullscreen;
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
// Copyright (C) 2017-2023 Smart code 203358507
|
||||
// Copyright (C) 2017-2025 Smart code 203358507
|
||||
|
||||
const React = require('react');
|
||||
const { useServices } = require('stremio/services');
|
||||
const { useProfile } = require('stremio/common');
|
||||
import { useCallback } from 'react';
|
||||
import { useServices } from 'stremio/services';
|
||||
import useProfile from './useProfile';
|
||||
|
||||
const useSettings = () => {
|
||||
const useSettings = (): [Settings, (settings: Settings) => void] => {
|
||||
const { core } = useServices();
|
||||
const profile = useProfile();
|
||||
const updateSettings = React.useCallback((settings) => {
|
||||
|
||||
const updateSettings = useCallback((settings: Settings) => {
|
||||
core.transport.dispatch({
|
||||
action: 'Ctx',
|
||||
args: {
|
||||
|
|
@ -19,7 +20,8 @@ const useSettings = () => {
|
|||
}
|
||||
});
|
||||
}, [profile]);
|
||||
|
||||
return [profile.settings, updateSettings];
|
||||
};
|
||||
|
||||
module.exports = useSettings;
|
||||
export default useSettings;
|
||||
|
|
@ -17,6 +17,10 @@ type ShellEvent = {
|
|||
args: string[];
|
||||
};
|
||||
|
||||
export type WindowVisibilityState = {
|
||||
isFullscreen: boolean;
|
||||
};
|
||||
|
||||
const createId = () => Math.floor(Math.random() * 9999) + 1;
|
||||
|
||||
const useShell = () => {
|
||||
|
|
@ -28,7 +32,7 @@ const useShell = () => {
|
|||
events.off(name, listener);
|
||||
};
|
||||
|
||||
const send = (method: string, ...args: (string | number)[]) => {
|
||||
const send = (method: string, ...args: (string | number | object)[]) => {
|
||||
try {
|
||||
transport?.postMessage(JSON.stringify({
|
||||
id: createId(),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const PropTypes = require('prop-types');
|
|||
const classnames = require('classnames');
|
||||
const { default: Icon } = require('@stremio/stremio-icons/react');
|
||||
const { Button, Image } = require('stremio/components');
|
||||
const useFullscreen = require('stremio/common/useFullscreen');
|
||||
const { default: useFullscreen } = require('stremio/common/useFullscreen');
|
||||
const usePWA = require('stremio/common/usePWA');
|
||||
const SearchBar = require('./SearchBar');
|
||||
const NavMenu = require('./NavMenu');
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const langs = require('langs');
|
|||
const { useTranslation } = require('react-i18next');
|
||||
const { useRouteFocused } = require('stremio-router');
|
||||
const { useServices } = require('stremio/services');
|
||||
const { onFileDrop, useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender, CONSTANTS } = require('stremio/common');
|
||||
const { onFileDrop, useSettings, useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender, CONSTANTS } = require('stremio/common');
|
||||
const { HorizontalNavBar, Transition, ContextMenu } = require('stremio/components');
|
||||
const BufferingLoader = require('./BufferingLoader');
|
||||
const VolumeChangeIndicator = require('./VolumeChangeIndicator');
|
||||
|
|
@ -23,7 +23,6 @@ const SpeedMenu = require('./SpeedMenu');
|
|||
const { default: SideDrawerButton } = require('./SideDrawerButton');
|
||||
const { default: SideDrawer } = require('./SideDrawer');
|
||||
const usePlayer = require('./usePlayer');
|
||||
const useSettings = require('./useSettings');
|
||||
const useStatistics = require('./useStatistics');
|
||||
const useVideo = require('./useVideo');
|
||||
const styles = require('./styles');
|
||||
|
|
@ -565,6 +564,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}
|
||||
case 'Escape': {
|
||||
closeMenus();
|
||||
!settings.escExitFullscreen && window.history.back();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -595,7 +595,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
window.removeEventListener('keyup', onKeyUp);
|
||||
window.removeEventListener('wheel', onWheel);
|
||||
};
|
||||
}, [player.metaItem, player.selected, streamingServer.statistics, settings.seekTimeDuration, settings.seekShortTimeDuration, routeFocused, menusOpen, nextVideoPopupOpen, video.state.paused, video.state.time, video.state.volume, video.state.audioTracks, video.state.subtitlesTracks, video.state.extraSubtitlesTracks, video.state.playbackSpeed, toggleSubtitlesMenu, toggleStatisticsMenu, toggleSideDrawer]);
|
||||
}, [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.audioTracks, video.state.subtitlesTracks, video.state.extraSubtitlesTracks, video.state.playbackSpeed, toggleSubtitlesMenu, toggleStatisticsMenu, toggleSideDrawer]);
|
||||
|
||||
React.useEffect(() => {
|
||||
video.events.on('error', onError);
|
||||
|
|
|
|||
2
src/routes/Player/useSettings.d.ts
vendored
2
src/routes/Player/useSettings.d.ts
vendored
|
|
@ -1,2 +0,0 @@
|
|||
declare const useSettings: () => [Settings, (settings: any) => void];
|
||||
export = useSettings;
|
||||
|
|
@ -342,6 +342,18 @@ const Settings = () => {
|
|||
/>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
shell.active &&
|
||||
<div className={styles['option-container']}>
|
||||
<div className={styles['option-name-container']}>
|
||||
<div className={styles['label']}>{ t('SETTINGS_FULLSCREEN_EXIT') }</div>
|
||||
</div>
|
||||
<Toggle
|
||||
className={classnames(styles['option-input-container'], styles['toggle-container'])}
|
||||
{...escExitFullscreenToggle}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
<div className={styles['option-container']}>
|
||||
<div className={styles['option-name-container']}>
|
||||
<div className={styles['label']}>{ t('SETTINGS_BLUR_UNWATCHED_IMAGE') }</div>
|
||||
|
|
@ -368,20 +380,6 @@ const Settings = () => {
|
|||
{...subtitlesLanguageSelect}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
shell.active ?
|
||||
<div className={styles['option-container']}>
|
||||
<div className={styles['option-name-container']}>
|
||||
<div className={styles['label']}>{ t('SETTINGS_FULLSCREEN_EXIT') }</div>
|
||||
</div>
|
||||
<Toggle
|
||||
className={classnames(styles['option-input-container'], styles['toggle-container'])}
|
||||
{...escExitFullscreenToggle}
|
||||
/>
|
||||
</div>
|
||||
:
|
||||
null
|
||||
}
|
||||
<div className={styles['option-container']}>
|
||||
<div className={styles['option-name-container']}>
|
||||
<div className={styles['label']}>{ t('SETTINGS_SUBTITLES_SIZE') }</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue