mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 17:15:48 +00:00
feat(SeasonsBar): Handle episodes options in multiselect menu
This commit is contained in:
parent
3bbbe66b33
commit
0b5c14aba4
2 changed files with 60 additions and 25 deletions
|
|
@ -9,19 +9,26 @@ const { Button, MultiselectMenu } = require('stremio/components');
|
|||
const SeasonsBarPlaceholder = require('./SeasonsBarPlaceholder');
|
||||
const styles = require('./styles');
|
||||
|
||||
const SeasonsBar = ({ className, seasons, season, onSelect }) => {
|
||||
const SeasonsBar = ({ className, seasons, season, episode, onSelect }) => {
|
||||
const options = React.useMemo(() => {
|
||||
return seasons.map((season) => ({
|
||||
value: String(season),
|
||||
label: season > 0 ? `${t('SEASON')} ${season}` : t('SPECIAL')
|
||||
return seasons.map(({ id, episodes }) => ({
|
||||
value: String(id),
|
||||
label: id > 0 ? `${t('SEASON')} ${id}` : t('SPECIAL'),
|
||||
options: episodes.map((episode) => ({
|
||||
value: String(episode),
|
||||
label: `${t('EPISODE')} ${episode}`
|
||||
})),
|
||||
}));
|
||||
}, [seasons]);
|
||||
const selectedSeason = React.useMemo(() => {
|
||||
return { label: String(season), value: String(season) };
|
||||
return { label: String(season.id), value: String(season.id), options: season.episodes.map((episode) => ({
|
||||
value: String(episode),
|
||||
label: `${t('EPISODE')} ${episode}`
|
||||
}))};
|
||||
}, [season]);
|
||||
const prevNextButtonOnClick = React.useCallback((event) => {
|
||||
if (typeof onSelect === 'function') {
|
||||
const seasonIndex = seasons.indexOf(season);
|
||||
const seasonIndex = seasons.findIndex(({ id }) => id === season.id);
|
||||
const valueIndex = event.currentTarget.dataset.action === 'next' ?
|
||||
seasonIndex + 1 < seasons.length ? seasonIndex + 1 : seasons.length - 1
|
||||
:
|
||||
|
|
@ -35,11 +42,12 @@ const SeasonsBar = ({ className, seasons, season, onSelect }) => {
|
|||
});
|
||||
}
|
||||
}, [season, seasons, onSelect]);
|
||||
const seasonOnSelect = React.useCallback((value) => {
|
||||
const seasonOnSelect = React.useCallback((level, value) => {
|
||||
if (typeof onSelect === 'function') {
|
||||
onSelect({
|
||||
type: 'select',
|
||||
value: value,
|
||||
level,
|
||||
reactEvent: event.reactEvent,
|
||||
nativeEvent: event.nativeEvent
|
||||
});
|
||||
|
|
@ -47,7 +55,7 @@ const SeasonsBar = ({ className, seasons, season, onSelect }) => {
|
|||
}, [onSelect]);
|
||||
|
||||
const [prevDisabled, nextDisabled] = React.useMemo(() => {
|
||||
const currentIndex = seasons.indexOf(season);
|
||||
const currentIndex = seasons.findIndex(({ id }) => id === season.id);
|
||||
return [
|
||||
currentIndex === 0,
|
||||
currentIndex === seasons.length - 1
|
||||
|
|
@ -63,7 +71,8 @@ const SeasonsBar = ({ className, seasons, season, onSelect }) => {
|
|||
<MultiselectMenu
|
||||
className={styles['seasons-popup-label-container']}
|
||||
options={options}
|
||||
title={season > 0 ? `${t('SEASON')} ${season}` : t('SPECIAL')}
|
||||
title={season.id > 0 ? `${t('SEASON')} ${season.id}` : t('SPECIAL')}
|
||||
subtitle={episode && `${t('EPISODE')} ${episode}`}
|
||||
selectedOption={selectedSeason}
|
||||
onSelect={seasonOnSelect}
|
||||
/>
|
||||
|
|
@ -79,8 +88,15 @@ SeasonsBar.Placeholder = SeasonsBarPlaceholder;
|
|||
|
||||
SeasonsBar.propTypes = {
|
||||
className: PropTypes.string,
|
||||
seasons: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
season: PropTypes.number.isRequired,
|
||||
seasons: PropTypes.arrayOf(PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
episodes: PropTypes.arrayOf(PropTypes.number),
|
||||
})).isRequired,
|
||||
season: PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
episodes: PropTypes.arrayOf(PropTypes.number),
|
||||
}).isRequired,
|
||||
episode: PropTypes.string,
|
||||
onSelect: PropTypes.func
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const styles = require('./styles');
|
|||
|
||||
const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect, toggleNotifications }) => {
|
||||
const { core } = useServices();
|
||||
const [selectedEpisode, setSelectedEpisode] = React.useState(null);
|
||||
const showNotificationsToggle = React.useMemo(() => {
|
||||
return metaItem?.content?.content?.inLibrary && metaItem?.content?.content?.videos?.length;
|
||||
}, [metaItem]);
|
||||
|
|
@ -21,22 +22,19 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect,
|
|||
[];
|
||||
}, [metaItem]);
|
||||
const seasons = React.useMemo(() => {
|
||||
return videos
|
||||
.map(({ season }) => season)
|
||||
.filter((season, index, seasons) => {
|
||||
return season !== null &&
|
||||
!isNaN(season) &&
|
||||
typeof season === 'number' &&
|
||||
seasons.indexOf(season) === index;
|
||||
})
|
||||
.sort((a, b) => (a || Number.MAX_SAFE_INTEGER) - (b || Number.MAX_SAFE_INTEGER));
|
||||
return [...new Set(videos.map(({ season }) => season))].map((season) => ({
|
||||
id: season,
|
||||
episodes: videos.filter(({ season: s }) => s === season).map(({ episode }) => episode)
|
||||
}))
|
||||
.sort((a, b) => (a.id || Number.MAX_SAFE_INTEGER) - (b.id || Number.MAX_SAFE_INTEGER));
|
||||
}, [videos]);
|
||||
const selectedSeason = React.useMemo(() => {
|
||||
if (seasons.includes(season)) {
|
||||
return season;
|
||||
const foundSeason = seasons.find(({ id }) => id === season);
|
||||
if (foundSeason) {
|
||||
return foundSeason;
|
||||
}
|
||||
|
||||
const nonSpecialSeasons = seasons.filter((season) => season !== 0);
|
||||
const nonSpecialSeasons = seasons.filter(({ id }) => id !== 0);
|
||||
if (nonSpecialSeasons.length > 0) {
|
||||
return nonSpecialSeasons[nonSpecialSeasons.length - 1];
|
||||
}
|
||||
|
|
@ -50,7 +48,7 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect,
|
|||
const videosForSeason = React.useMemo(() => {
|
||||
return videos
|
||||
.filter((video) => {
|
||||
return selectedSeason === null || video.season === selectedSeason;
|
||||
return selectedSeason === null || video.season === selectedSeason.id;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return a.episode - b.episode;
|
||||
|
|
@ -71,6 +69,26 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect,
|
|||
});
|
||||
};
|
||||
|
||||
const handleSelect = (event) => {
|
||||
if (!event.level) {
|
||||
seasonOnSelect(event);
|
||||
} else {
|
||||
setSelectedEpisode(event.value);
|
||||
const episode = videos.find(({ season: s, episode: e }) => s === season && e.toString() === event.value);
|
||||
if (episode.deepLinks) {
|
||||
if (typeof episode.deepLinks.player === 'string') {
|
||||
window.location = episode.deepLinks.player;
|
||||
} else if (typeof episode.deepLinks.metaDetailsStreams === 'string') {
|
||||
window.location.replace(episode.deepLinks.metaDetailsStreams);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
setSelectedEpisode(null);
|
||||
}, [season]);
|
||||
|
||||
return (
|
||||
<div className={classnames(className, styles['videos-list-container'])}>
|
||||
{
|
||||
|
|
@ -107,8 +125,9 @@ const VideosList = ({ className, metaItem, libraryItem, season, seasonOnSelect,
|
|||
<SeasonsBar
|
||||
className={styles['seasons-bar']}
|
||||
season={selectedSeason}
|
||||
episode={selectedEpisode}
|
||||
seasons={seasons}
|
||||
onSelect={seasonOnSelect}
|
||||
onSelect={handleSelect}
|
||||
/>
|
||||
:
|
||||
null
|
||||
|
|
|
|||
Loading…
Reference in a new issue