diff --git a/src/routes/MetaDetails/VideosList/Video/Video.js b/src/routes/MetaDetails/VideosList/Video/Video.js index eda4ef8d6..125932db8 100644 --- a/src/routes/MetaDetails/VideosList/Video/Video.js +++ b/src/routes/MetaDetails/VideosList/Video/Video.js @@ -3,12 +3,37 @@ const React = require('react'); const PropTypes = require('prop-types'); const classnames = require('classnames'); +const { useServices } = require('stremio/services'); +const { useRouteFocused } = require('stremio-router'); const Icon = require('@stremio/stremio-icons/dom'); -const { Button, Image } = require('stremio/common'); +const { Button, Image, Popup, useBinaryState } = require('stremio/common'); const VideoPlaceholder = require('./VideoPlaceholder'); const styles = require('./styles'); const Video = ({ className, id, title, thumbnail, episode, released, upcoming, watched, progress, scheduled, deepLinks, ...props }) => { + const { core } = useServices(); + const routeFocused = useRouteFocused(); + const [menuOpen, , closeMenu, toggleMenu] = useBinaryState(false); + const popupLabelOnContextMenu = React.useCallback((event) => { + if (!event.nativeEvent.togglePopupPrevented && !event.nativeEvent.ctrlKey) { + toggleMenu(); + event.nativeEvent.preventDefault(); + } + }, [toggleMenu]); + const popupMenuOnContextMenu = React.useCallback((event) => { + event.nativeEvent.togglePopupPrevented = true; + }, []); + const toggleWatchedOnClick = React.useCallback((event) => { + event.preventDefault(); + closeMenu(); + core.transport.dispatch({ + action: 'MetaDetails', + args: { + action: 'MarkAsWatched', + args: [id, !watched] + } + }); + }, [id, watched]); const href = React.useMemo(() => { return deepLinks ? typeof deepLinks.player === 'string' ? @@ -21,74 +46,115 @@ const Video = ({ className, id, title, thumbnail, episode, released, upcoming, w : null; }, [deepLinks]); - return ( - + ); + }, []); + const renderMenu = React.useMemo(() => function renderMenu() { + return ( +
+ +
- { - progress !== null && !isNaN(progress) && progress > 0 ? -
-
-
- : - null - } - + ); + }, [watched, toggleWatchedOnClick]); + React.useEffect(() => { + if (!routeFocused) { + closeMenu(); + } + }, [routeFocused]); + return ( + ); }; diff --git a/src/routes/MetaDetails/VideosList/Video/styles.less b/src/routes/MetaDetails/VideosList/Video/styles.less index 17f20bedf..e4023384e 100644 --- a/src/routes/MetaDetails/VideosList/Video/styles.less +++ b/src/routes/MetaDetails/VideosList/Video/styles.less @@ -2,13 +2,21 @@ @import (reference) '~@stremio/stremio-colors/less/stremio-colors.less'; +:import('~stremio/common/Popup/styles.less') { + context-menu-container: menu-container; + menu-direction-top-left: menu-direction-top-left; + menu-direction-bottom-left: menu-direction-bottom-left; + menu-direction-top-right: menu-direction-top-right; + menu-direction-bottom-right: menu-direction-bottom-right; +} + .video-container { display: flex; flex-direction: row; flex-wrap: wrap; padding: 0.5rem 1rem; - &:hover, &:focus { + &:hover, &:focus, &:global(.active) { background-color: @color-background; } @@ -119,4 +127,45 @@ background-color: @color-primaryvariant1; } } + + .context-menu-container { + max-width: calc(90% - 1.5rem); + + &.menu-direction-top-left, &.menu-direction-bottom-left { + right: 1.5rem; + } + + &.menu-direction-top-right, &.menu-direction-bottom-right { + left: 1.5rem; + } + + &.menu-direction-top-left, &.menu-direction-top-right { + bottom: 90%; + } + + &.menu-direction-bottom-left, &.menu-direction-bottom-right { + top: 90%; + } + + .context-menu-content { + background-color: @color-background-dark1; + + .context-menu-option-container { + display: flex; + flex-direction: row; + align-items: center; + padding: 0.5rem 1rem; + + &:hover, &:focus { + background-color: @color-background; + } + + .context-menu-option-label { + font-size: 1rem; + max-height: 2.4em; + color: @color-surface-light5-90; + } + } + } + } } \ No newline at end of file