memoize each module individually (#8111)

This commit is contained in:
Samuel Newman
2025-04-04 00:02:20 +03:00
committed by GitHub
parent faa5f40c53
commit 898065d0a2
+228 -232
View File
@@ -325,272 +325,268 @@ export function Explore({
fetchNextPageFeedPreviews, fetchNextPageFeedPreviews,
]) ])
const items = useMemo<ExploreScreenItems[]>(() => { const topBorder = useMemo(
() => ({type: 'topBorder', key: 'top-border'} as const),
[],
)
const trendingTopicsModule = useMemo(
() => ({type: 'trendingTopics', key: 'trending-topics'} as const),
[],
)
const suggestedFollowsModule = useMemo(() => {
const i: ExploreScreenItems[] = [] const i: ExploreScreenItems[] = []
i.push({
type: 'tabbedHeader',
key: 'suggested-accounts-header',
title: _(msg`Suggested Accounts`),
icon: Person,
searchButton: {
label: _(msg`Search for more accounts`),
metricsTag: 'suggestedAccounts',
tab: 'user',
},
})
const addTopBorder = () => { if (!canShowSuggestedProfiles) {
i.push({type: 'topBorder', key: 'top-border'}) i.push({type: 'profilePlaceholder', key: 'profilePlaceholder'})
} } else if (profilesError) {
const addTrendingTopicsModule = () => {
i.push({ i.push({
type: 'trendingTopics', type: 'error',
key: `trending-topics`, key: 'profilesError',
message: _(msg`Failed to load suggested follows`),
error: cleanError(profilesError),
}) })
} else {
// temp - disable trending videos if (profiles !== undefined) {
// if (isNative) { if (profiles.pages.length > 0 && moderationOpts) {
// i.push({ // Currently the responses contain duplicate items.
// type: 'trendingVideos', // Needs to be fixed on backend, but let's dedupe to be safe.
// key: `trending-videos`, let seen = new Set()
// }) const profileItems: ExploreScreenItems[] = []
// } for (const page of profiles.pages) {
} for (const actor of page.actors) {
if (!seen.has(actor.did) && !actor.viewer?.following) {
const addSuggestedFollowsModule = () => { seen.add(actor.did)
i.push({ profileItems.push({
type: 'tabbedHeader', type: 'profile',
key: 'suggested-accounts-header', key: actor.did,
title: _(msg`Suggested Accounts`), profile: actor,
icon: Person, recId: page.recId,
searchButton: { })
label: _(msg`Search for more accounts`),
metricsTag: 'suggestedAccounts',
tab: 'user',
},
})
if (!canShowSuggestedProfiles) {
i.push({type: 'profilePlaceholder', key: 'profilePlaceholder'})
} else if (profilesError) {
i.push({
type: 'error',
key: 'profilesError',
message: _(msg`Failed to load suggested follows`),
error: cleanError(profilesError),
})
} else {
if (profiles !== undefined) {
if (profiles.pages.length > 0 && moderationOpts) {
// Currently the responses contain duplicate items.
// Needs to be fixed on backend, but let's dedupe to be safe.
let seen = new Set()
const profileItems: ExploreScreenItems[] = []
for (const page of profiles.pages) {
for (const actor of page.actors) {
if (!seen.has(actor.did) && !actor.viewer?.following) {
seen.add(actor.did)
profileItems.push({
type: 'profile',
key: actor.did,
profile: actor,
recId: page.recId,
})
}
} }
} }
if (profileItems.length === 0) {
if (!hasNextProfilesPage) {
// no items! remove the header
i.pop()
}
} else {
i.push(...profileItems)
}
if (hasNextProfilesPage) {
i.push({
type: 'loadMore',
key: 'loadMoreProfiles',
message: _(msg`Load more suggested accounts`),
isLoadingMore: isLoadingMoreProfiles,
onLoadMore: onLoadMoreProfiles,
})
}
} else {
console.log('no pages')
} }
} else {
i.push({type: 'profilePlaceholder', key: 'profilePlaceholder'})
}
}
}
const addSuggestedFeedsModule = () => { if (profileItems.length === 0) {
i.push({ if (!hasNextProfilesPage) {
type: 'header', // no items! remove the header
key: 'suggested-feeds-header',
title: _(msg`Discover Feeds`),
icon: ListSparkle,
searchButton: {
label: _(msg`Search for more feeds`),
metricsTag: 'suggestedFeeds',
tab: 'feed',
},
})
if (feeds && preferences) {
// Currently the responses contain duplicate items.
// Needs to be fixed on backend, but let's dedupe to be safe.
let seen = new Set()
const feedItems: ExploreScreenItems[] = []
for (const page of feeds.pages) {
for (const feed of page.feeds) {
if (!seen.has(feed.uri)) {
seen.add(feed.uri)
feedItems.push({
type: 'feed',
key: feed.uri,
feed,
})
}
}
}
// feeds errors can occur during pagination, so feeds is truthy
if (feedsError) {
i.push({
type: 'error',
key: 'feedsError',
message: _(msg`Failed to load suggested feeds`),
error: cleanError(feedsError),
})
} else if (preferencesError) {
i.push({
type: 'error',
key: 'preferencesError',
message: _(msg`Failed to load feeds preferences`),
error: cleanError(preferencesError),
})
} else {
if (feedItems.length === 0) {
if (!hasNextFeedsPage) {
i.pop() i.pop()
} }
} else { } else {
// This query doesn't follow the limit very well, so the first press of the i.push(...profileItems)
// load more button just unslices the array back to ~10 items
if (!hasPressedLoadMoreFeeds) {
i.push(...feedItems.slice(0, 3))
} else {
i.push(...feedItems)
}
} }
if (hasNextFeedsPage) { if (hasNextProfilesPage) {
i.push({ i.push({
type: 'loadMore', type: 'loadMore',
key: 'loadMoreFeeds', key: 'loadMoreProfiles',
message: _(msg`Load more suggested feeds`), message: _(msg`Load more suggested accounts`),
isLoadingMore: isLoadingMoreFeeds, isLoadingMore: isLoadingMoreProfiles,
onLoadMore: onLoadMoreFeeds, onLoadMore: onLoadMoreProfiles,
})
}
} else {
console.log('no pages')
}
} else {
i.push({type: 'profilePlaceholder', key: 'profilePlaceholder'})
}
}
return i
}, [
profiles,
_,
canShowSuggestedProfiles,
hasNextProfilesPage,
isLoadingMoreProfiles,
moderationOpts,
onLoadMoreProfiles,
profilesError,
])
const suggestedFeedsModule = useMemo(() => {
const i: ExploreScreenItems[] = []
i.push({
type: 'header',
key: 'suggested-feeds-header',
title: _(msg`Discover Feeds`),
icon: ListSparkle,
searchButton: {
label: _(msg`Search for more feeds`),
metricsTag: 'suggestedFeeds',
tab: 'feed',
},
})
if (feeds && preferences) {
// Currently the responses contain duplicate items.
// Needs to be fixed on backend, but let's dedupe to be safe.
let seen = new Set()
const feedItems: ExploreScreenItems[] = []
for (const page of feeds.pages) {
for (const feed of page.feeds) {
if (!seen.has(feed.uri)) {
seen.add(feed.uri)
feedItems.push({
type: 'feed',
key: feed.uri,
feed,
}) })
} }
} }
}
// feeds errors can occur during pagination, so feeds is truthy
if (feedsError) {
i.push({
type: 'error',
key: 'feedsError',
message: _(msg`Failed to load suggested feeds`),
error: cleanError(feedsError),
})
} else if (preferencesError) {
i.push({
type: 'error',
key: 'preferencesError',
message: _(msg`Failed to load feeds preferences`),
error: cleanError(preferencesError),
})
} else { } else {
if (feedsError) { if (feedItems.length === 0) {
i.push({ if (!hasNextFeedsPage) {
type: 'error', i.pop()
key: 'feedsError', }
message: _(msg`Failed to load suggested feeds`),
error: cleanError(feedsError),
})
} else if (preferencesError) {
i.push({
type: 'error',
key: 'preferencesError',
message: _(msg`Failed to load feeds preferences`),
error: cleanError(preferencesError),
})
} else { } else {
i.push({type: 'feedPlaceholder', key: 'feedPlaceholder'}) // This query doesn't follow the limit very well, so the first press of the
// load more button just unslices the array back to ~10 items
if (!hasPressedLoadMoreFeeds) {
i.push(...feedItems.slice(0, 3))
} else {
i.push(...feedItems)
}
}
if (hasNextFeedsPage) {
i.push({
type: 'loadMore',
key: 'loadMoreFeeds',
message: _(msg`Load more suggested feeds`),
isLoadingMore: isLoadingMoreFeeds,
onLoadMore: onLoadMoreFeeds,
})
} }
} }
} } else {
if (feedsError) {
const addSuggestedStarterPacksModule = () => {
i.push({
type: 'header',
key: 'suggested-starterPacks-header',
title: _(msg`Starter Packs`),
icon: StarterPack,
})
if (isLoadingSuggestedSPs) {
Array.from({length: 3}).forEach((_, index) =>
i.push({
type: 'starterPackSkeleton',
key: `starterPackSkeleton-${index}`,
}),
)
} else if (suggestedSPsError || !suggestedSPs) {
// just get rid of the section
i.pop()
} else {
suggestedSPs.starterPacks.map(s => {
i.push({
type: 'starterPack',
key: s.uri,
view: s,
})
})
}
}
const addFeedPreviews = () => {
i.push(...feedPreviewSlices)
if (isFetchingNextPageFeedPreviews) {
i.push({ i.push({
type: 'preview:loading', type: 'error',
key: 'preview-loading-more', key: 'feedsError',
message: _(msg`Failed to load suggested feeds`),
error: cleanError(feedsError),
}) })
} else if (preferencesError) {
i.push({
type: 'error',
key: 'preferencesError',
message: _(msg`Failed to load feeds preferences`),
error: cleanError(preferencesError),
})
} else {
i.push({type: 'feedPlaceholder', key: 'feedPlaceholder'})
} }
} }
return i
}, [
feeds,
_,
feedsError,
hasNextFeedsPage,
hasPressedLoadMoreFeeds,
isLoadingMoreFeeds,
onLoadMoreFeeds,
preferences,
preferencesError,
])
const suggestedStarterPacksModule = useMemo(() => {
const i: ExploreScreenItems[] = []
i.push({
type: 'header',
key: 'suggested-starterPacks-header',
title: _(msg`Starter Packs`),
icon: StarterPack,
})
if (isLoadingSuggestedSPs) {
Array.from({length: 3}).forEach((__, index) =>
i.push({
type: 'starterPackSkeleton',
key: `starterPackSkeleton-${index}`,
}),
)
} else if (suggestedSPsError || !suggestedSPs) {
// just get rid of the section
i.pop()
} else {
suggestedSPs.starterPacks.map(s => {
i.push({
type: 'starterPack',
key: s.uri,
view: s,
})
})
}
return i
}, [suggestedSPs, _, isLoadingSuggestedSPs, suggestedSPsError])
const feedPreviewsModule = useMemo(() => {
const i: ExploreScreenItems[] = []
i.push(...feedPreviewSlices)
if (isFetchingNextPageFeedPreviews) {
i.push({
type: 'preview:loading',
key: 'preview-loading-more',
})
}
return i
}, [feedPreviewSlices, isFetchingNextPageFeedPreviews])
const isNewUser = guide?.guide === 'follow-10' && !guide.isComplete
const items = useMemo<ExploreScreenItems[]>(() => {
const i: ExploreScreenItems[] = []
// Dynamic module ordering // Dynamic module ordering
addTopBorder() i.push(topBorder)
if (isNewUser) {
if (guide?.guide === 'follow-10' && !guide.isComplete) { i.push(...suggestedFollowsModule)
addSuggestedFollowsModule() i.push(...suggestedStarterPacksModule)
addSuggestedStarterPacksModule() i.push(trendingTopicsModule)
addTrendingTopicsModule()
} else { } else {
addTrendingTopicsModule() i.push(trendingTopicsModule)
addSuggestedFollowsModule() i.push(...suggestedFollowsModule)
addSuggestedStarterPacksModule() i.push(...suggestedStarterPacksModule)
} }
if (gate('explore_show_suggested_feeds')) { if (gate('explore_show_suggested_feeds')) {
addSuggestedFeedsModule() i.push(...suggestedFeedsModule)
} }
i.push(...feedPreviewsModule)
addFeedPreviews()
return i return i
}, [ }, [
_, topBorder,
profiles, isNewUser,
feeds, suggestedFollowsModule,
preferences, suggestedStarterPacksModule,
onLoadMoreFeeds, suggestedFeedsModule,
onLoadMoreProfiles, trendingTopicsModule,
isLoadingMoreProfiles, feedPreviewsModule,
isLoadingMoreFeeds,
profilesError,
feedsError,
preferencesError,
hasNextProfilesPage,
hasNextFeedsPage,
guide,
gate, gate,
moderationOpts,
hasPressedLoadMoreFeeds,
suggestedSPs,
isLoadingSuggestedSPs,
suggestedSPsError,
feedPreviewSlices,
isFetchingNextPageFeedPreviews,
canShowSuggestedProfiles,
]) ])
const renderItem = useCallback( const renderItem = useCallback(
@@ -709,7 +705,7 @@ export function Explore({
case 'profilePlaceholder': { case 'profilePlaceholder': {
return ( return (
<> <>
{Array.from({length: 3}).map((_, index) => ( {Array.from({length: 3}).map((__, i) => (
<View <View
style={[ style={[
a.px_lg, a.px_lg,
@@ -717,7 +713,7 @@ export function Explore({
a.border_t, a.border_t,
t.atoms.border_contrast_low, t.atoms.border_contrast_low,
]} ]}
key={index}> key={i}>
<ProfileCard.Outer> <ProfileCard.Outer>
<ProfileCard.Header> <ProfileCard.Header>
<ProfileCard.AvatarPlaceholder /> <ProfileCard.AvatarPlaceholder />