Merge pull request #437 from Stremio/feat/library-items-new-videos

feat: library items new videos
This commit is contained in:
Tim 2023-08-14 14:07:53 +02:00 committed by GitHub
commit cbf28a4e1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 106 additions and 12 deletions

14
package-lock.json generated
View file

@ -12,7 +12,7 @@
"@babel/runtime": "7.16.0",
"@sentry/browser": "6.13.3",
"@stremio/stremio-colors": "5.0.1",
"@stremio/stremio-core-web": "0.44.20",
"@stremio/stremio-core-web": "0.44.21",
"@stremio/stremio-icons": "4.0.0",
"@stremio/stremio-video": "0.0.24",
"a-color-picker": "1.2.1",
@ -2703,9 +2703,9 @@
"integrity": "sha512-Dt3PYmy1DZ473QNs99KYXVWQPHtpIl37VUY0+gCEvvuCqE1fRrZIJtZ9KbysUKonvO7WwdQDztgcW0iGoc1dEA=="
},
"node_modules/@stremio/stremio-core-web": {
"version": "0.44.20",
"resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.20.tgz",
"integrity": "sha512-dcqs9svqe9iQHDIyIr7ML42H5Oa2GNjIy3Ngp/TSMPd0UIQ/kJ4ZU/qoZk17r/McI20FEzYIdGFdCcif7c/n9g==",
"version": "0.44.21",
"resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.21.tgz",
"integrity": "sha512-xVCE9A/ZWLJ8un1x6VYSDY4fYclxq4rV98UIgUcc9SZlleHOoB92kqy5TIXhQ6v+Ym9EX9OU2uLBv+d2fi6KHA==",
"dependencies": {
"@babel/runtime": "7.16.0"
}
@ -16804,9 +16804,9 @@
"integrity": "sha512-Dt3PYmy1DZ473QNs99KYXVWQPHtpIl37VUY0+gCEvvuCqE1fRrZIJtZ9KbysUKonvO7WwdQDztgcW0iGoc1dEA=="
},
"@stremio/stremio-core-web": {
"version": "0.44.20",
"resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.20.tgz",
"integrity": "sha512-dcqs9svqe9iQHDIyIr7ML42H5Oa2GNjIy3Ngp/TSMPd0UIQ/kJ4ZU/qoZk17r/McI20FEzYIdGFdCcif7c/n9g==",
"version": "0.44.21",
"resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.21.tgz",
"integrity": "sha512-xVCE9A/ZWLJ8un1x6VYSDY4fYclxq4rV98UIgUcc9SZlleHOoB92kqy5TIXhQ6v+Ym9EX9OU2uLBv+d2fi6KHA==",
"requires": {
"@babel/runtime": "7.16.0"
}

View file

@ -15,7 +15,7 @@
"@babel/runtime": "7.16.0",
"@sentry/browser": "6.13.3",
"@stremio/stremio-colors": "5.0.1",
"@stremio/stremio-core-web": "0.44.20",
"@stremio/stremio-core-web": "0.44.21",
"@stremio/stremio-icons": "4.0.0",
"@stremio/stremio-video": "0.0.24",
"a-color-picker": "1.2.1",

View file

@ -129,6 +129,12 @@ const App = () => {
action: 'SyncLibraryWithAPI'
}
});
services.core.transport.dispatch({
action: 'Ctx',
args: {
action: 'PullNotifications'
}
});
};
if (services.core.active) {
onWindowFocus();

View file

@ -4,6 +4,7 @@ const React = require('react');
const { useServices } = require('stremio/services');
const PropTypes = require('prop-types');
const MetaItem = require('stremio/common/MetaItem');
const useNotifications = require('stremio/common/useNotifications');
const { t } = require('i18next');
const OPTIONS = [
@ -15,6 +16,11 @@ const OPTIONS = [
const LibItem = ({ _id, removable, ...props }) => {
const { core } = useServices();
const notifications = useNotifications();
const newVideos = React.useMemo(() => {
const count = notifications.items?.[_id]?.length ?? 0;
return Math.min(Math.max(count, 0), 99);
}, [_id, notifications.items]);
const options = React.useMemo(() => {
return OPTIONS
.filter(({ value }) => {
@ -68,6 +74,13 @@ const LibItem = ({ _id, removable, ...props }) => {
args: _id
}
});
core.transport.dispatch({
action: 'Ctx',
args: {
action: 'DismissNotificationItem',
args: _id
}
});
}
break;
@ -91,6 +104,7 @@ const LibItem = ({ _id, removable, ...props }) => {
return (
<MetaItem
{...props}
newVideos={newVideos}
options={options}
optionOnSelect={optionOnSelect}
/>

View file

@ -13,7 +13,7 @@ const useBinaryState = require('stremio/common/useBinaryState');
const { ICON_FOR_TYPE } = require('stremio/common/CONSTANTS');
const styles = require('./styles');
const MetaItem = React.memo(({ className, type, name, poster, posterShape, playIcon, progress, options, deepLinks, dataset, optionOnSelect, ...props }) => {
const MetaItem = React.memo(({ className, type, name, poster, posterShape, playIcon, progress, newVideos, options, deepLinks, dataset, optionOnSelect, ...props }) => {
const [menuOpen, onMenuOpen, onMenuClose] = useBinaryState(false);
const href = React.useMemo(() => {
return deepLinks ?
@ -89,6 +89,18 @@ const MetaItem = React.memo(({ className, type, name, poster, posterShape, playI
:
null
}
{
newVideos > 0 ?
<div className={styles['new-videos']}>
<div className={styles['layer']} />
<div className={styles['layer']} />
<div className={styles['layer']}>
+{newVideos}
</div>
</div>
:
null
}
</div>
{
(typeof name === 'string' && name.length > 0) || (Array.isArray(options) && options.length > 0) ?
@ -129,6 +141,7 @@ MetaItem.propTypes = {
posterShape: PropTypes.oneOf(['poster', 'landscape', 'square']),
playIcon: PropTypes.bool,
progress: PropTypes.number,
newVideos: PropTypes.number,
options: PropTypes.array,
deepLinks: PropTypes.shape({
metaDetailsVideos: PropTypes.string,

View file

@ -118,6 +118,45 @@
background-color: @color-primaryvariant1;
}
}
.new-videos {
z-index: -1;
position: absolute;
top: 0;
right: 0;
overflow: visible;
.layer {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
height: 1.6rem;
width: 2.75rem;
border-radius: 0.25rem;
font-size: 1rem;
font-weight: 600;
color: @color-background-dark2-90;
&:nth-child(1) {
top: 0.5rem;
right: 0.5rem;
background-color: @color-surface-light5-40;
}
&:nth-child(2) {
top: 0.75rem;
right: 0.75rem;
background-color: @color-surface-light5-60;
}
&:nth-child(3) {
top: 1rem;
right: 1rem;
background-color: @color-surface-light5;
}
}
}
}
.title-bar-container {

View file

@ -36,6 +36,7 @@ const useBinaryState = require('./useBinaryState');
const useFullscreen = require('./useFullscreen');
const useLiveRef = require('./useLiveRef');
const useModelState = require('./useModelState');
const useNotifications = require('./useNotifications');
const useOnScrollToBottom = require('./useOnScrollToBottom');
const useProfile = require('./useProfile');
const useStreamingServer = require('./useStreamingServer');
@ -83,6 +84,7 @@ module.exports = {
useFullscreen,
useLiveRef,
useModelState,
useNotifications,
useOnScrollToBottom,
useProfile,
useStreamingServer,

2
src/common/useNotifications.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
declare const useNotifcations: () => Notifications;
export = useNotifcations;

View file

@ -0,0 +1,11 @@
// Copyright (C) 2017-2023 Smart code 203358507
const useModelState = require('stremio/common/useModelState');
const map = (ctx) => ctx.notifications;
const useNotifications = () => {
return useModelState({ model: 'ctx', map });
};
module.exports = useNotifications;

View file

@ -16,7 +16,7 @@ const Board = () => {
const streamingServer = useStreamingServer();
const continueWatchingPreview = useContinueWatchingPreview();
const [board, loadBoardRows] = useBoard();
const boardCatalogsOffset = continueWatchingPreview.libraryItems.length > 0 ? 1 : 0;
const boardCatalogsOffset = continueWatchingPreview.items.length > 0 ? 1 : 0;
const scrollContainerRef = React.useRef();
const onVisibleRangeChange = React.useCallback(() => {
const range = getVisibleChildrenRange(scrollContainerRef.current);
@ -41,11 +41,11 @@ const Board = () => {
<MainNavBars className={styles['board-content-container']} route={'board'}>
<div ref={scrollContainerRef} className={styles['board-content']} onScroll={onScroll}>
{
continueWatchingPreview.libraryItems.length > 0 ?
continueWatchingPreview.items.length > 0 ?
<MetaRow
className={classnames(styles['board-row'], styles['continue-watching-row'], 'animation-fade-in')}
title={t('BOARD_CONTINUE_WATCHING')}
items={continueWatchingPreview.libraryItems}
items={continueWatchingPreview.items}
itemComponent={LibItem}
deepLinks={continueWatchingPreview.deepLinks}
/>

View file

@ -42,6 +42,13 @@ type Profile = {
settings: Settings,
};
type Notifications = {
uid: string,
created: string,
items: Record<string, Video[]>,
};
type Ctx = {
profile: Profile,
notifications: Notifications,
};