diff --git a/src/routes/Discover/Discover.js b/src/routes/Discover/Discover.js
index e060cb12f..6954cbed0 100644
--- a/src/routes/Discover/Discover.js
+++ b/src/routes/Discover/Discover.js
@@ -1,14 +1,15 @@
const React = require('react');
const classnames = require('classnames');
-const { Dropdown, MainNavBar, MetaItem, MetaPreview } = require('stremio/common');
+const { MainNavBar, MetaItem, MetaPreview, Multiselect } = require('stremio/common');
const useCatalog = require('./useCatalog');
const styles = require('./styles');
+// TODO render only 4 pickers and a more button that opens a modal with all pickers
const Discover = ({ urlParams, queryParams }) => {
const [dropdowns, metaItems] = useCatalog(urlParams, queryParams);
const [selectedItem, setSelectedItem] = React.useState(null);
const metaItemsOnMouseDown = React.useCallback((event) => {
- event.nativeEvent.blurPrevented = true;
+ event.nativeEvent.buttonBlurPrevented = true;
}, []);
const metaItemsOnFocus = React.useCallback((event) => {
const metaItem = metaItems.find(({ id }) => {
@@ -27,8 +28,8 @@ const Discover = ({ urlParams, queryParams }) => {
- {dropdowns.map((dropdown) => (
-
+ {dropdowns.map((dropdown, index) => (
+
))}
diff --git a/src/routes/Discover/styles.less b/src/routes/Discover/styles.less
index 0f8251548..8f972da85 100644
--- a/src/routes/Discover/styles.less
+++ b/src/routes/Discover/styles.less
@@ -17,7 +17,7 @@
align-self: stretch;
display: grid;
grid-template-columns: 1fr 26rem;
- grid-template-rows: fit-content(15rem) 1fr;
+ grid-template-rows: 7rem 1fr;
grid-template-areas:
"dropdowns-area meta-preview-area"
"meta-items-area meta-preview-area";
@@ -29,7 +29,7 @@
grid-gap: 1rem;
margin: 2rem 0;
padding: 0 2rem;
- overflow-y: auto;
+ overflow: visible;
.dropdown {
height: 3rem;
diff --git a/src/routes/Discover/useCatalog.js b/src/routes/Discover/useCatalog.js
index 77dc11da4..bb81dbf13 100644
--- a/src/routes/Discover/useCatalog.js
+++ b/src/routes/Discover/useCatalog.js
@@ -1,104 +1,105 @@
const React = require('react');
+const { useServices } = require('stremio/services');
+
+const DEFAULT_TYPE = 'movie';
+const DEFAULT_ADDON_ID = 'com.linvo.cinemeta';
+const DEFAULT_CATALOG_ID = 'top';
const useCatalog = (urlParams, queryParams) => {
- const queryString = new URLSearchParams(queryParams).toString();
- const [addon, catalog] = React.useMemo(() => {
- // TODO impl this logic to stremio-core for code-reuse:
- // TODO use type if it is part of user's addons
- // TODO fallback to first type from user's addons
- // TODO find catalog for addonId, catalogId and type
- // TODO fallback to first catalog for the type from user's catalogs
- const addon = {
- id: 'com.linvo.cinemeta',
- version: '2.11.0',
- name: 'Cinemeta'
- };
- const catalog = {
- id: 'top',
- type: 'movie',
- name: 'Top',
- extra: [
- {
- name: 'genre',
- isRequired: false,
- options: ['Action', 'Drama', 'Boring']
- },
- {
- name: 'year',
- isRequired: false,
- options: ['2017', '2016', '2015']
+ const { core } = useServices();
+ const [selectInputs, setSelectInputs] = React.useState([]);
+ React.useEffect(() => {
+ const onNewModel = () => {
+ const state = core.getState();
+ const typeSelectInput = {
+ options: [{ value: urlParams.type, label: urlParams.type }].concat(state.discover.types.map(({ type_name }) => ({
+ value: type_name,
+ label: type_name
+ }))).filter((item, index, array) => {
+ // TODO findIndexRight
+ return array.findIndex(({ value }) => value === item.value) === index;
+ }),
+ selected: [urlParams.type].concat(state.discover.types.filter(({ is_selected }) => is_selected)
+ .map(({ type_name }) => type_name))
+ .filter((item, index, array) => {
+ return array.indexOf(item) === index;
+ }),
+ onSelect: (event) => {
+ const value = event.reactEvent.currentTarget.dataset.value;
+ // TODO queryparams
+ window.location = `#/discover/${value}/${typeof urlParams.catalog === 'string' ? urlParams.catalog : ''}`;
}
- ]
+ };
+ console.log(typeSelectInput);
+ setSelectInputs([typeSelectInput]);
};
- return [addon, catalog];
- }, [urlParams.type, urlParams.catalog]);
- const dropdowns = React.useMemo(() => {
- const onTypeChange = (event) => {
- const { value } = event.currentTarget.dataset;
- const query = new URLSearchParams(queryParams);
- window.location = `#/discover/${value}/${addon.id}:${catalog.id}?${query}`;
+ core.on('NewModel', onNewModel);
+ return () => {
+ core.off('NewModel', onNewModel);
};
- const onCatalogChange = (event) => {
- const { value } = event.currentTarget.dataset;
- const query = new URLSearchParams(queryParams);
- window.location = `#/discover/${catalog.type}/${value}?${query}`;
- };
- const onQueryParamChange = (event) => {
- const { name, value } = event.currentTarget.dataset;
- const query = new URLSearchParams({ ...queryParams, [name]: value });
- window.location = `#/discover/${catalog.type}/${addon.id}:${catalog.id}?${query}`;
- };
- const requiredDropdowns = [
- {
- name: 'type',
- selected: [catalog.type],
- options: [
- { value: 'movie', label: 'movie' },
- { value: 'series', label: 'series' },
- { value: 'channels', label: 'channels' },
- { value: 'games', label: 'games' }
- ],
- onSelect: onTypeChange
- },
- {
- name: 'catalog',
- selected: [`${addon.id}:${catalog.id}`],
- options: [
- { value: 'com.linvo.cinemeta:top', label: 'Top' },
- { value: 'com.linvo.cinemeta:year', label: 'By year' }
- ],
- onSelect: onCatalogChange
+ }, [urlParams, queryParams]);
+ React.useEffect(() => {
+ const state = core.getState();
+ let type = DEFAULT_TYPE;
+ let addonId = DEFAULT_ADDON_ID;
+ let catalogId = DEFAULT_CATALOG_ID;
+ if (typeof urlParams.type === 'string' && urlParams.type.length > 0) {
+ type = urlParams.type;
+ addonId = null;
+ catalogId = null;
+ if (typeof urlParams.catalog === 'string' && urlParams.catalog.includes(':')) {
+ [addonId = '', catalogId = ''] = urlParams.catalog.split(':');
}
- ];
- const extraDropdowns = catalog.extra
- .filter((extra) => {
- return extra.name !== 'skip' && extra.name !== 'search';
- })
- .map((extra) => ({
- ...extra,
- onSelect: onQueryParamChange,
- options: extra.options.map((option) => ({ value: option, label: option })),
- selected: extra.options.includes(queryParams[extra.name]) ?
- [queryParams[extra.name]]
- :
- extra.isRequired ?
- [extra.options[0]]
- :
- []
- }));
- return requiredDropdowns.concat(extraDropdowns);
- }, [addon, catalog, queryString]);
- const items = React.useMemo(() => {
- return Array(100).fill(null).map((_, index) => ({
- id: `tt${index}`,
- type: 'movie',
- name: `Stremio demo item ${index}`,
- poster: `https://www.stremio.com/website/technology-hero.jpg`,
- logo: `https://www.stremio.com/website/stremio-logo-small.png`,
- posterShape: 'poster'
- }));
- }, []);
- return [dropdowns, items];
+ }
+
+ const [addon, catalog] = state.ctx.content.addons.reduceRight((result, addon) => {
+ if (typeof addonId !== 'string' || addonId === addon.manifest.id) {
+ const catalog = addon.manifest.catalogs.find((catalog) => {
+ return (typeof catalogId !== 'string' || catalogId === catalog.id) &&
+ catalog.type === type; // TODO && extraRequired.every(...);
+ });
+ if (catalog) {
+ return [addon, catalog];
+ }
+ }
+
+ return result;
+ }, []);
+ if (catalog) {
+ core.dispatch({
+ action: 'Load',
+ args: {
+ load: 'CatalogFiltered',
+ args: {
+ base: addon.transportUrl,
+ path: {
+ resource: 'catalog',
+ type_name: type,
+ id: catalog.id,
+ extra: [] // TODO
+ }
+ }
+ }
+ });
+ } else {
+ core.dispatch({
+ action: 'Load',
+ args: {
+ load: 'CatalogFiltered',
+ args: {
+ base: '',
+ path: {
+ resource: 'catalog',
+ type_name: type,
+ id: '',
+ extra: [] // TODO
+ }
+ }
+ }
+ });
+ }
+ }, [urlParams, queryParams]);
+ return [selectInputs, []];
};
module.exports = useCatalog;