mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-04-20 10:42:12 +00:00
refactor(Player): make SideDrawer act like a menu
This commit is contained in:
parent
72b7a370fc
commit
f9cb1a5fd2
8 changed files with 101 additions and 23 deletions
|
|
@ -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 ?
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
2
src/routes/Player/SideDrawer/index.ts
Normal file
2
src/routes/Player/SideDrawer/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import SideDrawer from './SideDrawer';
|
||||
export default SideDrawer;
|
||||
31
src/routes/Player/SideDrawerButton/SideDrawerButton.less
Normal file
31
src/routes/Player/SideDrawerButton/SideDrawerButton.less
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/routes/Player/SideDrawerButton/SideDrawerButton.tsx
Normal file
19
src/routes/Player/SideDrawerButton/SideDrawerButton.tsx
Normal 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;
|
||||
2
src/routes/Player/SideDrawerButton/index.ts
Normal file
2
src/routes/Player/SideDrawerButton/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import SideDrawerButton from './SideDrawerButton';
|
||||
export default SideDrawerButton;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
10
src/types/models/Player.d.ts
vendored
10
src/types/models/Player.d.ts
vendored
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue