From aced8fb5939a759fcf35a71d9a7dc056cad304ee Mon Sep 17 00:00:00 2001 From: saltrafael Date: Fri, 18 Jun 2021 12:22:44 -0300 Subject: [PATCH] Add watch later hover action and Favorites add watch later hover action replace watch later popup item for favorites lint styling for watch_later overlay Add label Use just claim, add requiresAuth Add list icon Tone down text Turn WL Hover Button into component Change WL hover icons small revert Keep watch later in the menu --- ui/component/claimMenuList/index.js | 1 + ui/component/claimMenuList/view.jsx | 26 ++++++++ ui/component/claimPreview/view.jsx | 15 +++++ ui/component/claimPreviewTile/view.jsx | 16 +++++ .../collectionContentSidebar/view.jsx | 6 +- ui/component/collectionSelectItem/view.jsx | 2 +- ui/component/collectionsListMine/view.jsx | 4 +- ui/component/fileWatchLaterLink/index.js | 26 ++++++++ ui/component/fileWatchLaterLink/view.jsx | 62 +++++++++++++++++++ ui/page/collection/view.jsx | 5 +- ui/scss/component/_claim-list.scss | 26 +++++++- 11 files changed, 183 insertions(+), 6 deletions(-) create mode 100644 ui/component/fileWatchLaterLink/index.js create mode 100644 ui/component/fileWatchLaterLink/view.jsx diff --git a/ui/component/claimMenuList/index.js b/ui/component/claimMenuList/index.js index ee8a70625..3079b61cd 100644 --- a/ui/component/claimMenuList/index.js +++ b/ui/component/claimMenuList/index.js @@ -38,6 +38,7 @@ const select = (state, props) => { claim, claimIsMine: makeSelectSigningIsMine(props.uri)(state), hasClaimInWatchLater: makeSelectCollectionForIdHasClaimUrl(COLLECTIONS_CONSTS.WATCH_LATER_ID, permanentUri)(state), + hasClaimInCustom: makeSelectCollectionForIdHasClaimUrl(COLLECTIONS_CONSTS.FAVORITES_ID, permanentUri)(state), channelIsMuted: makeSelectChannelIsMuted(props.uri)(state), channelIsBlocked: makeSelectChannelIsBlocked(props.uri)(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state), diff --git a/ui/component/claimMenuList/view.jsx b/ui/component/claimMenuList/view.jsx index ce9e4de91..712a81c26 100644 --- a/ui/component/claimMenuList/view.jsx +++ b/ui/component/claimMenuList/view.jsx @@ -40,6 +40,7 @@ type Props = { isRepost: boolean, doCollectionEdit: (string, any) => void, hasClaimInWatchLater: boolean, + hasClaimInCustom: boolean, claimInCollection: boolean, collectionName?: string, collectionId: string, @@ -75,6 +76,7 @@ function ClaimMenuList(props: Props) { doCommentModUnBlockAsAdmin, doCollectionEdit, hasClaimInWatchLater, + hasClaimInCustom, collectionId, collectionName, isMyCollection, @@ -96,6 +98,7 @@ function ClaimMenuList(props: Props) { const isChannel = !incognitoClaim && signingChannel === claim; const showDelete = claimIsMine || (fileInfo && (fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0)); const subscriptionLabel = isSubscribed ? __('Unfollow') : __('Follow'); + const lastCollectionName = 'Favorites'; const { push, replace } = useHistory(); if (!claim) { @@ -245,6 +248,29 @@ function ClaimMenuList(props: Props) { )} + {/* CUSTOM LIST */} + {isPlayable && !collectionId && ( + { + doToast({ + message: __(`Item %action% ${lastCollectionName}`, { + action: hasClaimInCustom ? __('removed from') : __('added to'), + }), + }); + doCollectionEdit(COLLECTIONS_CONSTS.FAVORITES_ID, { + claims: [contentClaim], + remove: hasClaimInCustom, + type: 'playlist', + }); + }} + > +
+ + {hasClaimInCustom ? __(`In ${lastCollectionName}`) : __(`${lastCollectionName}`)} +
+
+ )} {/* COLLECTION OPERATIONS */} {collectionId && collectionName && isCollectionClaim && ( <> diff --git a/ui/component/claimPreview/view.jsx b/ui/component/claimPreview/view.jsx index f787ea852..4e04211b2 100644 --- a/ui/component/claimPreview/view.jsx +++ b/ui/component/claimPreview/view.jsx @@ -19,6 +19,7 @@ import ClaimPreviewTitle from 'component/claimPreviewTitle'; import ClaimPreviewSubtitle from 'component/claimPreviewSubtitle'; import ClaimRepostAuthor from 'component/claimRepostAuthor'; import FileDownloadLink from 'component/fileDownloadLink'; +import FileWatchLaterLink from 'component/fileWatchLaterLink'; import PublishPending from 'component/publishPending'; import ClaimMenuList from 'component/claimMenuList'; import ClaimPreviewLoading from './claim-preview-loading'; @@ -157,6 +158,15 @@ const ClaimPreview = forwardRef((props: Props, ref: any) => { isValid = false; } } + // $FlowFixMe + const isPlayable = + claim && + // $FlowFixMe + claim.value && + // $FlowFixMe + claim.value.stream_type && + // $FlowFixMe + (claim.value.stream_type === 'audio' || claim.value.stream_type === 'video'); const isCollection = claim && claim.value_type === 'collection'; const isChannelUri = isValid ? parseURI(uri).isChannel : false; const signingChannel = claim && claim.signing_channel; @@ -318,6 +328,11 @@ const ClaimPreview = forwardRef((props: Props, ref: any) => { )} + {isPlayable && ( +
+ +
+ )} ) : ( diff --git a/ui/component/claimPreviewTile/view.jsx b/ui/component/claimPreviewTile/view.jsx index fdf4c3a1a..6533dbba8 100644 --- a/ui/component/claimPreviewTile/view.jsx +++ b/ui/component/claimPreviewTile/view.jsx @@ -13,6 +13,7 @@ import { formatLbryUrlForWeb } from 'util/url'; import { parseURI, COLLECTIONS_CONSTS } from 'lbry-redux'; import PreviewOverlayProperties from 'component/previewOverlayProperties'; import FileDownloadLink from 'component/fileDownloadLink'; +import FileWatchLaterLink from 'component/fileWatchLaterLink'; import ClaimRepostAuthor from 'component/claimRepostAuthor'; import ClaimMenuList from 'component/claimMenuList'; import CollectionPreviewOverlay from 'component/collectionPreviewOverlay'; @@ -75,6 +76,15 @@ function ClaimPreviewTile(props: Props) { const isRepost = claim && claim.repost_channel_url; const isCollection = claim && claim.value_type === 'collection'; const isStream = claim && claim.value_type === 'stream'; + // $FlowFixMe + const isPlayable = + claim && + // $FlowFixMe + claim.value && + // $FlowFixMe + claim.value.stream_type && + // $FlowFixMe + (claim.value.stream_type === 'audio' || claim.value.stream_type === 'video'); const collectionClaimId = isCollection && claim && claim.claim_id; const shouldFetch = claim === undefined; const thumbnailUrl = useGetThumbnail(uri, claim, streamingUrl, getFile, placeholder) || thumbnail; @@ -195,6 +205,12 @@ function ClaimPreviewTile(props: Props) { )} {/* @endif */} + {isPlayable && ( +
+ +
+ )} +
diff --git a/ui/component/collectionContentSidebar/view.jsx b/ui/component/collectionContentSidebar/view.jsx index 7bdc7eeec..49d932100 100644 --- a/ui/component/collectionContentSidebar/view.jsx +++ b/ui/component/collectionContentSidebar/view.jsx @@ -6,6 +6,7 @@ import Button from 'component/button'; import * as PAGES from 'constants/pages'; import Icon from 'component/common/icon'; import * as ICONS from 'constants/icons'; +import { COLLECTIONS_CONSTS } from 'lbry-redux'; type Props = { collectionUrls: Array, @@ -26,7 +27,10 @@ export default function CollectionContent(props: Props) { className="file-page__recommended" title={ - + {collectionName} } diff --git a/ui/component/collectionSelectItem/view.jsx b/ui/component/collectionSelectItem/view.jsx index 14aab0079..267d0f2f3 100644 --- a/ui/component/collectionSelectItem/view.jsx +++ b/ui/component/collectionSelectItem/view.jsx @@ -25,7 +25,7 @@ function CollectionSelectItem(props: Props) { let icon; switch (category) { case 'builtin': - icon = id === COLLECTIONS_CONSTS.WATCH_LATER_ID ? ICONS.TIME : ICONS.STACK; + icon = (id === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) || (id === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) || ICONS.STACK; break; case 'published': icon = ICONS.STACK; diff --git a/ui/component/collectionsListMine/view.jsx b/ui/component/collectionsListMine/view.jsx index 324cee079..45b3b6c96 100644 --- a/ui/component/collectionsListMine/view.jsx +++ b/ui/component/collectionsListMine/view.jsx @@ -68,7 +68,9 @@ export default function CollectionsListMine(props: Props) { {__(`${list.name}`)}
- + {itemUrls.length}
diff --git a/ui/component/fileWatchLaterLink/index.js b/ui/component/fileWatchLaterLink/index.js new file mode 100644 index 000000000..107ac4eaf --- /dev/null +++ b/ui/component/fileWatchLaterLink/index.js @@ -0,0 +1,26 @@ +import { connect } from 'react-redux'; +import { + makeSelectClaimForUri, + COLLECTIONS_CONSTS, + makeSelectCollectionForIdHasClaimUrl, + doCollectionEdit, +} from 'lbry-redux'; +import FileWatchLaterLink from './view'; +import { doToast } from 'redux/actions/notifications'; + +const select = (state, props) => { + const claim = makeSelectClaimForUri(props.uri)(state); + const permanentUri = claim && claim.permanent_url; + + return { + claim, + hasClaimInWatchLater: makeSelectCollectionForIdHasClaimUrl(COLLECTIONS_CONSTS.WATCH_LATER_ID, permanentUri)(state), + }; +}; + +const perform = dispatch => ({ + doToast: (props) => dispatch(doToast(props)), + doCollectionEdit: (collection, props) => dispatch(doCollectionEdit(collection, props)), +}); + +export default connect(select, perform)(FileWatchLaterLink); diff --git a/ui/component/fileWatchLaterLink/view.jsx b/ui/component/fileWatchLaterLink/view.jsx new file mode 100644 index 000000000..daeb6d833 --- /dev/null +++ b/ui/component/fileWatchLaterLink/view.jsx @@ -0,0 +1,62 @@ +// @flow +import * as ICONS from 'constants/icons'; +import React, { useRef } from 'react'; +import Button from 'component/button'; +import useHover from 'effects/use-hover'; +import { COLLECTIONS_CONSTS } from 'lbry-redux'; + +type Props = { + uri: string, + claim: StreamClaim, + hasClaimInWatchLater: boolean, + doToast: ({ message: string }) => void, + doCollectionEdit: (string, any) => void, +}; + +function FileWatchLaterLink(props: Props) { + const { + claim, + hasClaimInWatchLater, + doToast, + doCollectionEdit, + } = props; + const buttonRef = useRef(); + let isHovering = useHover(buttonRef); + + if (!claim) { + return null; + } + + function handleWatchLater(e) { + e.preventDefault(); + doToast({ + message: __('Item %action% Watch Later', { + action: hasClaimInWatchLater ? __('removed from') : __('added to'), + }), + linkText: !hasClaimInWatchLater && __('See All'), + linkTarget: !hasClaimInWatchLater && '/list/watchlater', + }); + doCollectionEdit(COLLECTIONS_CONSTS.WATCH_LATER_ID, { + claims: [claim], + remove: hasClaimInWatchLater, + type: 'playlist', + }); + } + + const title = hasClaimInWatchLater ? __('Remove from Watch Later') : __('Add to Watch Later'); + const label = !hasClaimInWatchLater ? __('Add') : __('Added'); + + return ( +