From f092e8cb7b978305df6cf53a1edb062bc704be3d Mon Sep 17 00:00:00 2001 From: zeppi Date: Thu, 25 Mar 2021 20:46:15 -0400 Subject: [PATCH] fix isLivestream channelContent - live only poll streaming if has livestream claim check channel for livestream claims every minute update consts poll livestream claims on setup page do not poll livestream claims if live smoother loading unmerged redux bump --- package.json | 2 +- ui/component/claimPreview/view.jsx | 184 +++++++++++++------------ ui/component/claimPreviewTile/index.js | 4 +- ui/component/common/card.jsx | 3 + ui/component/livestreamLink/view.jsx | 13 +- ui/component/router/view.jsx | 3 - ui/page/file/index.js | 4 +- ui/page/livestream/view.jsx | 54 ++++++-- ui/page/livestreamSetup/view.jsx | 82 ++++++----- yarn.lock | 4 +- 10 files changed, 203 insertions(+), 150 deletions(-) diff --git a/package.json b/package.json index 0c662a04b..8498b29d3 100644 --- a/package.json +++ b/package.json @@ -142,7 +142,7 @@ "imagesloaded": "^4.1.4", "json-loader": "^0.5.4", "lbry-format": "https://github.com/lbryio/lbry-format.git", - "lbry-redux": "lbryio/lbry-redux#c494c92505cd531048de20bc37dc4d192b6ace01", + "lbry-redux": "lbryio/lbry-redux#db27091f5add9a6bb91c38471a369fca144fc96f", "lbryinc": "lbryio/lbryinc#7faea40d87b78ec91b901c62f501499dc4737025", "lint-staged": "^7.0.2", "localforage": "^1.7.1", diff --git a/ui/component/claimPreview/view.jsx b/ui/component/claimPreview/view.jsx index eb952e9e8..588e67a2b 100644 --- a/ui/component/claimPreview/view.jsx +++ b/ui/component/claimPreview/view.jsx @@ -249,106 +249,110 @@ const ClaimPreview = forwardRef((props: Props, ref: any) => { 'claim-preview__wrapper--small': type === 'small', })} > - {!hideRepostLabel && } + <> + {!hideRepostLabel && } -
- {isChannelUri && claim ? ( - - - - ) : ( - <> - {!pending ? ( - - - {/* @if TARGET='app' */} - {claim && ( -
- -
- )} - {/* @endif */} - {!isRepost && !isChannelUri && !isLivestream && ( -
- -
- )} -
-
- ) : ( - - )} - - )} - -
-
-
- {pending ? ( - - ) : ( +
+ {isChannelUri && claim ? ( + + + + ) : ( + <> + {!pending ? ( - + + {/* @if TARGET='app' */} + {claim && ( +
+ +
+ )} + {/* @endif */} + {!isRepost && !isChannelUri && !isLivestream && ( +
+ +
+ )} +
+ ) : ( + )} + + )} - {/* {type !== 'small' && !isChannelUri && signingChannel && SIMPLE_SITE && ( +
+
+
+ {pending ? ( + + ) : ( + + + + )} + + {/* {type !== 'small' && !isChannelUri && signingChannel && SIMPLE_SITE && ( )} */} +
+ + {(pending || !!reflectingProgress) && }
- - {(pending || !!reflectingProgress) && } + {type !== 'small' && ( +
+ {!pending && ( + <> + {renderActions && claim && renderActions(claim)} + {shouldHideActions || renderActions ? null : actions !== undefined ? ( + actions + ) : ( +
+ {!isChannelUri && signingChannel && ( +
+ +
+ )} + + {isChannelUri && !channelIsBlocked && !claimIsMine && ( + + )} + + {includeSupportAction && } +
+ )} + + )} + {claim && ( + + {typeof properties === 'function' ? ( + properties(claim) + ) : properties !== undefined ? ( + properties + ) : ( + + )} + + )} +
+ )}
- {type !== 'small' && ( -
- {!pending && ( - <> - {renderActions && claim && renderActions(claim)} - {shouldHideActions || renderActions ? null : actions !== undefined ? ( - actions - ) : ( -
- {!isChannelUri && signingChannel && ( -
- -
- )} - - {isChannelUri && !channelIsBlocked && !claimIsMine && ( - - )} - - {includeSupportAction && } -
- )} - - )} - {claim && ( - - {typeof properties === 'function' ? ( - properties(claim) - ) : properties !== undefined ? ( - properties - ) : ( - - )} - - )} -
- )}
-
- {!hideMenu && } + {!hideMenu && } + ); }); diff --git a/ui/component/claimPreviewTile/index.js b/ui/component/claimPreviewTile/index.js index aba27e1ac..256ca5f45 100644 --- a/ui/component/claimPreviewTile/index.js +++ b/ui/component/claimPreviewTile/index.js @@ -8,7 +8,7 @@ import { doFileGet, makeSelectChannelForClaimUri, makeSelectClaimIsNsfw, - makeSelectClaimHasSource, + makeSelectClaimIsStreamPlaceholder, } from 'lbry-redux'; import { selectMutedChannels } from 'redux/selectors/blocked'; import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc'; @@ -26,7 +26,7 @@ const select = (state, props) => ({ blockedChannelUris: selectMutedChannels(state), showMature: selectShowMatureContent(state), isMature: makeSelectClaimIsNsfw(props.uri)(state), - isLivestream: !makeSelectClaimHasSource(props.uri)(state), + isLivestream: makeSelectClaimIsStreamPlaceholder(props.uri)(state), }); const perform = (dispatch) => ({ diff --git a/ui/component/common/card.jsx b/ui/component/common/card.jsx index f3b06deb1..c87122339 100644 --- a/ui/component/common/card.jsx +++ b/ui/component/common/card.jsx @@ -21,6 +21,7 @@ type Props = { nag?: Node, smallTitle?: boolean, onClick?: () => void, + children?: any, // not sure how this works }; export default function Card(props: Props) { @@ -39,6 +40,7 @@ export default function Card(props: Props) { defaultExpand, nag, onClick, + children, } = props; const [expanded, setExpanded] = useState(defaultExpand); const expandable = defaultExpand !== undefined; @@ -102,6 +104,7 @@ export default function Card(props: Props) {
)} {actions &&
{actions}
} + {children &&
{children}
} )} diff --git a/ui/component/livestreamLink/view.jsx b/ui/component/livestreamLink/view.jsx index 39a1eaf13..a576c1ebc 100644 --- a/ui/component/livestreamLink/view.jsx +++ b/ui/component/livestreamLink/view.jsx @@ -64,11 +64,12 @@ export default function LivestreamLink(props: Props) { return null; } - return ( - } - /> + // gonna pass the wrapper in so I don't have to rewrite the dmca/blocking logic in claimPreview. + const element = (props: { children: any }) => ( + + {props.children} + ); + + return ; } diff --git a/ui/component/router/view.jsx b/ui/component/router/view.jsx index 1634bcb7c..65e46eac9 100644 --- a/ui/component/router/view.jsx +++ b/ui/component/router/view.jsx @@ -49,7 +49,6 @@ import BuyPage from 'page/buy'; import NotificationsPage from 'page/notifications'; import SignInWalletPasswordPage from 'page/signInWalletPassword'; import YoutubeSyncPage from 'page/youtubeSync'; -import LiveStreamPage from 'page/livestream'; import { LINKED_COMMENT_QUERY_PARAM } from 'constants/comment'; import { parseURI, isURIValid } from 'lbry-redux'; @@ -286,8 +285,6 @@ function AppRouter(props: Props) { - - {/* Below need to go at the end to make sure we don't match any of our pages first */} diff --git a/ui/page/file/index.js b/ui/page/file/index.js index 07e6511e9..360a4eb55 100644 --- a/ui/page/file/index.js +++ b/ui/page/file/index.js @@ -9,7 +9,7 @@ import { SETTINGS, makeSelectTagInClaimOrChannelForUri, makeSelectClaimIsMine, - makeSelectClaimHasSource, + makeSelectClaimIsStreamPlaceholder, } from 'lbry-redux'; import { makeSelectCostInfoForUri, doFetchCostInfoForUri } from 'lbryinc'; import { selectShowMatureContent, makeSelectClientSetting } from 'redux/selectors/settings'; @@ -35,7 +35,7 @@ const select = (state, props) => { videoTheaterMode: makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)(state), commentsDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_COMMENTS_TAG)(state), claimIsMine: makeSelectClaimIsMine(props.uri)(state), - isLivestream: !makeSelectClaimHasSource(props.uri)(state), + isLivestream: makeSelectClaimIsStreamPlaceholder(props.uri)(state), }; }; diff --git a/ui/page/livestream/view.jsx b/ui/page/livestream/view.jsx index 1d70dd7c7..8115dac8c 100644 --- a/ui/page/livestream/view.jsx +++ b/ui/page/livestream/view.jsx @@ -4,6 +4,7 @@ import React from 'react'; import Page from 'component/page'; import LivestreamLayout from 'component/livestreamLayout'; import analytics from 'analytics'; +import { Lbry } from 'lbry-redux'; type Props = { uri: string, @@ -19,8 +20,41 @@ export default function LivestreamPage(props: 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); + + const STREAMING_POLL_INTERVAL_IN_MS = 10000; + const LIVESTREAM_CLAIM_POLL_IN_MS = 60000; + + // the component needs to check if the channel has published a new livestream, so we know if it should check + React.useEffect(() => { + let checkClaimsInterval; + function checkHasLivestreamClaim() { + Lbry.claim_search({ + channel_ids: [livestreamChannelId], + has_no_source: true, + claim_type: ['stream'], + }) + .then((res) => { + if (res && res.items && res.items.length > 0) { + setHasLivestreamClaim(true); + } + }) + .catch(() => {}); + } + if (livestreamChannelId && !isLive) { + if (!checkClaimsInterval) checkHasLivestreamClaim(); + checkClaimsInterval = setInterval(checkHasLivestreamClaim, LIVESTREAM_CLAIM_POLL_IN_MS); + + return () => { + if (checkClaimsInterval) { + clearInterval(checkClaimsInterval); + } + }; + } + }, [livestreamChannelId, isLive]); React.useEffect(() => { + let interval; function checkIsLive() { // $FlowFixMe Bitwave's API can handle garbage fetch(`${BITWAVE_API}/${livestreamChannelId}`) @@ -38,19 +72,17 @@ export default function LivestreamPage(props: Props) { } }); } - - let interval; - if (livestreamChannelId) { + if (livestreamChannelId && hasLivestreamClaim) { if (!interval) checkIsLive(); - interval = setInterval(checkIsLive, 10 * 1000); - } + interval = setInterval(checkIsLive, STREAMING_POLL_INTERVAL_IN_MS); - return () => { - if (interval) { - clearInterval(interval); - } - }; - }, [livestreamChannelId]); + return () => { + if (interval) { + clearInterval(interval); + } + }; + } + }, [livestreamChannelId, hasLivestreamClaim]); const stringifiedClaim = JSON.stringify(claim); React.useEffect(() => { diff --git a/ui/page/livestreamSetup/view.jsx b/ui/page/livestreamSetup/view.jsx index 6783fbb1b..a4cad24a5 100644 --- a/ui/page/livestreamSetup/view.jsx +++ b/ui/page/livestreamSetup/view.jsx @@ -24,16 +24,34 @@ type Props = { }; export default function LivestreamSetupPage(props: Props) { + const LIVESTREAM_CLAIM_POLL_IN_MS = 60000; const { channels, fetchingChannels, activeChannelClaim, pendingClaims } = props; const [sigData, setSigData] = React.useState({ signature: undefined, signing_ts: undefined }); const [showHelpTest, setShowHelpTest] = usePersistedState('livestream-help-seen', true); const [spin, setSpin] = React.useState(true); + const [livestreamClaims, setLivestreamClaims] = React.useState([]); const hasChannels = channels && channels.length > 0; const activeChannelClaimStr = JSON.stringify(activeChannelClaim); - const streamKey = createStreamKey(); + function createStreamKey() { + if (!activeChannelClaim || !sigData.signature || !sigData.signing_ts) return null; + return `${activeChannelClaim.claim_id}?d=${toHex(activeChannelClaim.name)}&s=${sigData.signature}&t=${ + sigData.signing_ts + }`; + } + + const streamKey = createStreamKey(); + const pendingLiveStreamClaims = pendingClaims + ? pendingClaims.filter( + (claim) => + // $FlowFixMe + claim.value_type === 'stream' && !(claim.value && claim.value.source) + ) + : []; + const pendingLength = pendingLiveStreamClaims.length; + const totalLivestreamClaims = pendingLiveStreamClaims.concat(livestreamClaims); const helpText = (

