Save and load watch history

This commit is contained in:
Raphael Wickihalder 2022-04-22 13:16:27 +02:00 committed by Thomas Zarebczan
parent 6d4c15f72c
commit 1a7b92c4fa
6 changed files with 41 additions and 76 deletions

View file

@ -141,6 +141,7 @@ function App(props: Props) {
const [localeSwitchDismissed] = usePersistedState('locale-switch-dismissed', false); const [localeSwitchDismissed] = usePersistedState('locale-switch-dismissed', false);
const [showAnalyticsNag, setShowAnalyticsNag] = usePersistedState('analytics-nag', true); const [showAnalyticsNag, setShowAnalyticsNag] = usePersistedState('analytics-nag', true);
const [lbryTvApiStatus, setLbryTvApiStatus] = useState(STATUS_OK); const [lbryTvApiStatus, setLbryTvApiStatus] = useState(STATUS_OK);
usePersistedState('watch-history', []);
const { pathname, hash, search } = props.location; const { pathname, hash, search } = props.location;
const [upgradeNagClosed, setUpgradeNagClosed] = useState(false); const [upgradeNagClosed, setUpgradeNagClosed] = useState(false);

View file

@ -90,7 +90,7 @@ const PLAYLISTS: SideNavLink = {
const HISTORY: SideNavLink = { const HISTORY: SideNavLink = {
title: 'History', title: 'History',
link: `/$/${PAGES.HISTORY}`, link: `/$/${PAGES.HISTORY}`,
icon: ICONS.STACK, icon: ICONS.TIME,
hideForUnauth: true, hideForUnauth: true,
}; };

View file

@ -29,6 +29,7 @@ import debounce from 'util/debounce';
import { formatLbryUrlForWeb, generateListSearchUrlParams } from 'util/url'; import { formatLbryUrlForWeb, generateListSearchUrlParams } from 'util/url';
import useInterval from 'effects/use-interval'; import useInterval from 'effects/use-interval';
import { lastBandwidthSelector } from './internal/plugins/videojs-http-streaming--override/playlist-selectors'; import { lastBandwidthSelector } from './internal/plugins/videojs-http-streaming--override/playlist-selectors';
import usePersistedState from 'effects/use-persisted-state';
// const PLAY_TIMEOUT_ERROR = 'play_timeout_error'; // const PLAY_TIMEOUT_ERROR = 'play_timeout_error';
// const PLAY_TIMEOUT_LIMIT = 2000; // const PLAY_TIMEOUT_LIMIT = 2000;
@ -151,6 +152,23 @@ function VideoViewer(props: Props) {
const isFirstRender = React.useRef(true); const isFirstRender = React.useRef(true);
const playerRef = React.useRef(null); const playerRef = React.useRef(null);
const [history, setHistory] = usePersistedState('watch-history', []);
React.useEffect(() => {
if (!history[0].indexOf(claim.permanent_url) !== -1) {
if (!history || !history.length) {
setHistory([claim.permanent_url]);
} else {
if (history.find((entry) => entry === claim.permanent_url)) {
history.splice(history.indexOf(claim.permanent_url), 1);
history.unshift(claim.permanent_url);
} else {
history.unshift(claim.permanent_url);
}
setHistory(history);
}
}
}, [isPlaying]);
useEffect(() => { useEffect(() => {
if (isFirstRender.current) { if (isFirstRender.current) {
isFirstRender.current = false; isFirstRender.current = false;
@ -288,6 +306,7 @@ function VideoViewer(props: Props) {
setIsEndedEmbed(false); setIsEndedEmbed(false);
setReplay(false); setReplay(false);
setDoNavigate(false); setDoNavigate(false);
// setWatchHistory()
analytics.videoIsPlaying(true, player); analytics.videoIsPlaying(true, player);
} }

View file

@ -64,6 +64,9 @@ export default function CollectionPage(props: Props) {
deleteCollection, deleteCollection,
} = props; } = props;
console.log('collection: ', props.collection);
console.log('collectionUrls: ', props.collectionUrls);
const { const {
replace, replace,
location: { search }, location: { search },

View file

@ -2,20 +2,17 @@
import React from 'react'; import React from 'react';
import ClaimList from 'component/claimList'; import ClaimList from 'component/claimList';
import Page from 'component/page'; import Page from 'component/page';
import * as PAGES from 'constants/pages';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import CollectionEdit from 'component/collectionEdit';
import Card from 'component/common/card'; import Card from 'component/common/card';
import Button from 'component/button'; import Button from 'component/button';
import CollectionActions from 'component/collectionActions';
import classnames from 'classnames'; import classnames from 'classnames';
import ClaimAuthor from 'component/claimAuthor';
import FileDescription from 'component/fileDescription';
import * as COLLECTIONS_CONSTS from 'constants/collections'; import * as COLLECTIONS_CONSTS from 'constants/collections';
import Icon from 'component/common/icon'; import Icon from 'component/common/icon';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import Spinner from 'component/spinner'; import Spinner from 'component/spinner';
import usePersistedState from 'effects/use-persisted-state';
// prettier-ignore // prettier-ignore
const Lazy = { const Lazy = {
// $FlowFixMe // $FlowFixMe
@ -29,13 +26,10 @@ export const EDIT_PAGE = 'edit';
type Props = { type Props = {
collectionId: string, collectionId: string,
uri: string,
claim: Claim, claim: Claim,
title: string, title: string,
thumbnail: string, thumbnail: string,
collection: Collection,
collectionUrls: Array<string>, collectionUrls: Array<string>,
collectionCount: number,
isResolvingCollection: boolean, isResolvingCollection: boolean,
isMyClaim: boolean, isMyClaim: boolean,
isMyCollection: boolean, isMyCollection: boolean,
@ -51,11 +45,7 @@ type Props = {
export default function HistoryPage(props: Props) { export default function HistoryPage(props: Props) {
const { const {
collectionId, collectionId,
uri,
claim, claim,
collection,
collectionUrls,
collectionCount,
collectionHasEdits, collectionHasEdits,
claimIsPending, claimIsPending,
isResolvingCollection, isResolvingCollection,
@ -64,17 +54,21 @@ export default function HistoryPage(props: Props) {
deleteCollection, deleteCollection,
} = props; } = props;
const collection = {
id: 'watchhistory',
name: __('Watch History'),
type: 'playlist',
};
const collectionUrls = [];
const [history] = usePersistedState('watch-history', []);
const { const {
replace,
location: { search }, location: { search },
} = useHistory(); } = useHistory();
const [didTryResolve, setDidTryResolve] = React.useState(false); const [didTryResolve, setDidTryResolve] = React.useState(false);
const [showInfo, setShowInfo] = React.useState(false);
const [showEdit, setShowEdit] = React.useState(false);
const [unavailableUris, setUnavailable] = React.useState([]); const [unavailableUris, setUnavailable] = React.useState([]);
const { name, totalItems } = collection || {};
const isBuiltin = COLLECTIONS_CONSTS.BUILTIN_LISTS.includes(collectionId); const isBuiltin = COLLECTIONS_CONSTS.BUILTIN_LISTS.includes(collectionId);
function handleOnDragEnd(result) { function handleOnDragEnd(result) {
@ -91,8 +85,7 @@ export default function HistoryPage(props: Props) {
const urlParams = new URLSearchParams(search); const urlParams = new URLSearchParams(search);
const editing = urlParams.get(PAGE_VIEW_QUERY) === EDIT_PAGE; const editing = urlParams.get(PAGE_VIEW_QUERY) === EDIT_PAGE;
const urlsReady = const urlsReady = collectionUrls && history.length;
collectionUrls && (totalItems === undefined || (totalItems && totalItems === collectionUrls.length));
React.useEffect(() => { React.useEffect(() => {
if (collectionId && !urlsReady && !didTryResolve && !collection) { if (collectionId && !urlsReady && !didTryResolve && !collection) {
@ -135,15 +128,6 @@ export default function HistoryPage(props: Props) {
titleActions = pending; titleActions = pending;
} }
const subTitle = (
<div>
<span className="collection__subtitle">
{collectionCount === 1 ? __('1 item') : __('%collectionCount% items', { collectionCount })}
</span>
{uri && <ClaimAuthor uri={uri} />}
</div>
);
const listName = claim ? claim.value.title || claim.name : collection && collection.name; const listName = claim ? claim.value.title || claim.name : collection && collection.name;
const info = ( const info = (
@ -154,7 +138,7 @@ export default function HistoryPage(props: Props) {
icon={ icon={
(collectionId === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) || (collectionId === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) ||
(collectionId === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) || (collectionId === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) ||
ICONS.STACK ICONS.TIME
} }
className="icon--margin-right" className="icon--margin-right"
/> />
@ -162,27 +146,6 @@ export default function HistoryPage(props: Props) {
</span> </span>
} }
titleActions={unavailableUris.length > 0 ? removeUnavailable : titleActions} titleActions={unavailableUris.length > 0 ? removeUnavailable : titleActions}
subtitle={subTitle}
body={
<CollectionActions
uri={uri}
collectionId={collectionId}
setShowInfo={setShowInfo}
showInfo={showInfo}
isBuiltin={isBuiltin}
collectionUrls={collectionUrls}
setShowEdit={setShowEdit}
showEdit={showEdit}
/>
}
actions={
showInfo &&
uri && (
<div className="section">
<FileDescription uri={uri} expandOverride />
</div>
)
}
/> />
); );
@ -202,27 +165,6 @@ export default function HistoryPage(props: Props) {
); );
} }
if (editing) {
return (
<Page
noFooter
noSideNavigation={editing}
backout={{
title: __('%action% %collection%', { collection: name, action: uri ? __('Editing') : __('Publishing') }),
simpleTitle: uri ? __('Editing') : __('Publishing'),
}}
>
<CollectionEdit
uri={uri}
collectionId={collectionId}
onDone={(id) => {
replace(`/$/${PAGES.LIST}/${id}`);
}}
/>
</Page>
);
}
if (urlsReady) { if (urlsReady) {
return ( return (
<Page className="playlistPage-wrapper"> <Page className="playlistPage-wrapper">
@ -234,9 +176,9 @@ export default function HistoryPage(props: Props) {
<Lazy.Droppable droppableId="list__ordering"> <Lazy.Droppable droppableId="list__ordering">
{(DroppableProvided) => ( {(DroppableProvided) => (
<ClaimList <ClaimList
uris={collectionUrls} uris={history}
collectionId={collectionId} collectionId={collectionId}
showEdit={showEdit} // showEdit={showEdit}
droppableProvided={DroppableProvided} droppableProvided={DroppableProvided}
unavailableUris={unavailableUris} unavailableUris={unavailableUris}
/> />

View file

@ -41,7 +41,7 @@ $nag-error-z-index: 999;
background-color: var(--color-primary); background-color: var(--color-primary);
color: var(--color-white); color: var(--color-white);
z-index: $nag-helpful-z-index; z-index: $nag-helpful-z-index;
border-radius: var(--border-radius); // border-radius: var(--border-radius);
margin-top: var(--spacing-s); margin-top: var(--spacing-s);
} }
@ -88,7 +88,7 @@ $nag-error-z-index: 999;
.nag__button--helpful { .nag__button--helpful {
&:hover { &:hover {
color: var(--color-secondary); color: var(--color-primary);
} }
} }