mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-04-19 22:12:13 +00:00
feat(StreamsList): add multiselect to filter streams by addons
This commit is contained in:
parent
c89072e329
commit
704af55ccb
2 changed files with 86 additions and 16 deletions
|
|
@ -4,13 +4,19 @@ const React = require('react');
|
|||
const PropTypes = require('prop-types');
|
||||
const classnames = require('classnames');
|
||||
const Icon = require('@stremio/stremio-icons/dom');
|
||||
const { Button, Image } = require('stremio/common');
|
||||
const { Button, Image, Multiselect } = require('stremio/common');
|
||||
const { useServices } = require('stremio/services');
|
||||
const Stream = require('./Stream');
|
||||
const styles = require('./styles');
|
||||
|
||||
const ALL_ADDONS_KEY = 'ALL';
|
||||
|
||||
const StreamsList = ({ className, ...props }) => {
|
||||
const { core } = useServices();
|
||||
const [selectedAddon, setSelectedAddon] = React.useState(ALL_ADDONS_KEY);
|
||||
const onAddonSelected = React.useCallback((event) => {
|
||||
setSelectedAddon(event.value);
|
||||
}, []);
|
||||
const streams = React.useMemo(() => {
|
||||
return props.streams
|
||||
.filter((streams) => streams.content.type === 'Ready')
|
||||
|
|
@ -25,11 +31,39 @@ const StreamsList = ({ className, ...props }) => {
|
|||
}
|
||||
});
|
||||
},
|
||||
transportUrl: streams.addon.transportUrl,
|
||||
addonName: streams.addon.manifest.name
|
||||
}));
|
||||
})
|
||||
.flat(1);
|
||||
}, [props.streams]);
|
||||
const filteredStreams = React.useMemo(() => {
|
||||
return selectedAddon === ALL_ADDONS_KEY ?
|
||||
streams
|
||||
:
|
||||
streams.filter((stream) => stream.transportUrl === selectedAddon);
|
||||
}, [streams, selectedAddon]);
|
||||
const selectableOptions = React.useMemo(() => {
|
||||
const transportUrls = [...new Set(streams.map(({ transportUrl }) => transportUrl))];
|
||||
const sortedStreams = transportUrls.map((transportUrl) => streams.filter((stream) => stream.transportUrl === transportUrl));
|
||||
return {
|
||||
title: 'Select Addon',
|
||||
options: [
|
||||
{
|
||||
value: ALL_ADDONS_KEY,
|
||||
label: 'All',
|
||||
title: 'All'
|
||||
},
|
||||
...sortedStreams.map((streams) => ({
|
||||
value: streams[0].transportUrl,
|
||||
label: streams[0].addonName,
|
||||
title: streams[0].addonName
|
||||
}))
|
||||
],
|
||||
selected: [selectedAddon],
|
||||
onSelect: onAddonSelected
|
||||
};
|
||||
}, [streams, selectedAddon]);
|
||||
return (
|
||||
<div className={classnames(className, styles['streams-list-container'])}>
|
||||
{
|
||||
|
|
@ -45,26 +79,32 @@ const StreamsList = ({ className, ...props }) => {
|
|||
<div className={styles['label']}>No streams were found!</div>
|
||||
</div>
|
||||
:
|
||||
streams.length === 0 ?
|
||||
filteredStreams.length === 0 ?
|
||||
<div className={styles['streams-container']}>
|
||||
<Stream.Placeholder />
|
||||
<Stream.Placeholder />
|
||||
</div>
|
||||
:
|
||||
<div className={styles['streams-container']}>
|
||||
{streams.map((stream, index) => (
|
||||
<Stream
|
||||
key={index}
|
||||
addonName={stream.addonName}
|
||||
name={stream.name}
|
||||
description={stream.description}
|
||||
thumbnail={stream.thumbnail}
|
||||
progress={stream.progress}
|
||||
deepLinks={stream.deepLinks}
|
||||
onClick={stream.onClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<React.Fragment>
|
||||
<Multiselect
|
||||
{...selectableOptions}
|
||||
className={styles['select-input-container']}
|
||||
/>
|
||||
<div className={styles['streams-container']}>
|
||||
{filteredStreams.map((stream, index) => (
|
||||
<Stream
|
||||
key={index}
|
||||
addonName={stream.addonName}
|
||||
name={stream.name}
|
||||
description={stream.description}
|
||||
thumbnail={stream.thumbnail}
|
||||
progress={stream.progress}
|
||||
deepLinks={stream.deepLinks}
|
||||
onClick={stream.onClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
<Button className={styles['install-button-container']} title={'Install Addons'} href={'#/addons'}>
|
||||
<Icon className={styles['icon']} icon={'ic_addons'} />
|
||||
|
|
|
|||
|
|
@ -3,6 +3,12 @@
|
|||
@import (reference) '~@stremio/stremio-colors/less/stremio-colors.less';
|
||||
@import (reference) '~stremio/common/screen-sizes.less';
|
||||
|
||||
:import('~stremio/common/Multiselect/styles.less') {
|
||||
multiselect-menu-container: menu-container;
|
||||
multiselect-label: label;
|
||||
multiselect-icon: icon;
|
||||
}
|
||||
|
||||
.streams-list-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -35,6 +41,30 @@
|
|||
}
|
||||
}
|
||||
|
||||
.select-input-container {
|
||||
flex: 0 0 auto;
|
||||
height: 3.5rem;
|
||||
margin: 1em 1em 0 1em;
|
||||
background: none;
|
||||
|
||||
&:hover, &:focus, &:global(.active) {
|
||||
background-color: @color-background;
|
||||
}
|
||||
|
||||
& >.multiselect-label {
|
||||
color: @color-surface-light5-90;
|
||||
}
|
||||
|
||||
& >.multiselect-icon {
|
||||
fill: @color-surface-light5-90;
|
||||
}
|
||||
|
||||
.multiselect-menu-container {
|
||||
max-height: calc(3.2rem * 7);
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.streams-container {
|
||||
flex: 0 1 auto;
|
||||
align-self: stretch;
|
||||
|
|
|
|||
Loading…
Reference in a new issue