@@ -76,6 +94,7 @@ export default function LivestreamSetupPage(props: Props) {

{__(`Click Save and you are done!`)}

); + React.useEffect(() => { if (activeChannelClaimStr) { const channelClaim = JSON.parse(activeChannelClaimStr); @@ -96,47 +115,44 @@ export default function LivestreamSetupPage(props: Props) { } }, [activeChannelClaimStr, setSigData]); - function createStreamKey() { - if (!activeChannelClaim || !sigData.signature || !sigData.signing_ts) return null; - return `${activeChannelClaim.claim_id}?d=${toHex(activeChannelClaim.name)}&s=${sigData.signature}&t=${ - sigData.signing_ts - }`; - } - - const [livestreamClaims, setLivestreamClaims] = React.useState([]); - const pendingLiveStreamClaims = - // $FlowFixMe - pendingClaims ? pendingClaims.filter((claim) => !(claim && claim.value && claim.value.source)) : []; - const pendingLength = pendingLiveStreamClaims.length; - const totalLivestreamClaims = pendingLiveStreamClaims.concat(livestreamClaims); - React.useEffect(() => { + let checkClaimsInterval; if (!activeChannelClaimStr) return; - const channelClaim = JSON.parse(activeChannelClaimStr); - Lbry.claim_search({ - channel_ids: [channelClaim.claim_id], - has_no_source: true, - claim_type: ['stream'], - }) - .then((res) => { - if (res && res.items && res.items.length > 0) { - setLivestreamClaims(res.items.reverse()); - } else { - setLivestreamClaims([]); - } - setSpin(false); + function checkLivestreamClaims() { + Lbry.claim_search({ + channel_ids: [channelClaim.claim_id], + has_no_source: true, + claim_type: ['stream'], }) - .catch(() => { - setLivestreamClaims([]); - setSpin(false); - }); + .then((res) => { + if (res && res.items && res.items.length > 0) { + setLivestreamClaims(res.items.reverse()); + } else { + setLivestreamClaims([]); + } + setSpin(false); + }) + .catch(() => { + setLivestreamClaims([]); + setSpin(false); + }); + } + if (!checkClaimsInterval) { + checkLivestreamClaims(); + checkClaimsInterval = setInterval(checkLivestreamClaims, LIVESTREAM_CLAIM_POLL_IN_MS); + } + return () => { + if (checkClaimsInterval) { + clearInterval(checkClaimsInterval); + } + }; }, [activeChannelClaimStr, pendingLength, setSpin]); return ( - {fetchingChannels && ( + {(fetchingChannels || spin) && (
diff --git a/yarn.lock b/yarn.lock index 6ee4766f6..1cb821a86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6950,9 +6950,9 @@ lazy-val@^1.0.4: yargs "^13.2.2" zstd-codec "^0.1.1" -lbry-redux@lbryio/lbry-redux#c494c92505cd531048de20bc37dc4d192b6ace01: +lbry-redux@lbryio/lbry-redux#db27091f5add9a6bb91c38471a369fca144fc96f: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/c494c92505cd531048de20bc37dc4d192b6ace01" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/db27091f5add9a6bb91c38471a369fca144fc96f" dependencies: proxy-polyfill "0.1.6" reselect "^3.0.0"