Fix sidebar subs inefficiencies

- `filteredSubscriptions` was running the filter code whether or not it actually required filtering, because the `!subscriptionFilter` logic is placed in the predicate. While it is a clean one-liner, it is slow when the subs list is huge.
    - While at it, moved the code into `getSubscriptionSection` to isolate things.

- The sidebar was resolving the entire subs list, which is super slow for a list of 500+. Since we now have a "Manage Subscriptions" page, just batch-resolve the N visible subs.
    - TODO: the code should probably be moved from 'app' to 'sideNavigate'.
This commit is contained in:
infinite-persistence 2022-03-01 16:14:38 +08:00 committed by Thomas Zarebczan
parent 3edb00b99d
commit 6c76cff2a0
3 changed files with 20 additions and 17 deletions

View file

@ -23,6 +23,7 @@ import usePersistedState from 'effects/use-persisted-state';
import useConnectionStatus from 'effects/use-connection-status';
import Spinner from 'component/spinner';
import LANGUAGES from 'constants/languages';
import { SIDEBAR_SUBS_DISPLAYED } from 'constants/subscriptions';
import YoutubeWelcome from 'web/component/youtubeReferralWelcome';
import {
useDegradedPerformance,
@ -477,7 +478,7 @@ function App(props: Props) {
useLayoutEffect(() => {
if (sidebarOpen && isPersonalized && subscriptions && !resolvedSubscriptions) {
setResolvedSubscriptions(true);
resolveUris(subscriptions.map((sub) => sub.uri));
resolveUris(subscriptions.slice(0, SIDEBAR_SUBS_DISPLAYED).map((sub) => sub.uri));
}
}, [sidebarOpen, isPersonalized, resolvedSubscriptions, subscriptions, resolveUris, setResolvedSubscriptions]);

View file

@ -3,6 +3,7 @@ import type { Node } from 'react';
import * as PAGES from 'constants/pages';
import * as ICONS from 'constants/icons';
import * as KEYCODES from 'constants/keycodes';
import { SIDEBAR_SUBS_DISPLAYED } from 'constants/subscriptions';
import React, { useEffect } from 'react';
import Button from 'component/button';
import ClaimPreviewTitle from 'component/claimPreviewTitle';
@ -16,7 +17,6 @@ import { useIsMobile, useIsLargeScreen, isTouch } from 'effects/use-screensize';
import { GetLinksData } from 'util/buildHomepage';
import { DOMAIN, ENABLE_UI_NOTIFICATIONS, ENABLE_NO_SOURCE_CLAIMS, CHANNEL_STAKED_LEVEL_LIVESTREAM } from 'config';
const FOLLOWED_ITEM_INITIAL_LIMIT = 10;
const touch = isTouch();
type SideNavLink = {
@ -265,23 +265,13 @@ function SideNavigation(props: Props) {
const showPushMenu = sidebarOpen && !menuCanCloseCompletely;
const showOverlay = isAbsolute && sidebarOpen;
const showSubscriptionSection = shouldRenderLargeMenu && isPersonalized && subscriptions && subscriptions.length > 0;
const showTagSection = sidebarOpen && isPersonalized && followedTags && followedTags.length;
const [subscriptionFilter, setSubscriptionFilter] = React.useState('');
const filteredSubscriptions = subscriptions.filter(
(sub) => !subscriptionFilter || sub.channelName.toLowerCase().includes(subscriptionFilter.toLowerCase())
);
let displayedSubscriptions = filteredSubscriptions;
if (showSubscriptionSection && !subscriptionFilter && subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT) {
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);
if (showTagSection && followedTags.length > SIDEBAR_SUBS_DISPLAYED && !expandTags) {
displayedFollowedTags = followedTags.slice(0, SIDEBAR_SUBS_DISPLAYED);
}
function getLink(props: SideNavLink) {
@ -312,11 +302,20 @@ function SideNavigation(props: Props) {
}
function getSubscriptionSection() {
if (showSubscriptionSection) {
const showSubsSection = shouldRenderLargeMenu && isPersonalized && subscriptions && subscriptions.length > 0;
if (showSubsSection) {
let displayedSubscriptions;
if (subscriptionFilter) {
const filter = subscriptionFilter.toLowerCase();
displayedSubscriptions = subscriptions.filter((sub) => sub.channelName.toLowerCase().includes(filter));
} else {
displayedSubscriptions = subscriptions.slice(0, SIDEBAR_SUBS_DISPLAYED);
}
return (
<>
<ul className="navigation__secondary navigation-links">
{subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT && (
{subscriptions.length > SIDEBAR_SUBS_DISPLAYED && (
<li className="navigation-item">
<DebouncedInput icon={ICONS.SEARCH} placeholder={__('Filter')} onChange={setSubscriptionFilter} />
</li>
@ -356,7 +355,7 @@ function SideNavigation(props: Props) {
<Button navigate={`/$/discover?t=${name}`} label={`#${name}`} className="navigation-link" />
</li>
))}
{followedTags.length > FOLLOWED_ITEM_INITIAL_LIMIT && (
{followedTags.length > SIDEBAR_SUBS_DISPLAYED && (
<Button
key="showMore"
label={expandTags ? __('Show less') : __('Show more')}

View file

@ -10,3 +10,6 @@ export const NOTIFY_ONLY = 'NOTIFY_ONLY;';
export const SUGGESTED_TOP_BID = 'top_bid';
export const SUGGESTED_TOP_SUBSCRIBED = 'top_subscribed';
export const SUGGESTED_FEATURED = 'featured';
// Sidebar UI
export const SIDEBAR_SUBS_DISPLAYED = 10;