mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-04-21 03:22:11 +00:00
Compare commits
6 commits
b24426250b
...
c3f67454ff
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3f67454ff | ||
|
|
89515a2a75 | ||
|
|
5b83fa00b5 | ||
|
|
182782a60f | ||
|
|
3d119db049 | ||
|
|
df69e6eb18 |
4 changed files with 86 additions and 17 deletions
|
|
@ -96,6 +96,11 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
|
||||
const isNavigating = React.useRef(false);
|
||||
|
||||
const pressTimer = React.useRef(null);
|
||||
const longPress = React.useRef(false);
|
||||
|
||||
const HOLD_DELAY = 200;
|
||||
|
||||
const onImplementationChanged = React.useCallback(() => {
|
||||
video.setSubtitlesSize(settings.subtitlesSize);
|
||||
video.setSubtitlesOffset(settings.subtitlesOffset);
|
||||
|
|
@ -296,14 +301,14 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}, [player.nextVideo, handleNextVideoNavigation, profile.settings]);
|
||||
|
||||
const onVideoClick = React.useCallback(() => {
|
||||
if (video.state.paused !== null) {
|
||||
if (video.state.paused !== null && !longPress.current) {
|
||||
if (video.state.paused) {
|
||||
onPlayRequestedDebounced();
|
||||
} else {
|
||||
onPauseRequestedDebounced();
|
||||
}
|
||||
}
|
||||
}, [video.state.paused]);
|
||||
}, [video.state.paused, longPress.current]);
|
||||
|
||||
const onVideoDoubleClick = React.useCallback(() => {
|
||||
onPlayRequestedDebounced.cancel();
|
||||
|
|
@ -625,11 +630,11 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
if (video.state.paused) {
|
||||
onPlayRequested();
|
||||
setSeeking(false);
|
||||
} else {
|
||||
} else if (!pressTimer.current) {
|
||||
onPauseRequested();
|
||||
}
|
||||
}
|
||||
}, [menusOpen, nextVideoPopupOpen, video.state.paused, onPlayRequested, onPauseRequested]);
|
||||
}, [menusOpen, nextVideoPopupOpen, video.state.paused, pressTimer.current, onPlayRequested, onPauseRequested]);
|
||||
|
||||
onShortcut('seekForward', (combo) => {
|
||||
if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) {
|
||||
|
|
@ -726,11 +731,31 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}, [settings.escExitFullscreen]);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
const onKeyUp = (event) => {
|
||||
if (event.code === 'ArrowRight' || event.code === 'ArrowLeft') {
|
||||
const onKeyDown = (e) => {
|
||||
if (e.code !== 'Space' || e.repeat) return;
|
||||
|
||||
longPress.current = false;
|
||||
|
||||
pressTimer.current = setTimeout(() => {
|
||||
longPress.current = true;
|
||||
onPlaybackSpeedChanged(2);
|
||||
}, HOLD_DELAY);
|
||||
};
|
||||
|
||||
const onKeyUp = (e) => {
|
||||
if (e.code !== 'Space' && e.code !== 'ArrowRight' && e.code !== 'ArrowLeft') return;
|
||||
|
||||
if (e.code === 'ArrowRight' || e.code === 'ArrowLeft') {
|
||||
setSeeking(false);
|
||||
return;
|
||||
}
|
||||
if (e.code === 'Space') {
|
||||
clearTimeout(pressTimer.current);
|
||||
pressTimer.current = null;
|
||||
onPlaybackSpeedChanged(1);
|
||||
}
|
||||
};
|
||||
|
||||
const onWheel = ({ deltaY }) => {
|
||||
if (menusOpen || video.state.volume === null) return;
|
||||
|
||||
|
|
@ -742,13 +767,41 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseDownHold = (e) => {
|
||||
if (e.button !== 0) return; // left mouse button only
|
||||
|
||||
longPress.current = false;
|
||||
|
||||
pressTimer.current = setTimeout(() => {
|
||||
longPress.current = true;
|
||||
onPlaybackSpeedChanged(2);
|
||||
}, HOLD_DELAY);
|
||||
};
|
||||
|
||||
const onMouseUp = (e) => {
|
||||
if (e.button !== 0) return;
|
||||
|
||||
clearTimeout(pressTimer.current);
|
||||
|
||||
if (longPress.current) {
|
||||
onPlaybackSpeedChanged(1);
|
||||
}
|
||||
};
|
||||
|
||||
if (routeFocused) {
|
||||
window.addEventListener('keyup', onKeyUp);
|
||||
window.addEventListener('keydown', onKeyDown);
|
||||
window.addEventListener('wheel', onWheel);
|
||||
window.addEventListener('mousedown', onMouseDownHold);
|
||||
window.addEventListener('mouseup', onMouseUp);
|
||||
}
|
||||
return () => {
|
||||
window.removeEventListener('keyup', onKeyUp);
|
||||
window.removeEventListener('keydown', onKeyDown);
|
||||
window.removeEventListener('wheel', onWheel);
|
||||
window.removeEventListener('mousedown', onMouseDownHold);
|
||||
window.removeEventListener('mouseup', onMouseUp);
|
||||
};
|
||||
}, [routeFocused, menusOpen, video.state.volume]);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
.options-container {
|
||||
flex: 0 1 auto;
|
||||
max-height: calc(3.2rem * 8);
|
||||
max-height: calc(3.2rem * 10);
|
||||
padding: 0 1rem 0.5rem;
|
||||
|
||||
.option {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
|
|||
import { useServices } from 'stremio/services';
|
||||
import { Button } from 'stremio/components';
|
||||
import { SECTIONS } from '../constants';
|
||||
import { usePlatform } from 'stremio/common';
|
||||
import styles from './Menu.less';
|
||||
|
||||
type Props = {
|
||||
|
|
@ -15,6 +16,7 @@ type Props = {
|
|||
const Menu = ({ selected, streamingServer, onSelect }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { shell } = useServices();
|
||||
const platform = usePlatform();
|
||||
|
||||
const settings = useMemo(() => (
|
||||
streamingServer?.settings?.type === 'Ready' ?
|
||||
|
|
@ -35,9 +37,9 @@ const Menu = ({ selected, streamingServer, onSelect }: Props) => {
|
|||
<Button className={classNames(styles['button'], { [styles['selected']]: selected === SECTIONS.STREAMING })} title={t('SETTINGS_NAV_STREAMING')} data-section={SECTIONS.STREAMING} onClick={onSelect}>
|
||||
{ t('SETTINGS_NAV_STREAMING') }
|
||||
</Button>
|
||||
<Button className={classNames(styles['button'], { [styles['selected']]: selected === SECTIONS.SHORTCUTS })} title={t('SETTINGS_NAV_SHORTCUTS')} data-section={SECTIONS.SHORTCUTS} onClick={onSelect}>
|
||||
{ !platform.isMobile && <Button className={classNames(styles['button'], { [styles['selected']]: selected === SECTIONS.SHORTCUTS })} title={t('SETTINGS_NAV_SHORTCUTS')} data-section={SECTIONS.SHORTCUTS} onClick={onSelect}>
|
||||
{ t('SETTINGS_NAV_SHORTCUTS') }
|
||||
</Button>
|
||||
</Button> }
|
||||
|
||||
<div className={styles['spacing']} />
|
||||
<div className={styles['version-info-label']} title={process.env.VERSION}>
|
||||
|
|
|
|||
|
|
@ -41,13 +41,27 @@ const Settings = () => {
|
|||
|
||||
const updateSelectedSectionId = useCallback(() => {
|
||||
const container = sectionsContainerRef.current;
|
||||
for (const section of sections) {
|
||||
const sectionContainer = section.ref.current;
|
||||
if (sectionContainer && (sectionContainer.offsetTop + container!.offsetTop) < container!.scrollTop + 50) {
|
||||
setSelectedSectionId(section.id);
|
||||
}
|
||||
if (!container) return;
|
||||
|
||||
const availableSections = sections.filter((section) => section.ref.current);
|
||||
if (!availableSections.length) return;
|
||||
|
||||
const { scrollTop, clientHeight, scrollHeight, offsetTop } = container;
|
||||
const isAtBottom = scrollTop + clientHeight >= scrollHeight - 10;
|
||||
|
||||
if (isAtBottom) {
|
||||
setSelectedSectionId(availableSections[availableSections.length - 1].id);
|
||||
return;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const marker = scrollTop + 50;
|
||||
const activeSection = availableSections.reduce((current, section) => {
|
||||
const sectionTop = section.ref.current!.offsetTop + offsetTop;
|
||||
return sectionTop <= marker ? section : current;
|
||||
}, availableSections[0]);
|
||||
|
||||
setSelectedSectionId(activeSection.id);
|
||||
}, [sections]);
|
||||
|
||||
const onMenuSelect = useCallback((event: React.MouseEvent<HTMLDivElement>) => {
|
||||
const section = sections.find((section) => {
|
||||
|
|
@ -55,11 +69,11 @@ const Settings = () => {
|
|||
});
|
||||
|
||||
const container = sectionsContainerRef.current;
|
||||
section && container!.scrollTo({
|
||||
section && container?.scrollTo({
|
||||
top: section.ref.current!.offsetTop - container!.offsetTop,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}, []);
|
||||
}, [sections]);
|
||||
|
||||
const onContainerScroll = useCallback(throttle(() => {
|
||||
updateSelectedSectionId();
|
||||
|
|
|
|||
Loading…
Reference in a new issue