improve pending livestream dashboard #5810
1 changed files with 112 additions and 58 deletions
|
@ -15,6 +15,7 @@ import CopyableText from 'component/copyableText';
|
||||||
import Card from 'component/common/card';
|
import Card from 'component/common/card';
|
||||||
import ClaimList from 'component/claimList';
|
import ClaimList from 'component/claimList';
|
||||||
import usePersistedState from 'effects/use-persisted-state';
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
|
import usePrevious from 'effects/use-previous';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
channels: Array<ChannelClaim>,
|
channels: Array<ChannelClaim>,
|
||||||
|
@ -50,8 +51,116 @@ export default function LivestreamSetupPage(props: Props) {
|
||||||
claim.value_type === 'stream' && !(claim.value && claim.value.source)
|
claim.value_type === 'stream' && !(claim.value && claim.value.source)
|
||||||
)
|
)
|
||||||
: [];
|
: [];
|
||||||
|
const [localPending, setLocalPending] = React.useState([]); //
|
||||||
|
const localPendingStr = JSON.stringify(localPending);
|
||||||
|
const pendingLivestreamClaimsStr = JSON.stringify(pendingLiveStreamClaims);
|
||||||
|
const prevPendingLiveStreamClaimStr = usePrevious(pendingLivestreamClaimsStr);
|
||||||
|
const liveStreamClaimsStr = JSON.stringify(livestreamClaims);
|
||||||
|
const prevLiveStreamClaimsStr = JSON.stringify(liveStreamClaimsStr);
|
||||||
const pendingLength = pendingLiveStreamClaims.length;
|
const pendingLength = pendingLiveStreamClaims.length;
|
||||||
const totalLivestreamClaims = pendingLiveStreamClaims.concat(livestreamClaims);
|
|
||||||
|
// maintain a pendingClaims list by channelId that locally that things are removed from only when they show up in claim_search results.
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (activeChannelClaimStr) {
|
||||||
|
const channelClaim = JSON.parse(activeChannelClaimStr);
|
||||||
|
|
||||||
|
// ensure we have a channel
|
||||||
|
if (channelClaim.claim_id) {
|
||||||
|
Lbry.channel_sign({
|
||||||
|
channel_id: channelClaim.claim_id,
|
||||||
|
hexdata: toHex(channelClaim.name),
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
setSigData(data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setSigData({ signature: null, signing_ts: null });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [activeChannelClaimStr, setSigData]);
|
||||||
|
|
||||||
|
// The following 2 effects handle the time between pending disappearing and claim_search being able to find it.
|
||||||
|
// We'll maintain our own pending list:
|
||||||
|
// add to it when there are new things in pending
|
||||||
|
// remove items only when our claim_search finds it
|
||||||
|
React.useEffect(() => {
|
||||||
|
// add to localPending when pending changes
|
||||||
|
const localPending = JSON.parse(localPendingStr);
|
||||||
|
const pendingLivestreamClaims = JSON.parse(pendingLivestreamClaimsStr);
|
||||||
|
if (
|
||||||
|
pendingLiveStreamClaims !== prevPendingLiveStreamClaimStr ||
|
||||||
|
(pendingLivestreamClaims.length && !localPending.length)
|
||||||
|
) {
|
||||||
|
const prevPendingLivestreamClaims = prevPendingLiveStreamClaimStr
|
||||||
|
? JSON.parse(prevPendingLiveStreamClaimStr)
|
||||||
|
: [];
|
||||||
|
const pendingClaimIds = pendingLivestreamClaims.map((claim) => claim.claim_id);
|
||||||
|
const prevPendingClaimIds = prevPendingLivestreamClaims.map((claim) => claim.claim_id);
|
||||||
|
const newLocalPending = [];
|
||||||
|
if (pendingClaimIds.length > prevPendingClaimIds.length) {
|
||||||
|
pendingLivestreamClaims.forEach((pendingClaim) => {
|
||||||
|
if (!localPending.some((lClaim) => lClaim.claim_id === pendingClaim.claim_id)) {
|
||||||
|
newLocalPending.push(pendingClaim);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setLocalPending(localPending.concat(newLocalPending));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [pendingLivestreamClaimsStr, prevPendingLiveStreamClaimStr, localPendingStr, setLocalPending]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
// remove from localPending when livestreamClaims found
|
||||||
|
const localPending = JSON.parse(localPendingStr);
|
||||||
|
if (liveStreamClaimsStr !== prevLiveStreamClaimsStr && localPending.length) {
|
||||||
|
const livestreamClaims = JSON.parse(liveStreamClaimsStr);
|
||||||
|
setLocalPending(
|
||||||
|
localPending.filter((pending) => !livestreamClaims.some((claim) => claim.claim_id === pending.claim_id))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [liveStreamClaimsStr, prevLiveStreamClaimsStr, localPendingStr, setLocalPending]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
let checkClaimsInterval;
|
||||||
|
if (!activeChannelClaimStr) return;
|
||||||
|
const channelClaim = JSON.parse(activeChannelClaimStr);
|
||||||
|
|
||||||
|
function checkLivestreamClaims() {
|
||||||
|
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);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setLivestreamClaims([]);
|
||||||
|
setSpin(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!checkClaimsInterval) {
|
||||||
|
checkLivestreamClaims();
|
||||||
|
checkClaimsInterval = setInterval(checkLivestreamClaims, LIVESTREAM_CLAIM_POLL_IN_MS);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
if (checkClaimsInterval) {
|
||||||
|
clearInterval(checkClaimsInterval);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [activeChannelClaimStr, pendingLength, setSpin]);
|
||||||
|
const activeChannelId = activeChannelClaim && activeChannelClaim.claim_id;
|
||||||
|
const localPendingForChannel = localPending.filter(
|
||||||
|
(claim) => claim.signing_channel && claim.signing_channel.claim_id === activeChannelId
|
||||||
|
);
|
||||||
|
const totalLivestreamClaims = localPendingForChannel.concat(livestreamClaims);
|
||||||
|
|
||||||
const helpText = (
|
const helpText = (
|
||||||
<div className="section__subtitle">
|
<div className="section__subtitle">
|
||||||
<p>
|
<p>
|
||||||
|
@ -95,61 +204,6 @@ export default function LivestreamSetupPage(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (activeChannelClaimStr) {
|
|
||||||
const channelClaim = JSON.parse(activeChannelClaimStr);
|
|
||||||
|
|
||||||
// ensure we have a channel
|
|
||||||
if (channelClaim.claim_id) {
|
|
||||||
Lbry.channel_sign({
|
|
||||||
channel_id: channelClaim.claim_id,
|
|
||||||
hexdata: toHex(channelClaim.name),
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
setSigData(data);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
setSigData({ signature: null, signing_ts: null });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [activeChannelClaimStr, setSigData]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
let checkClaimsInterval;
|
|
||||||
if (!activeChannelClaimStr) return;
|
|
||||||
const channelClaim = JSON.parse(activeChannelClaimStr);
|
|
||||||
|
|
||||||
function checkLivestreamClaims() {
|
|
||||||
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);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setLivestreamClaims([]);
|
|
||||||
setSpin(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!checkClaimsInterval) {
|
|
||||||
checkLivestreamClaims();
|
|
||||||
checkClaimsInterval = setInterval(checkLivestreamClaims, LIVESTREAM_CLAIM_POLL_IN_MS);
|
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
if (checkClaimsInterval) {
|
|
||||||
clearInterval(checkClaimsInterval);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [activeChannelClaimStr, pendingLength, setSpin]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
{(fetchingChannels || spin) && (
|
{(fetchingChannels || spin) && (
|
||||||
|
@ -219,11 +273,11 @@ export default function LivestreamSetupPage(props: Props) {
|
||||||
|
|
||||||
{totalLivestreamClaims.length > 0 ? (
|
{totalLivestreamClaims.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
{Boolean(pendingLiveStreamClaims.length) && (
|
{Boolean(localPendingForChannel.length) && (
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<ClaimList
|
<ClaimList
|
||||||
header={__('Your pending livestream uploads')}
|
header={__('Your pending livestream uploads')}
|
||||||
uris={pendingLiveStreamClaims.map((claim) => claim.permanent_url)}
|
uris={localPendingForChannel.map((claim) => claim.permanent_url)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
Loading…
Reference in a new issue