mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
Search adapted to changes in core
This commit is contained in:
parent
f2607b2454
commit
b6c1f142cc
5 changed files with 79 additions and 94 deletions
|
|
@ -7,9 +7,8 @@ const MetaItem = require('stremio/common/MetaItem');
|
|||
const MetaRowPlaceholder = require('./MetaRowPlaceholder');
|
||||
const styles = require('./styles');
|
||||
|
||||
const MetaRow = ({ className, title, message, items, maximumItemsCount, itemMenuOptions, catalogHref }) => {
|
||||
maximumItemsCount = maximumItemsCount !== null && isFinite(maximumItemsCount) ? maximumItemsCount : 20;
|
||||
items = Array.isArray(items) ? items.slice(0, maximumItemsCount) : [];
|
||||
const MetaRow = ({ className, title, message, items, limit, href }) => {
|
||||
items = Array.isArray(items) ? items.slice(0, limit) : [];
|
||||
return (
|
||||
<div className={classnames(className, styles['meta-row-container'])}>
|
||||
{
|
||||
|
|
@ -28,17 +27,14 @@ const MetaRow = ({ className, title, message, items, maximumItemsCount, itemMenu
|
|||
<MetaItem
|
||||
{...item}
|
||||
key={index}
|
||||
data-id={item.id}
|
||||
data-type={item.type}
|
||||
className={classnames(styles['meta-item'], styles['poster-shape-poster'], styles[`poster-shape-${item.posterShape}`])}
|
||||
menuOptions={itemMenuOptions}
|
||||
/>
|
||||
))}
|
||||
{Array(Math.max(maximumItemsCount - items.length, 0)).fill(null).map((_, index) => (
|
||||
{Array(limit - items.length).fill(null).map((_, index) => (
|
||||
<div key={index} className={classnames(styles['meta-item'], styles['poster-shape-poster'])} />
|
||||
))}
|
||||
</div>
|
||||
<Button className={styles['see-all-container']} title={'SEE ALL'} href={catalogHref}>
|
||||
<Button className={styles['see-all-container']} title={'SEE ALL'} href={href}>
|
||||
<div className={styles['label']}>SEE ALL</div>
|
||||
<Icon className={styles['icon']} icon={'ic_arrow_thin_right'} />
|
||||
</Button>
|
||||
|
|
@ -57,9 +53,8 @@ MetaRow.propTypes = {
|
|||
items: PropTypes.arrayOf(PropTypes.shape({
|
||||
posterShape: PropTypes.string
|
||||
})),
|
||||
maximumItemsCount: PropTypes.number,
|
||||
itemMenuOptions: PropTypes.any,
|
||||
catalogHref: PropTypes.string
|
||||
limit: PropTypes.number.isRequired,
|
||||
href: PropTypes.string
|
||||
};
|
||||
|
||||
module.exports = MetaRow;
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ const PropTypes = require('prop-types');
|
|||
const classnames = require('classnames');
|
||||
const styles = require('./styles');
|
||||
|
||||
const MetaRowPlaceholder = ({ className, title, maximumItemsCount }) => {
|
||||
maximumItemsCount = maximumItemsCount !== null && isFinite(maximumItemsCount) ? maximumItemsCount : 20;
|
||||
const MetaRowPlaceholder = ({ className, title, limit }) => {
|
||||
return (
|
||||
<div className={classnames(className, styles['meta-row-placeholder-container'])}>
|
||||
<div className={styles['title-container']} title={title}>{title}</div>
|
||||
<div className={styles['meta-items-container']}>
|
||||
{Array(maximumItemsCount).fill(null).map((_, index) => (
|
||||
{Array(limit).fill(null).map((_, index) => (
|
||||
<div key={index} className={styles['meta-item']}>
|
||||
<div className={styles['poster-container']} />
|
||||
<div className={styles['title-bar-container']} />
|
||||
|
|
@ -24,7 +23,7 @@ const MetaRowPlaceholder = ({ className, title, maximumItemsCount }) => {
|
|||
MetaRowPlaceholder.propTypes = {
|
||||
className: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
maximumItemsCount: PropTypes.number
|
||||
limit: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
module.exports = MetaRowPlaceholder;
|
||||
|
|
|
|||
|
|
@ -5,62 +5,13 @@ const useSearch = require('./useSearch');
|
|||
const styles = require('./styles');
|
||||
|
||||
const Search = ({ queryParams }) => {
|
||||
const search = useSearch(queryParams);
|
||||
const searchSelected = React.useMemo(() => {
|
||||
return search.selected.some(([name, value]) => name === 'search' && value.length > 0)
|
||||
}, [search.selected]);
|
||||
const { selected, catalog_resources } = useSearch(queryParams);
|
||||
return (
|
||||
<div className={styles['search-container']}>
|
||||
<MainNavBar className={styles['nav-bar']} />
|
||||
<div className={styles['search-content']}>
|
||||
{
|
||||
searchSelected ?
|
||||
search.items_groups && search.items_groups.length > 0 ?
|
||||
search.items_groups.some(group => group.content.type !== 'Err') ?
|
||||
search.items_groups.map(({ href, request, content }, index) => {
|
||||
switch (content.type) {
|
||||
case 'Ready':
|
||||
return (
|
||||
<MetaRow
|
||||
key={`${index}${request.base}${content.type} Ready`}
|
||||
className={styles['search-row']}
|
||||
title={`${request.path.id} - ${request.path.type_name}`}
|
||||
items={content.content}
|
||||
catalogHref={href}
|
||||
/>
|
||||
);
|
||||
case 'Err':
|
||||
return (
|
||||
<MetaRow
|
||||
key={`${index}${request.base}${content.type}`}
|
||||
className={styles['search-row']}
|
||||
title={`${request.path.id} - ${request.path.type_name} Err`}
|
||||
message={`${content.content.type} ${typeof content.content.content === 'string' ? content.content.content : ''}`}
|
||||
/>
|
||||
);
|
||||
case 'Loading':
|
||||
return (
|
||||
<MetaRow.Placeholder
|
||||
key={`${index}${request.base}${content.type} Loading`}
|
||||
className={styles['search-row-placeholder']}
|
||||
title={`${request.path.id} - ${request.path.type_name}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})
|
||||
:
|
||||
<div className={styles['message-container']}>
|
||||
<div className={styles['message-content']}>
|
||||
<div className={styles['label']}>No metadata was found</div>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div className={styles['message-container']}>
|
||||
<div className={styles['message-content']}>
|
||||
<div className={styles['label']}> No addons were requested for metadata</div>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
selected === null || selected.extra.every(([name]) => name !== 'search') ?
|
||||
<div className={styles['message-container']}>
|
||||
<div className={styles['message-content']}>
|
||||
<Icon className={styles['icon']} icon={'ic_movies'} />
|
||||
|
|
@ -71,6 +22,48 @@ const Search = ({ queryParams }) => {
|
|||
<div className={styles['label']}>Search for actors, directors and writers</div>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
catalog_resources.length === 0 ?
|
||||
<div className={styles['message-container']}>
|
||||
<div className={styles['message-content']}>
|
||||
<div className={styles['label']}> No addons were requested for catalogs</div>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
catalog_resources.map((catalog, index) => {
|
||||
switch (catalog.content.type) {
|
||||
case 'Ready':
|
||||
return (
|
||||
<MetaRow
|
||||
key={index}
|
||||
className={styles['search-row']}
|
||||
title={catalog.addon_name}
|
||||
items={catalog.content.content}
|
||||
href={catalog.href}
|
||||
limit={10}
|
||||
/>
|
||||
);
|
||||
case 'Err':
|
||||
return (
|
||||
<MetaRow
|
||||
key={index}
|
||||
className={styles['search-row']}
|
||||
title={catalog.addon_name}
|
||||
message={`Error(${catalog.content.content.type})${typeof catalog.content.content.content === 'string' ? ` - ${catalog.content.content.content}` : ''}`}
|
||||
limit={10}
|
||||
/>
|
||||
);
|
||||
case 'Loading':
|
||||
return (
|
||||
<MetaRow.Placeholder
|
||||
key={index}
|
||||
className={styles['search-row-placeholder']}
|
||||
title={catalog.addon_name}
|
||||
limit={10}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
max-height: calc(100% - 10rem);
|
||||
margin: 5rem;
|
||||
|
||||
.message-content {
|
||||
|
|
@ -51,12 +52,16 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: 5rem;
|
||||
}
|
||||
|
||||
.icon {
|
||||
flex: none;
|
||||
width: 6rem;
|
||||
height: 6rem;
|
||||
margin-bottom: 2rem;
|
||||
fill: var(--color-surfacelighter40);
|
||||
fill: var(--color-surfacelighter80);
|
||||
}
|
||||
|
||||
.label {
|
||||
|
|
@ -64,22 +69,18 @@
|
|||
flex-shrink: 1;
|
||||
flex-basis: auto;
|
||||
font-size: 1.2rem;
|
||||
color: var(--color-surfacelighter40);
|
||||
color: var(--color-surfacelighter80);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 5rem;;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: @large) {
|
||||
.board-container {
|
||||
.board-content {
|
||||
.board-row, .board-row-placeholder {
|
||||
.search-container {
|
||||
.search-content {
|
||||
.search-row, .search-row-placeholder {
|
||||
.meta-item, .meta-item-placeholder {
|
||||
&:nth-child(n+9) {
|
||||
display: none;
|
||||
|
|
|
|||
|
|
@ -2,46 +2,43 @@ const React = require('react');
|
|||
const { useServices } = require('stremio/services');
|
||||
|
||||
const mapSearchState = (state) => {
|
||||
const query = state.search.selected.reduceRight((query, [name, value]) => {
|
||||
if (name === 'search') {
|
||||
return value;
|
||||
}
|
||||
return query;
|
||||
}, '');
|
||||
const queryString = state.search.selected !== null ?
|
||||
new URLSearchParams(state.search.selected.extra).toString()
|
||||
:
|
||||
'';
|
||||
const selected = state.search.selected;
|
||||
const items_groups = state.search.items_groups.map((group) => {
|
||||
group.href = `#/discover/${encodeURIComponent(group.request.base)}/${encodeURIComponent(group.request.path.id)}/${encodeURIComponent(group.request.path.type_name)}?search=${query}`;
|
||||
return group;
|
||||
const catalog_resources = state.search.catalog_resources.map((catalog_resource) => {
|
||||
catalog_resource.href = `#/discover/${encodeURIComponent(catalog_resource.request.base)}/${encodeURIComponent(catalog_resource.request.path.type_name)}/${encodeURIComponent(catalog_resource.request.path.id)}?${queryString}`;
|
||||
return catalog_resource;
|
||||
});
|
||||
return { selected, items_groups };
|
||||
return { selected, catalog_resources };
|
||||
};
|
||||
|
||||
const useSearch = (queryParams) => {
|
||||
const { core } = useServices();
|
||||
const [search, setSearch] = React.useState(() => {
|
||||
const state = core.getState();
|
||||
const search = mapSearchState(state);
|
||||
return search;
|
||||
});
|
||||
React.useEffect(() => {
|
||||
const [search, setSearch] = React.useState(() => ({
|
||||
selected: null,
|
||||
catalog_resources: []
|
||||
}));
|
||||
React.useLayoutEffect(() => {
|
||||
const onNewState = () => {
|
||||
const state = core.getState();
|
||||
const search = mapSearchState(state);
|
||||
setSearch(search);
|
||||
};
|
||||
core.on('NewModel', onNewState);
|
||||
if (queryParams.has('search')) {
|
||||
if (queryParams.has('search') && queryParams.get('search').length > 0) {
|
||||
core.dispatch({
|
||||
action: 'Load',
|
||||
args: {
|
||||
load: 'CatalogsGrouped',
|
||||
load: 'CatalogsWithExtra',
|
||||
args: {
|
||||
extra: [
|
||||
['search', queryParams.get('search')]
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 'Search');
|
||||
}
|
||||
return () => {
|
||||
core.off('NewModel', onNewState);
|
||||
|
|
|
|||
Loading…
Reference in a new issue