Make Wild-West a proper Category + additional features. (1353)

This commit is contained in:
infinite-persistence 2022-04-20 22:57:35 +08:00
commit 8e2ac343b0
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
12 changed files with 88 additions and 60 deletions

View file

@ -22,9 +22,11 @@ declare type RowDataItem = {
pinnedClaimIds?: Array<string>, // takes precedence over pinnedUrls pinnedClaimIds?: Array<string>, // takes precedence over pinnedUrls
options?: { options?: {
channelIds?: Array<string>, channelIds?: Array<string>,
excludedChannelIds?: Array<string>,
limitClaimsPerChannel?: number, limitClaimsPerChannel?: number,
pageSize?: number, pageSize?: number,
releaseTime?: string, releaseTime?: string,
searchLanguages?: Array<string>,
}, },
route?: string, route?: string,
hideForUnauth?: boolean, hideForUnauth?: boolean,

View file

@ -44,7 +44,8 @@ type Props = {
showHiddenByUser?: boolean, showHiddenByUser?: boolean,
showNoSourceClaims?: boolean, showNoSourceClaims?: boolean,
tileLayout: boolean, tileLayout: boolean,
ignoreSearchInLanguage?: boolean, searchLanguages?: Array<string>,
ignoreSearchInLanguage?: boolean, // Negate the redux setting where it doesn't make sense.
orderBy?: Array<string>, // Trending, New, Top orderBy?: Array<string>, // Trending, New, Top
defaultOrderBy?: string, defaultOrderBy?: string,
@ -70,6 +71,7 @@ type Props = {
limitClaimsPerChannel?: number, limitClaimsPerChannel?: number,
channelIds?: Array<string>, channelIds?: Array<string>,
excludedChannelIds?: Array<string>,
claimIds?: Array<string>, claimIds?: Array<string>,
subscribedChannels: Array<Subscription>, subscribedChannels: Array<Subscription>,
@ -127,6 +129,7 @@ function ClaimListDiscover(props: Props) {
meta, meta,
subSection, subSection,
channelIds, channelIds,
excludedChannelIds,
showNsfw, showNsfw,
hideReposts, hideReposts,
fetchViewCount, fetchViewCount,
@ -165,6 +168,7 @@ function ClaimListDiscover(props: Props) {
maxPages, maxPages,
forceShowReposts = false, forceShowReposts = false,
languageSetting, languageSetting,
searchLanguages,
searchInLanguage, searchInLanguage,
ignoreSearchInLanguage, ignoreSearchInLanguage,
limitClaimsPerChannel, limitClaimsPerChannel,
@ -211,9 +215,15 @@ function ClaimListDiscover(props: Props) {
new Set(mutedUris.concat(blockedUris).map((uri) => splitBySeparator(uri)[1])) new Set(mutedUris.concat(blockedUris).map((uri) => splitBySeparator(uri)[1]))
); );
// Precedence:
// - searchLanguages (per instance attribute)
// - urlParams
// - languageSetting (redux setting)
const language = searchLanguages ? searchLanguages.join(',') : languageSetting;
const langParam = urlParams.get(CS.LANGUAGE_KEY) || null; const langParam = urlParams.get(CS.LANGUAGE_KEY) || null;
const searchInSelectedLangOnly = searchInLanguage && !ignoreSearchInLanguage; const forcedSearchInLanguage = Boolean(searchLanguages);
const languageParams = resolveLangForClaimSearch(languageSetting, searchInSelectedLangOnly, langParam); const userSearchInLanguage = searchInLanguage && !ignoreSearchInLanguage;
const languageParams = resolveLangForClaimSearch(language, forcedSearchInLanguage || userSearchInLanguage, langParam);
let claimTypeParam = claimType || defaultClaimType || null; let claimTypeParam = claimType || defaultClaimType || null;
let streamTypeParam = streamType || defaultStreamType || null; let streamTypeParam = streamType || defaultStreamType || null;
@ -257,6 +267,7 @@ function ClaimListDiscover(props: Props) {
const durationParam = urlParams.get(CS.DURATION_KEY) || null; const durationParam = urlParams.get(CS.DURATION_KEY) || null;
const channelIdsInUrl = urlParams.get(CS.CHANNEL_IDS_KEY); const channelIdsInUrl = urlParams.get(CS.CHANNEL_IDS_KEY);
const channelIdsParam = channelIdsInUrl ? channelIdsInUrl.split(',') : channelIds; const channelIdsParam = channelIdsInUrl ? channelIdsInUrl.split(',') : channelIds;
const excludedIdsParam = excludedChannelIds;
const feeAmountParam = urlParams.get('fee_amount') || feeAmount; const feeAmountParam = urlParams.get('fee_amount') || feeAmount;
// const originalPageSize = pageSize || CS.PAGE_SIZE; // const originalPageSize = pageSize || CS.PAGE_SIZE;
const originalPageSize = 12; const originalPageSize = 12;
@ -346,6 +357,10 @@ function ClaimListDiscover(props: Props) {
options.channel_ids = channelIdsParam; options.channel_ids = channelIdsParam;
} }
if (excludedIdsParam) {
options.not_channel_ids = (options.not_channel_ids || []).concat(excludedIdsParam);
}
if (tagsParam) { if (tagsParam) {
if (tagsParam !== CS.TAGS_ALL && tagsParam !== '') { if (tagsParam !== CS.TAGS_ALL && tagsParam !== '') {
if (tagsParam === CS.TAGS_FOLLOWED) { if (tagsParam === CS.TAGS_FOLLOWED) {
@ -694,7 +709,7 @@ function ClaimListDiscover(props: Props) {
<div className="section__header--actions"> <div className="section__header--actions">
<div className="section__actions"> <div className="section__actions">
{headerToUse} {headerToUse}
{searchInSelectedLangOnly && <LangFilterIndicator />} {userSearchInLanguage && <LangFilterIndicator />}
</div> </div>
{meta && <div className="section__actions--no-margin">{meta}</div>} {meta && <div className="section__actions--no-margin">{meta}</div>}
</div> </div>
@ -734,7 +749,7 @@ function ClaimListDiscover(props: Props) {
<div className="section__header--actions"> <div className="section__header--actions">
<div className="section__actions"> <div className="section__actions">
{headerToUse} {headerToUse}
{searchInSelectedLangOnly && <LangFilterIndicator />} {userSearchInLanguage && <LangFilterIndicator />}
</div> </div>
{meta && <div className="section__actions--no-margin">{meta}</div>} {meta && <div className="section__actions--no-margin">{meta}</div>}
</div> </div>

View file

@ -2,6 +2,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import Icon from 'component/common/icon'; import Icon from 'component/common/icon';
import { HOMEPAGE_EXCLUDED_CATEGORIES } from 'constants/homepage_languages';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import 'scss/component/homepage-sort.scss'; import 'scss/component/homepage-sort.scss';
@ -48,26 +49,26 @@ function getInitialList(listId, savedOrder, homepageSections) {
const savedHiddenOrder = savedOrder.hidden || []; const savedHiddenOrder = savedOrder.hidden || [];
const sectionKeys = Object.keys(homepageSections); const sectionKeys = Object.keys(homepageSections);
if (sectionKeys.includes('NEWS') && !savedHiddenOrder.includes('NEWS') && !savedActiveOrder.includes('NEWS')) {
savedHiddenOrder.push('NEWS');
}
if (listId === 'ACTIVE') { if (listId === 'ACTIVE') {
// Start with saved order, excluding obsolete items (i.e. category removed or not available in non-English) // Start with saved order, excluding obsolete items (i.e. category removed or not available in non-English)
const finalOrder = savedActiveOrder.filter((x) => sectionKeys.includes(x)); const finalOrder = savedActiveOrder.filter((x) => sectionKeys.includes(x));
// Add new items (e.g. new categories) // Add new categories not seen previously.
sectionKeys.forEach((x) => { sectionKeys.forEach((x) => {
if (!finalOrder.includes(x)) { if (!finalOrder.includes(x)) {
finalOrder.push(x); finalOrder.push(x);
} }
}); });
// Exclude items that were moved to Hidden // Exclude items that were moved to Hidden, or intentionally excluded from Homepage.
return finalOrder.filter((x) => !savedHiddenOrder.includes(x)); return finalOrder
.filter((x) => !savedHiddenOrder.includes(x))
.filter((x) => !HOMEPAGE_EXCLUDED_CATEGORIES.includes(x));
} else { } else {
console.assert(listId === 'HIDDEN', `Unhandled listId: ${listId}`); console.assert(listId === 'HIDDEN', `Unhandled listId: ${listId}`);
return savedHiddenOrder.filter((x) => sectionKeys.includes(x)); return savedHiddenOrder
.filter((x) => sectionKeys.includes(x))
.filter((x) => !HOMEPAGE_EXCLUDED_CATEGORIES.includes(x));
} }
} }

View file

@ -190,21 +190,19 @@ function AppRouter(props: Props) {
const tagParams = urlParams.get(CS.TAGS_KEY); const tagParams = urlParams.get(CS.TAGS_KEY);
const isLargeScreen = useIsLargeScreen(); const isLargeScreen = useIsLargeScreen();
const homeCategoryPages = React.useMemo(() => { const categoryPages = React.useMemo(() => {
const dynamicRoutes = GetLinksData(homepageData, isLargeScreen).filter( const dynamicRoutes = GetLinksData(homepageData, isLargeScreen).filter(
(potentialRoute: any) => potentialRoute && potentialRoute.route (x: any) => x && x.route && (x.id !== 'WILD_WEST' || !wildWestDisabled)
); );
return dynamicRoutes.map((dynamicRouteProps: RowDataItem) => ( return dynamicRoutes.map((dynamicRouteProps: RowDataItem) => (
<Route <Route
key={dynamicRouteProps.route} key={dynamicRouteProps.route}
path={dynamicRouteProps.route} path={dynamicRouteProps.route}
component={(routerProps) => ( component={(routerProps) => <DiscoverPage {...routerProps} dynamicRouteProps={dynamicRouteProps} />}
<DiscoverPage {...routerProps} dynamicRouteProps={dynamicRouteProps} hideRepostRibbon />
)}
/> />
)); ));
}, [homepageData, isLargeScreen]); }, [homepageData, isLargeScreen, wildWestDisabled]);
// For people arriving at settings page from deeplinks, know whether they can "go back" // For people arriving at settings page from deeplinks, know whether they can "go back"
useEffect(() => { useEffect(() => {
@ -291,8 +289,7 @@ function AppRouter(props: Props) {
<Route path={`/`} exact component={HomePage} /> <Route path={`/`} exact component={HomePage} />
{(!wildWestDisabled || tagParams) && <Route path={`/$/${PAGES.DISCOVER}`} exact component={DiscoverPage} />} {(!wildWestDisabled || tagParams) && <Route path={`/$/${PAGES.DISCOVER}`} exact component={DiscoverPage} />}
{!wildWestDisabled && <Route path={`/$/${PAGES.WILD_WEST}`} exact component={DiscoverPage} />} {categoryPages}
{homeCategoryPages}
<Route path={`/$/${PAGES.AUTH_SIGNIN}`} exact component={SignInPage} /> <Route path={`/$/${PAGES.AUTH_SIGNIN}`} exact component={SignInPage} />
<Route path={`/$/${PAGES.AUTH_PASSWORD_RESET}`} exact component={PasswordResetPage} /> <Route path={`/$/${PAGES.AUTH_PASSWORD_RESET}`} exact component={PasswordResetPage} />

View file

@ -5,7 +5,7 @@ import { doClearClaimSearch } from 'redux/actions/claims';
import { doClearPurchasedUriSuccess } from 'redux/actions/file'; import { doClearPurchasedUriSuccess } from 'redux/actions/file';
import { selectFollowedTags } from 'redux/selectors/tags'; import { selectFollowedTags } from 'redux/selectors/tags';
import { selectUserVerifiedEmail, selectUser, selectOdyseeMembershipName } from 'redux/selectors/user'; import { selectUserVerifiedEmail, selectUser, selectOdyseeMembershipName } from 'redux/selectors/user';
import { selectHomepageData, selectWildWestDisabled } from 'redux/selectors/settings'; import { selectHomepageData } from 'redux/selectors/settings';
import { doSignOut } from 'redux/actions/app'; import { doSignOut } from 'redux/actions/app';
import { selectUnseenNotificationCount } from 'redux/selectors/notifications'; import { selectUnseenNotificationCount } from 'redux/selectors/notifications';
import { selectPurchaseUriSuccess, selectOdyseeMembershipForUri } from 'redux/selectors/claims'; import { selectPurchaseUriSuccess, selectOdyseeMembershipForUri } from 'redux/selectors/claims';
@ -21,7 +21,6 @@ const select = (state) => ({
unseenCount: selectUnseenNotificationCount(state), unseenCount: selectUnseenNotificationCount(state),
user: selectUser(state), user: selectUser(state),
homepageData: selectHomepageData(state), homepageData: selectHomepageData(state),
wildWestDisabled: selectWildWestDisabled(state),
odyseeMembership: selectOdyseeMembershipName(state), odyseeMembership: selectOdyseeMembershipName(state),
odyseeMembershipByUri: (uri) => selectOdyseeMembershipForUri(state, uri), odyseeMembershipByUri: (uri) => selectOdyseeMembershipForUri(state, uri),
}); });

View file

@ -118,12 +118,6 @@ const UNAUTH_LINKS: Array<SideNavLink> = [
}, },
]; ];
const WILD_WEST: SideNavLink = {
title: 'Wild West',
link: `/$/${PAGES.WILD_WEST}`,
icon: ICONS.WILD_WEST,
};
// **************************************************************************** // ****************************************************************************
// **************************************************************************** // ****************************************************************************
@ -143,7 +137,6 @@ type Props = {
doClearPurchasedUriSuccess: () => void, doClearPurchasedUriSuccess: () => void,
user: ?User, user: ?User,
homepageData: any, homepageData: any,
wildWestDisabled: boolean,
doClearClaimSearch: () => void, doClearClaimSearch: () => void,
odyseeMembership: string, odyseeMembership: string,
odyseeMembershipByUri: (uri: string) => string, odyseeMembershipByUri: (uri: string) => string,
@ -166,7 +159,6 @@ function SideNavigation(props: Props) {
homepageData, homepageData,
user, user,
followedTags, followedTags,
wildWestDisabled,
doClearClaimSearch, doClearClaimSearch,
odyseeMembership, odyseeMembership,
odyseeMembershipByUri, odyseeMembershipByUri,
@ -549,7 +541,6 @@ function SideNavigation(props: Props) {
<> <>
{/* $FlowFixMe: GetLinksData type needs an update */} {/* $FlowFixMe: GetLinksData type needs an update */}
{EXTRA_SIDEBAR_LINKS.map((linkProps) => getLink(linkProps))} {EXTRA_SIDEBAR_LINKS.map((linkProps) => getLink(linkProps))}
{!wildWestDisabled && getLink(WILD_WEST)}
</> </>
)} )}
</ul> </ul>

View file

@ -19,3 +19,5 @@ export function getHomepageLanguage(code) {
} }
export default HOMEPAGE_LANGUAGES; export default HOMEPAGE_LANGUAGES;
export const HOMEPAGE_EXCLUDED_CATEGORIES = Object.freeze(['NEWS', 'WILD_WEST']);

View file

@ -8,7 +8,7 @@ import ClaimListDiscover from 'component/claimListDiscover';
import { useIsMobile, useIsLargeScreen } from 'effects/use-screensize'; import { useIsMobile, useIsLargeScreen } from 'effects/use-screensize';
import usePersistedState from 'effects/use-persisted-state'; import usePersistedState from 'effects/use-persisted-state';
import { getLivestreamUris } from 'util/livestream'; import { getLivestreamUris } from 'util/livestream';
import { resolveLangForClaimSearch } from '../../util/default-languages'; import { resolveLangForClaimSearch } from 'util/default-languages';
const DEFAULT_LIVESTREAM_TILE_LIMIT = 8; const DEFAULT_LIVESTREAM_TILE_LIMIT = 8;
const SECTION = Object.freeze({ COLLAPSED: 1, EXPANDED: 2 }); const SECTION = Object.freeze({ COLLAPSED: 1, EXPANDED: 2 });
@ -23,8 +23,10 @@ function getTileLimit(isLargeScreen, originalSize) {
type Props = { type Props = {
tileLayout: boolean, tileLayout: boolean,
channelIds?: Array<string>, channelIds?: Array<string>,
excludedChannelIds?: Array<string>,
activeLivestreams: ?LivestreamInfo, activeLivestreams: ?LivestreamInfo,
doFetchActiveLivestreams: (orderBy: ?Array<string>, lang: ?Array<string>) => void, doFetchActiveLivestreams: (orderBy: ?Array<string>, lang: ?Array<string>) => void,
searchLanguages?: Array<string>,
languageSetting?: string, languageSetting?: string,
searchInLanguage?: boolean, searchInLanguage?: boolean,
langParam?: string | null, langParam?: string | null,
@ -34,8 +36,10 @@ export default function LivestreamSection(props: Props) {
const { const {
tileLayout, tileLayout,
channelIds, channelIds,
excludedChannelIds,
activeLivestreams, activeLivestreams,
doFetchActiveLivestreams, doFetchActiveLivestreams,
searchLanguages,
languageSetting, languageSetting,
searchInLanguage, searchInLanguage,
langParam, langParam,
@ -49,7 +53,7 @@ export default function LivestreamSection(props: Props) {
const initialLiveTileLimit = getTileLimit(isLargeScreen, DEFAULT_LIVESTREAM_TILE_LIMIT); const initialLiveTileLimit = getTileLimit(isLargeScreen, DEFAULT_LIVESTREAM_TILE_LIMIT);
const [liveSection, setLiveSection] = React.useState(liveSectionStore || SECTION.COLLAPSED); const [liveSection, setLiveSection] = React.useState(liveSectionStore || SECTION.COLLAPSED);
const livestreamUris = getLivestreamUris(activeLivestreams, channelIds); const livestreamUris = getLivestreamUris(activeLivestreams, channelIds, excludedChannelIds);
const liveTilesOverLimit = livestreamUris && livestreamUris.length > initialLiveTileLimit; const liveTilesOverLimit = livestreamUris && livestreamUris.length > initialLiveTileLimit;
function collapseSection() { function collapseSection() {
@ -66,7 +70,9 @@ export default function LivestreamSection(props: Props) {
React.useEffect(() => { React.useEffect(() => {
// Fetch active livestreams on mount // Fetch active livestreams on mount
const langCsv = resolveLangForClaimSearch(languageSetting, searchInLanguage, langParam); const language = searchLanguages ? searchLanguages.join(',') : languageSetting;
const searchInSelectedLangOnly = Boolean(searchLanguages) || searchInLanguage;
const langCsv = resolveLangForClaimSearch(language, searchInSelectedLangOnly, langParam);
const lang = langCsv ? langCsv.split(',') : null; const lang = langCsv ? langCsv.split(',') : null;
doFetchActiveLivestreams(CS.ORDER_BY_NEW_VALUE, lang); doFetchActiveLivestreams(CS.ORDER_BY_NEW_VALUE, lang);
// eslint-disable-next-line react-hooks/exhaustive-deps, (on mount only) // eslint-disable-next-line react-hooks/exhaustive-deps, (on mount only)

View file

@ -25,7 +25,6 @@ type Props = {
followedTags: Array<Tag>, followedTags: Array<Tag>,
repostedUri: string, repostedUri: string,
repostedClaim: ?GenericClaim, repostedClaim: ?GenericClaim,
hideRepostRibbon?: boolean,
languageSetting: string, languageSetting: string,
searchInLanguage: boolean, searchInLanguage: boolean,
doToggleTagFollowDesktop: (string) => void, doToggleTagFollowDesktop: (string) => void,
@ -41,7 +40,6 @@ function DiscoverPage(props: Props) {
followedTags, followedTags,
repostedClaim, repostedClaim,
repostedUri, repostedUri,
hideRepostRibbon,
languageSetting, languageSetting,
searchInLanguage, searchInLanguage,
doToggleTagFollowDesktop, doToggleTagFollowDesktop,
@ -55,7 +53,7 @@ function DiscoverPage(props: Props) {
const buttonRef = useRef(); const buttonRef = useRef();
const isHovering = useHover(buttonRef); const isHovering = useHover(buttonRef);
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const isWildWest = window.location.pathname === `/$/${PAGES.WILD_WEST}`; const isWildWest = dynamicRouteProps && dynamicRouteProps.id === 'WILD_WEST';
const urlParams = new URLSearchParams(search); const urlParams = new URLSearchParams(search);
const langParam = urlParams.get(CS.LANGUAGE_KEY) || null; const langParam = urlParams.get(CS.LANGUAGE_KEY) || null;
@ -63,14 +61,13 @@ function DiscoverPage(props: Props) {
const tagsQuery = urlParams.get('t') || null; const tagsQuery = urlParams.get('t') || null;
const tags = tagsQuery ? tagsQuery.split(',') : null; const tags = tagsQuery ? tagsQuery.split(',') : null;
const repostedClaimIsResolved = repostedUri && repostedClaim; const repostedClaimIsResolved = repostedUri && repostedClaim;
const hideRepostRibbon = !isWildWest;
const discoverIcon = SIMPLE_SITE ? ICONS.WILD_WEST : ICONS.DISCOVER;
const discoverLabel = SIMPLE_SITE ? __('Wild West') : __('All Content');
// Eventually allow more than one tag on this page // Eventually allow more than one tag on this page
// Restricting to one to make follow/unfollow simpler // Restricting to one to make follow/unfollow simpler
const tag = (tags && tags[0]) || null; const tag = (tags && tags[0]) || null;
const channelIds = const channelIds = dynamicRouteProps?.options?.channelIds || undefined;
(dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.channelIds) || undefined; const excludedChannelIds = dynamicRouteProps?.options?.excludedChannelIds || undefined;
const isFollowing = followedTags.map(({ name }) => name).includes(tag); const isFollowing = followedTags.map(({ name }) => name).includes(tag);
let label = isFollowing ? __('Following --[button label indicating a channel has been followed]--') : __('Follow'); let label = isFollowing ? __('Following --[button label indicating a channel has been followed]--') : __('Follow');
@ -116,8 +113,10 @@ function DiscoverPage(props: Props) {
<LivestreamSection <LivestreamSection
tileLayout={repostedUri ? false : tileLayout} tileLayout={repostedUri ? false : tileLayout}
channelIds={channelIds} channelIds={channelIds}
excludedChannelIds={excludedChannelIds}
activeLivestreams={activeLivestreams} activeLivestreams={activeLivestreams}
doFetchActiveLivestreams={doFetchActiveLivestreams} doFetchActiveLivestreams={doFetchActiveLivestreams}
searchLanguages={dynamicRouteProps?.options?.searchLanguages}
languageSetting={languageSetting} languageSetting={languageSetting}
searchInLanguage={searchInLanguage} searchInLanguage={searchInLanguage}
langParam={langParam} langParam={langParam}
@ -172,15 +171,15 @@ function DiscoverPage(props: Props) {
} else { } else {
headerLabel = ( headerLabel = (
<span> <span>
<Icon icon={(dynamicRouteProps && dynamicRouteProps.icon) || discoverIcon} size={10} /> <Icon icon={(dynamicRouteProps && dynamicRouteProps.icon) || ICONS.DISCOVER} size={10} />
{(dynamicRouteProps && __(`${dynamicRouteProps.title}`)) || discoverLabel} {(dynamicRouteProps && __(`${dynamicRouteProps.title}`)) || __('All Content')}
</span> </span>
); );
} }
let releaseTime = let releaseTime =
dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.releaseTime dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.releaseTime
? dynamicRouteProps.options.releaseTime ? dynamicRouteProps.options.releaseTime
: !dynamicRouteProps && !tags && `>${Math.floor(moment().subtract(0, 'hour').startOf('week').unix())}`; : !isWildWest && `>${Math.floor(moment().subtract(0, 'hour').startOf('week').unix())}`;
return ( return (
<Page <Page
@ -190,11 +189,11 @@ function DiscoverPage(props: Props) {
> >
<ClaimListDiscover <ClaimListDiscover
pins={getPins(dynamicRouteProps)} pins={getPins(dynamicRouteProps)}
hideFilters={SIMPLE_SITE ? !(dynamicRouteProps || tags) : undefined} hideFilters={isWildWest ? true : undefined}
header={repostedUri ? <span /> : undefined} header={repostedUri ? <span /> : undefined}
subSection={getSubSection()} subSection={getSubSection()}
tileLayout={repostedUri ? false : tileLayout} tileLayout={repostedUri ? false : tileLayout}
defaultOrderBy={SIMPLE_SITE ? (dynamicRouteProps ? undefined : CS.ORDER_BY_TRENDING) : undefined} defaultOrderBy={isWildWest || tags ? CS.ORDER_BY_TRENDING : undefined}
claimType={claimType ? [claimType] : undefined} claimType={claimType ? [claimType] : undefined}
headerLabel={headerLabel} headerLabel={headerLabel}
tags={tags} tags={tags}
@ -207,8 +206,9 @@ function DiscoverPage(props: Props) {
// TODO: find a better way to determine discover / wild west vs other modes release times // TODO: find a better way to determine discover / wild west vs other modes release times
// for now including && !tags so that // for now including && !tags so that
releaseTime={releaseTime || undefined} releaseTime={releaseTime || undefined}
feeAmount={SIMPLE_SITE ? !dynamicRouteProps && CS.FEE_AMOUNT_ANY : undefined} feeAmount={isWildWest || tags ? CS.FEE_AMOUNT_ANY : undefined}
channelIds={channelIds} channelIds={channelIds}
excludedChannelIds={excludedChannelIds}
limitClaimsPerChannel={ limitClaimsPerChannel={
SIMPLE_SITE SIMPLE_SITE
? (dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.limitClaimsPerChannel) || 3 ? (dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.limitClaimsPerChannel) || 3
@ -217,6 +217,7 @@ function DiscoverPage(props: Props) {
meta={getMeta()} meta={getMeta()}
hasSource hasSource
forceShowReposts={dynamicRouteProps} forceShowReposts={dynamicRouteProps}
searchLanguages={dynamicRouteProps?.options?.searchLanguages}
/> />
</Page> </Page>
); );

View file

@ -84,7 +84,6 @@ function HomePage(props: Props) {
showNsfw showNsfw
); );
// TODO: probably need memo, or incorporate into GetLinksData.
let sortedRowData: Array<RowDataItem> = []; let sortedRowData: Array<RowDataItem> = [];
if (homepageOrder.active && authenticated) { if (homepageOrder.active && authenticated) {
homepageOrder.active.forEach((key) => { homepageOrder.active.forEach((key) => {
@ -99,7 +98,7 @@ function HomePage(props: Props) {
if (homepageOrder.hidden) { if (homepageOrder.hidden) {
rowData.forEach((data: RowDataItem) => { rowData.forEach((data: RowDataItem) => {
// $FlowIssue: null 'hidden' already avoided, but flow can't see beyond this anonymous function? // $FlowIssue: null 'hidden' already avoided outside anonymous function.
if (!homepageOrder.hidden.includes(data.id)) { if (!homepageOrder.hidden.includes(data.id)) {
sortedRowData.push(data); sortedRowData.push(data);
} }
@ -107,14 +106,9 @@ function HomePage(props: Props) {
} }
} else { } else {
rowData.forEach((key) => { rowData.forEach((key) => {
// always inject FYP if homepage not customized, hide news. sortedRowData.push(key);
if (key.id === 'FOLLOWING') { if (key.id === 'FOLLOWING' && hasMembership) {
sortedRowData.push(key); sortedRowData.push(FYP_SECTION);
if (hasMembership) {
sortedRowData.push(FYP_SECTION);
}
} else if (key.id !== 'NEWS') {
sortedRowData.push(key);
} }
}); });
} }

View file

@ -2,6 +2,7 @@
import * as PAGES from 'constants/pages'; import * as PAGES from 'constants/pages';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import * as CS from 'constants/claim_search'; import * as CS from 'constants/claim_search';
import { HOMEPAGE_EXCLUDED_CATEGORIES } from 'constants/homepage_languages';
import { parseURI } from 'util/lbryURI'; import { parseURI } from 'util/lbryURI';
import moment from 'moment'; import moment from 'moment';
import { toCapitalCase } from 'util/string'; import { toCapitalCase } from 'util/string';
@ -20,6 +21,8 @@ export type HomepageCat = {
tags?: Array<string>, tags?: Array<string>,
pinnedUrls?: Array<string>, pinnedUrls?: Array<string>,
pinnedClaimIds?: Array<string>, // takes precedence over pinnedUrls pinnedClaimIds?: Array<string>, // takes precedence over pinnedUrls
excludedChannelIds?: Array<string>,
searchLanguages?: Array<string>,
mixIn?: Array<string>, mixIn?: Array<string>,
}; };
@ -94,9 +97,11 @@ export const getHomepageRowForCat = (key: string, cat: HomepageCat) => {
options: { options: {
claimType: cat.claimType || ['stream', 'repost'], claimType: cat.claimType || ['stream', 'repost'],
channelIds: cat.channelIds, channelIds: cat.channelIds,
excludedChannelIds: cat.excludedChannelIds,
orderBy: orderValue, orderBy: orderValue,
pageSize: cat.pageSize || undefined, pageSize: cat.pageSize || undefined,
limitClaimsPerChannel: limitClaims, limitClaimsPerChannel: limitClaims,
searchLanguages: cat.searchLanguages,
releaseTime: `>${Math.floor( releaseTime: `>${Math.floor(
moment() moment()
.subtract(cat.daysOfContent || 30, 'days') .subtract(cat.daysOfContent || 30, 'days')
@ -110,7 +115,7 @@ export const getHomepageRowForCat = (key: string, cat: HomepageCat) => {
export function GetLinksData( export function GetLinksData(
all: any, // HomepageData type? all: any, // HomepageData type?
isLargeScreen: boolean, isLargeScreen: boolean,
isHomepage?: boolean = false, isHomepage?: boolean,
authenticated?: boolean, authenticated?: boolean,
showPersonalizedChannels?: boolean, showPersonalizedChannels?: boolean,
showPersonalizedTags?: boolean, showPersonalizedTags?: boolean,
@ -338,6 +343,11 @@ export function GetLinksData(
const key = entries[i][0]; const key = entries[i][0];
const val = entries[i][1]; const val = entries[i][1];
// $FlowFixMe https://github.com/facebook/flow/issues/2221
if (isHomepage && HOMEPAGE_EXCLUDED_CATEGORIES.includes(key)) {
continue;
}
// $FlowFixMe https://github.com/facebook/flow/issues/2221 // $FlowFixMe https://github.com/facebook/flow/issues/2221
rowData.push(getHomepageRowForCat(key, val)); rowData.push(getHomepageRowForCat(key, val));
} }

View file

@ -34,9 +34,14 @@ type StreamData = {
* *
* @param activeLivestreams Object obtained from `selectActiveLivestreams`. * @param activeLivestreams Object obtained from `selectActiveLivestreams`.
* @param channelIds List of channel IDs to filter the results with. * @param channelIds List of channel IDs to filter the results with.
* @param excludedChannelIds
* @returns {[]|Array<*>} * @returns {[]|Array<*>}
*/ */
export function getLivestreamUris(activeLivestreams: ?LivestreamInfo, channelIds: ?Array<string>) { export function getLivestreamUris(
activeLivestreams: ?LivestreamInfo,
channelIds: ?Array<string>,
excludedChannelIds?: Array<string>
) {
let values = (activeLivestreams && Object.values(activeLivestreams)) || []; let values = (activeLivestreams && Object.values(activeLivestreams)) || [];
if (channelIds && channelIds.length > 0) { if (channelIds && channelIds.length > 0) {
@ -47,6 +52,11 @@ export function getLivestreamUris(activeLivestreams: ?LivestreamInfo, channelIds
values = values.filter((v) => Boolean(v.claimUri)); values = values.filter((v) => Boolean(v.claimUri));
} }
if (excludedChannelIds) {
// $FlowFixMe
values = values.filter((v) => !excludedChannelIds.includes(v.creatorId));
}
// $FlowFixMe // $FlowFixMe
return values.map((v) => v.claimUri); return values.map((v) => v.claimUri);
} }