record browsing history, persist content
This commit is contained in:
parent
58ed68d8c3
commit
5cd7794fa0
9 changed files with 75 additions and 8 deletions
|
@ -231,7 +231,6 @@ class FileViewer extends React.PureComponent<Props> {
|
|||
<div className={classnames('video', {}, className)}>
|
||||
{isPlaying && (
|
||||
<div className="content__view">
|
||||
<p>hai</p>
|
||||
{!isReadyToPlay ? (
|
||||
<div className={layoverClass} style={layoverStyle}>
|
||||
<LoadingScreen status={loadStatusMessage} />
|
||||
|
|
|
@ -73,8 +73,11 @@ export const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED';
|
|||
export const PUBLISH_STARTED = 'PUBLISH_STARTED';
|
||||
export const PUBLISH_COMPLETED = 'PUBLISH_COMPLETED';
|
||||
export const PUBLISH_FAILED = 'PUBLISH_FAILED';
|
||||
export const SET_PLAYING_URI = 'PLAY_URI';
|
||||
export const SET_PLAYING_URI = 'SET_PLAYING_URI';
|
||||
export const SET_CONTENT_POSITION = 'SET_CONTENT_POSITION';
|
||||
export const SET_CONTENT_LAST_VIEWED = 'SET_CONTENT_LAST_VIEWED';
|
||||
export const CLEAR_CONTENT_HISTORY_URI = 'CLEAR_CONTENT_HISTORY_URI';
|
||||
export const CLEAR_CONTENT_HISTORY_ALL = 'CLEAR_CONTENT_HISTORY_ALL';
|
||||
|
||||
// Files
|
||||
export const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
|
||||
|
|
1
src/renderer/constants/content.js
Normal file
1
src/renderer/constants/content.js
Normal file
|
@ -0,0 +1 @@
|
|||
export const HISTORY_ITEMS_PER_PAGE = 30;
|
|
@ -4,6 +4,7 @@ import { doNavigate } from 'redux/actions/navigation';
|
|||
import { selectRewardContentClaimIds, selectPlayingUri } from 'redux/selectors/content';
|
||||
import { doCheckSubscription } from 'redux/actions/subscriptions';
|
||||
import { doSetClientSetting } from 'redux/actions/settings';
|
||||
import { doSetContentHistoryItem } from 'redux/actions/content';
|
||||
import {
|
||||
doFetchFileInfo,
|
||||
doFetchCostInfoForUri,
|
||||
|
@ -42,6 +43,7 @@ const perform = dispatch => ({
|
|||
openModal: (modal, props) => dispatch(doNotify(modal, props)),
|
||||
prepareEdit: (publishData, uri) => dispatch(doPrepareEdit(publishData, uri)),
|
||||
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
|
||||
setViewed: uri => dispatch(doSetContentHistoryItem(uri)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -46,8 +46,7 @@ type Props = {
|
|||
prepareEdit: ({}, string) => void,
|
||||
checkSubscription: (uri: string) => void,
|
||||
subscriptions: Array<Subscription>,
|
||||
setClientSetting: (string, boolean | string) => void,
|
||||
autoplay: boolean,
|
||||
setViewed: string => void,
|
||||
};
|
||||
|
||||
class FilePage extends React.Component<Props> {
|
||||
|
@ -71,7 +70,7 @@ class FilePage extends React.Component<Props> {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { uri, fileInfo, fetchFileInfo, fetchCostInfo } = this.props;
|
||||
const { uri, fileInfo, fetchFileInfo, fetchCostInfo, setViewed } = this.props;
|
||||
|
||||
if (fileInfo === undefined) {
|
||||
fetchFileInfo(uri);
|
||||
|
@ -81,6 +80,8 @@ class FilePage extends React.Component<Props> {
|
|||
fetchCostInfo(uri);
|
||||
|
||||
this.checkSubscription(this.props);
|
||||
|
||||
setViewed(uri);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
|
@ -129,7 +130,7 @@ class FilePage extends React.Component<Props> {
|
|||
const { title, thumbnail } = metadata;
|
||||
const { height, channel_name: channelName, value } = claim;
|
||||
const { PLAYABLE_MEDIA_TYPES, PREVIEW_MEDIA_TYPES } = FilePage;
|
||||
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
||||
const isRewardContent = (rewardedContentClaimIds || []).includes(claim.claim_id);
|
||||
const shouldObscureThumbnail = obscureNsfw && metadata.nsfw;
|
||||
const fileName = fileInfo ? fileInfo.file_name : null;
|
||||
const mediaType = getMediaType(contentType, fileName);
|
||||
|
|
|
@ -504,3 +504,27 @@ export function savePosition(claimId: string, outpoint: string, position: number
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetContentHistoryItem(uri: string) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.SET_CONTENT_LAST_VIEWED,
|
||||
data: { uri, lastViewed: Date.now() },
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doClearContentHistoryUri(uri: string) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.CLEAR_CONTENT_HISTORY_URI,
|
||||
data: { uri },
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetContentHistoryAll() {
|
||||
return dispatch => {
|
||||
dispatch({ type: ACTIONS.CLEAR_CONTENT_HISTORY_ALL });
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ const defaultState = {
|
|||
rewardedContentClaimIds: [],
|
||||
channelClaimCounts: {},
|
||||
positions: {},
|
||||
history: [],
|
||||
};
|
||||
|
||||
reducers[ACTIONS.FETCH_FEATURED_CONTENT_STARTED] = state =>
|
||||
|
@ -94,6 +95,32 @@ reducers[ACTIONS.SET_CONTENT_POSITION] = (state, action) => {
|
|||
};
|
||||
};
|
||||
|
||||
reducers[ACTIONS.SET_CONTENT_LAST_VIEWED] = (state, action) => {
|
||||
const { uri, lastViewed } = action.data;
|
||||
const { history } = state;
|
||||
const historyObj = { uri, lastViewed };
|
||||
const index = history.findIndex(i => i.uri === uri);
|
||||
const newHistory =
|
||||
index === -1
|
||||
? [historyObj].concat(history)
|
||||
: [historyObj].concat(history.slice(0, index), history.slice(index + 1));
|
||||
return { ...state, history: [...newHistory] };
|
||||
};
|
||||
|
||||
reducers[ACTIONS.CLEAR_CONTENT_HISTORY_URI] = (state, action) => {
|
||||
const { uri } = action.data;
|
||||
const { history } = state;
|
||||
const index = history.findIndex(i => i.uri === uri);
|
||||
return index === -1
|
||||
? state
|
||||
: {
|
||||
...state,
|
||||
history: history.slice(0, index).concat(history.slice(index + 1)),
|
||||
};
|
||||
};
|
||||
|
||||
reducers[ACTIONS.CLEAR_CONTENT_HISTORY_ALL] = state => ({ ...state, history: [] });
|
||||
|
||||
export default function reducer(state = defaultState, action) {
|
||||
const handler = reducers[action.type];
|
||||
if (handler) return handler(state, action);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { createSelector } from 'reselect';
|
||||
import { makeSelectClaimForUri } from 'lbry-redux';
|
||||
import { HISTORY_ITEMS_PER_PAGE } from 'constants/content';
|
||||
|
||||
export const selectState = state => state.content || {};
|
||||
|
||||
|
@ -40,3 +41,11 @@ export const makeSelectContentPositionForUri = uri =>
|
|||
const id = claim.claim_id;
|
||||
return state.positions[id] ? state.positions[id][outpoint] : null;
|
||||
});
|
||||
|
||||
export const makeSelectHistoryForPage = (page = 1) =>
|
||||
createSelector(selectState, state =>
|
||||
state.history.slice((page - 1) * HISTORY_ITEMS_PER_PAGE, HISTORY_ITEMS_PER_PAGE)
|
||||
);
|
||||
|
||||
export const makeSelectHistoryForUri = uri =>
|
||||
createSelector(selectState, state => state.history.find(i => i.uri === uri));
|
||||
|
|
|
@ -100,15 +100,16 @@ const store = createStore(
|
|||
const compressor = createCompressor();
|
||||
const saveClaimsFilter = createFilter('claims', ['byId', 'claimsByUri']);
|
||||
const subscriptionsFilter = createFilter('subscriptions', ['subscriptions']);
|
||||
const contentFilter = createFilter('content', ['positions', 'history']);
|
||||
|
||||
// We only need to persist the receiveAddress for the wallet
|
||||
const walletFilter = createFilter('wallet', ['receiveAddress']);
|
||||
|
||||
const persistOptions = {
|
||||
whitelist: ['claims', 'subscriptions', 'publish', 'wallet'],
|
||||
whitelist: ['claims', 'subscriptions', 'publish', 'wallet', 'content'],
|
||||
// Order is important. Needs to be compressed last or other transforms can't
|
||||
// read the data
|
||||
transforms: [saveClaimsFilter, subscriptionsFilter, walletFilter, compressor],
|
||||
transforms: [saveClaimsFilter, subscriptionsFilter, walletFilter, contentFilter, compressor],
|
||||
debounce: 10000,
|
||||
storage: localForage,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue