Make Wild-West a proper Category + additional features. (1353)
This commit is contained in:
commit
8e2ac343b0
12 changed files with 88 additions and 60 deletions
2
flow-typed/homepage.js
vendored
2
flow-typed/homepage.js
vendored
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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} />
|
||||||
|
|
|
@ -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),
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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']);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue