mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-04-20 10:42:12 +00:00
feat(EpisodePicker): added season and episode picker when no streams loaded
This commit is contained in:
parent
e8a6e72b13
commit
15c6a231a6
5 changed files with 86 additions and 3 deletions
|
|
@ -76,6 +76,18 @@ const MetaDetails = ({ urlParams, queryParams }) => {
|
|||
const seasonOnSelect = React.useCallback((event) => {
|
||||
setSeason(event.value);
|
||||
}, [setSeason]);
|
||||
const handleEpisodeSearch = React.useCallback((season, episode) => {
|
||||
const searchVideoId = streamPath.id.replace(/(:\d+:\d+)$/, `:${season}:${episode}`);
|
||||
const videoFound = metaDetails.metaItem.content.content.videos.find((video) => video.id === searchVideoId);
|
||||
if (videoFound) {
|
||||
if (typeof videoFound.deepLinks.player === 'string') {
|
||||
window.location = videoFound.deepLinks.player;
|
||||
} else if (typeof videoFound.deepLinks.metaDetailsStreams === 'string') {
|
||||
window.location.replace(videoFound.deepLinks.metaDetailsStreams);
|
||||
}
|
||||
}
|
||||
}, [streamPath, metaDetails.metaItem]);
|
||||
|
||||
const renderBackgroundImageFallback = React.useCallback(() => null, []);
|
||||
const renderBackground = React.useMemo(() => !!(
|
||||
metaPath &&
|
||||
|
|
@ -129,7 +141,7 @@ const MetaDetails = ({ urlParams, queryParams }) => {
|
|||
metaDetails.metaItem === null ?
|
||||
<div className={styles['meta-message-container']}>
|
||||
<Image className={styles['image']} src={require('/images/empty.png')} alt={' '} />
|
||||
<div className={styles['message-label']}>No addons ware requested for this meta!</div>
|
||||
<div className={styles['message-label']}>No addons were requested for this meta!</div>
|
||||
</div>
|
||||
:
|
||||
metaDetails.metaItem.content.type === 'Err' ?
|
||||
|
|
@ -169,6 +181,7 @@ const MetaDetails = ({ urlParams, queryParams }) => {
|
|||
className={styles['streams-list']}
|
||||
streams={metaDetails.streams}
|
||||
video={video}
|
||||
onEpisodeSearch={handleEpisodeSearch}
|
||||
/>
|
||||
:
|
||||
metaPath !== null ?
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (C) 2017-2025 Smart code 203358507
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem 2.625rem;
|
||||
margin: 2rem 0;
|
||||
background-color: var(--primary-accent-color);
|
||||
transition: 0.3s all ease-in-out;
|
||||
border-radius: 2.625rem;
|
||||
color: var(--primary-foreground-color);
|
||||
border: 2px solid transparent;
|
||||
|
||||
&:hover, &:focus {
|
||||
outline: var(--focus-outline-size) solid var(--primary-foreground-color);
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (C) 2017-2025 Smart code 203358507
|
||||
|
||||
import React, { useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, NumberInput } from 'stremio/components';
|
||||
import styles from './EpisodePicker.less';
|
||||
|
||||
type Props = {
|
||||
className?: string,
|
||||
seriesId: string;
|
||||
onSubmit: (season: number, episode: number) => void;
|
||||
};
|
||||
export const EpisodePicker = ({ className, seriesId, onSubmit }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const [initialSeason, initialEpisode] = React.useMemo(() => {
|
||||
const [, season, episode] = seriesId ? seriesId.split(':') : [];
|
||||
return [parseInt(season || '1'), parseInt(episode || '1')];
|
||||
}, [seriesId]);
|
||||
const seasonRef = useRef(null);
|
||||
const episodeRef = useRef(null);
|
||||
|
||||
const handleSubmit = React.useCallback(() => {
|
||||
const season = seasonRef.current?.value;
|
||||
const episode = episodeRef.current?.value;
|
||||
if (typeof onSubmit === 'function') onSubmit(season, episode);
|
||||
}, [onSubmit, seasonRef, episodeRef]);
|
||||
|
||||
return <div className={className}>
|
||||
<NumberInput ref={seasonRef} min={1} label={t('SEASON')} defaultValue={initialSeason} showButtons />
|
||||
<NumberInput ref={episodeRef} min={1} label={t('EPISODE')} defaultValue={initialEpisode} showButtons />
|
||||
<Button className={styles['button-container']} onClick={handleSubmit}>{t('SIDEBAR_SHOW_STREAMS')}</Button>
|
||||
</div>;
|
||||
};
|
||||
|
||||
export default EpisodePicker;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright (C) 2017-2025 Smart code 203358507
|
||||
|
||||
import SeasonEpisodePicker from './EpisodePicker';
|
||||
|
||||
export default {
|
||||
SeasonEpisodePicker
|
||||
};
|
||||
|
|
@ -10,10 +10,11 @@ const { useServices } = require('stremio/services');
|
|||
const Stream = require('./Stream');
|
||||
const styles = require('./styles');
|
||||
const { usePlatform, useProfile } = require('stremio/common');
|
||||
const { SeasonEpisodePicker } = require('./EpisodePicker');
|
||||
|
||||
const ALL_ADDONS_KEY = 'ALL';
|
||||
|
||||
const StreamsList = ({ className, video, ...props }) => {
|
||||
const StreamsList = ({ className, video, onEpisodeSearch, ...props }) => {
|
||||
const { t } = useTranslation();
|
||||
const { core } = useServices();
|
||||
const platform = usePlatform();
|
||||
|
|
@ -93,6 +94,11 @@ const StreamsList = ({ className, video, ...props }) => {
|
|||
onSelect: onAddonSelected
|
||||
};
|
||||
}, [streamsByAddon, selectedAddon]);
|
||||
|
||||
const handleEpisodePicker = React.useCallback((season, episode) => {
|
||||
onEpisodeSearch(season, episode);
|
||||
}, [onEpisodeSearch]);
|
||||
|
||||
return (
|
||||
<div className={classnames(className, styles['streams-list-container'])}>
|
||||
<div className={styles['select-choices-wrapper']}>
|
||||
|
|
@ -122,12 +128,14 @@ const StreamsList = ({ className, video, ...props }) => {
|
|||
{
|
||||
props.streams.length === 0 ?
|
||||
<div className={styles['message-container']}>
|
||||
<SeasonEpisodePicker seriesId={video?.id} onSubmit={handleEpisodePicker} />
|
||||
<Image className={styles['image']} src={require('/images/empty.png')} alt={' '} />
|
||||
<div className={styles['label']}>No addons were requested for streams!</div>
|
||||
</div>
|
||||
:
|
||||
props.streams.every((streams) => streams.content.type === 'Err') ?
|
||||
<div className={styles['message-container']}>
|
||||
<SeasonEpisodePicker seriesId={video?.id} onSubmit={handleEpisodePicker} />
|
||||
<Image className={styles['image']} src={require('/images/empty.png')} alt={' '} />
|
||||
<div className={styles['label']}>{t('NO_STREAM')}</div>
|
||||
{
|
||||
|
|
@ -193,7 +201,8 @@ const StreamsList = ({ className, video, ...props }) => {
|
|||
StreamsList.propTypes = {
|
||||
className: PropTypes.string,
|
||||
streams: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
video: PropTypes.object
|
||||
video: PropTypes.object,
|
||||
onEpisodeSearch: PropTypes.func
|
||||
};
|
||||
|
||||
module.exports = StreamsList;
|
||||
|
|
|
|||
Loading…
Reference in a new issue