stremio-web/src/routes/Board/Board.js

120 lines
5.5 KiB
JavaScript

// Copyright (C) 2017-2023 Smart code 203358507
const React = require('react');
const classnames = require('classnames');
const debounce = require('lodash.debounce');
const { useTranslation } = require('react-i18next');
const { useStreamingServer, useNotifications, withCoreSuspender, getVisibleChildrenRange, useProfile } = require('stremio/common');
const { ContinueWatchingItem, EventModal, MainNavBars, MetaItem, MetaRow } = require('stremio/components');
const useBoard = require('./useBoard');
const useContinueWatchingPreview = require('./useContinueWatchingPreview');
const styles = require('./styles');
const { default: StreamingServerWarning } = require('./StreamingServerWarning');
const THRESHOLD = 5;
const Board = () => {
const { t } = useTranslation();
const streamingServer = useStreamingServer();
const continueWatchingPreview = useContinueWatchingPreview();
const [board, loadBoardRows] = useBoard();
const notifications = useNotifications();
const profile = useProfile();
const boardCatalogsOffset = continueWatchingPreview.items.length > 0 ? 1 : 0;
const scrollContainerRef = React.useRef();
const streamingServerWarningDismissed = React.useMemo(() => {
return streamingServer.settings !== null && streamingServer.settings.type === 'Ready' || (
!isNaN(profile.settings.streamingServerWarningDismissed.getTime()) &&
profile.settings.streamingServerWarningDismissed.getTime() > Date.now()
);
}, [profile.settings, streamingServer.settings]);
const onVisibleRangeChange = React.useCallback(() => {
const range = getVisibleChildrenRange(scrollContainerRef.current);
if (range === null) {
return;
}
const start = Math.max(0, range.start - boardCatalogsOffset - THRESHOLD);
const end = range.end - boardCatalogsOffset + THRESHOLD;
if (end < start) {
return;
}
loadBoardRows({ start, end });
}, [boardCatalogsOffset]);
const onScroll = React.useCallback(debounce(onVisibleRangeChange, 250), [onVisibleRangeChange]);
React.useLayoutEffect(() => {
onVisibleRangeChange();
}, [board.catalogs, onVisibleRangeChange]);
return (
<div className={styles['board-container']}>
<EventModal />
<MainNavBars className={styles['board-content-container']} route={'board'}>
<div ref={scrollContainerRef} className={styles['board-content']} onScroll={onScroll}>
{
continueWatchingPreview.items.length > 0 ?
<MetaRow
className={classnames(styles['board-row'], styles['continue-watching-row'], 'animation-fade-in')}
title={t('BOARD_CONTINUE_WATCHING')}
catalog={continueWatchingPreview}
itemComponent={ContinueWatchingItem}
notifications={notifications}
/>
:
null
}
{board.catalogs.map((catalog, index) => {
switch (catalog.content?.type) {
case 'Ready': {
return (
<MetaRow
key={index}
className={classnames(styles['board-row'], styles[`board-row-${catalog.content.content[0].posterShape}`], 'animation-fade-in')}
catalog={catalog}
itemComponent={MetaItem}
/>
);
}
case 'Err': {
if (catalog.content.content !== 'EmptyContent') {
return (
<MetaRow
key={index}
className={classnames(styles['board-row'], 'animation-fade-in')}
catalog={catalog}
message={catalog.content.content}
/>
);
}
return null;
}
default: {
return (
<MetaRow.Placeholder
key={index}
className={classnames(styles['board-row'], styles['board-row-poster'], 'animation-fade-in')}
catalog={catalog}
/>
);
}
}
})}
</div>
</MainNavBars>
{
!streamingServerWarningDismissed ?
<StreamingServerWarning className={styles['board-warning-container']} />
:
null
}
</div>
);
};
const BoardFallback = () => (
<div className={styles['board-container']}>
<MainNavBars className={styles['board-content-container']} route={'board'} />
</div>
);
module.exports = withCoreSuspender(Board, BoardFallback);