diff --git a/ui/component/claimTilesDiscover/view.jsx b/ui/component/claimTilesDiscover/view.jsx
index 8ab754962..56410ffe7 100644
--- a/ui/component/claimTilesDiscover/view.jsx
+++ b/ui/component/claimTilesDiscover/view.jsx
@@ -40,8 +40,7 @@ type Props = {
limitClaimsPerChannel?: number,
hasNoSource?: boolean,
renderProperties?: (Claim) => ?Node,
- // Passing in 'livestreamMap' indicates that we want to sort "live"
- // livestreams first, and also embelish the "live" tiles.
+ liveLivestreamsFirst?: boolean,
livestreamMap?: { [string]: any },
};
@@ -71,6 +70,7 @@ function ClaimTilesDiscover(props: Props) {
renderProperties,
blockedUris,
mutedUris,
+ liveLivestreamsFirst,
livestreamMap,
} = props;
@@ -156,25 +156,50 @@ function ClaimTilesDiscover(props: Props) {
const claimSearchCacheQuery = createNormalizedClaimSearchKey(options);
let uris = (prefixUris || []).concat(claimSearchByQuery[claimSearchCacheQuery] || []);
- // Push active livestreams to the front:
- if (livestreamMap) {
- const liveChannelIds = Object.keys(livestreamMap);
+ if (liveLivestreamsFirst && livestreamMap) {
+ let liveChannelIds = Object.keys(livestreamMap);
- uris.forEach((uri) => {
- const claim = claimsByUri[uri];
- if (
+ const claimIsLive = (claim, liveChannelIds) => {
+ // This function relies on:
+ // 1. Only 1 actual livestream per channel (i.e. all other livestream-claims
+ // for that channel actually point to the same source).
+ // 2. 'liveChannelIds' needs to be pruned after being accounted for,
+ // otherwise all livestream-claims will be "live" (we'll only take the
+ // latest one as "live").
+ return (
claim &&
claim.value_type === 'stream' &&
claim.value.source === undefined &&
claim.signing_channel &&
liveChannelIds.includes(claim.signing_channel.claim_id)
- ) {
+ );
+ };
+
+ // 1. Collect active livestreams from the primary search to put in front.
+ uris.forEach((uri) => {
+ const claim = claimsByUri[uri];
+ if (claimIsLive(claim, liveChannelIds)) {
liveUris.push(uri);
- // This live channel has been accounted for, so ignore it's older livestreams:
+ // This live channel has been accounted for, so remove it.
liveChannelIds.splice(liveChannelIds.indexOf(claim.signing_channel.claim_id), 1);
}
});
+ // 2. Now, repeat on the secondary search.
+ const livestreamsOnlySearchCacheQuery = createNormalizedClaimSearchKey({ ...options, has_no_source: true });
+ const livestreamsOnlyUris = claimSearchByQuery[livestreamsOnlySearchCacheQuery];
+ if (livestreamsOnlyUris) {
+ livestreamsOnlyUris.forEach((uri) => {
+ const claim = claimsByUri[uri];
+ if (!uris.includes(uri) && claimIsLive(claim, liveChannelIds)) {
+ liveUris.push(uri);
+ // This live channel has been accounted for, so remove it.
+ liveChannelIds.splice(liveChannelIds.indexOf(claim.signing_channel.claim_id), 1);
+ }
+ });
+ }
+
+ // 3. Finalize uris by putting live livestreams in front.
uris = liveUris.concat(uris.filter((uri) => !liveUris.includes(uri)));
}
@@ -187,11 +212,14 @@ function ClaimTilesDiscover(props: Props) {
if (shouldPerformSearch) {
const searchOptions = JSON.parse(optionsStringForEffect);
doClaimSearch(searchOptions);
+ if (liveLivestreamsFirst) {
+ doClaimSearch({ ...searchOptions, has_no_source: true });
+ }
}
- }, [doClaimSearch, shouldPerformSearch, optionsStringForEffect]);
+ }, [doClaimSearch, shouldPerformSearch, optionsStringForEffect, liveLivestreamsFirst]);
const resolveLive = (index) => {
- if (livestreamMap && index < liveUris.length) {
+ if (liveLivestreamsFirst && livestreamMap && index < liveUris.length) {
return true;
}
return undefined;
diff --git a/ui/page/home/view.jsx b/ui/page/home/view.jsx
index fb74dec3f..08f2475e0 100644
--- a/ui/page/home/view.jsx
+++ b/ui/page/home/view.jsx
@@ -93,7 +93,7 @@ function HomePage(props: Props) {
)}
-
+
{(route || link) && (