Homepage: move "LIVE" livestreams to the front.

This commit is contained in:
infinite-persistence 2021-04-28 17:53:04 +08:00 committed by Sean Yesmunt
parent 3a884152b1
commit 41380d20df
3 changed files with 54 additions and 4 deletions

View file

@ -1,5 +1,11 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doClaimSearch, selectClaimSearchByQuery, selectFetchingClaimSearchByQuery, SETTINGS } from 'lbry-redux'; import {
doClaimSearch,
selectClaimSearchByQuery,
selectFetchingClaimSearchByQuery,
SETTINGS,
selectClaimsByUri,
} from 'lbry-redux';
import { doToggleTagFollowDesktop } from 'redux/actions/tags'; import { doToggleTagFollowDesktop } from 'redux/actions/tags';
import { makeSelectClientSetting, selectShowMatureContent } from 'redux/selectors/settings'; import { makeSelectClientSetting, selectShowMatureContent } from 'redux/selectors/settings';
import { selectModerationBlockList } from 'redux/selectors/comments'; import { selectModerationBlockList } from 'redux/selectors/comments';
@ -8,6 +14,7 @@ import ClaimListDiscover from './view';
const select = (state) => ({ const select = (state) => ({
claimSearchByQuery: selectClaimSearchByQuery(state), claimSearchByQuery: selectClaimSearchByQuery(state),
claimsByUri: selectClaimsByUri(state),
fetchingClaimSearchByQuery: selectFetchingClaimSearchByQuery(state), fetchingClaimSearchByQuery: selectFetchingClaimSearchByQuery(state),
showNsfw: selectShowMatureContent(state), showNsfw: selectShowMatureContent(state),
hideReposts: makeSelectClientSetting(SETTINGS.HIDE_REPOSTS)(state), hideReposts: makeSelectClientSetting(SETTINGS.HIDE_REPOSTS)(state),

View file

@ -20,6 +20,9 @@ type Props = {
fetchingClaimSearchByQuery: { fetchingClaimSearchByQuery: {
[string]: boolean, [string]: boolean,
}, },
claimsByUri: {
[string]: any,
},
// claim search options are below // claim search options are below
tags: Array<string>, tags: Array<string>,
blockedUris: Array<string>, blockedUris: Array<string>,
@ -37,12 +40,16 @@ type Props = {
limitClaimsPerChannel?: number, limitClaimsPerChannel?: number,
hasNoSource?: boolean, hasNoSource?: boolean,
renderProperties?: (Claim) => ?Node, renderProperties?: (Claim) => ?Node,
// Passing in 'livestreamMap' indicates that we want to sort "live"
// livestreams first, and also embelish the "live" tiles.
livestreamMap?: { [string]: any },
}; };
function ClaimTilesDiscover(props: Props) { function ClaimTilesDiscover(props: Props) {
const { const {
doClaimSearch, doClaimSearch,
claimSearchByQuery, claimSearchByQuery,
claimsByUri,
showNsfw, showNsfw,
hideReposts, hideReposts,
// Below are options to pass that are forwarded to claim_search // Below are options to pass that are forwarded to claim_search
@ -64,6 +71,7 @@ function ClaimTilesDiscover(props: Props) {
renderProperties, renderProperties,
blockedUris, blockedUris,
mutedUris, mutedUris,
livestreamMap,
} = props; } = props;
const { location } = useHistory(); const { location } = useHistory();
@ -71,6 +79,7 @@ function ClaimTilesDiscover(props: Props) {
const feeAmountInUrl = urlParams.get('fee_amount'); const feeAmountInUrl = urlParams.get('fee_amount');
const feeAmountParam = feeAmountInUrl || feeAmount; const feeAmountParam = feeAmountInUrl || feeAmount;
const mutedAndBlockedChannelIds = Array.from(new Set(mutedUris.concat(blockedUris).map((uri) => uri.split('#')[1]))); const mutedAndBlockedChannelIds = Array.from(new Set(mutedUris.concat(blockedUris).map((uri) => uri.split('#')[1])));
const liveUris = [];
const options: { const options: {
page_size: number, page_size: number,
@ -145,7 +154,30 @@ function ClaimTilesDiscover(props: Props) {
} }
const claimSearchCacheQuery = createNormalizedClaimSearchKey(options); const claimSearchCacheQuery = createNormalizedClaimSearchKey(options);
const uris = (prefixUris || []).concat(claimSearchByQuery[claimSearchCacheQuery] || []); let uris = (prefixUris || []).concat(claimSearchByQuery[claimSearchCacheQuery] || []);
// Push active livestreams to the front:
if (livestreamMap) {
const liveChannelIds = Object.keys(livestreamMap);
uris.forEach((uri) => {
const claim = claimsByUri[uri];
if (
claim &&
claim.value_type === 'stream' &&
claim.value.source === undefined &&
claim.signing_channel &&
liveChannelIds.includes(claim.signing_channel.claim_id)
) {
liveUris.push(uri);
// This live channel has been accounted for, so ignore it's older livestreams:
liveChannelIds.splice(liveChannelIds.indexOf(claim.signing_channel.claim_id), 1);
}
});
uris = liveUris.concat(uris.filter((uri) => !liveUris.includes(uri)));
}
// Don't use the query from createNormalizedClaimSearchKey for the effect since that doesn't include page & release_time // Don't use the query from createNormalizedClaimSearchKey for the effect since that doesn't include page & release_time
const optionsStringForEffect = JSON.stringify(options); const optionsStringForEffect = JSON.stringify(options);
const isLoading = fetchingClaimSearchByQuery[claimSearchCacheQuery]; const isLoading = fetchingClaimSearchByQuery[claimSearchCacheQuery];
@ -158,10 +190,19 @@ function ClaimTilesDiscover(props: Props) {
} }
}, [doClaimSearch, shouldPerformSearch, optionsStringForEffect]); }, [doClaimSearch, shouldPerformSearch, optionsStringForEffect]);
const resolveLive = (index) => {
if (livestreamMap && index < liveUris.length) {
return true;
}
return undefined;
};
return ( return (
<ul className="claim-grid"> <ul className="claim-grid">
{uris && uris.length {uris && uris.length
? uris.map((uri) => <ClaimPreviewTile key={uri} uri={uri} properties={renderProperties} />) ? uris.map((uri, index) => (
<ClaimPreviewTile key={uri} uri={uri} properties={renderProperties} live={resolveLive(index)} />
))
: new Array(pageSize).fill(1).map((x, i) => <ClaimPreviewTile key={i} placeholder />)} : new Array(pageSize).fill(1).map((x, i) => <ClaimPreviewTile key={i} placeholder />)}
</ul> </ul>
); );

View file

@ -9,6 +9,7 @@ import ClaimTilesDiscover from 'component/claimTilesDiscover';
import Icon from 'component/common/icon'; import Icon from 'component/common/icon';
import I18nMessage from 'component/i18nMessage'; import I18nMessage from 'component/i18nMessage';
import LbcSymbol from 'component/common/lbc-symbol'; import LbcSymbol from 'component/common/lbc-symbol';
import useGetLivestreams from 'effects/use-get-livestreams';
type Props = { type Props = {
authenticated: boolean, authenticated: boolean,
@ -24,6 +25,7 @@ function HomePage(props: Props) {
const showPersonalizedTags = (authenticated || !IS_WEB) && followedTags && followedTags.length > 0; const showPersonalizedTags = (authenticated || !IS_WEB) && followedTags && followedTags.length > 0;
const showIndividualTags = showPersonalizedTags && followedTags.length < 5; const showIndividualTags = showPersonalizedTags && followedTags.length < 5;
const { default: getHomepage } = homepageData; const { default: getHomepage } = homepageData;
const { livestreamMap } = useGetLivestreams(0);
const rowData: Array<RowDataItem> = getHomepage( const rowData: Array<RowDataItem> = getHomepage(
authenticated, authenticated,
@ -91,7 +93,7 @@ function HomePage(props: Props) {
</h1> </h1>
)} )}
<ClaimTilesDiscover {...options} /> <ClaimTilesDiscover {...options} livestreamMap={livestreamMap} />
{(route || link) && ( {(route || link) && (
<Button <Button
className="claim-grid__title--secondary" className="claim-grid__title--secondary"