diff --git a/package.json b/package.json index 2d7ba6a2a..f748de73d 100644 --- a/package.json +++ b/package.json @@ -155,7 +155,7 @@ "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", "lbry-redux": "lbryio/lbry-redux#49b9db5aae8db84ec21231444bf8345d450812b2", - "lbryinc": "lbryio/lbryinc#8f9a58bfc8312a65614fd7327661cdcc502c4e59", + "lbryinc": "lbryio/lbryinc#0b4e41ef90d6347819dd3453f2f9398a5c1b4f36", "lint-staged": "^7.0.2", "localforage": "^1.7.1", "lodash-es": "^4.17.14", diff --git a/ui/component/channelContent/view.jsx b/ui/component/channelContent/view.jsx index 917568b8c..a6981cd15 100644 --- a/ui/component/channelContent/view.jsx +++ b/ui/component/channelContent/view.jsx @@ -146,6 +146,7 @@ function ChannelContent(props: Props) { defaultFreshness={CS.FRESH_ALL} showHiddenByUser={viewHiddenChannels} forceShowReposts + fetchViewCount hideFilters={!showFilters} hideAdvancedFilter={!showFilters} tileLayout={tileLayout} diff --git a/ui/component/claimListDiscover/index.js b/ui/component/claimListDiscover/index.js index db5d76259..f1d93ca49 100644 --- a/ui/component/claimListDiscover/index.js +++ b/ui/component/claimListDiscover/index.js @@ -1,6 +1,7 @@ import { connect } from 'react-redux'; import { doClaimSearch, + selectClaimsByUri, selectClaimSearchByQuery, selectClaimSearchByQueryLastPageReached, selectFetchingClaimSearch, @@ -12,11 +13,13 @@ import { doToggleTagFollowDesktop } from 'redux/actions/tags'; import { makeSelectClientSetting, selectShowMatureContent, selectLanguage } from 'redux/selectors/settings'; import { selectModerationBlockList } from 'redux/selectors/comments'; import ClaimListDiscover from './view'; +import { doFetchViewCount } from 'lbryinc'; const select = (state) => ({ followedTags: selectFollowedTags(state), claimSearchByQuery: selectClaimSearchByQuery(state), claimSearchByQueryLastPageReached: selectClaimSearchByQueryLastPageReached(state), + claimsByUri: selectClaimsByUri(state), loading: selectFetchingClaimSearch(state), showNsfw: selectShowMatureContent(state), hideReposts: makeSelectClientSetting(SETTINGS.HIDE_REPOSTS)(state), @@ -29,6 +32,7 @@ const select = (state) => ({ const perform = { doClaimSearch, doToggleTagFollowDesktop, + doFetchViewCount, }; export default connect(select, perform)(ClaimListDiscover); diff --git a/ui/component/claimListDiscover/view.jsx b/ui/component/claimListDiscover/view.jsx index 843541054..5fe667b29 100644 --- a/ui/component/claimListDiscover/view.jsx +++ b/ui/component/claimListDiscover/view.jsx @@ -28,6 +28,7 @@ type Props = { meta?: Node, showNsfw: boolean, hideReposts: boolean, + fetchViewCount?: boolean, history: { action: string, push: (string) => void, replace: (string) => void }, location: { search: string, pathname: string }, claimSearchByQuery: { @@ -78,6 +79,8 @@ type Props = { showNoSourceClaims?: boolean, isChannel?: boolean, empty?: string, + claimsByUri: { [string]: any }, + doFetchViewCount: (claimIdCsv: string) => void, }; function ClaimListDiscover(props: Props) { @@ -94,6 +97,7 @@ function ClaimListDiscover(props: Props) { channelIds, showNsfw, hideReposts, + fetchViewCount, history, location, mutedUris, @@ -138,6 +142,8 @@ function ClaimListDiscover(props: Props) { isChannel = false, showNoSourceClaims, empty, + claimsByUri, + doFetchViewCount, } = props; const didNavigateForward = history.action === 'PUSH'; const { search } = location; @@ -518,6 +524,16 @@ function ClaimListDiscover(props: Props) { } } + function fetchViewCountForUris(uris) { + const claimIds = []; + uris.forEach((uri) => { + if (claimsByUri[uri]) { + claimIds.push(claimsByUri[uri].claim_id); + } + }); + doFetchViewCount(claimIds.join(',')); + } + // ************************************************************************** // ************************************************************************** @@ -547,6 +563,12 @@ function ClaimListDiscover(props: Props) { } }, [uris, claimSearchResult, finalUris, setFinalUris, liveLivestreamsFirst, livestreamSearchResult]); + React.useEffect(() => { + if (fetchViewCount) { + fetchViewCountForUris(finalUris); + } + }, [finalUris]); // eslint-disable-line react-hooks/exhaustive-deps + const headerToUse = header || ( )} + (isLivestream && ENABLE_NO_SOURCE_CLAIMS ? ( + __('Livestream') + ) : ( + <> + + + + ))} )} diff --git a/ui/component/claimPreviewTile/view.jsx b/ui/component/claimPreviewTile/view.jsx index 00539dfb2..64ee6c232 100644 --- a/ui/component/claimPreviewTile/view.jsx +++ b/ui/component/claimPreviewTile/view.jsx @@ -7,6 +7,7 @@ import UriIndicator from 'component/uriIndicator'; import TruncatedText from 'component/common/truncated-text'; import DateTime from 'component/dateTime'; import ChannelThumbnail from 'component/channelThumbnail'; +import FileViewCountInline from 'component/fileViewCountInline'; import SubscribeButton from 'component/subscribeButton'; import useGetThumbnail from 'effects/use-get-thumbnail'; import { formatLbryUrlForWeb } from 'util/url'; @@ -210,15 +211,11 @@ function ClaimPreviewTile(props: Props) { {!isChannel && (
- {isPlayable && ( - - )} + {isPlayable && }
{/* @if TARGET='app' */}
- {isStream && ( - - )} + {isStream && }
{/* @endif */} @@ -226,7 +223,6 @@ function ClaimPreviewTile(props: Props) {
- )} {isCollection && ( @@ -264,7 +260,10 @@ function ClaimPreviewTile(props: Props) {
- +
+ + +
)} diff --git a/ui/component/claimTilesDiscover/index.js b/ui/component/claimTilesDiscover/index.js index 8e210f9f0..a12963202 100644 --- a/ui/component/claimTilesDiscover/index.js +++ b/ui/component/claimTilesDiscover/index.js @@ -6,6 +6,7 @@ import { SETTINGS, selectClaimsByUri, } from 'lbry-redux'; +import { doFetchViewCount } from 'lbryinc'; import { doToggleTagFollowDesktop } from 'redux/actions/tags'; import { makeSelectClientSetting, selectShowMatureContent } from 'redux/selectors/settings'; import { selectModerationBlockList } from 'redux/selectors/comments'; @@ -25,6 +26,7 @@ const select = (state) => ({ const perform = { doClaimSearch, doToggleTagFollowDesktop, + doFetchViewCount, }; export default connect(select, perform)(ClaimListDiscover); diff --git a/ui/component/claimTilesDiscover/view.jsx b/ui/component/claimTilesDiscover/view.jsx index bcd755f18..79edd5a2e 100644 --- a/ui/component/claimTilesDiscover/view.jsx +++ b/ui/component/claimTilesDiscover/view.jsx @@ -92,6 +92,7 @@ type Props = { livestreamMap?: { [string]: any }, showNoSourceClaims?: boolean, renderProperties?: (Claim) => ?Node, + fetchViewCount?: boolean, // claim search options are below tags: Array, claimIds?: Array, @@ -117,6 +118,7 @@ type Props = { blockedUris: Array, // --- perform --- doClaimSearch: ({}) => void, + doFetchViewCount: (claimIdCsv: string) => void, }; function ClaimTilesDiscover(props: Props) { @@ -126,6 +128,7 @@ function ClaimTilesDiscover(props: Props) { claimsByUri, showNsfw, hideReposts, + fetchViewCount, // Below are options to pass that are forwarded to claim_search tags, channelIds, @@ -150,6 +153,7 @@ function ClaimTilesDiscover(props: Props) { pinUrls, prefixUris, showNoSourceClaims, + doFetchViewCount, } = props; const { location } = useHistory(); @@ -294,6 +298,16 @@ function ClaimTilesDiscover(props: Props) { return undefined; } + function fetchViewCountForUris(uris) { + const claimIds = []; + uris.forEach((uri) => { + if (claimsByUri[uri]) { + claimIds.push(claimsByUri[uri].claim_id); + } + }); + doFetchViewCount(claimIds.join(',')); + } + // ************************************************************************** // ************************************************************************** @@ -310,9 +324,14 @@ function ClaimTilesDiscover(props: Props) { React.useEffect(() => { if (JSON.stringify(prevUris) !== JSON.stringify(uris) && !shouldPerformSearch) { + // Stash new results for next render cycle: setPrevUris(uris); + // Fetch view count: + if (fetchViewCount) { + fetchViewCountForUris(uris); + } } - }, [shouldPerformSearch, prevUris, uris]); + }, [shouldPerformSearch, prevUris, uris]); // eslint-disable-line react-hooks/exhaustive-deps // ************************************************************************** // ************************************************************************** diff --git a/ui/component/fileViewCountInline/index.js b/ui/component/fileViewCountInline/index.js new file mode 100644 index 000000000..7bd072e79 --- /dev/null +++ b/ui/component/fileViewCountInline/index.js @@ -0,0 +1,13 @@ +import { connect } from 'react-redux'; +import { makeSelectClaimForUri } from 'lbry-redux'; +import { makeSelectViewCountForUri } from 'lbryinc'; +import FileViewCountInline from './view'; + +const select = (state, props) => { + return { + claim: makeSelectClaimForUri(props.uri)(state), + viewCount: makeSelectViewCountForUri(props.uri)(state), + }; +}; + +export default connect(select, null)(FileViewCountInline); diff --git a/ui/component/fileViewCountInline/view.jsx b/ui/component/fileViewCountInline/view.jsx new file mode 100644 index 000000000..78b49334f --- /dev/null +++ b/ui/component/fileViewCountInline/view.jsx @@ -0,0 +1,30 @@ +// @flow +import React from 'react'; + +type Props = { + uri: string, + isLivestream?: boolean, + // --- select --- + claim: ?StreamClaim, + viewCount: string, +}; + +export default function FileViewCountInline(props: Props) { + const { isLivestream, claim, viewCount } = props; + const formattedViewCount = Number(viewCount).toLocaleString(); + + if (!viewCount || (claim && claim.repost_url) || isLivestream) { + // (1) Currently, makeSelectViewCountForUri doesn't differentiate between + // unfetched view-count vs zero view-count. But since it's probably not + // ideal to highlight that a view has 0 count, let's just not show anything. + // (2) No idea how to get the repost src's claim ID from the repost claim, + // so hiding it for now. + return null; + } + + return ( + + {viewCount !== 1 ? __('%view_count% views', { view_count: formattedViewCount }) : __('1 view')} + + ); +} diff --git a/ui/scss/component/_claim-list.scss b/ui/scss/component/_claim-list.scss index 4304359f8..724c8f331 100644 --- a/ui/scss/component/_claim-list.scss +++ b/ui/scss/component/_claim-list.scss @@ -598,6 +598,18 @@ font-size: var(--font-body); } +.claim-tile__about--counts { + display: flex; + flex-wrap: wrap; +} + +.view_count { + &::after { + content: '•'; + margin: 0 var(--spacing-xxs); + } +} + .claim-preview__file-property-overlay { position: absolute; bottom: var(--spacing-xxs); @@ -681,14 +693,13 @@ // div that displays watch later button .claim-preview__hover-actions { - // if the user is using a mouse - @media (pointer: fine){ + @media (pointer: fine) { display: none; } // if the user doesn't have a pointer (mouse etc) hide watch later button - @media (pointer: none), (pointer:coarse) { + @media (pointer: none), (pointer: coarse) { display: none !important; } diff --git a/yarn.lock b/yarn.lock index e229530b2..407ee8e65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10148,9 +10148,9 @@ lbry-redux@lbryio/lbry-redux#49b9db5aae8db84ec21231444bf8345d450812b2: reselect "^3.0.0" uuid "^8.3.1" -lbryinc@lbryio/lbryinc#8f9a58bfc8312a65614fd7327661cdcc502c4e59: +lbryinc@lbryio/lbryinc#0b4e41ef90d6347819dd3453f2f9398a5c1b4f36: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/8f9a58bfc8312a65614fd7327661cdcc502c4e59" + resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/0b4e41ef90d6347819dd3453f2f9398a5c1b4f36" dependencies: reselect "^3.0.0"