diff --git a/src/routes/Library/Library.js b/src/routes/Library/Library.js index 5b75fcfaf..95ed7eb93 100644 --- a/src/routes/Library/Library.js +++ b/src/routes/Library/Library.js @@ -1,26 +1,27 @@ const React = require('react'); -const { Dropdown, MainNavBar, MetaItem } = require('stremio/common'); +const { Multiselect, MainNavBar, MetaItem } = require('stremio/common'); const useLibrary = require('./useLibrary'); const styles = require('./styles'); const Library = ({ urlParams, queryParams }) => { - const [metaItems, dropdowns] = useLibrary(urlParams.type, queryParams.get('sort')); + const [metaItems, dropdowns] = useLibrary(urlParams, queryParams); return (
- {dropdowns.map((dropdown) => ( - + {dropdowns.map((dropdown, index) => ( + ))}
- {metaItems.map((metaItem) => ( - - ))} + {metaItems + .map((metaItem, index) => ( + + ))}
diff --git a/src/routes/Library/styles.less b/src/routes/Library/styles.less index 156166891..31a302c9e 100644 --- a/src/routes/Library/styles.less +++ b/src/routes/Library/styles.less @@ -27,6 +27,7 @@ display: flex; flex-direction: row; margin: 2rem; + overflow: visible; .dropdown { flex-grow: 0; diff --git a/src/routes/Library/useLibrary.js b/src/routes/Library/useLibrary.js index 452f63bd9..73291f847 100644 --- a/src/routes/Library/useLibrary.js +++ b/src/routes/Library/useLibrary.js @@ -1,99 +1,69 @@ const React = require('react'); +const { useServices } = require('stremio/services'); const DEFAULT_TYPE = 'movie'; -const libraryItems = [ - { - id: '1', - type: 'movie', - name: 'Stremio demo item movie 1', - poster: '/images/intro_background.jpg', - logo: '/images/default_avatar.png', - posterShape: 'poster' - }, - { - id: '2', - type: 'movie', - name: 'Stremio demo item movie 2', - poster: '/images/intro_background.jpg', - logo: '/images/default_avatar.png', - posterShape: 'poster' - }, - { - id: '3', - type: 'series', - name: 'Stremio demo item series 1', - poster: '/images/default_avatar.png', - logo: '/images/default_avatar.png', - posterShape: 'poster' - }, - { - id: '4', - type: 'series', - name: 'Stremio demo item series 2', - poster: '/images/default_avatar.png', - logo: '/images/default_avatar.png', - posterShape: 'poster' - }, - { - id: '5', - type: 'channel', - name: 'Stremio demo item channel 1', - poster: '/images/anonymous.png', - logo: '/images/default_avatar.png', - posterShape: 'square' - }, - { - id: '6', - type: 'channel', - name: 'Stremio demo item channel 2', - poster: '/images/anonymous.png', - logo: '/images/default_avatar.png', - posterShape: 'square' - } -]; +const DEFAULT_SORT = 'recent'; -const useLibrary = (type, sort) => { - type = typeof type === 'string' && type.length > 0 ? type : DEFAULT_TYPE; - const items = React.useMemo(() => { - return libraryItems.filter(item => item.type === type); - }, [type, sort]); - const onSelect = React.useCallback((event) => { - const { name, value } = event.currentTarget.dataset; - if (name === 'type') { - const nextQuery = new URLSearchParams({ sort: typeof sort === 'string' ? sort : '' }); - const nextType = typeof value === 'string' ? value : ''; - window.location.replace(`#/library/${nextType}?${nextQuery}`); - } else if (name === 'sort') { - const nextQuery = new URLSearchParams({ sort: typeof value === 'string' ? value : '' }); - const nextType = typeof type === 'string' ? type : ''; - window.location.replace(`#/library/${nextType}?${nextQuery}`); +const useLibrary = (urlParams, queryParams) => { + const { core } = useServices(); + const [library, setLibrary] = React.useState([[], []]); + + React.useEffect(() => { + const type = typeof urlParams.type === 'string' && urlParams.type.length > 0 ? urlParams.type : DEFAULT_TYPE; + const sort = typeof queryParams.get('sort') === 'string' && queryParams.get('sort').length > 0 ? queryParams.get('sort') : DEFAULT_SORT; + const onNewState = () => { + const state = core.getState(); + const sortItems = (items, prop) => { + return items + .filter(item => !item.removed) + .sort((a, b) => { + if (a[prop] < b[prop]) return -1; + if (a[prop] > b[prop]) return 1; + return 0; + }); + } + const selectInputs = [ + { + selected: [type], + options: state.library.types + .map((type) => ({ + label: type, + value: type + })), + onSelect: (event) => { + const value = event.value; + const nextQuery = new URLSearchParams({ sort: typeof sort === 'string' ? sort : '' }); + const nextType = typeof value === 'string' ? value : ''; + window.location.replace(`#/library/${nextType}?${nextQuery}`); + } + }, + { + selected: [sort], + options: [{ label: 'A-Z', value: 'a-z' }, { label: 'Recent', value: 'recent' }], + onSelect: (event) => { + const value = event.value; + const nextQuery = new URLSearchParams({ sort: typeof value === 'string' ? value : '' }); + const nextType = typeof type === 'string' ? type : ''; + window.location.replace(`#/library/${nextType}?${nextQuery}`); + } + } + ]; + const items = sort === 'recent' ? sortItems(state.library.items, '_ctime') : sortItems(state.library.items, 'name'); + setLibrary([items, selectInputs]); } - }, [type, sort]); - const typeDropdown = React.useMemo(() => { - const selected = typeof type === 'string' && type.length > 0 ? [type] : []; - const options = libraryItems - .map(({ type }) => type) - .concat(selected) - .filter((type, index, types) => types.indexOf(type) === index) - .map((type) => ({ label: type, value: type })); - return { - name: 'type', - selected, - options, - onSelect + core.on('NewModel', onNewState); + core.dispatch({ + action: 'Load', + args: { + load: 'LibItemsByType', + args: type + } + }); + return () => { + core.off('NewModel', onNewState); }; - }, [type, onSelect]); - const sortDropdown = React.useMemo(() => { - const selected = typeof sort === 'string' && sort.length > 0 ? [sort] : []; - const options = [{ label: 'A-Z', value: 'a-z' }, { label: 'Recent', value: 'recent' }]; - return { - name: 'sort', - selected, - options, - onSelect - }; - }, [sort, onSelect]); - return [items, [typeDropdown, sortDropdown]]; -}; + }, [urlParams, queryParams]); + return library; +} module.exports = useLibrary;