Replace local sorage with redux
This commit is contained in:
parent
f3fd0ba08f
commit
d3fc96d961
7 changed files with 41 additions and 28 deletions
|
@ -141,7 +141,6 @@ 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);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { selectIsSubscribedForUri } from 'redux/selectors/subscriptions';
|
||||||
import { isClaimNsfw, isStreamPlaceholderClaim } from 'util/claim';
|
import { isClaimNsfw, isStreamPlaceholderClaim } from 'util/claim';
|
||||||
import ClaimPreview from './view';
|
import ClaimPreview from './view';
|
||||||
import formatMediaDuration from 'util/formatMediaDuration';
|
import formatMediaDuration from 'util/formatMediaDuration';
|
||||||
|
import { doClearContentHistoryUri } from 'redux/actions/content';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
const claim = props.uri && selectClaimForUri(state, props.uri);
|
const claim = props.uri && selectClaimForUri(state, props.uri);
|
||||||
|
@ -55,6 +56,7 @@ const select = (state, props) => {
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
resolveUri: (uri) => dispatch(doResolveUri(uri)),
|
resolveUri: (uri) => dispatch(doResolveUri(uri)),
|
||||||
getFile: (uri) => dispatch(doFileGet(uri, false)),
|
getFile: (uri) => dispatch(doFileGet(uri, false)),
|
||||||
|
doClearContentHistoryUri: (uri) => dispatch(doClearContentHistoryUri(uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(ClaimPreview);
|
export default connect(select, perform)(ClaimPreview);
|
||||||
|
|
|
@ -37,7 +37,6 @@ import { ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
||||||
import CollectionEditButtons from 'component/collectionEditButtons';
|
import CollectionEditButtons from 'component/collectionEditButtons';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import { useIsMobile } from 'effects/use-screensize';
|
import { useIsMobile } from 'effects/use-screensize';
|
||||||
import usePersistedState from 'effects/use-persisted-state';
|
|
||||||
|
|
||||||
const AbandonedChannelPreview = lazyImport(() =>
|
const AbandonedChannelPreview = lazyImport(() =>
|
||||||
import('component/abandonedChannelPreview' /* webpackChunkName: "abandonedChannelPreview" */)
|
import('component/abandonedChannelPreview' /* webpackChunkName: "abandonedChannelPreview" */)
|
||||||
|
@ -98,6 +97,7 @@ type Props = {
|
||||||
unavailableUris?: Array<string>,
|
unavailableUris?: Array<string>,
|
||||||
showMemberBadge?: boolean,
|
showMemberBadge?: boolean,
|
||||||
inWatchHistory?: boolean,
|
inWatchHistory?: boolean,
|
||||||
|
doClearContentHistoryUri: (uri: string) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
|
@ -164,6 +164,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
unavailableUris,
|
unavailableUris,
|
||||||
showMemberBadge,
|
showMemberBadge,
|
||||||
inWatchHistory,
|
inWatchHistory,
|
||||||
|
doClearContentHistoryUri,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
@ -214,7 +215,6 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
? claim.permanent_url || claim.canonical_url
|
? claim.permanent_url || claim.canonical_url
|
||||||
: undefined;
|
: undefined;
|
||||||
const repostedContentUri = claim && (claim.reposted_claim ? claim.reposted_claim.permanent_url : claim.permanent_url);
|
const repostedContentUri = claim && (claim.reposted_claim ? claim.reposted_claim.permanent_url : claim.permanent_url);
|
||||||
const [watchHistory, setWatchHistory] = usePersistedState('watch-history', []);
|
|
||||||
|
|
||||||
// Get channel title ( use name as fallback )
|
// Get channel title ( use name as fallback )
|
||||||
let channelTitle = null;
|
let channelTitle = null;
|
||||||
|
@ -298,10 +298,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
|
|
||||||
function removeFromHistory(e, uri) {
|
function removeFromHistory(e, uri) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (watchHistory.find((entry) => entry === uri)) {
|
doClearContentHistoryUri(uri);
|
||||||
watchHistory.splice(watchHistory.indexOf(uri), 1);
|
|
||||||
setWatchHistory(watchHistory);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -16,7 +16,13 @@ import {
|
||||||
doAnalyticsView,
|
doAnalyticsView,
|
||||||
} from 'redux/actions/app';
|
} from 'redux/actions/app';
|
||||||
import { selectVolume, selectMute } from 'redux/selectors/app';
|
import { selectVolume, selectMute } from 'redux/selectors/app';
|
||||||
import { savePosition, clearPosition, doPlayUri, doSetPlayingUri } from 'redux/actions/content';
|
import {
|
||||||
|
savePosition,
|
||||||
|
clearPosition,
|
||||||
|
doPlayUri,
|
||||||
|
doSetPlayingUri,
|
||||||
|
doSetContentHistoryItem,
|
||||||
|
} from 'redux/actions/content';
|
||||||
import { makeSelectIsPlayerFloating, selectContentPositionForUri, selectPlayingUri } from 'redux/selectors/content';
|
import { makeSelectIsPlayerFloating, selectContentPositionForUri, selectPlayingUri } from 'redux/selectors/content';
|
||||||
import { selectRecommendedContentForUri } from 'redux/selectors/search';
|
import { selectRecommendedContentForUri } from 'redux/selectors/search';
|
||||||
import VideoViewer from './view';
|
import VideoViewer from './view';
|
||||||
|
@ -104,6 +110,7 @@ const perform = (dispatch) => ({
|
||||||
doAnalyticsView: (uri, timeToStart) => dispatch(doAnalyticsView(uri, timeToStart)),
|
doAnalyticsView: (uri, timeToStart) => dispatch(doAnalyticsView(uri, timeToStart)),
|
||||||
claimRewards: () => dispatch(doClaimEligiblePurchaseRewards()),
|
claimRewards: () => dispatch(doClaimEligiblePurchaseRewards()),
|
||||||
doToast: (props) => dispatch(doToast(props)),
|
doToast: (props) => dispatch(doToast(props)),
|
||||||
|
doSetContentHistoryItem: (uri) => dispatch(doSetContentHistoryItem(uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default withRouter(connect(select, perform)(VideoViewer));
|
export default withRouter(connect(select, perform)(VideoViewer));
|
||||||
|
|
|
@ -29,7 +29,6 @@ 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;
|
||||||
|
@ -73,6 +72,9 @@ type Props = {
|
||||||
activeLivestreamForChannel: any,
|
activeLivestreamForChannel: any,
|
||||||
defaultQuality: ?string,
|
defaultQuality: ?string,
|
||||||
doToast: ({ message: string, linkText: string, linkTarget: string }) => void,
|
doToast: ({ message: string, linkText: string, linkTarget: string }) => void,
|
||||||
|
selectHistory: Array<string>,
|
||||||
|
doSetContentHistoryItem: (uri: string) => void,
|
||||||
|
doClearContentHistoryUri: (uri: string) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -119,6 +121,7 @@ function VideoViewer(props: Props) {
|
||||||
activeLivestreamForChannel,
|
activeLivestreamForChannel,
|
||||||
defaultQuality,
|
defaultQuality,
|
||||||
doToast,
|
doToast,
|
||||||
|
doSetContentHistoryItem,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const permanentUrl = claim && claim.permanent_url;
|
const permanentUrl = claim && claim.permanent_url;
|
||||||
|
@ -152,21 +155,9 @@ 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 [watchHistory, setWatchHistory] = usePersistedState('watch-history', []);
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!watchHistory[0] || !watchHistory[0].indexOf(claim.permanent_url) !== -1) {
|
if (isPlaying) {
|
||||||
if (!watchHistory || !watchHistory.length) {
|
doSetContentHistoryItem(claim.permanent_url);
|
||||||
setWatchHistory([claim.permanent_url]);
|
|
||||||
} else {
|
|
||||||
let newWatchHistory = watchHistory;
|
|
||||||
if (newWatchHistory.find((entry) => entry === claim.permanent_url)) {
|
|
||||||
newWatchHistory.splice(newWatchHistory.indexOf(claim.permanent_url), 1);
|
|
||||||
newWatchHistory.unshift(claim.permanent_url);
|
|
||||||
} else {
|
|
||||||
newWatchHistory.unshift(claim.permanent_url);
|
|
||||||
}
|
|
||||||
setWatchHistory(newWatchHistory);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [isPlaying]);
|
}, [isPlaying]);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,10 @@ import {
|
||||||
makeSelectChannelForClaimUri,
|
makeSelectChannelForClaimUri,
|
||||||
} from 'redux/selectors/claims';
|
} from 'redux/selectors/claims';
|
||||||
|
|
||||||
|
import { selectHistory } from 'redux/selectors/content';
|
||||||
|
|
||||||
|
import { doClearContentHistoryAll } from 'redux/actions/content';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
makeSelectCollectionForId,
|
makeSelectCollectionForId,
|
||||||
makeSelectUrlsForCollectionId,
|
makeSelectUrlsForCollectionId,
|
||||||
|
@ -38,6 +42,7 @@ const select = (state, props) => {
|
||||||
collectionUrls: makeSelectUrlsForCollectionId(collectionId)(state),
|
collectionUrls: makeSelectUrlsForCollectionId(collectionId)(state),
|
||||||
collectionCount: makeSelectCountForCollectionId(collectionId)(state),
|
collectionCount: makeSelectCountForCollectionId(collectionId)(state),
|
||||||
isResolvingCollection: makeSelectIsResolvingCollectionForId(collectionId)(state),
|
isResolvingCollection: makeSelectIsResolvingCollectionForId(collectionId)(state),
|
||||||
|
selectHistory: selectHistory(state, uri),
|
||||||
title: selectTitleForUri(state, uri),
|
title: selectTitleForUri(state, uri),
|
||||||
thumbnail: getThumbnailFromClaim(claim),
|
thumbnail: getThumbnailFromClaim(claim),
|
||||||
isMyClaim: selectClaimIsMine(state, claim), // or collection is mine?
|
isMyClaim: selectClaimIsMine(state, claim), // or collection is mine?
|
||||||
|
@ -51,6 +56,7 @@ const select = (state, props) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
|
doClearContentHistoryAll: () => dispatch(doClearContentHistoryAll()),
|
||||||
fetchCollectionItems: (claimId, cb) => dispatch(doFetchItemsInCollection({ collectionId: claimId }, cb)), // if this collection is not resolved, resolve it
|
fetchCollectionItems: (claimId, cb) => dispatch(doFetchItemsInCollection({ collectionId: claimId }, cb)), // if this collection is not resolved, resolve it
|
||||||
deleteCollection: (id, colKey) => dispatch(doCollectionDelete(id, colKey)),
|
deleteCollection: (id, colKey) => dispatch(doCollectionDelete(id, colKey)),
|
||||||
editCollection: (id, params) => dispatch(doCollectionEdit(id, params)),
|
editCollection: (id, params) => dispatch(doCollectionEdit(id, params)),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import ClaimList from 'component/claimList';
|
import ClaimList from 'component/claimList';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -8,7 +8,6 @@ import Icon from 'component/common/icon';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import { YRBL_SAD_IMG_URL } from 'config';
|
import { YRBL_SAD_IMG_URL } from 'config';
|
||||||
import Tooltip from 'component/common/tooltip';
|
import Tooltip from 'component/common/tooltip';
|
||||||
import usePersistedState from 'effects/use-persisted-state';
|
|
||||||
|
|
||||||
export const PAGE_VIEW_QUERY = 'view';
|
export const PAGE_VIEW_QUERY = 'view';
|
||||||
|
|
||||||
|
@ -19,20 +18,32 @@ type Props = {
|
||||||
thumbnail: string,
|
thumbnail: string,
|
||||||
collectionUrls: Array<string>,
|
collectionUrls: Array<string>,
|
||||||
isResolvingCollection: boolean,
|
isResolvingCollection: boolean,
|
||||||
|
selectHistory: Array<any>,
|
||||||
|
doClearContentHistoryAll: () => void,
|
||||||
fetchCollectionItems: (string, () => void) => void,
|
fetchCollectionItems: (string, () => void) => void,
|
||||||
resolveUris: (string) => void,
|
resolveUris: (string) => void,
|
||||||
user: ?User,
|
user: ?User,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function WatchHistoryPage(props: Props) {
|
export default function WatchHistoryPage(props: Props) {
|
||||||
const { collectionId } = props;
|
const { collectionId, selectHistory, doClearContentHistoryAll } = props;
|
||||||
const [watchHistory, setWatchHistory] = usePersistedState('watch-history', []);
|
const [watchHistory, setWatchHistory] = useState([]);
|
||||||
const [unavailableUris] = React.useState([]);
|
const [unavailableUris] = React.useState([]);
|
||||||
|
|
||||||
function clearHistory() {
|
function clearHistory() {
|
||||||
setWatchHistory([]);
|
doClearContentHistoryAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
let newWatchHistory = [];
|
||||||
|
for (let entry of selectHistory) {
|
||||||
|
if (entry.uri.indexOf('@') !== -1) {
|
||||||
|
newWatchHistory.push(entry.uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setWatchHistory(newWatchHistory);
|
||||||
|
}, [selectHistory]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page className="historyPage-wrapper">
|
<Page className="historyPage-wrapper">
|
||||||
<div className={classnames('section card-stack')}>
|
<div className={classnames('section card-stack')}>
|
||||||
|
|
Loading…
Reference in a new issue