Add persistent watch time setting. #7547

Merged
Ruk33 merged 8 commits from 7543-settings-option-to-persist-fully-watched-files-for-view-indicator into master 2022-04-22 05:00:57 +02:00
6 changed files with 63 additions and 14 deletions
Showing only changes of commit 58716ce5d9 - Show all commits

View file

@ -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--"
}

View file

@ -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),
};
};

View file

@ -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>

View file

@ -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>

View file

@ -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;
}

View file

@ -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) =>