From bdfe9ed99867fe9daff43a15d7495ec6ffb092d9 Mon Sep 17 00:00:00 2001 From: Franco Montenegro Date: Mon, 18 Apr 2022 14:54:29 -0300 Subject: [PATCH 1/8] Add persistent watch time setting. --- static/app-strings.json | 3 +++ ui/component/fileThumbnail/index.js | 17 ++++++++++++----- ui/component/settingContent/index.js | 1 + ui/component/settingContent/view.jsx | 11 +++++++++++ ui/constants/settings.js | 1 + ui/redux/reducers/content.js | 1 + ui/redux/selectors/content.js | 10 ++++++++++ 7 files changed, 39 insertions(+), 5 deletions(-) diff --git a/static/app-strings.json b/static/app-strings.json index 0b7f246ca..357f52efe 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -2324,5 +2324,8 @@ "%repost% %publish%": "%repost% %publish%", "Failed to view lbry://@MicheL-PDF#7/LaDameAuPain#f, please try again. If this problem persists, visit https://lbry.com/faq/support for support.": "Failed to view lbry://@MicheL-PDF#7/LaDameAuPain#f, please try again. If this problem persists, visit https://lbry.com/faq/support for support.", "Go to": "Go to", + "* 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.", "--end--": "--end--" } diff --git a/ui/component/fileThumbnail/index.js b/ui/component/fileThumbnail/index.js index 61122facd..9dfd3400b 100644 --- a/ui/component/fileThumbnail/index.js +++ b/ui/component/fileThumbnail/index.js @@ -1,12 +1,19 @@ import { connect } from 'react-redux'; +import * as SETTINGS from 'constants/settings'; import { doResolveUri } from 'redux/actions/claims'; +import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClaimForUri } from 'redux/selectors/claims'; -import { makeSelectContentPositionForUri } from 'redux/selectors/content'; +import { makeSelectContentPositionForUri, makeSelectContentPositionPersistedForUri } from 'redux/selectors/content'; import CardMedia from './view'; -const select = (state, props) => ({ - position: makeSelectContentPositionForUri(props.uri)(state), - claim: makeSelectClaimForUri(props.uri)(state), -}); +const select = (state, props) => { + const persistWatchTime = makeSelectClientSetting(SETTINGS.PERSIST_WATCH_TIME)(state); + return { + position: persistWatchTime + ? makeSelectContentPositionPersistedForUri(props.uri)(state) + : makeSelectContentPositionForUri(props.uri)(state), + claim: makeSelectClaimForUri(props.uri)(state), + }; +}; export default connect(select, { doResolveUri })(CardMedia); diff --git a/ui/component/settingContent/index.js b/ui/component/settingContent/index.js index c0315f279..bfa054385 100644 --- a/ui/component/settingContent/index.js +++ b/ui/component/settingContent/index.js @@ -14,6 +14,7 @@ const select = (state) => ({ autoplayMedia: makeSelectClientSetting(SETTINGS.AUTOPLAY_MEDIA)(state), autoplayNext: makeSelectClientSetting(SETTINGS.AUTOPLAY_NEXT)(state), hideReposts: makeSelectClientSetting(SETTINGS.HIDE_REPOSTS)(state), + persistWatchTime: makeSelectClientSetting(SETTINGS.PERSIST_WATCH_TIME)(state), showNsfw: selectShowMatureContent(state), myChannelUrls: selectMyChannelUrls(state), instantPurchaseEnabled: makeSelectClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED)(state), diff --git a/ui/component/settingContent/view.jsx b/ui/component/settingContent/view.jsx index bce8a4a17..a388c345d 100644 --- a/ui/component/settingContent/view.jsx +++ b/ui/component/settingContent/view.jsx @@ -24,6 +24,7 @@ type Props = { autoplayNext: boolean, hideReposts: ?boolean, showNsfw: boolean, + persistWatchTime: boolean, myChannelUrls: ?Array, instantPurchaseEnabled: boolean, instantPurchaseMax: Price, @@ -40,6 +41,7 @@ export default function SettingContent(props: Props) { autoplayMedia, autoplayNext, hideReposts, + persistWatchTime, showNsfw, myChannelUrls, instantPurchaseEnabled, @@ -102,6 +104,14 @@ export default function SettingContent(props: Props) { checked={hideReposts} /> + + setClientSetting(SETTINGS.PERSIST_WATCH_TIME, !persistWatchTime)} + checked={persistWatchTime} + /> + { [claimId]: { ...state.positions[claimId], [outpoint]: position, + [`${outpoint}:persisted`]: position, }, }, }; diff --git a/ui/redux/selectors/content.js b/ui/redux/selectors/content.js index f3d4e9784..298f8988f 100644 --- a/ui/redux/selectors/content.js +++ b/ui/redux/selectors/content.js @@ -63,6 +63,16 @@ export const makeSelectContentPositionForUri = (uri: string) => return state.positions[id] ? state.positions[id][outpoint] : null; }); +export const makeSelectContentPositionPersistedForUri = (uri: string) => + createSelector(selectState, makeSelectClaimForUri(uri), (state, claim) => { + if (!claim) { + return null; + } + const outpoint = `${claim.txid}:${claim.nout}:persisted`; + const id = claim.claim_id; + return state.positions[id] ? state.positions[id][outpoint] : null; + }); + export const selectHistory = createSelector(selectState, (state) => state.history || []); export const selectHistoryPageCount = createSelector(selectHistory, (history) => -- 2.45.3 From 6c498d02e18139ffda8b67b75faeff5561c497f3 Mon Sep 17 00:00:00 2001 From: zeppi Date: Wed, 20 Apr 2022 17:14:16 -0400 Subject: [PATCH 2/8] floating bugfix --- ui/component/viewers/videoViewer/view.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/component/viewers/videoViewer/view.jsx b/ui/component/viewers/videoViewer/view.jsx index da2a9c6bf..519e1a3a4 100644 --- a/ui/component/viewers/videoViewer/view.jsx +++ b/ui/component/viewers/videoViewer/view.jsx @@ -270,7 +270,11 @@ function VideoViewer(props: Props) { } function handlePosition(player) { - savePosition(uri, player.currentTime()); + const currTime = player.currentTime(); + const durationInSeconds = claim.value.video && claim.value.video.duration; + if (Number(durationInSeconds) > Number(currTime)) { + savePosition(uri, player.currentTime()); + } } function restorePlaybackRate(player) { -- 2.45.3 From 26918e3d58eae00ead6d3a83adbd69df60b875a0 Mon Sep 17 00:00:00 2001 From: Franco Montenegro Date: Thu, 21 Apr 2022 14:43:23 -0300 Subject: [PATCH 3/8] Improve how the persist watch time is being stored; add clear cache button. --- ui/component/fileThumbnail/index.js | 9 ++------- ui/component/fileThumbnail/view.jsx | 9 ++++++--- ui/component/settingContent/index.js | 3 ++- ui/component/settingContent/view.jsx | 25 +++++++++++++++++++------ ui/constants/action_types.js | 1 + ui/redux/actions/content.js | 15 +++++++++++++++ ui/redux/reducers/content.js | 8 +++++++- ui/redux/reducers/settings.js | 1 + ui/redux/selectors/content.js | 10 ---------- ui/scss/component/_settings.scss | 10 ++++++++++ 10 files changed, 63 insertions(+), 28 deletions(-) diff --git a/ui/component/fileThumbnail/index.js b/ui/component/fileThumbnail/index.js index 9dfd3400b..f657b7e66 100644 --- a/ui/component/fileThumbnail/index.js +++ b/ui/component/fileThumbnail/index.js @@ -1,17 +1,12 @@ import { connect } from 'react-redux'; -import * as SETTINGS from 'constants/settings'; import { doResolveUri } from 'redux/actions/claims'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClaimForUri } from 'redux/selectors/claims'; -import { makeSelectContentPositionForUri, makeSelectContentPositionPersistedForUri } from 'redux/selectors/content'; +import { makeSelectContentPositionForUri } from 'redux/selectors/content'; import CardMedia from './view'; const select = (state, props) => { - const persistWatchTime = makeSelectClientSetting(SETTINGS.PERSIST_WATCH_TIME)(state); return { - position: persistWatchTime - ? makeSelectContentPositionPersistedForUri(props.uri)(state) - : makeSelectContentPositionForUri(props.uri)(state), + position: makeSelectContentPositionForUri(props.uri)(state), claim: makeSelectClaimForUri(props.uri)(state), }; }; diff --git a/ui/component/fileThumbnail/view.jsx b/ui/component/fileThumbnail/view.jsx index b658ac215..1e16cadd1 100644 --- a/ui/component/fileThumbnail/view.jsx +++ b/ui/component/fileThumbnail/view.jsx @@ -16,7 +16,7 @@ type Props = { claim: ?StreamClaim, doResolveUri: (string) => void, className?: string, - position?: number, + position: number | null, }; function FileThumbnail(props: Props) { @@ -32,9 +32,12 @@ function FileThumbnail(props: Props) { const media = claim && claim.value && (claim.value.video || claim.value.audio); const duration = media && media.duration; - const viewedBar = position && 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 && (
-
+
); diff --git a/ui/component/settingContent/index.js b/ui/component/settingContent/index.js index bfa054385..a934aa76b 100644 --- a/ui/component/settingContent/index.js +++ b/ui/component/settingContent/index.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux'; import { selectMyChannelUrls } from 'redux/selectors/claims'; import * as SETTINGS from 'constants/settings'; -import { doSetPlayingUri } from 'redux/actions/content'; +import { doSetPlayingUri, clearContentCache } from 'redux/actions/content'; import { doSetClientSetting } from 'redux/actions/settings'; import { selectShowMatureContent, makeSelectClientSetting } from 'redux/selectors/settings'; import { selectUserVerifiedEmail } from 'redux/selectors/user'; @@ -25,6 +25,7 @@ const select = (state) => ({ const perform = (dispatch) => ({ setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), clearPlayingUri: () => dispatch(doSetPlayingUri({ uri: null })), + clearContentCache: () => dispatch(clearContentCache()), }); export default connect(select, perform)(SettingContent); diff --git a/ui/component/settingContent/view.jsx b/ui/component/settingContent/view.jsx index a388c345d..114c6c3ba 100644 --- a/ui/component/settingContent/view.jsx +++ b/ui/component/settingContent/view.jsx @@ -32,6 +32,7 @@ type Props = { // --- perform --- setClientSetting: (string, boolean | string | number) => void, clearPlayingUri: () => void, + clearContentCache: () => void, }; export default function SettingContent(props: Props) { @@ -49,6 +50,7 @@ export default function SettingContent(props: Props) { enablePublishPreview, setClientSetting, clearPlayingUri, + clearContentCache, } = props; return ( @@ -105,12 +107,23 @@ export default function SettingContent(props: Props) { /> - setClientSetting(SETTINGS.PERSIST_WATCH_TIME, !persistWatchTime)} - checked={persistWatchTime} - /> +
+ setClientSetting(SETTINGS.PERSIST_WATCH_TIME, !persistWatchTime)} + checked={persistWatchTime} + /> +
+
+
any) => { const state = getState(); const claim = makeSelectClaimForUri(uri)(state); + const persistWatchTime = makeSelectClientSetting(SETTINGS.PERSIST_WATCH_TIME)(state); const { claim_id: claimId, txid, nout } = claim; const outpoint = `${txid}:${nout}`; + if (persistWatchTime) { + dispatch({ + type: ACTIONS.SET_CONTENT_POSITION, + data: { claimId, outpoint, position: -1 }, + }); + return; + } + dispatch({ type: ACTIONS.CLEAR_CONTENT_POSITION, data: { claimId, outpoint }, @@ -249,6 +258,12 @@ export function clearPosition(uri: string) { }; } +export function clearContentCache() { + return { + type: ACTIONS.CLEAR_CONTENT_CACHE, + }; +} + export function doSetContentHistoryItem(uri: string) { return (dispatch: Dispatch) => { dispatch({ diff --git a/ui/redux/reducers/content.js b/ui/redux/reducers/content.js index 9596d5365..72ef10562 100644 --- a/ui/redux/reducers/content.js +++ b/ui/redux/reducers/content.js @@ -55,7 +55,6 @@ reducers[ACTIONS.SET_CONTENT_POSITION] = (state, action) => { [claimId]: { ...state.positions[claimId], [outpoint]: position, - [`${outpoint}:persisted`]: position, }, }, }; @@ -91,6 +90,13 @@ reducers[ACTIONS.CLEAR_CONTENT_POSITION] = (state, action) => { } }; +reducers[ACTIONS.CLEAR_CONTENT_CACHE] = (state, action) => { + return { + ...state, + positions: {}, + }; +}; + reducers[ACTIONS.SET_CONTENT_LAST_VIEWED] = (state, action) => { const { uri, lastViewed } = action.data; const { history } = state; diff --git a/ui/redux/reducers/settings.js b/ui/redux/reducers/settings.js index 3a868b8ab..5eb440a8c 100644 --- a/ui/redux/reducers/settings.js +++ b/ui/redux/reducers/settings.js @@ -67,6 +67,7 @@ const defaultState = { [SETTINGS.FLOATING_PLAYER]: true, [SETTINGS.AUTO_DOWNLOAD]: true, [SETTINGS.HIDE_REPOSTS]: false, + [SETTINGS.PERSIST_WATCH_TIME]: false, // OS [SETTINGS.AUTO_LAUNCH]: true, diff --git a/ui/redux/selectors/content.js b/ui/redux/selectors/content.js index 298f8988f..f3d4e9784 100644 --- a/ui/redux/selectors/content.js +++ b/ui/redux/selectors/content.js @@ -63,16 +63,6 @@ export const makeSelectContentPositionForUri = (uri: string) => return state.positions[id] ? state.positions[id][outpoint] : null; }); -export const makeSelectContentPositionPersistedForUri = (uri: string) => - createSelector(selectState, makeSelectClaimForUri(uri), (state, claim) => { - if (!claim) { - return null; - } - const outpoint = `${claim.txid}:${claim.nout}:persisted`; - const id = claim.claim_id; - return state.positions[id] ? state.positions[id][outpoint] : null; - }); - export const selectHistory = createSelector(selectState, (state) => state.history || []); export const selectHistoryPageCount = createSelector(selectHistory, (history) => diff --git a/ui/scss/component/_settings.scss b/ui/scss/component/_settings.scss index 631e0e606..c5d7241da 100644 --- a/ui/scss/component/_settings.scss +++ b/ui/scss/component/_settings.scss @@ -18,3 +18,13 @@ margin-left: 2.2rem; } } + +.settings { + &__persistWatchTimeCheckbox { + display: flex; + justify-content: end; + } + &__persistWatchTimeClearCache { + text-align: right; + } +} -- 2.45.3 From 58716ce5d9d842028ef8d314632092b2acab642a Mon Sep 17 00:00:00 2001 From: Franco Montenegro Date: Thu, 21 Apr 2022 18:16:12 -0300 Subject: [PATCH 4/8] Add makeSelectContentWatchedPercentageForUri selector and give feedback when clearing cache. --- static/app-strings.json | 2 ++ ui/component/fileThumbnail/index.js | 4 ++-- ui/component/fileThumbnail/view.jsx | 20 ++++++++++++-------- ui/component/settingContent/view.jsx | 24 +++++++++++++++++++++--- ui/redux/actions/content.js | 2 +- ui/redux/selectors/content.js | 25 +++++++++++++++++++++++++ 6 files changed, 63 insertions(+), 14 deletions(-) diff --git a/static/app-strings.json b/static/app-strings.json index 357f52efe..712de9a86 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -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--" } diff --git a/ui/component/fileThumbnail/index.js b/ui/component/fileThumbnail/index.js index f657b7e66..c817b8193 100644 --- a/ui/component/fileThumbnail/index.js +++ b/ui/component/fileThumbnail/index.js @@ -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), }; }; diff --git a/ui/component/fileThumbnail/view.jsx b/ui/component/fileThumbnail/view.jsx index 1e16cadd1..3a9124950 100644 --- a/ui/component/fileThumbnail/view.jsx +++ b/ui/component/fileThumbnail/view.jsx @@ -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 && (
diff --git a/ui/component/settingContent/view.jsx b/ui/component/settingContent/view.jsx index 114c6c3ba..dead73189 100644 --- a/ui/component/settingContent/view.jsx +++ b/ui/component/settingContent/view.jsx @@ -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) {
diff --git a/ui/redux/actions/content.js b/ui/redux/actions/content.js index a37962c6c..11f0be3fa 100644 --- a/ui/redux/actions/content.js +++ b/ui/redux/actions/content.js @@ -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; } diff --git a/ui/redux/selectors/content.js b/ui/redux/selectors/content.js index f3d4e9784..6ec055e4a 100644 --- a/ui/redux/selectors/content.js +++ b/ui/redux/selectors/content.js @@ -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) => -- 2.45.3 From 758fc6ac7a79fbdcfe1e881fac6f8288281cc78a Mon Sep 17 00:00:00 2001 From: zeppi Date: Thu, 21 Apr 2022 19:44:00 -0400 Subject: [PATCH 5/8] tweaks --- static/app-strings.json | 18 ++---------------- ui/component/settingContent/view.jsx | 6 +++--- ui/redux/reducers/settings.js | 2 +- ui/scss/component/_settings.scss | 16 ++++++++-------- 4 files changed, 14 insertions(+), 28 deletions(-) diff --git a/static/app-strings.json b/static/app-strings.json index 712de9a86..b819708b2 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -2300,7 +2300,6 @@ "In %collection%": "In %collection%", "Add to %collection%": "Add to %collection%", "Show this channel your appreciation by sending a donation of Credits. ": "Show this channel your appreciation by sending a donation of Credits. ", - "%action% %collection%": "%action% %collection%", "You've entered the land of content freedom! Let's make sure everything is ship shape.": "You've entered the land of content freedom! Let's make sure everything is ship shape.", "By continuing, you agree to the %terms%": "By continuing, you agree to the %terms%", "Privacy": "Privacy", @@ -2308,26 +2307,13 @@ "Yes, share with LBRY": "Yes, share with LBRY", "Search Uploads": "Search Uploads", "This refundable boost will improve the discoverability of this %claimTypeText% while active. ": "This refundable boost will improve the discoverability of this %claimTypeText% while active. ", - "%repost_channel_link%": "%repost_channel_link%", "Show less": "Show less", - "Channel \"realporno\" blocked.": "Channel \"realporno\" blocked.", "Elements": "Elements", "Icons": "Icons", - "You followed @MinutePhysics!": "You followed @MinutePhysics!", - "Unfollowed @samtime.": "Unfollowed @samtime.", - "You followed @samtime!": "You followed @samtime!", - "Unfollowed @gatogalactico.": "Unfollowed @gatogalactico.", - "You followed @gatogalactico!": "You followed @gatogalactico!", - "Unfollowed @Odysee.": "Unfollowed @Odysee.", - "Unfollowed @rossmanngroup.": "Unfollowed @rossmanngroup.", - "You followed @rossmanngroup!": "You followed @rossmanngroup!", - "%repost% %publish%": "%repost% %publish%", - "Failed to view lbry://@MicheL-PDF#7/LaDameAuPain#f, please try again. If this problem persists, visit https://lbry.com/faq/support for support.": "Failed to view lbry://@MicheL-PDF#7/LaDameAuPain#f, please try again. If this problem persists, visit https://lbry.com/faq/support for support.", "Go to": "Go to", - "* 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", + "Clear Views": "Clear Views", + "Persist the watch time of the videos you have watched. This will not erase or hide any blockchain activity or downloads.": "Persist the watch time of the videos you have watched. This will not erase or hide any blockchain activity or downloads.", "--end--": "--end--" } diff --git a/ui/component/settingContent/view.jsx b/ui/component/settingContent/view.jsx index dead73189..6040507ac 100644 --- a/ui/component/settingContent/view.jsx +++ b/ui/component/settingContent/view.jsx @@ -133,10 +133,10 @@ export default function SettingContent(props: Props) { icon={ICONS.ALERT} label={ contentCacheCleared - ? __('Cache cleared') + ? __('Views cleared') : clearingContentCache ? __('Clearing...') - : __('Clear Cache') + : __('Clear Views') } onClick={onClearContentCache} disabled={clearingContentCache || contentCacheCleared} @@ -229,7 +229,7 @@ const HELP = { AUTOPLAY_MEDIA: 'Autoplay video and audio files when navigating to a file.', AUTOPLAY_NEXT: 'Autoplay the next related item when a file (video or audio) finishes playing.', HIDE_REPOSTS: 'You will not see reposts by people you follow or receive email notifying about them.', - PERSIST_WATCH_TIME: 'Persist the watch time of the videos you have watched.', + PERSIST_WATCH_TIME: 'Persist the watch time of the videos you have fully. This will not erase or hide any blockchain activity or downloads.', SHOW_MATURE: 'Mature content may include nudity, intense sexuality, profanity, or other adult content. By displaying mature content, you are affirming you are of legal age to view mature content in your country or jurisdiction. ', MAX_PURCHASE_PRICE: 'This will prevent you from purchasing any content over a certain cost, as a safety measure.', ONLY_CONFIRM_OVER_AMOUNT: '', // [feel redundant. Disable for now] "When this option is chosen, LBRY won't ask you to confirm purchases or tips below your chosen amount.", diff --git a/ui/redux/reducers/settings.js b/ui/redux/reducers/settings.js index 5eb440a8c..7ceea70d3 100644 --- a/ui/redux/reducers/settings.js +++ b/ui/redux/reducers/settings.js @@ -67,7 +67,7 @@ const defaultState = { [SETTINGS.FLOATING_PLAYER]: true, [SETTINGS.AUTO_DOWNLOAD]: true, [SETTINGS.HIDE_REPOSTS]: false, - [SETTINGS.PERSIST_WATCH_TIME]: false, + [SETTINGS.PERSIST_WATCH_TIME]: true, // OS [SETTINGS.AUTO_LAUNCH]: true, diff --git a/ui/scss/component/_settings.scss b/ui/scss/component/_settings.scss index c5d7241da..f1861b15b 100644 --- a/ui/scss/component/_settings.scss +++ b/ui/scss/component/_settings.scss @@ -19,12 +19,12 @@ } } -.settings { - &__persistWatchTimeCheckbox { - display: flex; - justify-content: end; - } - &__persistWatchTimeClearCache { - text-align: right; - } +.settings__persistWatchTimeCheckbox { + display: flex; + justify-content: end; + padding-bottom: var(--spacing-m); +} + +.settings__persistWatchTimeCheckbox { + text-align: right; } -- 2.45.3 From c685bb4922721d38292fea1798bad950e9b72af1 Mon Sep 17 00:00:00 2001 From: zeppi Date: Thu, 21 Apr 2022 19:57:21 -0400 Subject: [PATCH 6/8] progress style --- ui/scss/component/_file-thumbnail.scss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/scss/component/_file-thumbnail.scss b/ui/scss/component/_file-thumbnail.scss index a4824fc07..7fffcaf97 100644 --- a/ui/scss/component/_file-thumbnail.scss +++ b/ui/scss/component/_file-thumbnail.scss @@ -4,10 +4,11 @@ left: 0; width: 100%; height: 5px; - background-color: gray; + background-color: var(--color-gray-7); + opacity: 0.5; } .file-thumbnail__viewed-bar-progress { height: 5px; - background-color: red; + background-color: var(--color-primary); } -- 2.45.3 From b4669d841efa54340ef93f35017f6ecff9d9f509 Mon Sep 17 00:00:00 2001 From: zeppi Date: Thu, 21 Apr 2022 21:26:29 -0400 Subject: [PATCH 7/8] watch time ux --- static/app-strings.json | 4 +- ui/component/fileThumbnail/index.js | 3 + ui/component/fileThumbnail/view.jsx | 4 +- ui/component/settingContent/view.jsx | 80 +++++++++++++------------- ui/scss/component/_file-thumbnail.scss | 1 - ui/scss/component/_settings.scss | 1 + 6 files changed, 50 insertions(+), 43 deletions(-) diff --git a/static/app-strings.json b/static/app-strings.json index b819708b2..1a8fc9997 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -2311,9 +2311,9 @@ "Elements": "Elements", "Icons": "Icons", "Go to": "Go to", - "Persist watch time": "Persist watch time", "Clearing...": "Clearing...", "Clear Views": "Clear Views", - "Persist the watch time of the videos you have watched. This will not erase or hide any blockchain activity or downloads.": "Persist the watch time of the videos you have watched. This will not erase or hide any blockchain activity or downloads.", + "Show Video View Progress": "Show Video View Progress", + "Display view progress on thumbnail. This setting will not hide any blockchain activity or downloads.": "Display view progress on thumbnail. This setting will not hide any blockchain activity or downloads.", "--end--": "--end--" } diff --git a/ui/component/fileThumbnail/index.js b/ui/component/fileThumbnail/index.js index c817b8193..f9f447877 100644 --- a/ui/component/fileThumbnail/index.js +++ b/ui/component/fileThumbnail/index.js @@ -3,11 +3,14 @@ import { doResolveUri } from 'redux/actions/claims'; import { makeSelectClaimForUri } from 'redux/selectors/claims'; import { makeSelectContentWatchedPercentageForUri } from 'redux/selectors/content'; import CardMedia from './view'; +import { makeSelectClientSetting } from 'redux/selectors/settings'; +import * as SETTINGS from 'constants/settings'; const select = (state, props) => { return { watchedPercentage: makeSelectContentWatchedPercentageForUri(props.uri)(state), claim: makeSelectClaimForUri(props.uri)(state), + showPercentage: makeSelectClientSetting(SETTINGS.PERSIST_WATCH_TIME)(state), }; }; diff --git a/ui/component/fileThumbnail/view.jsx b/ui/component/fileThumbnail/view.jsx index 3a9124950..8d642c00f 100644 --- a/ui/component/fileThumbnail/view.jsx +++ b/ui/component/fileThumbnail/view.jsx @@ -17,6 +17,7 @@ type Props = { doResolveUri: (string) => void, className?: string, watchedPercentage: number, + showPercentage: boolean, }; function FileThumbnail(props: Props) { @@ -29,6 +30,7 @@ function FileThumbnail(props: Props) { allowGifs = false, className, watchedPercentage, + showPercentage, } = props; const passedThumbnail = rawThumbnail && rawThumbnail.trim().replace(/^http:\/\//i, 'https://'); @@ -39,7 +41,7 @@ function FileThumbnail(props: Props) { const hasResolvedClaim = claim !== undefined; const isGif = thumbnail && thumbnail.endsWith('gif'); - const viewedBar = watchedPercentage && ( + const viewedBar = showPercentage && watchedPercentage && (
diff --git a/ui/component/settingContent/view.jsx b/ui/component/settingContent/view.jsx index 6040507ac..4a23f529d 100644 --- a/ui/component/settingContent/view.jsx +++ b/ui/component/settingContent/view.jsx @@ -32,7 +32,7 @@ type Props = { // --- perform --- setClientSetting: (string, boolean | string | number) => void, clearPlayingUri: () => void, - clearContentCache: () => void, + // clearContentCache: () => void, }; export default function SettingContent(props: Props) { @@ -50,20 +50,21 @@ export default function SettingContent(props: Props) { enablePublishPreview, setClientSetting, clearPlayingUri, - clearContentCache, + // 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]); + // feature disabled until styling is ironed out + // 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 ( <> @@ -118,30 +119,31 @@ export default function SettingContent(props: Props) { checked={hideReposts} /> - -
- setClientSetting(SETTINGS.PERSIST_WATCH_TIME, !persistWatchTime)} - checked={persistWatchTime} - /> -
-
-
+ + {/*
*/} + setClientSetting(SETTINGS.PERSIST_WATCH_TIME, !persistWatchTime)} + checked={persistWatchTime} + /> + {/*
*/} + {/* Disabled until styling is better */} + {/*
*/} + {/*
*/}
Date: Thu, 21 Apr 2022 21:34:41 -0400 Subject: [PATCH 8/8] flow fix --- ui/component/settingContent/view.jsx | 34 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/ui/component/settingContent/view.jsx b/ui/component/settingContent/view.jsx index 4a23f529d..50d0ada0e 100644 --- a/ui/component/settingContent/view.jsx +++ b/ui/component/settingContent/view.jsx @@ -127,23 +127,23 @@ export default function SettingContent(props: Props) { onChange={() => setClientSetting(SETTINGS.PERSIST_WATCH_TIME, !persistWatchTime)} checked={persistWatchTime} /> - {/*
*/} - {/* Disabled until styling is better */} - {/*
*/} - {/*
*/} + {/*
+ Disabled until styling is better +
+
*/}