memoize each module individually (#8111)
This commit is contained in:
+228
-232
@@ -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 />
|
||||||
|
|||||||
Reference in New Issue
Block a user