mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
feat(context menu): enable context menu on right click on video
This commit is contained in:
parent
79a43ef444
commit
9a3be29a39
3 changed files with 63 additions and 11 deletions
|
|
@ -9,7 +9,7 @@ const { useServices } = require('stremio/services');
|
|||
const Option = require('./Option');
|
||||
const styles = require('./styles');
|
||||
|
||||
const OptionsMenu = ({ className, stream, playbackDevices }) => {
|
||||
const OptionsMenu = ({ className, stream, playbackDevices, style }) => {
|
||||
const { t } = useTranslation();
|
||||
const { core } = useServices();
|
||||
const platform = usePlatform();
|
||||
|
|
@ -70,7 +70,7 @@ const OptionsMenu = ({ className, stream, playbackDevices }) => {
|
|||
event.nativeEvent.optionsMenuClosePrevented = true;
|
||||
}, []);
|
||||
return (
|
||||
<div className={classnames(className, styles['options-menu-container'])} onMouseDown={onMouseDown}>
|
||||
<div style={style} className={classnames(className, styles['options-menu-container'])} onMouseDown={onMouseDown}>
|
||||
{
|
||||
streamingUrl || downloadUrl ?
|
||||
<Option
|
||||
|
|
@ -112,7 +112,8 @@ const OptionsMenu = ({ className, stream, playbackDevices }) => {
|
|||
OptionsMenu.propTypes = {
|
||||
className: PropTypes.string,
|
||||
stream: PropTypes.object,
|
||||
playbackDevices: PropTypes.array
|
||||
playbackDevices: PropTypes.array,
|
||||
style: PropTypes.object,
|
||||
};
|
||||
|
||||
module.exports = OptionsMenu;
|
||||
|
|
|
|||
|
|
@ -61,9 +61,14 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
const [statisticsMenuOpen, , closeStatisticsMenu, toggleStatisticsMenu] = useBinaryState(false);
|
||||
const [nextVideoPopupOpen, openNextVideoPopup, closeNextVideoPopup] = useBinaryState(false);
|
||||
const [sideDrawerOpen, , closeSideDrawer, toggleSideDrawer] = useBinaryState(false);
|
||||
const [contextMenuOpen, openContextMenu, closeContextMenu] = useBinaryState(false);
|
||||
const [contextCoords, setContextCoords] = React.useState({
|
||||
x: 0,
|
||||
y: 0,
|
||||
});
|
||||
|
||||
const menusOpen = React.useMemo(() => {
|
||||
return optionsMenuOpen || subtitlesMenuOpen || audioMenuOpen || speedMenuOpen || statisticsMenuOpen || sideDrawerOpen;
|
||||
return optionsMenuOpen || subtitlesMenuOpen || audioMenuOpen || speedMenuOpen || statisticsMenuOpen || sideDrawerOpen || contextMenuOpen;
|
||||
}, [optionsMenuOpen, subtitlesMenuOpen, audioMenuOpen, speedMenuOpen, statisticsMenuOpen, sideDrawerOpen]);
|
||||
|
||||
const closeMenus = React.useCallback(() => {
|
||||
|
|
@ -73,6 +78,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
closeSpeedMenu();
|
||||
closeStatisticsMenu();
|
||||
closeSideDrawer();
|
||||
closeContextMenu();
|
||||
}, []);
|
||||
|
||||
const overlayHidden = React.useMemo(() => {
|
||||
|
|
@ -216,13 +222,17 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}
|
||||
}, [player.nextVideo]);
|
||||
|
||||
const onVideoClick = React.useCallback(() => {
|
||||
if (video.state.paused !== null) {
|
||||
if (video.state.paused) {
|
||||
onPlayRequestedDebounced();
|
||||
} else {
|
||||
onPauseRequestedDebounced();
|
||||
const onVideoClick = React.useCallback((e) => {
|
||||
if (e.type === 'click') {
|
||||
if (video.state.paused !== null) {
|
||||
if (video.state.paused) {
|
||||
onPlayRequestedDebounced();
|
||||
} else {
|
||||
onPauseRequestedDebounced();
|
||||
}
|
||||
}
|
||||
} else if (e.type === 'contextmenu') {
|
||||
onContextMenu(e);
|
||||
}
|
||||
}, [video.state.paused]);
|
||||
|
||||
|
|
@ -232,6 +242,28 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
toggleFullscreen();
|
||||
}, [toggleFullscreen]);
|
||||
|
||||
const onContextMenu = React.useCallback((e) => {
|
||||
e.preventDefault();
|
||||
let baseFontSize = 14;
|
||||
const { clientX, clientY } = event;
|
||||
const { innerWidth, innerHeight } = window;
|
||||
|
||||
if (innerWidth > 1600) baseFontSize = 15;
|
||||
if (innerWidth > 2200) baseFontSize = 16;
|
||||
|
||||
const menuWidth = 16 * baseFontSize;
|
||||
const minMenuHeight = 9 * baseFontSize;
|
||||
|
||||
const adjustedX = clientX + menuWidth > innerWidth ? clientX - menuWidth : clientX;
|
||||
const adjustedY = clientY + minMenuHeight > innerHeight ? clientY - minMenuHeight : clientY;
|
||||
|
||||
setContextCoords({
|
||||
x: adjustedX,
|
||||
y: adjustedY,
|
||||
});
|
||||
openContextMenu();
|
||||
}, []);
|
||||
|
||||
const onContainerMouseDown = React.useCallback((event) => {
|
||||
if (!event.nativeEvent.optionsMenuClosePrevented) {
|
||||
closeOptionsMenu();
|
||||
|
|
@ -250,6 +282,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}
|
||||
|
||||
closeSideDrawer();
|
||||
closeContextMenu();
|
||||
}, []);
|
||||
|
||||
const onContainerMouseMove = React.useCallback((event) => {
|
||||
|
|
@ -656,6 +689,24 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
:
|
||||
null
|
||||
}
|
||||
{
|
||||
contextMenuOpen ?
|
||||
<OptionsMenu
|
||||
style={
|
||||
{
|
||||
top: `${contextCoords.y}px`,
|
||||
left: `${contextCoords.x}px`,
|
||||
right: 'auto',
|
||||
bottom: 'auto'
|
||||
}
|
||||
}
|
||||
className={classnames(styles['layer'], styles['menu-layer'])}
|
||||
stream={player.selected.stream}
|
||||
playbackDevices={streamingServer.playbackDevices !== null && streamingServer.playbackDevices.type === 'Ready' ? streamingServer.playbackDevices.content : []}
|
||||
/>
|
||||
:
|
||||
null
|
||||
}
|
||||
<HorizontalNavBar
|
||||
className={classnames(styles['layer'], styles['nav-bar-layer'])}
|
||||
title={player.title !== null ? player.title : ''}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ const styles = require('./styles');
|
|||
|
||||
const Video = React.forwardRef(({ className, onClick, onDoubleClick }, ref) => {
|
||||
return (
|
||||
<div className={classnames(className, styles['video-container'])} onClick={onClick} onDoubleClick={onDoubleClick}>
|
||||
<div className={classnames(className, styles['video-container'])} onClick={onClick} onContextMenu={onClick} onDoubleClick={onDoubleClick}>
|
||||
<div ref={ref} className={styles['video']} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue