Still learning to use Git. All files should be good now.
This commit is contained in:
parent
121e22e17f
commit
63ccfc1304
9 changed files with 160 additions and 54 deletions
|
@ -4,6 +4,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## [0.53.8] - [2022-11-17]
|
## [0.53.8] - [2022-11-17]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Added the ability for users to hide content they've already watched throughout the app via a checkbox ([#7645](https://github.com/lbryio/lbry-desktop/issues/7645))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Selecting a large file in publish no longer crashes ([#7736](https://github.com/lbryio/lbry-desktop/pull/7736))
|
- Selecting a large file in publish no longer crashes ([#7736](https://github.com/lbryio/lbry-desktop/pull/7736))
|
||||||
- Unfollowing unpublished channels ([#7737](https://github.com/lbryio/lbry-desktop/pull/7737))
|
- Unfollowing unpublished channels ([#7737](https://github.com/lbryio/lbry-desktop/pull/7737))
|
||||||
|
|
|
@ -106,6 +106,7 @@ function ChannelForm(props: Props) {
|
||||||
const languageParam = params.languages;
|
const languageParam = params.languages;
|
||||||
const primaryLanguage = Array.isArray(languageParam) && languageParam.length && languageParam[0];
|
const primaryLanguage = Array.isArray(languageParam) && languageParam.length && languageParam[0];
|
||||||
const secondaryLanguage = Array.isArray(languageParam) && languageParam.length >= 2 && languageParam[1];
|
const secondaryLanguage = Array.isArray(languageParam) && languageParam.length >= 2 && languageParam[1];
|
||||||
|
const [hideWatched, setHideWatched] = usePersistedState('hideWatched', false);
|
||||||
const submitLabel = React.useMemo(() => {
|
const submitLabel = React.useMemo(() => {
|
||||||
if (isClaimingInitialRewards) {
|
if (isClaimingInitialRewards) {
|
||||||
return __('Claiming credits...');
|
return __('Claiming credits...');
|
||||||
|
@ -240,6 +241,22 @@ function ChannelForm(props: Props) {
|
||||||
errorMsg = __('Invalid %error_type%', { error_type: (thumbError && 'thumbnail') || (coverError && 'cover image') });
|
errorMsg = __('Invalid %error_type%', { error_type: (thumbError && 'thumbnail') || (coverError && 'cover image') });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getHideWatchedElem() {
|
||||||
|
return (
|
||||||
|
<div className={classnames(`card claim-search__menus`)}>
|
||||||
|
<FormField
|
||||||
|
label={__('Hide Watched')}
|
||||||
|
name="hide_watched"
|
||||||
|
type="checkbox"
|
||||||
|
checked={hideWatched}
|
||||||
|
onChange={() => {
|
||||||
|
setHideWatched((prev) => !prev);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
let nameError;
|
let nameError;
|
||||||
if (!name && name !== undefined) {
|
if (!name && name !== undefined) {
|
||||||
|
@ -526,6 +543,7 @@ function ChannelForm(props: Props) {
|
||||||
<ClaimAbandonButton uri={uri} abandonActionCallback={() => replace(`/$/${PAGES.CHANNELS}`)} />
|
<ClaimAbandonButton uri={uri} abandonActionCallback={() => replace(`/$/${PAGES.CHANNELS}`)} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{getHideWatchedElem()}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -67,6 +67,7 @@ function ClaimListHeader(props: Props) {
|
||||||
const [orderParamUser, setOrderParamUser] = usePersistedState(`orderUser-${location.pathname}`, CS.ORDER_BY_TRENDING);
|
const [orderParamUser, setOrderParamUser] = usePersistedState(`orderUser-${location.pathname}`, CS.ORDER_BY_TRENDING);
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
const freshnessParam = freshness || urlParams.get(CS.FRESH_KEY) || defaultFreshness;
|
const freshnessParam = freshness || urlParams.get(CS.FRESH_KEY) || defaultFreshness;
|
||||||
|
const [hideWatched, setHideWatched] = usePersistedState('hideWatched', false);
|
||||||
const contentTypeParam = urlParams.get(CS.CONTENT_KEY);
|
const contentTypeParam = urlParams.get(CS.CONTENT_KEY);
|
||||||
const streamTypeParam =
|
const streamTypeParam =
|
||||||
streamType || (CS.FILE_TYPES.includes(contentTypeParam) && contentTypeParam) || defaultStreamType || null;
|
streamType || (CS.FILE_TYPES.includes(contentTypeParam) && contentTypeParam) || defaultStreamType || null;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { selectIsSubscribedForUri } from 'redux/selectors/subscriptions';
|
||||||
import { isClaimNsfw } from 'util/claim';
|
import { isClaimNsfw } from 'util/claim';
|
||||||
import ClaimPreview from './view';
|
import ClaimPreview from './view';
|
||||||
import formatMediaDuration from 'util/formatMediaDuration';
|
import formatMediaDuration from 'util/formatMediaDuration';
|
||||||
|
import { makeSelectContentWatchedPercentageForUri } from 'redux/selectors/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);
|
||||||
|
@ -46,6 +47,7 @@ const select = (state, props) => {
|
||||||
wasPurchased: props.uri && makeSelectClaimWasPurchased(props.uri)(state),
|
wasPurchased: props.uri && makeSelectClaimWasPurchased(props.uri)(state),
|
||||||
isCollectionMine: makeSelectCollectionIsMine(props.collectionId)(state),
|
isCollectionMine: makeSelectCollectionIsMine(props.collectionId)(state),
|
||||||
lang: selectLanguage(state),
|
lang: selectLanguage(state),
|
||||||
|
isWatched: makeSelectContentWatchedPercentageForUri(props.uri)(state) > 80,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import ClaimPreviewNoContent from './claim-preview-no-content';
|
||||||
import CollectionEditButtons from 'component/collectionEditButtons';
|
import CollectionEditButtons from 'component/collectionEditButtons';
|
||||||
import { useIsMobile } from 'effects/use-screensize';
|
import { useIsMobile } from 'effects/use-screensize';
|
||||||
import AbandonedChannelPreview from 'component/abandonedChannelPreview';
|
import AbandonedChannelPreview from 'component/abandonedChannelPreview';
|
||||||
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
|
|
||||||
// preview images used on the landing page and on the channel page
|
// preview images used on the landing page and on the channel page
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -82,6 +83,7 @@ type Props = {
|
||||||
showEdit?: boolean,
|
showEdit?: boolean,
|
||||||
dragHandleProps?: any,
|
dragHandleProps?: any,
|
||||||
unavailableUris?: Array<string>,
|
unavailableUris?: Array<string>,
|
||||||
|
isWatched: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
|
@ -141,10 +143,11 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
showEdit,
|
showEdit,
|
||||||
dragHandleProps,
|
dragHandleProps,
|
||||||
unavailableUris,
|
unavailableUris,
|
||||||
|
isWatched,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
const [hideWatched, setHideWatched] = usePersistedState('hideWatched', false);
|
||||||
const isCollection = claim && claim.value_type === 'collection';
|
const isCollection = claim && claim.value_type === 'collection';
|
||||||
const collectionClaimId = isCollection && claim && claim.claim_id;
|
const collectionClaimId = isCollection && claim && claim.claim_id;
|
||||||
const listId = collectionId || collectionClaimId;
|
const listId = collectionId || collectionClaimId;
|
||||||
|
@ -278,6 +281,14 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
}
|
}
|
||||||
}, [isValid, uri, isResolvingUri, shouldFetch, resolveUri]);
|
}, [isValid, uri, isResolvingUri, shouldFetch, resolveUri]);
|
||||||
|
|
||||||
|
if (isWatched && hideWatched) {
|
||||||
|
shouldHide = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldHide) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldHide && !showNullPlaceholder) {
|
if (shouldHide && !showNullPlaceholder) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { doFileGet } from 'redux/actions/file';
|
||||||
import { doResolveUri } from 'redux/actions/claims';
|
import { doResolveUri } from 'redux/actions/claims';
|
||||||
import { selectViewCountForUri, selectBanStateForUri } from 'lbryinc';
|
import { selectViewCountForUri, selectBanStateForUri } from 'lbryinc';
|
||||||
import { selectShowMatureContent } from 'redux/selectors/settings';
|
import { selectShowMatureContent } from 'redux/selectors/settings';
|
||||||
|
import { makeSelectContentWatchedPercentageForUri } from 'redux/selectors/content';
|
||||||
import { isClaimNsfw } from 'util/claim';
|
import { isClaimNsfw } from 'util/claim';
|
||||||
import ClaimPreviewTile from './view';
|
import ClaimPreviewTile from './view';
|
||||||
import formatMediaDuration from 'util/formatMediaDuration';
|
import formatMediaDuration from 'util/formatMediaDuration';
|
||||||
|
@ -30,6 +31,7 @@ const select = (state, props) => {
|
||||||
showMature: selectShowMatureContent(state),
|
showMature: selectShowMatureContent(state),
|
||||||
isMature: claim ? isClaimNsfw(claim) : false,
|
isMature: claim ? isClaimNsfw(claim) : false,
|
||||||
viewCount: selectViewCountForUri(state, props.uri),
|
viewCount: selectViewCountForUri(state, props.uri),
|
||||||
|
isWatched: makeSelectContentWatchedPercentageForUri(props.uri)(state) > 80,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import ClaimMenuList from 'component/claimMenuList';
|
||||||
import CollectionPreviewOverlay from 'component/collectionPreviewOverlay';
|
import CollectionPreviewOverlay from 'component/collectionPreviewOverlay';
|
||||||
// $FlowFixMe cannot resolve ...
|
// $FlowFixMe cannot resolve ...
|
||||||
import PlaceholderTx from 'static/img/placeholderTx.gif';
|
import PlaceholderTx from 'static/img/placeholderTx.gif';
|
||||||
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -42,6 +43,7 @@ type Props = {
|
||||||
collectionId?: string,
|
collectionId?: string,
|
||||||
viewCount: string,
|
viewCount: string,
|
||||||
swipeLayout: boolean,
|
swipeLayout: boolean,
|
||||||
|
isWatched: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
// preview image cards used in related video functionality, channel overview page and homepage
|
// preview image cards used in related video functionality, channel overview page and homepage
|
||||||
|
@ -67,10 +69,12 @@ function ClaimPreviewTile(props: Props) {
|
||||||
mediaDuration,
|
mediaDuration,
|
||||||
viewCount,
|
viewCount,
|
||||||
swipeLayout = false,
|
swipeLayout = false,
|
||||||
|
isWatched,
|
||||||
} = props;
|
} = props;
|
||||||
const isRepost = claim && claim.repost_channel_url;
|
const isRepost = claim && claim.repost_channel_url;
|
||||||
const isCollection = claim && claim.value_type === 'collection';
|
const isCollection = claim && claim.value_type === 'collection';
|
||||||
const isStream = claim && claim.value_type === 'stream';
|
const isStream = claim && claim.value_type === 'stream';
|
||||||
|
const [hideWatched, setHideWatched] = usePersistedState('hideWatched', false);
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
const isPlayable =
|
const isPlayable =
|
||||||
claim &&
|
claim &&
|
||||||
|
@ -126,6 +130,22 @@ function ClaimPreviewTile(props: Props) {
|
||||||
|
|
||||||
let shouldHide = false;
|
let shouldHide = false;
|
||||||
|
|
||||||
|
if (isMature && !showMature) {
|
||||||
|
// Unfortunately needed until this is resolved
|
||||||
|
// https://github.com/lbryio/lbry-sdk/issues/2785
|
||||||
|
shouldHide = true;
|
||||||
|
} else {
|
||||||
|
shouldHide =
|
||||||
|
banState.blacklisted ||
|
||||||
|
banState.filtered ||
|
||||||
|
(!showHiddenByUser && (banState.muted || banState.blocked)) ||
|
||||||
|
(isWatched && hideWatched);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldHide) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (isMature && !showMature) {
|
if (isMature && !showMature) {
|
||||||
// Unfortunately needed until this is resolved
|
// Unfortunately needed until this is resolved
|
||||||
// https://github.com/lbryio/lbry-sdk/issues/2785
|
// https://github.com/lbryio/lbry-sdk/issues/2785
|
||||||
|
|
|
@ -61,6 +61,8 @@ const SearchOptions = (props: Props) => {
|
||||||
delete TYPES_ADVANCED[SEARCH_OPTIONS.MEDIA_IMAGE];
|
delete TYPES_ADVANCED[SEARCH_OPTIONS.MEDIA_IMAGE];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [hideWatched, setHideWatched] = usePersistedState('hideWatched', false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
// We no longer let the user set the search results count, but the value
|
// We no longer let the user set the search results count, but the value
|
||||||
// will be in local storage for existing users. Override that.
|
// will be in local storage for existing users. Override that.
|
||||||
|
@ -69,6 +71,30 @@ const SearchOptions = (props: Props) => {
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
function getHideWatchedElem() {
|
||||||
|
return (
|
||||||
|
<div className={`claim-search__checkbox_searchbox`}>
|
||||||
|
<FormField
|
||||||
|
name="hide_watched"
|
||||||
|
type="checkbox"
|
||||||
|
checked={hideWatched}
|
||||||
|
onChange={() => {
|
||||||
|
setHideWatched((prev) => !prev);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
className="icon--help"
|
||||||
|
icon={ICONS.HELP}
|
||||||
|
tooltip
|
||||||
|
size={16}
|
||||||
|
customTooltipText={__(
|
||||||
|
'Hide content you have already viewed from search results.'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function updateSearchOptions(option, value) {
|
function updateSearchOptions(option, value) {
|
||||||
setSearchOption(option, value);
|
setSearchOption(option, value);
|
||||||
if (onSearchOptionsChanged) {
|
if (onSearchOptionsChanged) {
|
||||||
|
@ -149,7 +175,7 @@ const SearchOptions = (props: Props) => {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const otherOptionsElem = (
|
const exactMatchElem = (
|
||||||
<>
|
<>
|
||||||
<div className="filter-values">
|
<div className="filter-values">
|
||||||
<FormField
|
<FormField
|
||||||
|
@ -157,7 +183,6 @@ const SearchOptions = (props: Props) => {
|
||||||
name="exact-match"
|
name="exact-match"
|
||||||
checked={options[SEARCH_OPTIONS.EXACT]}
|
checked={options[SEARCH_OPTIONS.EXACT]}
|
||||||
onChange={() => updateSearchOptions(SEARCH_OPTIONS.EXACT, !options[SEARCH_OPTIONS.EXACT])}
|
onChange={() => updateSearchOptions(SEARCH_OPTIONS.EXACT, !options[SEARCH_OPTIONS.EXACT])}
|
||||||
label={__('Exact match')}
|
|
||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
className="icon--help"
|
className="icon--help"
|
||||||
|
@ -169,6 +194,7 @@ const SearchOptions = (props: Props) => {
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -194,6 +220,12 @@ const SearchOptions = (props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const hideWatchedElem = (
|
||||||
|
<div>
|
||||||
|
{getHideWatchedElem()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
const sortByElem = (
|
const sortByElem = (
|
||||||
<div className="filter-values">
|
<div className="filter-values">
|
||||||
<FormField
|
<FormField
|
||||||
|
@ -230,7 +262,8 @@ const SearchOptions = (props: Props) => {
|
||||||
{addRow(__('Type'), typeElem)}
|
{addRow(__('Type'), typeElem)}
|
||||||
{addRow(uploadDateLabel, uploadDateElem)}
|
{addRow(uploadDateLabel, uploadDateElem)}
|
||||||
{addRow(__('Sort By'), sortByElem)}
|
{addRow(__('Sort By'), sortByElem)}
|
||||||
{addRow(__('Other Options'), otherOptionsElem)}
|
{addRow(__('Exact Match'), exactMatchElem)}
|
||||||
|
{addRow(__('Hide Watched Content'), hideWatchedElem)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -27,6 +27,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UPDATE: Add style for checkbox
|
||||||
|
.claim-search__checkbox {
|
||||||
|
padding-left: 45%;
|
||||||
|
padding-top: 7%;
|
||||||
|
}
|
||||||
|
|
||||||
|
//UPDATE: Added style for checkbox on search page
|
||||||
|
.claim-search__checkbox_searchbox {
|
||||||
|
// Placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
// UPDATE: Add style for checkbox label
|
||||||
|
.checkbox-label {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.claim-search__dropdown {
|
.claim-search__dropdown {
|
||||||
font-size: var(--font-body);
|
font-size: var(--font-body);
|
||||||
background-color: var(--color-input-bg);
|
background-color: var(--color-input-bg);
|
||||||
|
|
Loading…
Reference in a new issue