diff --git a/images/library_placeholder.png b/images/library_placeholder.png new file mode 100644 index 000000000..07ac6dc4d Binary files /dev/null and b/images/library_placeholder.png differ diff --git a/src/routes/Library/Library.js b/src/routes/Library/Library.js index 2871a9b3f..8e19f123b 100644 --- a/src/routes/Library/Library.js +++ b/src/routes/Library/Library.js @@ -5,7 +5,8 @@ const PropTypes = require('prop-types'); const classnames = require('classnames'); const NotFound = require('stremio/routes/NotFound'); const { useProfile, useNotifications, routesRegexp, useOnScrollToBottom, withCoreSuspender } = require('stremio/common'); -const { Button, DelayedRenderer, Chips, Image, MainNavBars, Multiselect, LibItem } = require('stremio/components'); +const { DelayedRenderer, Chips, Image, MainNavBars, Multiselect, LibItem } = require('stremio/components'); +const { default: Placeholder } = require('./Placeholder'); const useLibrary = require('./useLibrary'); const useSelectableInputs = require('./useSelectableInputs'); const styles = require('./styles'); @@ -58,65 +59,58 @@ const Library = ({ model, urlParams, queryParams }) => { }, [hasNextPage, loadNextPage]); const onScroll = useOnScrollToBottom(onScrollToBottom, SCROLL_TO_BOTTOM_TRESHOLD); React.useLayoutEffect(() => { - if (profile.auth !== null && library.selected && library.selected.request.page === 1 && library.catalog.length !== 0 ) { + if (profile.auth !== null && library.selected && library.selected.request.page === 1 && library.catalog.length !== 0) { scrollContainerRef.current.scrollTop = 0; } }, [profile.auth, library.selected]); return ( -
- { - model === 'continue_watching' || profile.auth !== null ? -
- - -
- : - null - } - { - model === 'library' && profile.auth === null ? -
- {' -
Library is only available for logged in users!
- -
- : - library.selected === null ? - -
- {' -
{model === 'library' ? 'Library' : 'Continue Watching'} not loaded!
-
-
- : - library.catalog.length === 0 ? -
- {' -
Empty {model === 'library' ? 'Library' : 'Continue Watching'}
+ { + profile.auth === null ? + + :
+ { + model === 'continue_watching' ? +
+ +
: -
- {library.catalog.map((libItem, index) => ( - - ))} -
- } -
+ null + } + { + model === 'library' ? + library.selected === null ? + +
+ {' +
{model === 'library' ? 'Library' : 'Continue Watching'} not loaded!
+
+
+ : + library.catalog.length === 0 ? +
+ {' +
Empty {model === 'library' ? 'Library' : 'Continue Watching'}
+
+ : +
+ {library.catalog.map((libItem, index) => ( + + ))} +
+ : null + } +
+ } ); }; diff --git a/src/routes/Library/Placeholder/Placeholder.less b/src/routes/Library/Placeholder/Placeholder.less new file mode 100644 index 000000000..55de0356a --- /dev/null +++ b/src/routes/Library/Placeholder/Placeholder.less @@ -0,0 +1,132 @@ +// Copyright (C) 2017-2025 Smart code 203358507 + +@import (reference) '~stremio/common/screen-sizes.less'; + +.placeholder { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 100%; + width: 100%; + overflow-y: auto; + + .title { + font-size: 1.75rem; + font-weight: 400; + text-align: center; + color: var(--primary-foreground-color); + margin-bottom: 1rem; + opacity: 0.5; + } + + .image-container { + padding: 1.5rem 0; + + .image { + height: 100%; + max-height: 14rem; + object-fit: contain; + } + } + + .overview { + display: flex; + flex-direction: row; + align-items: center; + gap: 4rem; + margin-bottom: 1rem; + + .point { + display: flex; + flex-direction: row; + align-items: center; + gap: 1.5rem; + width: 18rem; + + .icon { + flex: none; + height: 3.25rem; + width: 3.25rem; + color: var(--primary-foreground-color); + opacity: 0.3; + } + + .text { + flex: auto; + font-size: 1.1rem; + font-size: 500; + color: var(--primary-foreground-color); + opacity: 0.9; + } + } + } + + .button-container { + margin: 1rem 0; + + .button { + display: flex; + justify-content: center; + height: 4rem; + line-height: 4rem; + padding: 0 5rem; + font-size: 1.1rem; + color: var(--primary-foreground-color); + text-align: center; + border-radius: 3.5rem; + background-color: var(--overlay-color); + + &:hover { + outline: var(--focus-outline-size) solid var(--primary-foreground-color); + background-color: transparent; + } + } + } +} + +@media only screen and (max-width: @xsmall) { + .placeholder { + padding: 1rem 2rem; + + .title { + margin-bottom: 0; + } + + .image-container { + padding: 1rem; + + .image { + max-height: 10rem; + } + } + + .button-container { + margin: 1rem 0 0; + } + } +} + +@media only screen and (max-width: @minimum) { + .placeholder { + padding: 1rem 2rem; + + .overview { + flex-direction: column; + gap: 1rem; + + .point { + .text { + font-size: 1rem; + } + } + } + + .button-container { + .button { + width: 100%; + } + } + } +} \ No newline at end of file diff --git a/src/routes/Library/Placeholder/Placeholder.tsx b/src/routes/Library/Placeholder/Placeholder.tsx new file mode 100644 index 000000000..d854a2d54 --- /dev/null +++ b/src/routes/Library/Placeholder/Placeholder.tsx @@ -0,0 +1,47 @@ +// Copyright (C) 2017-2025 Smart code 203358507 + +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import Icon from '@stremio/stremio-icons/react'; +import { Button, Image } from 'stremio/components'; +import styles from './Placeholder.less'; + +const Placeholder = () => { + const { t } = useTranslation(); + + return ( +
+
+ {t('LIBRARY_NOT_LOGGED_IN')} +
+
+ {' +
+
+
+ +
+ {t('NOT_LOGGED_IN_CLOUD')} +
+
+
+ +
+ {t('NOT_LOGGED_IN_RECOMMENDATIONS')} +
+
+
+
+ +
+
+ ); +}; + +export default Placeholder; diff --git a/src/routes/Library/Placeholder/index.ts b/src/routes/Library/Placeholder/index.ts new file mode 100644 index 000000000..b068f608e --- /dev/null +++ b/src/routes/Library/Placeholder/index.ts @@ -0,0 +1,5 @@ +// Copyright (C) 2017-2025 Smart code 203358507 + +import Placeholder from './Placeholder'; + +export default Placeholder; diff --git a/src/routes/Library/styles.less b/src/routes/Library/styles.less index 2bdbc13ec..76a16940e 100644 --- a/src/routes/Library/styles.less +++ b/src/routes/Library/styles.less @@ -66,38 +66,6 @@ padding: 4rem; } - &.no-user-message-container { - .login-button-container { - flex: none; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - width: 20rem; - height: 3.5rem; - border-radius: 3.5rem; - padding: 0.5rem 1rem; - margin-bottom: 1rem; - background-color: var(--secondary-accent-color); - - &:hover { - outline: var(--focus-outline-size) solid var(--secondary-accent-color); - background-color: transparent; - } - - .label { - flex-grow: 0; - flex-shrink: 1; - flex-basis: auto; - max-height: 4.8em; - font-size: 1.2rem; - font-weight: 700; - color: var(--primary-foreground-color); - text-align: center; - } - } - } - .image { flex: none; width: 12rem;