refactor(Player): make SideDrawer act like a menu

This commit is contained in:
Tim 2024-12-18 09:32:36 +01:00
parent 72b7a370fc
commit f9cb1a5fd2
8 changed files with 101 additions and 23 deletions

View file

@ -18,13 +18,14 @@ const StatisticsMenu = require('./StatisticsMenu');
const OptionsMenu = require('./OptionsMenu');
const SubtitlesMenu = require('./SubtitlesMenu');
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');
const Video = require('./Video');
const { default: SideDrawer } = require('./SideDrawer/SideDrawer');
const Player = ({ urlParams, queryParams }) => {
const { t } = useTranslation();
@ -59,8 +60,8 @@ const Player = ({ urlParams, queryParams }) => {
const [sideDrawerOpen, , closeSideDrawer, toggleSideDrawer] = useBinaryState(false);
const menusOpen = React.useMemo(() => {
return optionsMenuOpen || subtitlesMenuOpen || speedMenuOpen || statisticsMenuOpen;
}, [optionsMenuOpen, subtitlesMenuOpen, speedMenuOpen, statisticsMenuOpen]);
return optionsMenuOpen || subtitlesMenuOpen || speedMenuOpen || statisticsMenuOpen || sideDrawerOpen;
}, [optionsMenuOpen, subtitlesMenuOpen, speedMenuOpen, statisticsMenuOpen, sideDrawerOpen]);
const closeMenus = React.useCallback(() => {
closeOptionsMenu();
@ -240,6 +241,8 @@ const Player = ({ urlParams, queryParams }) => {
if (!event.nativeEvent.statisticsMenuClosePrevented) {
closeStatisticsMenu();
}
closeSideDrawer();
}, []);
const onContainerMouseMove = React.useCallback((event) => {
@ -478,14 +481,14 @@ const Player = ({ urlParams, queryParams }) => {
break;
}
case 'ArrowUp': {
if (!menusOpen && !nextVideoPopupOpen && !sideDrawerOpen && video.state.volume !== null) {
if (!menusOpen && !nextVideoPopupOpen && video.state.volume !== null) {
onVolumeChangeRequested(video.state.volume + 5);
}
break;
}
case 'ArrowDown': {
if (!menusOpen && !nextVideoPopupOpen && !sideDrawerOpen && video.state.volume !== null) {
if (!menusOpen && !nextVideoPopupOpen && video.state.volume !== null) {
onVolumeChangeRequested(video.state.volume - 5);
}
@ -538,11 +541,11 @@ const Player = ({ urlParams, queryParams }) => {
};
const onWheel = ({ deltaY }) => {
if (deltaY > 0) {
if (!menusOpen && !sideDrawerOpen && video.state.volume !== null) {
if (!menusOpen && video.state.volume !== null) {
onVolumeChangeRequested(video.state.volume - 5);
}
} else {
if (!menusOpen && !sideDrawerOpen && video.state.volume !== null) {
if (!menusOpen && video.state.volume !== null) {
onVolumeChangeRequested(video.state.volume + 5);
}
}
@ -642,6 +645,15 @@ const Player = ({ urlParams, queryParams }) => {
onMouseMove={onBarMouseMove}
onMouseOver={onBarMouseMove}
/>
{
player.metaItem?.type === 'Ready' ?
<SideDrawerButton
className={classnames(styles['layer'], styles['side-drawer-button-layer'])}
onClick={toggleSideDrawer}
/>
:
null
}
<ControlBar
className={classnames(styles['layer'], styles['control-bar-layer'])}
paused={video.state.paused}
@ -694,14 +706,15 @@ const Player = ({ urlParams, queryParams }) => {
null
}
{
player.metaItem !== null && player.metaItem.type === 'Ready' && sideDrawerOpen ?
sideDrawerOpen ?
<SideDrawer
metaItem={player.metaItem.content}
seriesInfo={player.seriesInfo}
className={classnames(styles['layer'], styles['side-drawer-layer'])}
metaItem={player.metaItem?.content}
seriesInfo={player.seriesInfo}
closeSideDrawer={closeSideDrawer}
/>
: null
:
null
}
{
subtitlesMenuOpen ?

View file

@ -1,25 +1,23 @@
import React, { useMemo, useCallback, useState } from 'react';
import classNames from 'classnames';
import Icon from '@stremio/stremio-icons/react';
import { useServices } from 'stremio/services';
import { CONSTANTS } from 'stremio/common';
import MetaPreview from 'stremio/common/MetaPreview/MetaPreview';
import Video from 'stremio/common/Video/Video';
import SeasonsBar from 'stremio/routes/MetaDetails/VideosList/SeasonsBar';
import classNames from 'classnames';
import styles from './SideDrawer.less';
import { useServices } from 'stremio/services';
import Icon from '@stremio/stremio-icons/react';
import useOutsideClick from 'stremio/common/useOutsideClick';
type Props = {
seriesInfo: { season: number, episode: number };
metaItem: MetaItem;
className?: string;
seriesInfo: SeriesInfo;
metaItem: MetaItem;
closeSideDrawer: () => void;
};
const SideDrawer = ({ seriesInfo, className, closeSideDrawer, ...props }: Props) => {
const { core } = useServices();
const [season, setSeason] = useState<number>(seriesInfo?.season);
const sideDrawerRef = useOutsideClick(() => closeSideDrawer());
const metaItem = useMemo(() => {
return seriesInfo ?
{
@ -58,8 +56,12 @@ const SideDrawer = ({ seriesInfo, className, closeSideDrawer, ...props }: Props)
});
}, []);
const onMouseDown = (event: React.MouseEvent) => {
event.stopPropagation();
};
return (
<div className={classNames(styles['side-drawer'], className)} ref={sideDrawerRef}>
<div className={classNames(styles['side-drawer'], className)} onMouseDown={onMouseDown}>
<div className={styles['close-button']} onClick={closeSideDrawer}>
<Icon className={styles['icon']} name={'chevron-forward'} />
</div>

View file

@ -0,0 +1,2 @@
import SideDrawer from './SideDrawer';
export default SideDrawer;

View file

@ -0,0 +1,31 @@
.side-drawer-button {
height: 12.5rem;
width: 7.5rem;
display: flex;
align-items: center;
justify-content: start;
padding-left: 0.5rem;
border-radius: 50%;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
background-color: var(--modal-background-color);
-webkit-tap-highlight-color: transparent;
cursor: pointer;
opacity: 1;
will-change: opacity;
transition: opacity 0.3s ease-in-out, border-radius 0.3s ease-in-out;
.icon {
position: relative;
width: 2.5rem;
height: 2.5rem;
color: var(--primary-foreground-color);
opacity: 0.6;
transition: 0.3s opacity ease-in-out;
}
&:hover {
.icon {
opacity: 1;
}
}
}

View file

@ -0,0 +1,19 @@
import React from 'react';
import classNames from 'classnames';
import Icon from '@stremio/stremio-icons/react';
import styles from './SideDrawerButton.less';
type Props = {
className: string,
onClick: () => void,
};
const SideDrawerButton = ({ className, onClick }: Props) => {
return (
<div className={classNames(className, styles['side-drawer-button'])} onClick={onClick}>
<Icon name={'chevron-back'} className={styles['icon']} />
</div>
);
};
export default SideDrawerButton;

View file

@ -0,0 +1,2 @@
import SideDrawerButton from './SideDrawerButton';
export default SideDrawerButton;

View file

@ -84,6 +84,13 @@ html:not(.active-slider-within) {
}
}
&.side-drawer-button-layer {
top: 50%;
right: -4rem;
left: initial;
transform: translateY(-50%);
}
&.control-bar-layer {
top: initial;
overflow: visible;

View file

@ -25,6 +25,11 @@ type Subtitle = {
url: string,
};
type SeriesInfo = {
episode: number,
season: number,
};
type Player = {
addon: Addon | null,
libraryItem: LibraryItemPlayer | null,
@ -36,10 +41,7 @@ type Player = {
streamRequest: ResourceRequest,
subtitlesPath: ResourceRequestPath,
} | null,
seriesInfo: {
season: number,
episode: number,
} | null,
seriesInfo: SeriesInfo | null,
subtitles: Subtitle[],
title: string | null,
};