Add persistent watch time setting. #7547
6 changed files with 63 additions and 14 deletions
|
@ -2327,5 +2327,7 @@
|
|||
"* Note that as\n peer-to-peer software, your IP address and potentially other system information can be sent to other\n users, though this information is not stored permanently.": "* Note that as\n peer-to-peer software, your IP address and potentially other system information can be sent to other\n users, though this information is not stored permanently.",
|
||||
"Persist watch time": "Persist watch time",
|
||||
"Persist the watch time of the videos you have watched.": "Persist the watch time of the videos you have watched.",
|
||||
"Clearing...": "Clearing...",
|
||||
"Cache cleared": "Cache cleared",
|
||||
"--end--": "--end--"
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doResolveUri } from 'redux/actions/claims';
|
||||
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
||||
import { makeSelectContentPositionForUri } from 'redux/selectors/content';
|
||||
import { makeSelectContentWatchedPercentageForUri } from 'redux/selectors/content';
|
||||
import CardMedia from './view';
|
||||
|
||||
const select = (state, props) => {
|
||||
return {
|
||||
position: makeSelectContentPositionForUri(props.uri)(state),
|
||||
watchedPercentage: makeSelectContentWatchedPercentageForUri(props.uri)(state),
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -16,11 +16,20 @@ type Props = {
|
|||
claim: ?StreamClaim,
|
||||
doResolveUri: (string) => void,
|
||||
className?: string,
|
||||
position: number | null,
|
||||
watchedPercentage: number,
|
||||
};
|
||||
|
||||
function FileThumbnail(props: Props) {
|
||||
const { claim, uri, doResolveUri, thumbnail: rawThumbnail, children, allowGifs = false, className, position } = props;
|
||||
const {
|
||||
claim,
|
||||
uri,
|
||||
doResolveUri,
|
||||
thumbnail: rawThumbnail,
|
||||
children,
|
||||
allowGifs = false,
|
||||
className,
|
||||
watchedPercentage,
|
||||
} = props;
|
||||
|
||||
const passedThumbnail = rawThumbnail && rawThumbnail.trim().replace(/^http:\/\//i, 'https://');
|
||||
const thumbnailFromClaim =
|
||||
|
@ -30,12 +39,7 @@ function FileThumbnail(props: Props) {
|
|||
const hasResolvedClaim = claim !== undefined;
|
||||
const isGif = thumbnail && thumbnail.endsWith('gif');
|
||||
|
||||
const media = claim && claim.value && (claim.value.video || claim.value.audio);
|
||||
const duration = media && media.duration;
|
||||
// When the position is -1, it means the user has watched the entire
|
||||
// video and he/she is using the persist watch setting.
|
||||
const watchedPercentage = position === -1 ? 100 : ((position || 0) / (duration || 1)) * 100 || 0;
|
||||
const viewedBar = position && (
|
||||
const viewedBar = watchedPercentage && (
|
||||
<div className="file-thumbnail__viewed-bar">
|
||||
<div className="file-thumbnail__viewed-bar-progress" style={{ width: `${watchedPercentage}%` }} />
|
||||
</div>
|
||||
|
|
|
@ -52,6 +52,18 @@ export default function SettingContent(props: Props) {
|
|||
clearPlayingUri,
|
||||
clearContentCache,
|
||||
} = props;
|
||||
const [contentCacheCleared, setContentCacheCleared] = React.useState(false);
|
||||
const [clearingContentCache, setClearingContentCache] = React.useState(false);
|
||||
const onClearContentCache = React.useCallback(() => {
|
||||
setClearingContentCache(true);
|
||||
clearContentCache();
|
||||
// Just a small timer to give the user a visual effect
|
||||
// that the content is being cleared.
|
||||
setTimeout(() => {
|
||||
setClearingContentCache(false);
|
||||
setContentCacheCleared(true);
|
||||
}, 2000);
|
||||
}, [setClearingContentCache, clearContentCache, setContentCacheCleared]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -119,9 +131,15 @@ export default function SettingContent(props: Props) {
|
|||
<Button
|
||||
button="primary"
|
||||
icon={ICONS.ALERT}
|
||||
label="Clear Cache"
|
||||
onClick={clearContentCache}
|
||||
disabled={false}
|
||||
label={
|
||||
contentCacheCleared
|
||||
? __('Cache cleared')
|
||||
: clearingContentCache
|
||||
? __('Clearing...')
|
||||
: __('Clear Cache')
|
||||
}
|
||||
onClick={onClearContentCache}
|
||||
disabled={clearingContentCache || contentCacheCleared}
|
||||
/>
|
||||
</div>
|
||||
</SettingsRow>
|
||||
|
|
|
@ -246,7 +246,7 @@ export function clearPosition(uri: string) {
|
|||
if (persistWatchTime) {
|
||||
dispatch({
|
||||
type: ACTIONS.SET_CONTENT_POSITION,
|
||||
data: { claimId, outpoint, position: -1 },
|
||||
data: { claimId, outpoint, position: null },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,31 @@ export const makeSelectContentPositionForUri = (uri: string) =>
|
|||
return state.positions[id] ? state.positions[id][outpoint] : null;
|
||||
});
|
||||
|
||||
export const makeSelectContentWatchedPercentageForUri = (uri: string) =>
|
||||
createSelector(selectState, makeSelectClaimForUri(uri), (state, claim) => {
|
||||
if (!claim) {
|
||||
return 0;
|
||||
}
|
||||
const media = claim.value && (claim.value.video || claim.value.audio);
|
||||
if (!media) {
|
||||
return 0;
|
||||
}
|
||||
const id = claim.claim_id;
|
||||
if (!state.positions[id]) {
|
||||
return 0;
|
||||
}
|
||||
const outpoint = `${claim.txid}:${claim.nout}`;
|
||||
const watched = state.positions[id][outpoint];
|
||||
// If the user turns on the persist watch setting,
|
||||
// clearing the position will set it to null,
|
||||
// which means the entire video has been watched.
|
||||
if (watched === null) {
|
||||
return 100;
|
||||
}
|
||||
const duration = media.duration;
|
||||
return (watched / duration) * 100;
|
||||
});
|
||||
|
||||
export const selectHistory = createSelector(selectState, (state) => state.history || []);
|
||||
|
||||
export const selectHistoryPageCount = createSelector(selectHistory, (history) =>
|
||||
|
|
Loading…
Reference in a new issue