Merge pull request #144 from Stremio/meta-details-design

Meta details design
This commit is contained in:
Nikola Hristov 2020-03-29 18:23:57 +03:00 committed by GitHub
commit 5f6a5dfc0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 552 additions and 256 deletions

BIN
images/empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View file

@ -1,10 +1,13 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
.action-button-container {
display: flex;
flex-direction: column;
justify-content: center;
background-color: @color-surface-light5-20;
&:hover, &:focus {
background-color: var(--color-surfacedarker60);
background-color: @color-accent3;
}
.icon-container {
@ -21,7 +24,7 @@
display: block;
width: 100%;
height: 100%;
fill: var(--color-surfacelighter);
fill: @color-surface-light5-90;
}
}
@ -38,7 +41,7 @@
padding: 0 0.2rem;
max-height: 2.4em;
text-align: center;
color: var(--color-surfacelighter);
color: @color-surface-light5-90;
}
}
}

View file

@ -9,7 +9,7 @@ const MetaLinks = ({ className, label, links }) => {
<div className={classnames(className, styles['meta-links-container'])}>
{
typeof label === 'string' && label.length > 0 ?
<div className={styles['label-container']}>{label}:</div>
<div className={styles['label-container']}>{label}</div>
:
null
}
@ -17,9 +17,8 @@ const MetaLinks = ({ className, label, links }) => {
Array.isArray(links) && links.length > 0 ?
<div className={styles['links-container']}>
{links.map(({ label, href }, index) => (
<Button key={index} className={styles['link-container']} title={label} tabIndex={-1} href={href}>
<Button key={index} className={styles['link-container']} title={label} href={href}>
{label}
{index < links.length - 1 ? ',' : null}
</Button>
))}
</div>

View file

@ -1,8 +1,10 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
.meta-links-container {
.label-container {
margin-bottom: 0.2rem;
font-size: 1.2rem;
color: var(--color-surfacelighter);
text-transform: uppercase;
color: @color-surface-dark3-90;
}
.links-container {
@ -16,12 +18,21 @@
flex-basis: auto;
margin-right: 0.5rem;
margin-bottom: 0.2rem;
padding: 0.3rem 0.5rem;
white-space: nowrap;
text-overflow: ellipsis;
color: var(--color-surfacelighter);
border-radius: 2rem;
border: var(--focus-outline-size) solid transparent;
color: @color-surface-light2-90;
background-color: @color-surface-light5-20;
&:hover {
text-decoration: underline;
&:hover, &:focus {
background-color: @color-surface-light5-30;
}
&:focus {
outline: none;
border-color: @color-surface-light5;
}
}
}

View file

@ -3,6 +3,7 @@ const PropTypes = require('prop-types');
const classnames = require('classnames');
const UrlUtils = require('url');
const Icon = require('stremio-icons/dom');
const Button = require('stremio/common/Button');
const Image = require('stremio/common/Image');
const ModalDialog = require('stremio/common/ModalDialog');
const SharePrompt = require('stremio/common/SharePrompt');
@ -102,8 +103,14 @@ const MetaPreview = ({ className, compact, name, logo, background, runtime, rele
null
}
{
(typeof releaseInfo === 'string' && releaseInfo.length > 0) || (released instanceof Date && !isNaN(released.getTime())) || (typeof runtime === 'string' && runtime.length > 0) ?
(typeof releaseInfo === 'string' && releaseInfo.length > 0) || (released instanceof Date && !isNaN(released.getTime())) || (typeof runtime === 'string' && runtime.length > 0) || typeof linksGroups[IMDB_LINK_CATEGORY] === 'object' ?
<div className={styles['runtime-release-info-container']}>
{
typeof runtime === 'string' && runtime.length > 0 ?
<div className={styles['runtime-label']}>{runtime}</div>
:
null
}
{
typeof releaseInfo === 'string' && releaseInfo.length > 0 ?
<div className={styles['release-info-label']}>{releaseInfo}</div>
@ -114,8 +121,17 @@ const MetaPreview = ({ className, compact, name, logo, background, runtime, rele
null
}
{
typeof runtime === 'string' && runtime.length > 0 ?
<div className={styles['runtime-label']}>{runtime}</div>
typeof linksGroups[IMDB_LINK_CATEGORY] === 'object' ?
<Button
className={styles['imdb-button-container']}
title={linksGroups[IMDB_LINK_CATEGORY].label}
href={linksGroups[IMDB_LINK_CATEGORY].href}
target={'_blank'}
{...(compact ? { tabIndex: -1 } : null)}
>
<Icon className={styles['icon']} icon={'ic_imdbnoframe'} />
<div className={styles['label']}>{linksGroups[IMDB_LINK_CATEGORY].label}</div>
</Button>
:
null
}
@ -178,18 +194,6 @@ const MetaPreview = ({ className, compact, name, logo, background, runtime, rele
:
null
}
{
typeof linksGroups[IMDB_LINK_CATEGORY] === 'object' ?
<ActionButton
{...linksGroups[IMDB_LINK_CATEGORY]}
className={styles['action-button']}
icon={'ic_imdb'}
target={'_blank'}
{...(compact ? { tabIndex: -1 } : null)}
/>
:
null
}
{
!compact && typeof linksGroups[SHARE_LINK_CATEGORY] === 'object' ?
<React.Fragment>

View file

@ -1,3 +1,5 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
.meta-preview-container {
position: relative;
z-index: 0;
@ -50,9 +52,27 @@
.meta-info-container {
flex: 1;
align-self: stretch;
padding: 0 1rem;
padding: 0 2rem;
overflow-y: auto;
&:hover {
&::-webkit-scrollbar-thumb {
background-color: @color-secondaryvariant2-light1;
}
&::-webkit-scrollbar-track {
background-color: @color-background-dark2;
}
}
&::-webkit-scrollbar-thumb {
background-color: transparent;
}
&::-webkit-scrollbar-track {
background-color: transparent;
}
.logo, .logo-placeholder-icon {
display: block;
max-width: 100%;
@ -74,6 +94,7 @@
.runtime-release-info-container {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
margin-top: 1rem;
@ -81,22 +102,62 @@
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
margin: 1rem 1rem 1rem 0;
font-size: 1.2rem;
text-align: center;
color: var(--color-surfacelighter);
margin-right: 2rem;
margin-bottom: 0.5rem;
font-size: 1.4rem;
color: @color-surface-light5-90;
}
.imdb-button-container {
flex: 0 1 none;
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 0.5rem;
padding: 0.3rem 1rem;
border-radius: 2.3rem;
border: var(--focus-outline-size) solid transparent;
background-color: @color-surface-light5-20;
&:hover, &:focus {
background-color: @color-surface-light5-30;
}
&:focus {
outline: none;
border: var(--focus-outline-size) solid @color-surface-light5;
}
.icon {
flex: none;
width: 3rem;
margin-right: 1rem;
fill: @color-surface-dark2-90;
}
.label {
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
max-height: 1.2em;
font-size: 1.6rem;
font-weight: 500;
color: @color-surface-light5-90;
}
}
}
.name-container {
margin-top: 1rem;
font-size: 1.4rem;
color: var(--color-surfacelighter);
font-size: 1.7rem;
color: @color-surface-light5-90;
}
.description-container {
max-height: 6.8em;
margin-top: 1rem;
color: var(--color-surfacelighter);
line-height: 1.7em;
color: @color-surface-light5-90;
}
.meta-links {
@ -110,13 +171,17 @@
display: flex;
flex-direction: row;
flex-wrap: wrap;
padding: 0 1rem;
padding: 0 2rem;
.action-button {
flex: none;
width: 6rem;
height: 6rem;
margin: 1rem 0;
margin: 2rem 0;
&:not(:last-child) {
margin-right: 2rem;
}
}
}
}

View file

@ -2,7 +2,7 @@ const React = require('react');
const PropTypes = require('prop-types');
const classnames = require('classnames');
const Icon = require('stremio-icons/dom');
const { Button, Image } = require('stremio/common');
const { Button, Image, PlayIconCircleCentered } = require('stremio/common');
const StreamPlaceholder = require('./StreamPlaceholder');
const styles = require('./styles');
@ -11,7 +11,7 @@ const Stream = ({ className, addonName, title, thumbnail, progress, ...props })
<Button {...props} className={classnames(className, styles['stream-container'])} title={title}>
{
typeof thumbnail === 'string' && thumbnail.length > 0 ?
<div className={styles['thumbnail-container']}>
<div className={styles['thumbnail-container']} title={addonName}>
<Image
className={styles['thumbnail']}
src={thumbnail}
@ -29,18 +29,8 @@ const Stream = ({ className, addonName, title, thumbnail, progress, ...props })
<div className={styles['addon-name']}>{addonName}</div>
</div>
}
<div className={styles['info-container']}>
{
typeof thumbnail === 'string' && thumbnail.length > 0 ?
<div className={styles['addon-name-label']}>{addonName}</div>
:
null
}
<div className={styles['title-label']}>{title}</div>
</div>
<div className={styles['play-icon-container']}>
<Icon className={styles['play-icon']} icon={'ic_play'} />
</div>
<div className={styles['info-container']}>{title}</div>
<PlayIconCircleCentered className={styles['play-icon']} />
{
progress !== null && !isNaN(progress) && progress > 0 ?
<div className={styles['progress-bar-container']}>

View file

@ -1,13 +1,29 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
:import('~stremio/common/PlayIconCircleCentered/styles.less') {
play-icon-circle-centered-background: background;
play-icon-circle-centered-icon: icon;
}
.stream-container {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
min-width: 18rem;
background-color: var(--color-surfacedarker60);
background-color: @color-background-dark3-80;
&:hover, &:focus {
background-color: var(--color-surfacedarker);
background-color: @color-background;
.play-icon {
.play-icon-circle-centered-background {
fill: @color-accent4;
}
.play-icon-circle-centered-icon {
fill: @color-surface-light5;
}
}
}
.thumbnail-container, .addon-name-container {
@ -26,7 +42,7 @@
display: block;
width: 5rem;
height: 5rem;
fill: var(--color-surfacelight20);
fill: @color-secondaryvariant1-light3;
}
.addon-name {
@ -34,38 +50,29 @@
max-height: 3.6em;
font-size: 1.1rem;
text-align: center;
color: var(--color-surfacelighter);
color: @color-surface-light5;
}
}
.info-container {
flex: 1;
padding: 0.5rem;
.addon-name-label {
font-size: 1.1rem;
max-height: 3.6em;
margin-bottom: 0.5rem;
color: var(--color-surfacelighter);
}
.title-label {
max-height: 3.6em;
color: var(--color-surfacelighter);
}
max-height: 3.6em;
margin: 0.5rem;
font-size: 0.8rem;
color: @color-surface-90;
}
.play-icon-container {
flex: none;
width: 6rem;
height: 6rem;
padding: 2rem;
.play-icon {
width: 3.5rem;
height: 5rem;
margin: 0.5rem 1.5rem 0.5rem 0.5rem;
.play-icon {
display: block;
width: 100%;
height: 100%;
fill: var(--color-surfacelighter);
.play-icon-circle-centered-background {
fill: none;
}
.play-icon-circle-centered-icon {
fill: @color-surface-dark5;
}
}
@ -73,11 +80,11 @@
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100%;
background-color: var(--color-backgroundlighter);
background-color: @color-background-light2;
.progress-bar {
height: 0.5rem;
background-color: var(--color-primary);
background-color: @color-primaryvariant1;
}
}
}

View file

@ -2,7 +2,7 @@ const React = require('react');
const PropTypes = require('prop-types');
const classnames = require('classnames');
const Icon = require('stremio-icons/dom');
const { Button } = require('stremio/common');
const { Button, Image } = require('stremio/common');
const Stream = require('./Stream');
const styles = require('./styles');
@ -14,14 +14,21 @@ const StreamsList = ({ className, streamsResources }) => {
.flat(1);
}, [streamsResources]);
return (
<div className={classnames(className, styles['streams-list-container'])}>
<div className={classnames(className, styles['streams-list-container'], { 'streams-list-message': streamsResources.length === 0 || streamsResources.every((streamsResource) => streamsResource.content.type === 'Err') })}>
<div className={styles['streams-scroll-container']}>
{
streamsResources.length === 0 ?
<div className={styles['message-label']}>No addons ware requested for streams</div>
<div className={styles['message-container']}>
<Image className={styles['image']} src={'/images/empty.png'} />
<div className={styles['label']}>No addons were requested for streams</div>
</div>
:
streamsResources.every((streamsResource) => streamsResource.content.type === 'Err') ?
<div className={styles['message-label']}>No streams were found</div>
<div className={styles['message-container']}>
<Image className={styles['image']} src={'/images/empty.png'} />
<div className={styles['label']}>No streams were found!</div>
<div className={styles['description']}>Please install some addons to find more streams</div>
</div>
:
streams.length > 0 ?
streams.map((stream, index) => (
@ -38,9 +45,9 @@ const StreamsList = ({ className, streamsResources }) => {
</React.Fragment>
}
</div>
<Button className={styles['install-addons-container']} title={'Install addons'} href={'#/addons'}>
<Button className={styles['install-addons-container']} title={'Install Addons'} href={'#/addons'}>
<Icon className={styles['icon']} icon={'ic_addons'} />
<div className={styles['label']}>Install addons</div>
<div className={styles['label']}>Install Addons</div>
</Button>
</div>
);

View file

@ -1,7 +1,12 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
.streams-list-container {
display: flex;
flex-direction: column;
background: var(--color-backgrounddark80);
&:global(.streams-list-message) {
background-color: @color-background-dark3-80;
}
.streams-scroll-container {
flex-grow: 0;
@ -10,24 +15,40 @@
align-self: stretch;
overflow-y: auto;
.message-label {
padding: 2rem 0;
font-size: 2rem;
text-align: center;
color: var(--color-surfacelighter);
.message-container {
display: flex;
flex-direction: column;
align-items: center;
width: var(--item-size);
height: 100%;
padding: 2rem;
&>:not(:last-child) {
margin-bottom: 1rem;
}
.image {
flex: none;
width: 10rem;
opacity: 0.9;
}
.label {
flex: none;
font-size: 1.4rem;
text-align: center;
color: @color-surface-light5-90;
}
.description {
flex: none;
text-align: center;
color: @color-surface-dark1-90;
}
}
.stream {
width: var(--item-size);
margin: 1rem 2rem;
&:first-child {
margin-top: 2rem;
}
&:last-child {
margin-bottom: 0;
}
}
}
@ -38,30 +59,28 @@
flex-direction: row;
align-items: center;
justify-content: center;
width: var(--item-size);
margin: 1rem 2rem 2rem 2rem;
padding: 1rem;
background-color: var(--color-signal5);
padding: 1.3rem;
background-color: @color-accent3;
&:hover, &:focus {
filter: brightness(1.2);
background-color: @color-accent3-light2;
}
.icon {
flex: none;
width: 3rem;
height: 3rem;
width: 2rem;
height: 2rem;
margin-right: 1rem;
fill: var(--color-surfacelighter);
fill: @color-surface-light5-90;
}
.label {
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
font-size: 1.5rem;
font-size: 1.4rem;
max-height: 3.6em;
color: var(--color-surfacelighter);
color: @color-surface-light5-90;
}
}
}

View file

@ -16,9 +16,6 @@ const SeasonsBar = ({ className, seasons, season, onSelect }) => {
const selected = React.useMemo(() => {
return [String(season)];
}, [season]);
const renderMultiselectLabelContent = React.useMemo(() => () => (
<div className={styles['season-label']}>Season {season}</div>
), [season]);
const prevNextButtonOnClick = React.useCallback((event) => {
if (typeof onSelect === 'function') {
const seasonIndex = seasons.indexOf(season);
@ -50,6 +47,7 @@ const SeasonsBar = ({ className, seasons, season, onSelect }) => {
<div className={classnames(className, styles['seasons-bar-container'])}>
<Button className={styles['prev-season-button']} data-action={'prev'} onClick={prevNextButtonOnClick}>
<Icon className={styles['icon']} icon={'ic_arrow_left'} />
<div className={styles['label']}>Prev</div>
</Button>
<Multiselect
className={styles['seasons-popup-label-container']}
@ -57,10 +55,10 @@ const SeasonsBar = ({ className, seasons, season, onSelect }) => {
options={options}
selected={selected}
disabled={false}
renderLabelContent={renderMultiselectLabelContent}
onSelect={seasonOnSelect}
/>
<Button className={styles['next-season-button']} data-action={'next'} onClick={prevNextButtonOnClick}>
<div className={styles['label']}>Next</div>
<Icon className={styles['icon']} icon={'ic_arrow_right'} />
</Button>
</div>

View file

@ -1,24 +1,54 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
:import('~stremio/common/Multiselect/styles.less') {
season-label: label;
season-icon: icon;
}
.seasons-bar-container {
display: flex;
flex-direction: row;
overflow: visible;
background: @color-background-dark3-80;
.prev-season-button, .next-season-button {
flex: none;
width: 4rem;
height: 4rem;
padding: 1rem;
background-color: var(--color-surfacedarker60);
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
width: 6.5rem;
padding: 0.5rem;
&:hover, &:focus {
background-color: var(--color-surfacedarker);
.label {
color: @color-surface-dark1;
}
.icon {
fill: @color-surface-dark3;
}
}
&:focus {
outline: none;
background-color: @color-surface-light5-10;
}
&>:first-child {
margin-right: 1rem;
}
.label {
max-height: 1.2em;
color: @color-surface-dark3-90;
}
.icon {
display: block;
width: 100%;
height: 100%;
fill: var(--color-surfacelighter);
width: 1.5rem;
height: 1.5rem;
fill: @color-surface-dark5;
}
}
@ -28,26 +58,29 @@
display: flex;
align-items: center;
justify-content: center;
margin: 0 1rem;
background-color: var(--color-surfacedarker60);
margin: 0 2rem;
background: none;
overflow: visible;
&:hover, &:focus {
background-color: var(--color-surfacedarker);
background-color: @color-background-dark1;
.season-icon {
fill: @color-surface-dark3;
}
}
&:global(.active) {
background-color: var(--color-surfacedark);
background-color: @color-background;
}
.season-label {
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
max-height: 3.6em;
padding: 0 0.2rem;
font-size: 1.1rem;
color: var(--color-surfacelighter);
flex: none;
color: @color-surface-light5-90;
}
.season-icon {
fill: @color-surface-dark5;
}
}
}

View file

@ -32,33 +32,34 @@ const Video = ({ className, id, title, thumbnail, episode, released, upcoming, w
{episode !== null && !isNaN(episode) ? `${episode}. ` : null}
{typeof title === 'string' && title.length > 0 ? title : id}
</div>
{
released instanceof Date && !isNaN(released.getTime()) ?
<div className={styles['released-container']}>
{released.toLocaleString(undefined, { year: '2-digit', month: 'short', day: 'numeric' })}
</div>
:
null
}
{
upcoming ?
<div className={styles['upcoming-container']}>
<div className={styles['flag-label']}>Upcoming</div>
</div>
:
null
}
{
watched ?
<div className={styles['watched-container']}>
<div className={styles['flag-label']}>Watched</div>
</div>
:
null
}
</div>
<div className={styles['next-icon-container']}>
<Icon className={styles['next-icon']} icon={'ic_arrow_thin_right'} />
<div className={styles['flex-row-container']}>
{
released instanceof Date && !isNaN(released.getTime()) ?
<div className={styles['released-container']}>
{released.toLocaleString(undefined, { year: '2-digit', month: 'short', day: 'numeric' })}
</div>
:
null
}
<div className={styles['upcoming-watched-container']}>
{
upcoming ?
<div className={styles['upcoming-container']}>
<div className={styles['flag-label']}>Upcoming</div>
</div>
:
null
}
{
watched ?
<div className={styles['watched-container']}>
<div className={styles['flag-label']}>Watched</div>
</div>
:
null
}
</div>
</div>
</div>
{
progress !== null && !isNaN(progress) && progress > 0 ?

View file

@ -1,11 +1,13 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
.video-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
background-color: var(--color-surfacedarker60);
background-color: @color-background-dark3-80;
&:hover, &:focus {
background-color: var(--color-surfacedarker);
background-color: @color-background;
}
.thumbnail-container {
@ -16,7 +18,7 @@
.thumbnail {
display: block;
width: 5rem;
max-height: 10rem;
height: 5rem;
object-fit: contain;
object-position: center;
}
@ -25,7 +27,7 @@
display: block;
width: 5rem;
height: 5rem;
fill: var(--color-surfacelight20);
fill: @color-secondaryvariant1-light3;
}
}
@ -33,69 +35,75 @@
flex: 1;
align-self: stretch;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
flex-direction: column;
justify-content: space-between;
padding: 0.5rem;
&:first-child {
align-content: center;
}
height: 4rem;
.title-container {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100%;
max-height: 4.8em;
color: var(--color-surfacelighter);
}
.released-container {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100%;
margin-top: 0.5rem;
font-size: 0.8rem;
max-height: 2.4em;
color: var(--color-surfacelight);
}
.watched-container, .upcoming-container {
flex: none;
max-width: 100%;
margin-top: 0.5rem;
margin-right: 0.5rem;
padding: 0.2rem 0.4rem;
.flag-label {
max-height: 2.4em;
font-size: 0.8rem;
font-weight: 700;
text-transform: uppercase;
color: var(--color-surfacelighter);
text-shadow: 1px 1px var(--color-surfacedarker60);
.title-container {
max-height: 1.2em;
}
}
.upcoming-container {
background-color: var(--color-signal5);
.title-container {
max-height: 2.4em;
color: @color-surface-light5-90;
}
.watched-container {
background-color: var(--color-primarylight);
}
}
.flex-row-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
.next-icon-container {
flex: none;
align-self: center;
padding: 0.5rem;
.released-container {
flex: 1;
margin-right: 0.5rem;
font-size: 0.8rem;
white-space: nowrap;
text-overflow: ellipsis;
text-transform: uppercase;
color: @color-surface-dark5-90;
}
.next-icon {
display: block;
width: 1rem;
height: 1.5rem;
fill: var(--color-surfacelighter);
.upcoming-watched-container {
flex: 0 1 auto;
display: flex;
flex-direction: row;
&>:nth-child(2) {
margin-left: 0.5rem;
}
.upcoming-container, .watched-container {
flex: none;
padding: 0.2rem 0.4rem;
max-width: 10rem;
&:not(:only-child) {
max-width: 5rem;
}
.flag-label {
font-size: 0.8rem;
font-weight: 500;
white-space: nowrap;
text-overflow: ellipsis;
text-transform: uppercase;
color: @color-background-90;
}
}
.upcoming-container {
background-color: @color-accent4;
}
.watched-container {
background-color: @color-accent5;
}
}
}
}
@ -103,11 +111,11 @@
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100%;
background-color: var(--color-backgroundlighter);
background-color: @color-background-light2;
.progress-bar {
height: 0.5rem;
background-color: var(--color-primary);
background-color: @color-primaryvariant1;
}
}
}

View file

@ -1,6 +1,9 @@
const React = require('react');
const PropTypes = require('prop-types');
const classnames = require('classnames');
const Icon = require('stremio-icons/dom');
const Image = require('stremio/common/Image');
const TextInput = require('stremio/common/TextInput');
const SeasonsBar = require('./SeasonsBar');
const Video = require('./Video');
const useSelectableSeasons = require('./useSelectableSeasons');
@ -17,6 +20,10 @@ const VideosList = ({ className, metaResource }) => {
const seasonOnSelect = React.useCallback((event) => {
selectSeason(event.value);
}, []);
const [search, setSearch] = React.useState('');
const searchInputOnChange = React.useCallback((event) => {
setSearch(event.currentTarget.value);
}, []);
return (
<div className={classnames(className, styles['videos-list-container'])}>
{
@ -33,8 +40,9 @@ const VideosList = ({ className, metaResource }) => {
</React.Fragment>
:
metaResource.content.type === 'Err' || videosForSeason.length === 0 ?
<div className={styles['message-label']}>
No videos found for this meta
<div className={styles['message-container']}>
<Image className={styles['image']} src={'/images/empty.png'} />
<div className={styles['label']}>No videos found for this meta</div>
</div>
:
<React.Fragment>
@ -49,14 +57,34 @@ const VideosList = ({ className, metaResource }) => {
:
null
}
<div className={styles['videos-scroll-container']}>
{videosForSeason.map((video, index) => (
<Video
{...video}
key={index}
className={styles['video']}
<div className={styles['search-container']}>
<label className={styles['search-bar-container']}>
<TextInput
className={styles['search-input']}
type={'text'}
placeholder={'Search videos'}
value={search}
onChange={searchInputOnChange}
/>
))}
<Icon className={styles['icon']} icon={'ic_search'} />
</label>
</div>
<div className={styles['videos-scroll-container']}>
{videosForSeason
.filter((video) => {
return search.length === 0 ||
(
(typeof video.title === 'string' && video.title.toLowerCase().includes(search.toLowerCase())) ||
(video.released.toLocaleString(undefined, { year: '2-digit', month: 'short', day: 'numeric' }).toLowerCase().includes(search.toLowerCase()))
);
})
.map((video, index) => (
<Video
{...video}
key={index}
className={styles['video']}
/>
))}
</div>
</React.Fragment>
}

View file

@ -1,18 +1,90 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
.videos-list-container {
display: flex;
flex-direction: column;
background: var(--color-backgrounddark80);
background-color: @color-background-dark3-80;
.seasons-bar, .message-label {
.seasons-bar {
flex: none;
width: var(--item-size);
margin: 2rem 2rem 1rem 2rem;
align-self: stretch;
padding: 1rem 0;
}
.message-label {
font-size: 1.4rem;
text-align: center;
color: var(--color-surfacelighter);
.message-container {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
width: var(--item-size);
padding: 2rem;
background-color: @color-background-dark3-80;
.image {
flex: none;
width: 10rem;
margin-bottom: 1rem;
opacity: 0.9;
}
.label {
flex: 0 1 auto;
font-size: 1.4rem;
text-align: center;
color: @color-surface-light5-90;
}
}
.search-container {
flex: none;
min-width: var(--item-size);
padding: 0 1.5rem 1rem 1.5rem;
background-color: @color-background-dark3-80;
&:first-child {
padding-top: 1rem;
}
.search-bar-container {
display: flex;
flex-direction: row;
align-items: center;
height: 3.5rem;
padding: 0 1rem;
border-radius: 2.3rem;
border: var(--focus-outline-size) solid transparent;
background-color: @color-background;
cursor: text;
&:hover, &:focus-within {
background-color: @color-background-light1;
}
&:focus-within {
border: var(--focus-outline-size) solid @color-surface-light5;
}
.search-input {
flex: 1;
margin-right: 1rem;
font-size: 1.1rem;
color: @color-surface-light5;
&::placeholder {
max-height: 1.2em;
opacity: 1;
color: @color-secondaryvariant1-light1-90;
}
}
.icon {
flex: none;
width: 1.5rem;
height: 1.5rem;
fill: @color-secondaryvariant1;
}
}
}
.videos-scroll-container {
@ -20,25 +92,8 @@
align-self: stretch;
overflow-y: auto;
&:first-child {
.video {
&:first-child {
margin-top: 2rem;
}
}
}
.video {
width: var(--item-size);
margin: 1rem 2rem;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 2rem;
}
}
}
}

View file

@ -1,9 +1,17 @@
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
@import (reference) '~stremio/common/screen-sizes.less';
:import('~stremio/common/MetaPreview/styles.less') {
meta-info-container: meta-info-container;
}
.metadetails-container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
background-color: var(--color-background);
background:
linear-gradient(to right, @color-background-dark3-60, @color-background-dark3-80);
.nav-bar {
flex: none;
@ -30,9 +38,9 @@
display: block;
width: 100%;
height: 100%;
opacity: 0.2;
object-fit: cover;
object-position: top left;
filter: brightness(50%);
}
}
@ -42,11 +50,71 @@
}
.videos-list, .streams-list {
--item-size: 28rem;
--item-size: 26.5rem;
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
align-self: stretch;
}
}
}
@media only screen and (min-width: @large) {
.metadetails-container {
.metadetails-content {
.meta-preview {
.meta-info-container {
width: 58rem;
}
}
}
}
}
@media only screen and (max-width: @large) {
.metadetails-container {
.metadetails-content {
.meta-preview {
.meta-info-container {
width: 48rem;
}
}
}
}
}
@media only screen and (max-width: @medium) {
.metadetails-container {
.metadetails-content {
.meta-preview {
.meta-info-container {
width: 40rem;
}
}
}
}
}
@media only screen and (max-width: @small) {
.metadetails-container {
.metadetails-content {
.meta-preview {
.meta-info-container {
width: 34rem;
}
}
}
}
}
@media only screen and (max-width: @xsmall) {
.metadetails-container {
.metadetails-content {
.meta-preview {
.meta-info-container {
width: 30rem;
}
}
}
}
}