mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-04-20 19:02:15 +00:00
feat: add mark season as watched for videos
This commit is contained in:
parent
9b197c8712
commit
6e00a3384c
3 changed files with 49 additions and 2 deletions
|
|
@ -11,7 +11,7 @@ const useBinaryState = require('stremio/common/useBinaryState');
|
||||||
const VideoPlaceholder = require('./VideoPlaceholder');
|
const VideoPlaceholder = require('./VideoPlaceholder');
|
||||||
const styles = require('./styles');
|
const styles = require('./styles');
|
||||||
|
|
||||||
const Video = ({ className, id, title, thumbnail, episode, released, upcoming, watched, progress, scheduled, deepLinks, onMarkVideoAsWatched, ...props }) => {
|
const Video = ({ className, id, title, thumbnail, season, episode, released, upcoming, watched, progress, scheduled, seasonWatched, deepLinks, onMarkVideoAsWatched, onMarkSeasonAsWatched, ...props }) => {
|
||||||
const routeFocused = useRouteFocused();
|
const routeFocused = useRouteFocused();
|
||||||
const [menuOpen, , closeMenu, toggleMenu] = useBinaryState(false);
|
const [menuOpen, , closeMenu, toggleMenu] = useBinaryState(false);
|
||||||
const popupLabelOnMouseUp = React.useCallback((event) => {
|
const popupLabelOnMouseUp = React.useCallback((event) => {
|
||||||
|
|
@ -50,6 +50,12 @@ const Video = ({ className, id, title, thumbnail, episode, released, upcoming, w
|
||||||
closeMenu();
|
closeMenu();
|
||||||
onMarkVideoAsWatched({ id, released }, watched);
|
onMarkVideoAsWatched({ id, released }, watched);
|
||||||
}, [id, released, watched]);
|
}, [id, released, watched]);
|
||||||
|
const toggleWatchedSeasonOnClick = React.useCallback((event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
closeMenu();
|
||||||
|
onMarkSeasonAsWatched(season, seasonWatched);
|
||||||
|
}, [season, seasonWatched, onMarkSeasonAsWatched]);
|
||||||
const videoButtonOnClick = React.useCallback(() => {
|
const videoButtonOnClick = React.useCallback(() => {
|
||||||
if (deepLinks) {
|
if (deepLinks) {
|
||||||
if (typeof deepLinks.player === 'string') {
|
if (typeof deepLinks.player === 'string') {
|
||||||
|
|
@ -142,9 +148,12 @@ const Video = ({ className, id, title, thumbnail, episode, released, upcoming, w
|
||||||
<Button className={styles['context-menu-option-container']} title={watched ? 'Mark as non-watched' : 'Mark as watched'} onClick={toggleWatchedOnClick}>
|
<Button className={styles['context-menu-option-container']} title={watched ? 'Mark as non-watched' : 'Mark as watched'} onClick={toggleWatchedOnClick}>
|
||||||
<div className={styles['context-menu-option-label']}>{watched ? t('CTX_MARK_NON_WATCHED') : t('CTX_MARK_WATCHED')}</div>
|
<div className={styles['context-menu-option-label']}>{watched ? t('CTX_MARK_NON_WATCHED') : t('CTX_MARK_WATCHED')}</div>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button className={styles['context-menu-option-container']} title={seasonWatched ? t('CTX_UNMARK_REST') : t('CTX_MARK_REST')} onClick={toggleWatchedSeasonOnClick}>
|
||||||
|
<div className={styles['context-menu-option-label']}>{seasonWatched ? t('CTX_UNMARK_REST') : t('CTX_MARK_REST')}</div>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}, [watched, toggleWatchedOnClick]);
|
}, [watched, seasonWatched, toggleWatchedOnClick]);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!routeFocused) {
|
if (!routeFocused) {
|
||||||
closeMenu();
|
closeMenu();
|
||||||
|
|
@ -182,17 +191,20 @@ Video.propTypes = {
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
thumbnail: PropTypes.string,
|
thumbnail: PropTypes.string,
|
||||||
|
season: PropTypes.number,
|
||||||
episode: PropTypes.number,
|
episode: PropTypes.number,
|
||||||
released: PropTypes.instanceOf(Date),
|
released: PropTypes.instanceOf(Date),
|
||||||
upcoming: PropTypes.bool,
|
upcoming: PropTypes.bool,
|
||||||
watched: PropTypes.bool,
|
watched: PropTypes.bool,
|
||||||
progress: PropTypes.number,
|
progress: PropTypes.number,
|
||||||
scheduled: PropTypes.bool,
|
scheduled: PropTypes.bool,
|
||||||
|
seasonWatched: PropTypes.bool,
|
||||||
deepLinks: PropTypes.shape({
|
deepLinks: PropTypes.shape({
|
||||||
metaDetailsStreams: PropTypes.string,
|
metaDetailsStreams: PropTypes.string,
|
||||||
player: PropTypes.string
|
player: PropTypes.string
|
||||||
}),
|
}),
|
||||||
onMarkVideoAsWatched: PropTypes.func,
|
onMarkVideoAsWatched: PropTypes.func,
|
||||||
|
onMarkSeasonAsWatched: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Video;
|
module.exports = Video;
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,11 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect,
|
||||||
return a.episode - b.episode;
|
return a.episode - b.episode;
|
||||||
});
|
});
|
||||||
}, [videos, selectedSeason]);
|
}, [videos, selectedSeason]);
|
||||||
|
|
||||||
|
const seasonWatched = React.useMemo(() => {
|
||||||
|
return videosForSeason.every((video) => video.watched);
|
||||||
|
}, [videosForSeason]);
|
||||||
|
|
||||||
const [search, setSearch] = React.useState('');
|
const [search, setSearch] = React.useState('');
|
||||||
const searchInputOnChange = React.useCallback((event) => {
|
const searchInputOnChange = React.useCallback((event) => {
|
||||||
setSearch(event.currentTarget.value);
|
setSearch(event.currentTarget.value);
|
||||||
|
|
@ -71,6 +76,16 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onMarkSeasonAsWatched = (season, watched) => {
|
||||||
|
core.transport.dispatch({
|
||||||
|
action: 'MetaDetails',
|
||||||
|
args: {
|
||||||
|
action: 'MarkSeasonAsWatched',
|
||||||
|
args: [season, !watched]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames(className, styles['videos-list-container'])}>
|
<div className={classnames(className, styles['videos-list-container'])}>
|
||||||
{
|
{
|
||||||
|
|
@ -135,6 +150,7 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect,
|
||||||
id={video.id}
|
id={video.id}
|
||||||
title={video.title}
|
title={video.title}
|
||||||
thumbnail={video.thumbnail}
|
thumbnail={video.thumbnail}
|
||||||
|
season={video.season}
|
||||||
episode={video.episode}
|
episode={video.episode}
|
||||||
released={video.released}
|
released={video.released}
|
||||||
upcoming={video.upcoming}
|
upcoming={video.upcoming}
|
||||||
|
|
@ -142,7 +158,9 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect,
|
||||||
progress={video.progress}
|
progress={video.progress}
|
||||||
deepLinks={video.deepLinks}
|
deepLinks={video.deepLinks}
|
||||||
scheduled={video.scheduled}
|
scheduled={video.scheduled}
|
||||||
|
seasonWatched={seasonWatched}
|
||||||
onMarkVideoAsWatched={onMarkVideoAsWatched}
|
onMarkVideoAsWatched={onMarkVideoAsWatched}
|
||||||
|
onMarkSeasonAsWatched={onMarkSeasonAsWatched}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,10 @@ const SideDrawer = memo(forwardRef<HTMLDivElement, Props>(({ seriesInfo, classNa
|
||||||
setSeason(parseInt(event.value));
|
setSeason(parseInt(event.value));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const seasonWatched = React.useMemo(() => {
|
||||||
|
return videos.every((video) => video.watched);
|
||||||
|
}, [videos]);
|
||||||
|
|
||||||
const onMarkVideoAsWatched = useCallback((video: Video, watched: boolean) => {
|
const onMarkVideoAsWatched = useCallback((video: Video, watched: boolean) => {
|
||||||
core.transport.dispatch({
|
core.transport.dispatch({
|
||||||
action: 'Player',
|
action: 'Player',
|
||||||
|
|
@ -57,6 +61,16 @@ const SideDrawer = memo(forwardRef<HTMLDivElement, Props>(({ seriesInfo, classNa
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const onMarkSeasonAsWatched = (season: number, watched: boolean) => {
|
||||||
|
core.transport.dispatch({
|
||||||
|
action: 'MetaDetails',
|
||||||
|
args: {
|
||||||
|
action: 'MarkSeasonAsWatched',
|
||||||
|
args: [season, !watched]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const onMouseDown = (event: React.MouseEvent) => {
|
const onMouseDown = (event: React.MouseEvent) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
@ -95,14 +109,17 @@ const SideDrawer = memo(forwardRef<HTMLDivElement, Props>(({ seriesInfo, classNa
|
||||||
id={video.id}
|
id={video.id}
|
||||||
title={video.title}
|
title={video.title}
|
||||||
thumbnail={video.thumbnail}
|
thumbnail={video.thumbnail}
|
||||||
|
season={video.season}
|
||||||
episode={video.episode}
|
episode={video.episode}
|
||||||
released={video.released}
|
released={video.released}
|
||||||
upcoming={video.upcoming}
|
upcoming={video.upcoming}
|
||||||
watched={video.watched}
|
watched={video.watched}
|
||||||
|
seasonWatched={seasonWatched}
|
||||||
progress={video.progress}
|
progress={video.progress}
|
||||||
deepLinks={video.deepLinks}
|
deepLinks={video.deepLinks}
|
||||||
scheduled={video.scheduled}
|
scheduled={video.scheduled}
|
||||||
onMarkVideoAsWatched={onMarkVideoAsWatched}
|
onMarkVideoAsWatched={onMarkVideoAsWatched}
|
||||||
|
onMarkSeasonAsWatched={onMarkSeasonAsWatched}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue