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
This commit is contained in:
parent
2e87b2fd22
commit
f092e8cb7b
10 changed files with 203 additions and 150 deletions
|
@ -142,7 +142,7 @@
|
||||||
"imagesloaded": "^4.1.4",
|
"imagesloaded": "^4.1.4",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
"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",
|
"lbryinc": "lbryio/lbryinc#7faea40d87b78ec91b901c62f501499dc4737025",
|
||||||
"lint-staged": "^7.0.2",
|
"lint-staged": "^7.0.2",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
|
|
|
@ -249,6 +249,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
'claim-preview__wrapper--small': type === 'small',
|
'claim-preview__wrapper--small': type === 'small',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
<>
|
||||||
{!hideRepostLabel && <ClaimRepostAuthor uri={uri} />}
|
{!hideRepostLabel && <ClaimRepostAuthor uri={uri} />}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -325,7 +326,9 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isChannelUri && !channelIsBlocked && !claimIsMine && (
|
{isChannelUri && !channelIsBlocked && !claimIsMine && (
|
||||||
<SubscribeButton uri={contentUri.startsWith('lbry://') ? contentUri : `lbry://${contentUri}`} />
|
<SubscribeButton
|
||||||
|
uri={contentUri.startsWith('lbry://') ? contentUri : `lbry://${contentUri}`}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{includeSupportAction && <ClaimSupportButton uri={uri} />}
|
{includeSupportAction && <ClaimSupportButton uri={uri} />}
|
||||||
|
@ -349,6 +352,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!hideMenu && <ClaimMenuList uri={uri} />}
|
{!hideMenu && <ClaimMenuList uri={uri} />}
|
||||||
|
</>
|
||||||
</WrapperElement>
|
</WrapperElement>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
doFileGet,
|
doFileGet,
|
||||||
makeSelectChannelForClaimUri,
|
makeSelectChannelForClaimUri,
|
||||||
makeSelectClaimIsNsfw,
|
makeSelectClaimIsNsfw,
|
||||||
makeSelectClaimHasSource,
|
makeSelectClaimIsStreamPlaceholder,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { selectMutedChannels } from 'redux/selectors/blocked';
|
import { selectMutedChannels } from 'redux/selectors/blocked';
|
||||||
import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
|
import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
|
||||||
|
@ -26,7 +26,7 @@ const select = (state, props) => ({
|
||||||
blockedChannelUris: selectMutedChannels(state),
|
blockedChannelUris: selectMutedChannels(state),
|
||||||
showMature: selectShowMatureContent(state),
|
showMature: selectShowMatureContent(state),
|
||||||
isMature: makeSelectClaimIsNsfw(props.uri)(state),
|
isMature: makeSelectClaimIsNsfw(props.uri)(state),
|
||||||
isLivestream: !makeSelectClaimHasSource(props.uri)(state),
|
isLivestream: makeSelectClaimIsStreamPlaceholder(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
|
|
|
@ -21,6 +21,7 @@ type Props = {
|
||||||
nag?: Node,
|
nag?: Node,
|
||||||
smallTitle?: boolean,
|
smallTitle?: boolean,
|
||||||
onClick?: () => void,
|
onClick?: () => void,
|
||||||
|
children?: any, // not sure how this works
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Card(props: Props) {
|
export default function Card(props: Props) {
|
||||||
|
@ -39,6 +40,7 @@ export default function Card(props: Props) {
|
||||||
defaultExpand,
|
defaultExpand,
|
||||||
nag,
|
nag,
|
||||||
onClick,
|
onClick,
|
||||||
|
children,
|
||||||
} = props;
|
} = props;
|
||||||
const [expanded, setExpanded] = useState(defaultExpand);
|
const [expanded, setExpanded] = useState(defaultExpand);
|
||||||
const expandable = defaultExpand !== undefined;
|
const expandable = defaultExpand !== undefined;
|
||||||
|
@ -102,6 +104,7 @@ export default function Card(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{actions && <div className="card__main-actions">{actions}</div>}
|
{actions && <div className="card__main-actions">{actions}</div>}
|
||||||
|
{children && <div className="card__main-actions">{children}</div>}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,12 @@ export default function LivestreamLink(props: Props) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
// gonna pass the wrapper in so I don't have to rewrite the dmca/blocking logic in claimPreview.
|
||||||
<Card
|
const element = (props: { children: any }) => (
|
||||||
className="livestream__channel-link"
|
<Card className="livestream__channel-link" title={__('Live stream in progress')}>
|
||||||
title={__('Live stream in progress')}
|
{props.children}
|
||||||
actions={<ClaimPreview uri={livestreamClaim.canonical_url} livestream type="inline" />}
|
</Card>
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return <ClaimPreview uri={livestreamClaim.canonical_url} wrapperElement={element} type="inline" />;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ import BuyPage from 'page/buy';
|
||||||
import NotificationsPage from 'page/notifications';
|
import NotificationsPage from 'page/notifications';
|
||||||
import SignInWalletPasswordPage from 'page/signInWalletPassword';
|
import SignInWalletPasswordPage from 'page/signInWalletPassword';
|
||||||
import YoutubeSyncPage from 'page/youtubeSync';
|
import YoutubeSyncPage from 'page/youtubeSync';
|
||||||
import LiveStreamPage from 'page/livestream';
|
|
||||||
|
|
||||||
import { LINKED_COMMENT_QUERY_PARAM } from 'constants/comment';
|
import { LINKED_COMMENT_QUERY_PARAM } from 'constants/comment';
|
||||||
import { parseURI, isURIValid } from 'lbry-redux';
|
import { parseURI, isURIValid } from 'lbry-redux';
|
||||||
|
@ -286,8 +285,6 @@ function AppRouter(props: Props) {
|
||||||
<Route path={`/$/${PAGES.EMBED}/:claimName`} exact component={EmbedWrapperPage} />
|
<Route path={`/$/${PAGES.EMBED}/:claimName`} exact component={EmbedWrapperPage} />
|
||||||
<Route path={`/$/${PAGES.EMBED}/:claimName/:claimId`} exact component={EmbedWrapperPage} />
|
<Route path={`/$/${PAGES.EMBED}/:claimName/:claimId`} exact component={EmbedWrapperPage} />
|
||||||
|
|
||||||
<Route path={`/$/${PAGES.LIVESTREAM}`} component={LiveStreamPage} />
|
|
||||||
|
|
||||||
{/* Below need to go at the end to make sure we don't match any of our pages first */}
|
{/* Below need to go at the end to make sure we don't match any of our pages first */}
|
||||||
<Route path="/:claimName" exact component={ShowPage} />
|
<Route path="/:claimName" exact component={ShowPage} />
|
||||||
<Route path="/:claimName/:streamName" exact component={ShowPage} />
|
<Route path="/:claimName/:streamName" exact component={ShowPage} />
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
SETTINGS,
|
SETTINGS,
|
||||||
makeSelectTagInClaimOrChannelForUri,
|
makeSelectTagInClaimOrChannelForUri,
|
||||||
makeSelectClaimIsMine,
|
makeSelectClaimIsMine,
|
||||||
makeSelectClaimHasSource,
|
makeSelectClaimIsStreamPlaceholder,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { makeSelectCostInfoForUri, doFetchCostInfoForUri } from 'lbryinc';
|
import { makeSelectCostInfoForUri, doFetchCostInfoForUri } from 'lbryinc';
|
||||||
import { selectShowMatureContent, makeSelectClientSetting } from 'redux/selectors/settings';
|
import { selectShowMatureContent, makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
|
@ -35,7 +35,7 @@ const select = (state, props) => {
|
||||||
videoTheaterMode: makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)(state),
|
videoTheaterMode: makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)(state),
|
||||||
commentsDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_COMMENTS_TAG)(state),
|
commentsDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_COMMENTS_TAG)(state),
|
||||||
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||||
isLivestream: !makeSelectClaimHasSource(props.uri)(state),
|
isLivestream: makeSelectClaimIsStreamPlaceholder(props.uri)(state),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||||
import Page from 'component/page';
|
import Page from 'component/page';
|
||||||
import LivestreamLayout from 'component/livestreamLayout';
|
import LivestreamLayout from 'component/livestreamLayout';
|
||||||
import analytics from 'analytics';
|
import analytics from 'analytics';
|
||||||
|
import { Lbry } from 'lbry-redux';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
@ -19,8 +20,41 @@ export default function LivestreamPage(props: Props) {
|
||||||
const [activeViewers, setActiveViewers] = React.useState(0);
|
const [activeViewers, setActiveViewers] = React.useState(0);
|
||||||
const [isLive, setIsLive] = React.useState(false);
|
const [isLive, setIsLive] = React.useState(false);
|
||||||
const livestreamChannelId = channelClaim && channelClaim.signing_channel && channelClaim.signing_channel.claim_id;
|
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(() => {
|
React.useEffect(() => {
|
||||||
|
let interval;
|
||||||
function checkIsLive() {
|
function checkIsLive() {
|
||||||
// $FlowFixMe Bitwave's API can handle garbage
|
// $FlowFixMe Bitwave's API can handle garbage
|
||||||
fetch(`${BITWAVE_API}/${livestreamChannelId}`)
|
fetch(`${BITWAVE_API}/${livestreamChannelId}`)
|
||||||
|
@ -38,19 +72,17 @@ export default function LivestreamPage(props: Props) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (livestreamChannelId && hasLivestreamClaim) {
|
||||||
let interval;
|
|
||||||
if (livestreamChannelId) {
|
|
||||||
if (!interval) checkIsLive();
|
if (!interval) checkIsLive();
|
||||||
interval = setInterval(checkIsLive, 10 * 1000);
|
interval = setInterval(checkIsLive, STREAMING_POLL_INTERVAL_IN_MS);
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (interval) {
|
if (interval) {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [livestreamChannelId]);
|
}
|
||||||
|
}, [livestreamChannelId, hasLivestreamClaim]);
|
||||||
|
|
||||||
const stringifiedClaim = JSON.stringify(claim);
|
const stringifiedClaim = JSON.stringify(claim);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|
|
@ -24,16 +24,34 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function LivestreamSetupPage(props: Props) {
|
export default function LivestreamSetupPage(props: Props) {
|
||||||
|
const LIVESTREAM_CLAIM_POLL_IN_MS = 60000;
|
||||||
const { channels, fetchingChannels, activeChannelClaim, pendingClaims } = props;
|
const { channels, fetchingChannels, activeChannelClaim, pendingClaims } = props;
|
||||||
|
|
||||||
const [sigData, setSigData] = React.useState({ signature: undefined, signing_ts: undefined });
|
const [sigData, setSigData] = React.useState({ signature: undefined, signing_ts: undefined });
|
||||||
const [showHelpTest, setShowHelpTest] = usePersistedState('livestream-help-seen', true);
|
const [showHelpTest, setShowHelpTest] = usePersistedState('livestream-help-seen', true);
|
||||||
const [spin, setSpin] = React.useState(true);
|
const [spin, setSpin] = React.useState(true);
|
||||||
|
const [livestreamClaims, setLivestreamClaims] = React.useState([]);
|
||||||
|
|
||||||
const hasChannels = channels && channels.length > 0;
|
const hasChannels = channels && channels.length > 0;
|
||||||
const activeChannelClaimStr = JSON.stringify(activeChannelClaim);
|
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 = (
|
const helpText = (
|
||||||
<div className="section__subtitle">
|
<div className="section__subtitle">
|
||||||
<p>
|
<p>
|
||||||
|
@ -76,6 +94,7 @@ export default function LivestreamSetupPage(props: Props) {
|
||||||
<p>{__(`Click Save and you are done!`)}</p>
|
<p>{__(`Click Save and you are done!`)}</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (activeChannelClaimStr) {
|
if (activeChannelClaimStr) {
|
||||||
const channelClaim = JSON.parse(activeChannelClaimStr);
|
const channelClaim = JSON.parse(activeChannelClaimStr);
|
||||||
|
@ -96,25 +115,12 @@ export default function LivestreamSetupPage(props: Props) {
|
||||||
}
|
}
|
||||||
}, [activeChannelClaimStr, setSigData]);
|
}, [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(() => {
|
React.useEffect(() => {
|
||||||
|
let checkClaimsInterval;
|
||||||
if (!activeChannelClaimStr) return;
|
if (!activeChannelClaimStr) return;
|
||||||
|
|
||||||
const channelClaim = JSON.parse(activeChannelClaimStr);
|
const channelClaim = JSON.parse(activeChannelClaimStr);
|
||||||
|
|
||||||
|
function checkLivestreamClaims() {
|
||||||
Lbry.claim_search({
|
Lbry.claim_search({
|
||||||
channel_ids: [channelClaim.claim_id],
|
channel_ids: [channelClaim.claim_id],
|
||||||
has_no_source: true,
|
has_no_source: true,
|
||||||
|
@ -132,11 +138,21 @@ export default function LivestreamSetupPage(props: Props) {
|
||||||
setLivestreamClaims([]);
|
setLivestreamClaims([]);
|
||||||
setSpin(false);
|
setSpin(false);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
if (!checkClaimsInterval) {
|
||||||
|
checkLivestreamClaims();
|
||||||
|
checkClaimsInterval = setInterval(checkLivestreamClaims, LIVESTREAM_CLAIM_POLL_IN_MS);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
if (checkClaimsInterval) {
|
||||||
|
clearInterval(checkClaimsInterval);
|
||||||
|
}
|
||||||
|
};
|
||||||
}, [activeChannelClaimStr, pendingLength, setSpin]);
|
}, [activeChannelClaimStr, pendingLength, setSpin]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
{fetchingChannels && (
|
{(fetchingChannels || spin) && (
|
||||||
<div className="main--empty">
|
<div className="main--empty">
|
||||||
<Spinner delayed />
|
<Spinner delayed />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6950,9 +6950,9 @@ lazy-val@^1.0.4:
|
||||||
yargs "^13.2.2"
|
yargs "^13.2.2"
|
||||||
zstd-codec "^0.1.1"
|
zstd-codec "^0.1.1"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#c494c92505cd531048de20bc37dc4d192b6ace01:
|
lbry-redux@lbryio/lbry-redux#db27091f5add9a6bb91c38471a369fca144fc96f:
|
||||||
version "0.0.1"
|
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:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
Loading…
Reference in a new issue