From 03e921e6df2c6e95a801eb40d20dafdfa4ffe5a5 Mon Sep 17 00:00:00 2001 From: zeppi <jessopb@gmail.com> Date: Thu, 17 Jun 2021 14:55:23 -0400 Subject: [PATCH] use commentron for live view counts --- flow-typed/livestream.js | 1 + ui/component/fileTitleSection/index.js | 16 +++++++++++----- ui/component/fileTitleSection/view.jsx | 6 +++--- ui/component/fileViewCount/view.jsx | 17 +++++++++-------- ui/component/livestreamLayout/view.jsx | 5 ++--- ui/constants/action_types.js | 1 + ui/page/livestream/view.jsx | 5 +---- ui/redux/actions/websocket.js | 7 +++++++ ui/redux/reducers/livestream.js | 7 +++++++ ui/redux/selectors/livestream.js | 4 ++++ 10 files changed, 46 insertions(+), 23 deletions(-) diff --git a/flow-typed/livestream.js b/flow-typed/livestream.js index be888611e..40ed13f19 100644 --- a/flow-typed/livestream.js +++ b/flow-typed/livestream.js @@ -23,4 +23,5 @@ declare type LivestreamReplayData = Array<LivestreamReplayItem>; declare type LivestreamState = { fetchingById: {}, + viewersById: {}, } diff --git a/ui/component/fileTitleSection/index.js b/ui/component/fileTitleSection/index.js index 21a62b415..a6a79fd5f 100644 --- a/ui/component/fileTitleSection/index.js +++ b/ui/component/fileTitleSection/index.js @@ -1,11 +1,17 @@ import { connect } from 'react-redux'; -import { makeSelectTitleForUri } from 'lbry-redux'; +import { makeSelectTitleForUri, makeSelectClaimForUri } from 'lbry-redux'; import { makeSelectInsufficientCreditsForUri } from 'redux/selectors/content'; +import { makeSelectViewersForId } from 'redux/selectors/livestream'; import FileTitleSection from './view'; -const select = (state, props) => ({ - isInsufficientCredits: makeSelectInsufficientCreditsForUri(props.uri)(state), - title: makeSelectTitleForUri(props.uri)(state), -}); +const select = (state, props) => { + const claim = makeSelectClaimForUri(props.uri)(state); + const viewers = claim && makeSelectViewersForId(claim.claim_id)(state); + return { + viewers, + isInsufficientCredits: makeSelectInsufficientCreditsForUri(props.uri)(state), + title: makeSelectTitleForUri(props.uri)(state), + }; +}; export default connect(select)(FileTitleSection); diff --git a/ui/component/fileTitleSection/view.jsx b/ui/component/fileTitleSection/view.jsx index 75fcfe60d..e2e06e038 100644 --- a/ui/component/fileTitleSection/view.jsx +++ b/ui/component/fileTitleSection/view.jsx @@ -21,11 +21,11 @@ type Props = { isNsfwBlocked: boolean, livestream?: boolean, isLive?: boolean, - activeViewers?: number, + viewers?: number, }; function FileTitleSection(props: Props) { - const { title, uri, nsfw, isNsfwBlocked, livestream = false, isLive = false, activeViewers } = props; + const { title, uri, nsfw, isNsfwBlocked, livestream = false, isLive = false, viewers } = props; const [hasAcknowledgedSec, setHasAcknowledgedSec] = usePersistedState('sec-nag', false); return ( @@ -57,7 +57,7 @@ function FileTitleSection(props: Props) { body={ <React.Fragment> <ClaimInsufficientCredits uri={uri} /> - <FileSubtitle uri={uri} isLive={isLive} livestream={livestream} activeViewers={activeViewers} /> + <FileSubtitle uri={uri} isLive={isLive} livestream={livestream} activeViewers={viewers} /> </React.Fragment> } actions={ diff --git a/ui/component/fileViewCount/view.jsx b/ui/component/fileViewCount/view.jsx index 41b5db9ab..9881b3f4d 100644 --- a/ui/component/fileViewCount/view.jsx +++ b/ui/component/fileViewCount/view.jsx @@ -6,6 +6,7 @@ import HelpLink from 'component/common/help-link'; type Props = { claim: ?StreamClaim, fetchViewCount: (string) => void, + fetchingViewCount: boolean, uri: string, viewCount: string, livestream?: boolean, @@ -36,14 +37,14 @@ function FileViewCount(props: Props) { return ( <span className="media__subtitle--centered"> - {activeViewers !== undefined - ? __('%viewer_count% currently %viewer_state%', { - viewer_count: activeViewers, - viewer_state: isLive ? __('watching') : __('waiting'), - }) - : viewCount !== 1 - ? __('%view_count% views', { view_count: formattedViewCount }) - : __('1 view')} + {isLive && + __('%viewer_count% currently %viewer_state%', { + viewer_count: activeViewers === undefined ? '...' : activeViewers, + viewer_state: isLive ? __('watching') : __('waiting'), + })} + {!isLive && + activeViewers === undefined && + (viewCount !== 1 ? __('%view_count% views', { view_count: formattedViewCount }) : __('1 view'))} {!SIMPLE_SITE && <HelpLink href="https://lbry.com/faq/views" />} </span> ); diff --git a/ui/component/livestreamLayout/view.jsx b/ui/component/livestreamLayout/view.jsx index ff18ddd27..92c44fb71 100644 --- a/ui/component/livestreamLayout/view.jsx +++ b/ui/component/livestreamLayout/view.jsx @@ -9,12 +9,11 @@ type Props = { uri: string, claim: ?StreamClaim, isLive: boolean, - activeViewers: number, chatDisabled: boolean, }; export default function LivestreamLayout(props: Props) { - const { claim, uri, isLive, activeViewers, chatDisabled } = props; + const { claim, uri, isLive, chatDisabled } = props; const isMobile = useIsMobile(); if (!claim || !claim.signing_channel) { @@ -55,7 +54,7 @@ export default function LivestreamLayout(props: Props) { {isMobile && <LivestreamComments uri={uri} />} - <FileTitleSection uri={uri} livestream isLive={isLive} activeViewers={activeViewers} /> + <FileTitleSection uri={uri} livestream isLive={isLive} /> </div> </> ); diff --git a/ui/constants/action_types.js b/ui/constants/action_types.js index f405876bc..fffb684f4 100644 --- a/ui/constants/action_types.js +++ b/ui/constants/action_types.js @@ -339,3 +339,4 @@ export const REPORT_CONTENT_FAILED = 'REPORT_CONTENT_FAILED'; export const FETCH_NO_SOURCE_CLAIMS_STARTED = 'FETCH_NO_SOURCE_CLAIMS_STARTED'; export const FETCH_NO_SOURCE_CLAIMS_COMPLETED = 'FETCH_NO_SOURCE_CLAIMS_COMPLETED'; export const FETCH_NO_SOURCE_CLAIMS_FAILED = 'FETCH_NO_SOURCE_CLAIMS_FAILED'; +export const VIEWERS_RECEIVED = 'VIEWERS_RECEIVED'; diff --git a/ui/page/livestream/view.jsx b/ui/page/livestream/view.jsx index 3e5857295..b6845194a 100644 --- a/ui/page/livestream/view.jsx +++ b/ui/page/livestream/view.jsx @@ -19,7 +19,6 @@ type Props = { export default function LivestreamPage(props: Props) { const { uri, claim, doSetPlayingUri, isAuthenticated, doUserSetReferrer, channelClaim, chatDisabled } = props; - const [activeViewers, setActiveViewers] = React.useState(0); const [isLive, setIsLive] = React.useState(false); const livestreamChannelId = channelClaim && channelClaim.signing_channel && channelClaim.signing_channel.claim_id; const [hasLivestreamClaim, setHasLivestreamClaim] = React.useState(false); @@ -66,8 +65,6 @@ export default function LivestreamPage(props: Props) { return; } - setActiveViewers(res.data.viewCount); - if (res.data.hasOwnProperty('live')) { setIsLive(res.data.live); } @@ -120,7 +117,7 @@ export default function LivestreamPage(props: Props) { chatDisabled={chatDisabled} rightSide={!chatDisabled && <LivestreamComments uri={uri} />} > - <LivestreamLayout uri={uri} activeViewers={activeViewers} isLive={isLive} /> + <LivestreamLayout uri={uri} isLive={isLive} /> </Page> ); } diff --git a/ui/redux/actions/websocket.js b/ui/redux/actions/websocket.js index 34cf7e5f2..c4c6090b9 100644 --- a/ui/redux/actions/websocket.js +++ b/ui/redux/actions/websocket.js @@ -102,6 +102,13 @@ export const doCommentSocketConnect = (uri, claimId) => (dispatch) => { data: { comment: newComment, claimId, uri }, }); } + if (response.type === 'viewers') { + const connected = response.data.connected; + dispatch({ + type: ACTIONS.VIEWERS_RECEIVED, + data: { connected, claimId }, + }); + } }); }; diff --git a/ui/redux/reducers/livestream.js b/ui/redux/reducers/livestream.js index ce339e4a3..5a74b0a39 100644 --- a/ui/redux/reducers/livestream.js +++ b/ui/redux/reducers/livestream.js @@ -4,6 +4,7 @@ import { handleActions } from 'util/redux-utils'; const defaultState: LivestreamState = { fetchingById: {}, + viewersById: {}, }; export default handleActions( @@ -29,6 +30,12 @@ export default handleActions( return { ...state, fetchingById: newIdsFetching }; }, + [ACTIONS.VIEWERS_RECEIVED]: (state: LivestreamState, action: any) => { + const { connected, claimId } = action.data; + const newViewersById = Object.assign({}, state.viewersById); + newViewersById[claimId] = connected; + return { ...state, viewersById: newViewersById }; + }, }, defaultState ); diff --git a/ui/redux/selectors/livestream.js b/ui/redux/selectors/livestream.js index 11280b0e2..27ea16ddb 100644 --- a/ui/redux/selectors/livestream.js +++ b/ui/redux/selectors/livestream.js @@ -21,10 +21,14 @@ export const makeSelectLivestreamsForChannelId = (channelId: string) => }); export const selectFetchingLivestreams = createSelector(selectState, (state) => state.fetchingById); +export const selectViewersById = createSelector(selectState, (state) => state.viewersById); export const makeSelectIsFetchingLivestreams = (channelId: string) => createSelector(selectFetchingLivestreams, (fetchingLivestreams) => Boolean(fetchingLivestreams[channelId])); +export const makeSelectViewersForId = (channelId: string) => + createSelector(selectViewersById, (viewers) => viewers[channelId]); + export const makeSelectPendingLivestreamsForChannelId = (channelId: string) => createSelector(selectPendingClaims, (pendingClaims) => { return pendingClaims.filter(