mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
Merge pull request #144 from Stremio/meta-details-design
Meta details design
This commit is contained in:
commit
5f6a5dfc0e
17 changed files with 552 additions and 256 deletions
BIN
images/empty.png
Normal file
BIN
images/empty.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.8 KiB |
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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']}>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 ?
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue