Attempt to speed up sidebar menu for mobile (#283)
* Exclude default homepage data at compile time The youtuber IDs alone is pretty huge, and is unused in the `CUSTOM_HOMEPAGE=true` configuration. * Remove Desktop items and other cleanup - Moved constants out of the component. - Remove SIMPLE_SITE check. - Remove Desktop-only items * Sidebar: limit subscription and tag section ## Issue Too slow for huge lists ## Change Limit to 10 initially, and load everything on "Show more" * Fix makeSelectThumbnailForUri - Fix memo - Expose function to extract directly from claim if client already have it.
This commit is contained in:
parent
529a9cbc40
commit
6d217dbc50
17 changed files with 190 additions and 197 deletions
|
@ -1,7 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
makeSelectTitleForUri,
|
||||
makeSelectThumbnailForUri,
|
||||
selectThumbnailForUri,
|
||||
makeSelectCoverForUri,
|
||||
makeSelectMetadataItemForUri,
|
||||
makeSelectAmountForUri,
|
||||
|
@ -22,7 +22,7 @@ import ChannelForm from './view';
|
|||
const select = (state, props) => ({
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
title: makeSelectTitleForUri(props.uri)(state),
|
||||
thumbnailUrl: makeSelectThumbnailForUri(props.uri)(state),
|
||||
thumbnailUrl: selectThumbnailForUri(state, props.uri),
|
||||
coverUrl: makeSelectCoverForUri(props.uri)(state),
|
||||
description: makeSelectMetadataItemForUri(props.uri, 'description')(state),
|
||||
website: makeSelectMetadataItemForUri(props.uri, 'website_url')(state),
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectThumbnailForUri, makeSelectClaimForUri, makeSelectIsUriResolving } from 'redux/selectors/claims';
|
||||
import { selectThumbnailForUri, selectClaimForUri, makeSelectIsUriResolving } from 'redux/selectors/claims';
|
||||
import { doResolveUri } from 'redux/actions/claims';
|
||||
import ChannelThumbnail from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
thumbnail: selectThumbnailForUri(state, props.uri),
|
||||
claim: selectClaimForUri(state, props.uri),
|
||||
isResolving: makeSelectIsUriResolving(props.uri)(state),
|
||||
});
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
|||
import {
|
||||
makeSelectClaimForUri,
|
||||
makeSelectIsUriResolving,
|
||||
makeSelectThumbnailForUri,
|
||||
getThumbnailFromClaim,
|
||||
makeSelectTitleForUri,
|
||||
makeSelectChannelForClaimUri,
|
||||
makeSelectClaimIsNsfw,
|
||||
|
@ -28,7 +28,7 @@ const select = (state, props) => {
|
|||
date: props.uri && selectDateForUri(state, props.uri),
|
||||
channel: props.uri && makeSelectChannelForClaimUri(props.uri)(state),
|
||||
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
|
||||
thumbnail: props.uri && makeSelectThumbnailForUri(props.uri)(state),
|
||||
thumbnail: getThumbnailFromClaim(claim),
|
||||
title: props.uri && makeSelectTitleForUri(props.uri)(state),
|
||||
banState: selectBanStateForUri(state, props.uri),
|
||||
showMature: selectShowMatureContent(state),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
makeSelectTitleForUri,
|
||||
makeSelectThumbnailForUri,
|
||||
selectThumbnailForUri,
|
||||
makeSelectMetadataItemForUri,
|
||||
makeSelectAmountForUri,
|
||||
makeSelectClaimForUri,
|
||||
|
@ -26,7 +26,7 @@ import { doSetActiveChannel, doSetIncognito } from 'redux/actions/app';
|
|||
const select = (state, props) => ({
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
title: makeSelectTitleForUri(props.uri)(state),
|
||||
thumbnailUrl: makeSelectThumbnailForUri(props.uri)(state),
|
||||
thumbnailUrl: selectThumbnailForUri(state, props.uri),
|
||||
description: makeSelectMetadataItemForUri(props.uri, 'description')(state),
|
||||
tags: makeSelectMetadataItemForUri(props.uri, 'tags')(state),
|
||||
locations: makeSelectMetadataItemForUri(props.uri, 'locations')(state),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
makeSelectIsUriResolving,
|
||||
makeSelectThumbnailForUri,
|
||||
getThumbnailFromClaim,
|
||||
makeSelectTitleForUri,
|
||||
makeSelectChannelForClaimUri,
|
||||
makeSelectClaimIsNsfw,
|
||||
|
@ -40,7 +40,7 @@ const select = (state, props) => {
|
|||
isResolvingCollectionClaims: makeSelectIsResolvingCollectionForId(collectionId)(state),
|
||||
channelClaim: collectionUri && makeSelectChannelForClaimUri(collectionUri)(state),
|
||||
isResolvingUri: collectionUri && makeSelectIsUriResolving(collectionUri)(state),
|
||||
thumbnail: collectionUri && makeSelectThumbnailForUri(collectionUri)(state),
|
||||
thumbnail: getThumbnailFromClaim(claim),
|
||||
title: collectionUri && makeSelectTitleForUri(collectionUri)(state),
|
||||
blackListedOutpoints: selectBlackListedOutpoints(state),
|
||||
filteredOutpoints: selectFilteredOutpoints(state),
|
||||
|
|
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
|||
import {
|
||||
selectStakedLevelForChannelUri,
|
||||
makeSelectClaimForUri,
|
||||
makeSelectThumbnailForUri,
|
||||
selectThumbnailForUri,
|
||||
selectHasChannels,
|
||||
} from 'redux/selectors/claims';
|
||||
import { doCommentUpdate, doCommentList } from 'redux/actions/comments';
|
||||
|
@ -26,7 +26,7 @@ const select = (state, props) => {
|
|||
|
||||
return {
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
thumbnail: props.authorUri && makeSelectThumbnailForUri(props.authorUri)(state),
|
||||
thumbnail: props.authorUri && selectThumbnailForUri(state, props.authorUri),
|
||||
channelIsBlocked: props.authorUri && makeSelectChannelIsMuted(props.authorUri)(state),
|
||||
commentingEnabled: IS_WEB ? Boolean(selectUserVerifiedEmail(state)) : true,
|
||||
othersReacts: selectOthersReactsForComment(state, reactionKey),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectThumbnailForUri, makeSelectClaimForUri } from 'redux/selectors/claims';
|
||||
import { selectThumbnailForUri, makeSelectClaimForUri } from 'redux/selectors/claims';
|
||||
import { doResolveUri } from 'redux/actions/claims';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { doFetchCostInfoForUri, makeSelectCostInfoForUri } from 'lbryinc';
|
||||
|
@ -11,7 +11,7 @@ import { makeSelectFileRenderModeForUri } from 'redux/selectors/content';
|
|||
import ChannelThumbnail from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
thumbnail: selectThumbnailForUri(state, props.uri),
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
floatingPlayerEnabled: makeSelectClientSetting(SETTINGS.FLOATING_PLAYER)(state),
|
||||
costInfo: makeSelectCostInfoForUri(props.uri)(state),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectDownloadPathForUri, makeSelectStreamingUrlForUri } from 'redux/selectors/file_info';
|
||||
import { makeSelectClaimForUri, makeSelectThumbnailForUri, makeSelectContentTypeForUri } from 'redux/selectors/claims';
|
||||
import { makeSelectClaimForUri, selectThumbnailForUri, makeSelectContentTypeForUri } from 'redux/selectors/claims';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { makeSelectFileRenderModeForUri, makeSelectFileExtensionForUri } from 'redux/selectors/content';
|
||||
|
@ -11,7 +11,7 @@ const select = (state, props) => {
|
|||
return {
|
||||
currentTheme: makeSelectClientSetting(SETTINGS.THEME)(state),
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
thumbnail: selectThumbnailForUri(state, props.uri),
|
||||
contentType: makeSelectContentTypeForUri(props.uri)(state),
|
||||
downloadPath: makeSelectDownloadPathForUri(props.uri)(state),
|
||||
fileExtension: makeSelectFileExtensionForUri(props.uri)(state),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doPlayUri, doSetPlayingUri, doSetPrimaryUri } from 'redux/actions/content';
|
||||
import { makeSelectThumbnailForUri, makeSelectClaimForUri, makeSelectClaimWasPurchased } from 'redux/selectors/claims';
|
||||
import { selectThumbnailForUri, makeSelectClaimForUri, makeSelectClaimWasPurchased } from 'redux/selectors/claims';
|
||||
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import * as COLLECTIONS_CONSTS from 'constants/collections';
|
||||
|
@ -23,7 +23,7 @@ const select = (state, props) => {
|
|||
const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID);
|
||||
|
||||
return {
|
||||
claimThumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
claimThumbnail: selectThumbnailForUri(state, props.uri),
|
||||
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
|
||||
obscurePreview: makeSelectShouldObscurePreview(props.uri)(state),
|
||||
isPlaying: makeSelectIsPlaying(props.uri)(state),
|
||||
|
|
|
@ -2,14 +2,14 @@ import { connect } from 'react-redux';
|
|||
import {
|
||||
makeSelectClaimForUri,
|
||||
makeSelectTagInClaimOrChannelForUri,
|
||||
makeSelectThumbnailForUri,
|
||||
selectThumbnailForUri,
|
||||
} from 'redux/selectors/claims';
|
||||
import LivestreamLayout from './view';
|
||||
import { DISABLE_COMMENTS_TAG } from 'constants/tags';
|
||||
|
||||
const select = (state, props) => ({
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
thumbnail: selectThumbnailForUri(state, props.uri),
|
||||
chatDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_COMMENTS_TAG)(state),
|
||||
});
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
|||
import {
|
||||
selectClaimIsMine,
|
||||
makeSelectTitleForUri,
|
||||
makeSelectThumbnailForUri,
|
||||
getThumbnailFromClaim,
|
||||
selectClaimForUri,
|
||||
makeSelectIsUriResolving,
|
||||
makeSelectMetadataItemForUri,
|
||||
|
@ -18,7 +18,7 @@ const select = (state, props) => {
|
|||
uri: props.uri,
|
||||
claim,
|
||||
title: makeSelectTitleForUri(props.uri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
thumbnail: getThumbnailFromClaim(claim),
|
||||
description: makeSelectMetadataItemForUri(props.uri, 'description')(state),
|
||||
channelIsMine: selectClaimIsMine(state, claim),
|
||||
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
||||
|
|
|
@ -11,16 +11,19 @@ import NotificationBubble from 'component/notificationBubble';
|
|||
import I18nMessage from 'component/i18nMessage';
|
||||
import ChannelThumbnail from 'component/channelThumbnail';
|
||||
import { GetLinksData } from 'util/buildHomepage';
|
||||
import {
|
||||
SIMPLE_SITE,
|
||||
DOMAIN,
|
||||
ENABLE_UI_NOTIFICATIONS,
|
||||
ENABLE_NO_SOURCE_CLAIMS,
|
||||
CHANNEL_STAKED_LEVEL_LIVESTREAM,
|
||||
} from 'config';
|
||||
// @if TARGET='app'
|
||||
import { IS_MAC } from 'component/app/view';
|
||||
// @endif
|
||||
import { DOMAIN, ENABLE_UI_NOTIFICATIONS, ENABLE_NO_SOURCE_CLAIMS, CHANNEL_STAKED_LEVEL_LIVESTREAM } from 'config';
|
||||
|
||||
const FOLLOWED_ITEM_INITIAL_LIMIT = 10;
|
||||
|
||||
type SideNavLink = {
|
||||
title: string,
|
||||
link?: string,
|
||||
route?: string,
|
||||
onClick?: () => any,
|
||||
icon: string,
|
||||
extra?: Node,
|
||||
hideForUnauth?: boolean,
|
||||
};
|
||||
|
||||
const HOME = {
|
||||
title: 'Home',
|
||||
|
@ -37,6 +40,39 @@ const RECENT_FROM_FOLLOWING = {
|
|||
icon: ICONS.SUBSCRIBE,
|
||||
};
|
||||
|
||||
const PLAYLISTS = {
|
||||
title: 'Lists',
|
||||
link: `/$/${PAGES.LISTS}`,
|
||||
icon: ICONS.STACK,
|
||||
hideForUnauth: true,
|
||||
};
|
||||
|
||||
const UNAUTH_LINKS: Array<SideNavLink> = [
|
||||
{
|
||||
title: 'Log In',
|
||||
link: `/$/${PAGES.AUTH_SIGNIN}`,
|
||||
icon: ICONS.SIGN_IN,
|
||||
},
|
||||
{
|
||||
title: 'Sign Up',
|
||||
link: `/$/${PAGES.AUTH}`,
|
||||
icon: ICONS.SIGN_UP,
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
link: `/$/${PAGES.SETTINGS}`,
|
||||
icon: ICONS.SETTINGS,
|
||||
},
|
||||
{
|
||||
title: 'Help',
|
||||
link: `/$/${PAGES.HELP}`,
|
||||
icon: ICONS.HELP,
|
||||
},
|
||||
];
|
||||
|
||||
// ****************************************************************************
|
||||
// ****************************************************************************
|
||||
|
||||
type Props = {
|
||||
subscriptions: Array<Subscription>,
|
||||
followedTags: Array<Tag>,
|
||||
|
@ -55,16 +91,6 @@ type Props = {
|
|||
activeChannelStakedLevel: number,
|
||||
};
|
||||
|
||||
type SideNavLink = {
|
||||
title: string,
|
||||
link?: string,
|
||||
route?: string,
|
||||
onClick?: () => any,
|
||||
icon: string,
|
||||
extra?: Node,
|
||||
hideForUnauth?: boolean,
|
||||
};
|
||||
|
||||
function SideNavigation(props: Props) {
|
||||
const {
|
||||
subscriptions,
|
||||
|
@ -85,26 +111,6 @@ function SideNavigation(props: Props) {
|
|||
|
||||
const EXTRA_SIDEBAR_LINKS = GetLinksData(homepageData).map(({ pinnedUrls, ...theRest }) => theRest);
|
||||
|
||||
const FULL_LINKS: Array<SideNavLink> = [
|
||||
{
|
||||
title: 'Your Tags',
|
||||
link: `/$/${PAGES.TAGS_FOLLOWING}`,
|
||||
icon: ICONS.TAG,
|
||||
hideForUnauth: true,
|
||||
},
|
||||
{
|
||||
title: 'Discover',
|
||||
link: `/$/${PAGES.DISCOVER}`,
|
||||
icon: ICONS.DISCOVER,
|
||||
},
|
||||
{
|
||||
title: IS_WEB ? 'Purchased' : 'Library',
|
||||
link: `/$/${PAGES.LIBRARY}`,
|
||||
icon: ICONS.PURCHASED,
|
||||
hideForUnauth: true,
|
||||
},
|
||||
];
|
||||
|
||||
const MOBILE_LINKS: Array<SideNavLink> = [
|
||||
{
|
||||
title: 'Notifications',
|
||||
|
@ -181,56 +187,17 @@ function SideNavigation(props: Props) {
|
|||
},
|
||||
];
|
||||
|
||||
const UNAUTH_LINKS: Array<SideNavLink> = [
|
||||
{
|
||||
title: 'Log In',
|
||||
link: `/$/${PAGES.AUTH_SIGNIN}`,
|
||||
icon: ICONS.SIGN_IN,
|
||||
},
|
||||
{
|
||||
title: 'Sign Up',
|
||||
link: `/$/${PAGES.AUTH}`,
|
||||
icon: ICONS.SIGN_UP,
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
link: `/$/${PAGES.SETTINGS}`,
|
||||
icon: ICONS.SETTINGS,
|
||||
},
|
||||
{
|
||||
title: 'Help',
|
||||
link: `/$/${PAGES.HELP}`,
|
||||
icon: ICONS.HELP,
|
||||
},
|
||||
];
|
||||
|
||||
const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui);
|
||||
const isAuthenticated = Boolean(email);
|
||||
|
||||
// SIDE LINKS: FOLLOWING, HOME, [FULL,] [EXTRA]
|
||||
let SIDE_LINKS: Array<SideNavLink> = [];
|
||||
|
||||
SIDE_LINKS.push(HOME);
|
||||
SIDE_LINKS.push(RECENT_FROM_FOLLOWING);
|
||||
if (!SIMPLE_SITE) {
|
||||
FULL_LINKS.push({
|
||||
title: 'Lists',
|
||||
link: `/$/${PAGES.LISTS}`,
|
||||
icon: ICONS.STACK,
|
||||
hideForUnauth: true,
|
||||
});
|
||||
}
|
||||
if (!SIMPLE_SITE) {
|
||||
SIDE_LINKS.push(...FULL_LINKS);
|
||||
} else if (SIMPLE_SITE) {
|
||||
SIDE_LINKS.push({
|
||||
title: 'Lists',
|
||||
link: `/$/${PAGES.LISTS}`,
|
||||
icon: ICONS.STACK,
|
||||
hideForUnauth: true,
|
||||
});
|
||||
}
|
||||
SIDE_LINKS.push(PLAYLISTS);
|
||||
|
||||
if (SIMPLE_SITE && EXTRA_SIDEBAR_LINKS) {
|
||||
if (EXTRA_SIDEBAR_LINKS) {
|
||||
// $FlowFixMe
|
||||
SIDE_LINKS.push(...EXTRA_SIDEBAR_LINKS);
|
||||
|
||||
|
@ -251,6 +218,9 @@ function SideNavigation(props: Props) {
|
|||
);
|
||||
|
||||
const [pulseLibrary, setPulseLibrary] = React.useState(false);
|
||||
const [expandSubscriptions, setExpandSubscriptions] = React.useState(false);
|
||||
const [expandTags, setExpandTags] = React.useState(false);
|
||||
|
||||
const isPersonalized = !IS_WEB || isAuthenticated;
|
||||
const isAbsolute = isOnFilePage || isMediumScreen;
|
||||
const microNavigation = !sidebarOpen || isMediumScreen;
|
||||
|
@ -264,6 +234,65 @@ function SideNavigation(props: Props) {
|
|||
})
|
||||
: UNAUTH_LINKS;
|
||||
|
||||
const showSubscriptionSection = sidebarOpen && isPersonalized && subscriptions && subscriptions.length > 0;
|
||||
const showTagSection = sidebarOpen && isPersonalized && followedTags && followedTags.length;
|
||||
|
||||
let displayedSubscriptions = subscriptions;
|
||||
if (showSubscriptionSection && subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT && !expandSubscriptions) {
|
||||
displayedSubscriptions = subscriptions.slice(0, FOLLOWED_ITEM_INITIAL_LIMIT);
|
||||
}
|
||||
|
||||
let displayedFollowedTags = followedTags;
|
||||
if (showTagSection && followedTags.length > FOLLOWED_ITEM_INITIAL_LIMIT && !expandTags) {
|
||||
displayedFollowedTags = followedTags.slice(0, FOLLOWED_ITEM_INITIAL_LIMIT);
|
||||
}
|
||||
|
||||
function getSubscriptionSection() {
|
||||
if (showSubscriptionSection) {
|
||||
return (
|
||||
<>
|
||||
<ul className="navigation__secondary navigation-links">
|
||||
{displayedSubscriptions.map((subscription) => (
|
||||
<SubscriptionListItem key={subscription.uri} subscription={subscription} />
|
||||
))}
|
||||
</ul>
|
||||
{subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT && (
|
||||
<Button
|
||||
label={expandSubscriptions ? __('Show less') : __('Show more')}
|
||||
className="navigation-link"
|
||||
onClick={() => setExpandSubscriptions(!expandSubscriptions)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getFollowedTagsSection() {
|
||||
if (showTagSection) {
|
||||
return (
|
||||
<>
|
||||
<ul className="navigation__secondary navigation-links navigation-links--small">
|
||||
{displayedFollowedTags.map(({ name }, key) => (
|
||||
<li key={name} className="navigation-link__wrapper">
|
||||
<Button navigate={`/$/discover?t=${name}`} label={`#${name}`} className="navigation-link" />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{followedTags.length > FOLLOWED_ITEM_INITIAL_LIMIT && (
|
||||
<Button
|
||||
label={expandTags ? __('Show less') : __('Show more')}
|
||||
className="navigation-link"
|
||||
onClick={() => setExpandTags(!expandTags)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (purchaseSuccess) {
|
||||
setPulseLibrary(true);
|
||||
|
@ -316,11 +345,9 @@ function SideNavigation(props: Props) {
|
|||
<li className="navigation-link">
|
||||
<Button label={__('FAQ and Support')} href="https://odysee.com/@OdyseeHelp:b" />
|
||||
</li>
|
||||
{SIMPLE_SITE && ( // GUIDELINES_URL?
|
||||
<li className="navigation-link">
|
||||
<Button label={__('Community Guidelines')} href="https://odysee.com/@OdyseeHelp:b/Community-Guidelines:c" />
|
||||
</li>
|
||||
)}
|
||||
<li className="navigation-link">
|
||||
<Button label={__('Community Guidelines')} href="https://odysee.com/@OdyseeHelp:b/Community-Guidelines:c" />
|
||||
</li>
|
||||
<li className="navigation-link">
|
||||
<Button label={__('Terms')} href="https://odysee.com/$/tos" />
|
||||
</li>
|
||||
|
@ -342,9 +369,6 @@ function SideNavigation(props: Props) {
|
|||
aria-label={'Sidebar'}
|
||||
className={classnames('navigation', {
|
||||
'navigation--micro': microNavigation,
|
||||
// @if TARGET='app'
|
||||
'navigation--mac': IS_MAC,
|
||||
// @endif
|
||||
})}
|
||||
>
|
||||
<div>
|
||||
|
@ -372,40 +396,18 @@ function SideNavigation(props: Props) {
|
|||
);
|
||||
})}
|
||||
</ul>
|
||||
|
||||
{sidebarOpen && isPersonalized && subscriptions && subscriptions.length > 0 && (
|
||||
<ul className="navigation__secondary navigation-links">
|
||||
{subscriptions.map((subscription) => (
|
||||
<SubscriptionListItem key={subscription.uri} subscription={subscription} />
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{sidebarOpen && isPersonalized && followedTags && followedTags.length > 0 && (
|
||||
<ul className="navigation__secondary navigation-links navigation-links--small">
|
||||
{followedTags.map(({ name }, key) => (
|
||||
<li key={name} className="navigation-link__wrapper">
|
||||
<Button navigate={`/$/discover?t=${name}`} label={`#${name}`} className="navigation-link" />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
{getSubscriptionSection()}
|
||||
{getFollowedTagsSection()}
|
||||
{!isAuthenticated && sidebarOpen && unAuthNudge}
|
||||
</div>
|
||||
|
||||
{SIMPLE_SITE && sidebarOpen && helpLinks}
|
||||
{sidebarOpen && helpLinks}
|
||||
</nav>
|
||||
)}
|
||||
|
||||
{(isOnFilePage || isMediumScreen) && sidebarOpen && (
|
||||
<>
|
||||
<nav
|
||||
className={classnames('navigation--absolute', {
|
||||
// @if TARGET='app'
|
||||
'navigation--mac': IS_MAC,
|
||||
// @endif
|
||||
})}
|
||||
>
|
||||
<nav className="navigation--absolute">
|
||||
<div>
|
||||
<ul className="navigation-links--absolute mobile-only">
|
||||
{email && livestreamEnabled && (
|
||||
|
@ -463,34 +465,13 @@ function SideNavigation(props: Props) {
|
|||
);
|
||||
})}
|
||||
</ul>
|
||||
{sidebarOpen && isPersonalized && subscriptions && subscriptions.length > 0 && (
|
||||
<ul className="navigation__secondary navigation-links">
|
||||
{subscriptions.map((subscription) => (
|
||||
<SubscriptionListItem key={subscription.uri} subscription={subscription} />
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{sidebarOpen && isPersonalized && followedTags && followedTags.length > 0 && (
|
||||
<ul className="navigation__secondary navigation-links navigation-links--small">
|
||||
{followedTags.map(({ name }, key) => (
|
||||
<li key={name} className="navigation-link__wrapper">
|
||||
<Button navigate={`/$/discover?t=${name}`} label={`#${name}`} className="navigation-link" />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{getSubscriptionSection()}
|
||||
{getFollowedTagsSection()}
|
||||
{!isAuthenticated && unAuthNudge}
|
||||
{SIMPLE_SITE && helpLinks}
|
||||
{helpLinks}
|
||||
</div>
|
||||
</nav>
|
||||
<div
|
||||
className={classnames('navigation__overlay', {
|
||||
// @if TARGET='app'
|
||||
'navigation__overlay--mac': IS_MAC,
|
||||
// @endif
|
||||
})}
|
||||
onClick={() => setSidebarOpen(false)}
|
||||
/>
|
||||
<div className="navigation__overlay" onClick={() => setSidebarOpen(false)} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectClaimForUri, makeSelectThumbnailForUri } from 'redux/selectors/claims';
|
||||
import { makeSelectClaimForUri, selectThumbnailForUri } from 'redux/selectors/claims';
|
||||
import {
|
||||
makeSelectNextUrlForCollectionAndUrl,
|
||||
makeSelectPreviousUrlForCollectionAndUrl,
|
||||
|
@ -61,7 +61,7 @@ const select = (state, props) => {
|
|||
volume: selectVolume(state),
|
||||
muted: selectMute(state),
|
||||
videoPlaybackRate: makeSelectClientSetting(SETTINGS.VIDEO_PLAYBACK_RATE)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(uri)(state),
|
||||
thumbnail: selectThumbnailForUri(state, uri),
|
||||
claim: makeSelectClaimForUri(uri)(state),
|
||||
homepageData: selectHomepageData(state),
|
||||
authenticated: selectUserVerifiedEmail(state),
|
||||
|
|
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
|||
import {
|
||||
selectClaimIsMine,
|
||||
makeSelectTitleForUri,
|
||||
makeSelectThumbnailForUri,
|
||||
getThumbnailFromClaim,
|
||||
makeSelectCoverForUri,
|
||||
selectCurrentChannelPage,
|
||||
selectClaimForUri,
|
||||
|
@ -22,7 +22,7 @@ const select = (state, props) => {
|
|||
|
||||
return {
|
||||
title: makeSelectTitleForUri(props.uri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(props.uri)(state),
|
||||
thumbnail: getThumbnailFromClaim(claim),
|
||||
cover: makeSelectCoverForUri(props.uri)(state),
|
||||
channelIsMine: selectClaimIsMine(state, claim),
|
||||
page: selectCurrentChannelPage(state),
|
||||
|
|
|
@ -4,7 +4,7 @@ import { withRouter } from 'react-router-dom';
|
|||
import CollectionPage from './view';
|
||||
import {
|
||||
makeSelectTitleForUri,
|
||||
makeSelectThumbnailForUri,
|
||||
getThumbnailFromClaim,
|
||||
selectClaimIsMine,
|
||||
makeSelectClaimIsPending,
|
||||
makeSelectClaimForClaimId,
|
||||
|
@ -39,7 +39,7 @@ const select = (state, props) => {
|
|||
collectionCount: makeSelectCountForCollectionId(collectionId)(state),
|
||||
isResolvingCollection: makeSelectIsResolvingCollectionForId(collectionId)(state),
|
||||
title: makeSelectTitleForUri(uri)(state),
|
||||
thumbnail: makeSelectThumbnailForUri(uri)(state),
|
||||
thumbnail: getThumbnailFromClaim(claim),
|
||||
isMyClaim: selectClaimIsMine(state, claim), // or collection is mine?
|
||||
isMyCollection: makeSelectCollectionIsMine(collectionId)(state),
|
||||
claimIsPending: makeSelectClaimIsPending(uri)(state),
|
||||
|
|
|
@ -388,11 +388,14 @@ export const makeSelectContentTypeForUri = (uri: string) =>
|
|||
return source ? source.media_type : undefined;
|
||||
});
|
||||
|
||||
export const makeSelectThumbnailForUri = (uri: string) =>
|
||||
createSelector(makeSelectClaimForUri(uri), (claim) => {
|
||||
const thumbnail = claim && claim.value && claim.value.thumbnail;
|
||||
return thumbnail && thumbnail.url ? thumbnail.url.trim().replace(/^http:\/\//i, 'https://') : undefined;
|
||||
});
|
||||
export const getThumbnailFromClaim = (claim: Claim) => {
|
||||
const thumbnail = claim && claim.value && claim.value.thumbnail;
|
||||
return thumbnail && thumbnail.url ? thumbnail.url.trim().replace(/^http:\/\//i, 'https://') : undefined;
|
||||
};
|
||||
|
||||
export const selectThumbnailForUri = createCachedSelector(selectClaimForUri, (claim) => {
|
||||
return getThumbnailFromClaim(claim);
|
||||
})((state, uri) => String(uri));
|
||||
|
||||
export const makeSelectCoverForUri = (uri: string) =>
|
||||
createSelector(makeSelectClaimForUri(uri), (claim) => {
|
||||
|
|
|
@ -147,6 +147,32 @@ export function GetLinksData(
|
|||
let rowData: Array<RowDataItem> = [];
|
||||
const individualTagDataItems: Array<RowDataItem> = [];
|
||||
|
||||
if (isHomepage && showPersonalizedChannels && subscribedChannels) {
|
||||
const RECENT_FROM_FOLLOWING = {
|
||||
title: __('Recent From Following'),
|
||||
link: `/$/${PAGES.CHANNELS_FOLLOWING}`,
|
||||
icon: ICONS.SUBSCRIBE,
|
||||
options: {
|
||||
orderBy: CS.ORDER_BY_NEW_VALUE,
|
||||
releaseTime:
|
||||
subscribedChannels.length > 20
|
||||
? `>${Math.floor(moment().subtract(9, 'months').startOf('week').unix())}`
|
||||
: `>${Math.floor(moment().subtract(1, 'year').startOf('week').unix())}`,
|
||||
pageSize: getPageSize(subscribedChannels.length > 3 ? (subscribedChannels.length > 6 ? 16 : 8) : 4),
|
||||
streamTypes: null,
|
||||
channelIds: subscribedChannels.map((subscription: Subscription) => {
|
||||
const { channelClaimId } = parseURI(subscription.uri);
|
||||
if (channelClaimId) return channelClaimId;
|
||||
}),
|
||||
},
|
||||
};
|
||||
// $FlowFixMe flow thinks this might not be Array<string>
|
||||
rowData.push(RECENT_FROM_FOLLOWING);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// @if CUSTOM_HOMEPAGE='false'
|
||||
|
||||
const YOUTUBER_CHANNEL_IDS = [
|
||||
'fb364ef587872515f545a5b4b3182b58073f230f',
|
||||
'589276465a23c589801d874f484cc39f307d7ec7',
|
||||
|
@ -277,28 +303,6 @@ export function GetLinksData(
|
|||
},
|
||||
};
|
||||
|
||||
if (isHomepage && showPersonalizedChannels && subscribedChannels) {
|
||||
const RECENT_FROM_FOLLOWING = {
|
||||
title: __('Recent From Following'),
|
||||
link: `/$/${PAGES.CHANNELS_FOLLOWING}`,
|
||||
icon: ICONS.SUBSCRIBE,
|
||||
options: {
|
||||
orderBy: CS.ORDER_BY_NEW_VALUE,
|
||||
releaseTime:
|
||||
subscribedChannels.length > 20
|
||||
? `>${Math.floor(moment().subtract(9, 'months').startOf('week').unix())}`
|
||||
: `>${Math.floor(moment().subtract(1, 'year').startOf('week').unix())}`,
|
||||
pageSize: getPageSize(subscribedChannels.length > 3 ? (subscribedChannels.length > 6 ? 16 : 8) : 4),
|
||||
streamTypes: null,
|
||||
channelIds: subscribedChannels.map((subscription: Subscription) => {
|
||||
const { channelClaimId } = parseURI(subscription.uri);
|
||||
if (channelClaimId) return channelClaimId;
|
||||
}),
|
||||
},
|
||||
};
|
||||
// $FlowFixMe flow thinks this might not be Array<string>
|
||||
rowData.push(RECENT_FROM_FOLLOWING);
|
||||
}
|
||||
if (isHomepage && !CUSTOM_HOMEPAGE) {
|
||||
if (followedTags) {
|
||||
const TRENDING_FOR_TAGS = {
|
||||
|
@ -333,6 +337,7 @@ export function GetLinksData(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!CUSTOM_HOMEPAGE) {
|
||||
if (!authenticated) {
|
||||
rowData.push(YOUTUBE_CREATOR_ROW);
|
||||
|
@ -341,6 +346,10 @@ export function GetLinksData(
|
|||
rowData.push(LATEST_FROM_LBRY);
|
||||
if (!showPersonalizedChannels) rowData.push(TOP_CHANNELS);
|
||||
}
|
||||
|
||||
// @endif
|
||||
// **************************************************************************
|
||||
|
||||
// TODO: provide better method for exempting from homepage
|
||||
(Object.values(all): any)
|
||||
.filter((row) => !(isHomepage && row.name === 'news'))
|
||||
|
|
Loading…
Reference in a new issue