mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
Merge pull request #176 from Stremio/video-season
selected season as query param
This commit is contained in:
commit
ca4e19339d
4 changed files with 45 additions and 151 deletions
|
|
@ -9,7 +9,7 @@ const useMetaDetails = require('./useMetaDetails');
|
|||
const useMetaExtensions = require('./useMetaExtensions');
|
||||
const styles = require('./styles');
|
||||
|
||||
const MetaDetails = ({ urlParams }) => {
|
||||
const MetaDetails = ({ urlParams, queryParams }) => {
|
||||
const metaDetails = useMetaDetails(urlParams);
|
||||
const { tabs, selectedMetaExtension, clearSelectedMetaExtension } = useMetaExtensions(metaDetails.meta_resources);
|
||||
const metaResourceRef = React.useMemo(() => {
|
||||
|
|
@ -26,6 +26,15 @@ const MetaDetails = ({ urlParams }) => {
|
|||
}, [metaDetails]);
|
||||
const streamsResourceRef = metaDetails.selected !== null ? metaDetails.selected.streams_resource_ref : null;
|
||||
const streamsResources = metaDetails.streams_resources;
|
||||
const seasonQueryParam = React.useMemo(() => {
|
||||
return queryParams.has('season') && !isNaN(queryParams.get('season')) ?
|
||||
parseInt(queryParams.get('season'))
|
||||
:
|
||||
null;
|
||||
}, [queryParams]);
|
||||
const seasonOnSelect = React.useCallback((event) => {
|
||||
window.location.replace(`#/metadetails/${selectedMetaResource.request.path.type_name}/${selectedMetaResource.request.path.id}?season=${event.value}`);
|
||||
}, [selectedMetaResource]);
|
||||
const selectedVideo = React.useMemo(() => {
|
||||
return streamsResourceRef !== null && selectedMetaResource !== null ?
|
||||
selectedMetaResource.content.content.videos.reduce((result, video) => {
|
||||
|
|
@ -125,6 +134,8 @@ const MetaDetails = ({ urlParams }) => {
|
|||
<VideosList
|
||||
className={styles['videos-list']}
|
||||
metaResource={selectedMetaResource}
|
||||
season={seasonQueryParam}
|
||||
seasonOnSelect={seasonOnSelect}
|
||||
/>
|
||||
:
|
||||
null
|
||||
|
|
|
|||
|
|
@ -7,20 +7,44 @@ const Image = require('stremio/common/Image');
|
|||
const SearchBar = require('stremio/common/SearchBar');
|
||||
const SeasonsBar = require('./SeasonsBar');
|
||||
const Video = require('./Video');
|
||||
const useSelectableSeasons = require('./useSelectableSeasons');
|
||||
const styles = require('./styles');
|
||||
|
||||
const VideosList = ({ className, metaResource }) => {
|
||||
const VideosList = ({ className, metaResource, season, seasonOnSelect }) => {
|
||||
const videos = React.useMemo(() => {
|
||||
return metaResource && metaResource.content.type === 'Ready' ?
|
||||
metaResource.content.content.videos
|
||||
:
|
||||
[];
|
||||
}, [metaResource]);
|
||||
const [seasons, selectedSeason, videosForSeason, selectSeason] = useSelectableSeasons(videos);
|
||||
const seasonOnSelect = React.useCallback((event) => {
|
||||
selectSeason(event.value);
|
||||
}, []);
|
||||
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 - b);
|
||||
}, [videos]);
|
||||
const selectedSeason = React.useMemo(() => {
|
||||
return seasons.includes(season) ?
|
||||
season
|
||||
:
|
||||
seasons.length > 0 ?
|
||||
seasons[seasons.length - 1]
|
||||
:
|
||||
null;
|
||||
}, [seasons, season]);
|
||||
const videosForSeason = React.useMemo(() => {
|
||||
return videos
|
||||
.filter((video) => {
|
||||
return selectedSeason === null || video.season === selectedSeason;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return a.episode - b.episode;
|
||||
});
|
||||
}, [videos, selectedSeason]);
|
||||
const [search, setSearch] = React.useState('');
|
||||
const searchInputOnChange = React.useCallback((event) => {
|
||||
setSearch(event.currentTarget.value);
|
||||
|
|
@ -88,7 +112,9 @@ const VideosList = ({ className, metaResource }) => {
|
|||
|
||||
VideosList.propTypes = {
|
||||
className: PropTypes.string,
|
||||
metaResource: PropTypes.object
|
||||
metaResource: PropTypes.object,
|
||||
season: PropTypes.number,
|
||||
seasonOnSelect: PropTypes.func
|
||||
};
|
||||
|
||||
module.exports = VideosList;
|
||||
|
|
|
|||
|
|
@ -1,91 +0,0 @@
|
|||
// Copyright (C) 2017-2020 Smart code 203358507
|
||||
|
||||
const React = require('react');
|
||||
|
||||
const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case 'videos-changed': {
|
||||
const seasons = action.videos
|
||||
.map(({ season }) => season)
|
||||
.filter((season, index, seasons) => {
|
||||
return season !== null &&
|
||||
!isNaN(season) &&
|
||||
typeof season === 'number' &&
|
||||
seasons.indexOf(season) === index;
|
||||
})
|
||||
.sort((a, b) => a - b);
|
||||
const selectedSeason = seasons.includes(state.selectedSeason) ?
|
||||
state.selectedSeason
|
||||
:
|
||||
seasons.length > 0 ?
|
||||
seasons[seasons.length - 1]
|
||||
:
|
||||
null;
|
||||
return {
|
||||
...state,
|
||||
videos: action.videos,
|
||||
seasons,
|
||||
selectedSeason
|
||||
};
|
||||
}
|
||||
case 'season-changed': {
|
||||
const selectedSeason = state.seasons.includes(action.season) ?
|
||||
action.season
|
||||
:
|
||||
state.season;
|
||||
return {
|
||||
...state,
|
||||
selectedSeason
|
||||
};
|
||||
}
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const initializer = (videos) => {
|
||||
const initialState = {
|
||||
videos: [],
|
||||
seasons: [],
|
||||
selectedSeason: null
|
||||
};
|
||||
const initAction = {
|
||||
type: 'videos-changed',
|
||||
videos
|
||||
};
|
||||
|
||||
return reducer(initialState, initAction);
|
||||
};
|
||||
|
||||
const useSelectableSeasons = (videos) => {
|
||||
const [state, dispatch] = React.useReducer(
|
||||
reducer,
|
||||
videos,
|
||||
initializer
|
||||
);
|
||||
const selectSeason = React.useCallback((season) => {
|
||||
dispatch({
|
||||
type: 'season-changed',
|
||||
season
|
||||
});
|
||||
}, []);
|
||||
const videosForSeason = React.useMemo(() => {
|
||||
return state.videos
|
||||
.filter((video) => {
|
||||
return state.selectedSeason === null || video.season === state.selectedSeason;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return a.episode - b.episode;
|
||||
});
|
||||
}, [state.videos, state.selectedSeason]);
|
||||
React.useEffect(() => {
|
||||
dispatch({
|
||||
type: 'videos-changed',
|
||||
videos
|
||||
});
|
||||
}, [videos]);
|
||||
return [state.seasons, state.selectedSeason, videosForSeason, selectSeason];
|
||||
};
|
||||
|
||||
module.exports = useSelectableSeasons;
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
// Copyright (C) 2017-2020 Smart code 203358507
|
||||
|
||||
const { renderHook, act } = require('@testing-library/react-hooks');
|
||||
const useSelectableSeasons = require('../src/routes/MetaDetails/VideosList/useSelectableSeasons');
|
||||
|
||||
const videos = [{ 'season': 4 }, { 'season': 5 }, { 'season': 4 }, { 'season': 7 }];
|
||||
|
||||
describe('hooks tests', () => {
|
||||
describe('useSelectableSeasons hook', () => {
|
||||
it('match 7', async () => {
|
||||
const { result } = renderHook(() => useSelectableSeasons(videos));
|
||||
const [, selectedSeason] = result.current;
|
||||
expect(selectedSeason).toBe(7);
|
||||
});
|
||||
|
||||
it('match 5', async () => {
|
||||
const { result } = renderHook(() => useSelectableSeasons(videos));
|
||||
|
||||
act(() => {
|
||||
const [, , , selectSeason] = result.current;
|
||||
selectSeason(5);
|
||||
});
|
||||
|
||||
const [, selectedSeason] = result.current;
|
||||
expect(selectedSeason).toBe(5);
|
||||
});
|
||||
|
||||
it('not match 6', async () => {
|
||||
const { result } = renderHook(() => useSelectableSeasons(videos));
|
||||
|
||||
act(() => {
|
||||
const [, , , selectSeason] = result.current;
|
||||
selectSeason(6);
|
||||
});
|
||||
|
||||
const [, selectedSeason] = result.current;
|
||||
expect(selectedSeason).toBe(undefined);
|
||||
});
|
||||
|
||||
it('not match $', async () => {
|
||||
const { result } = renderHook(() => useSelectableSeasons(videos));
|
||||
|
||||
act(() => {
|
||||
const [, , , selectSeason] = result.current;
|
||||
selectSeason('$');
|
||||
});
|
||||
|
||||
const [, selectedSeason] = result.current;
|
||||
expect(selectedSeason).toBe(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue