Fix missing header on Likes/Reposted By, add missing perf optimizations (#4867)

* fix liked by list

* fix lists

* tweaks to style

* change string
zio/stable
Hailey 2024-08-01 10:32:36 -07:00 committed by GitHub
parent c78e9e3147
commit f056cb646e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 131 additions and 129 deletions

View File

@ -1,38 +1,57 @@
import React, {useCallback, useMemo, useState} from 'react'
import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api'
import {CenteredView} from '../util/Views'
import {List} from '../util/List'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
import {logger} from '#/logger'
import {LoadingScreen} from '../util/LoadingScreen'
import {useResolveUriQuery} from '#/state/queries/resolve-uri'
import {useLikedByQuery} from '#/state/queries/post-liked-by'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {cleanError} from '#/lib/strings/errors'
import {logger} from '#/logger'
import {useLikedByQuery} from '#/state/queries/post-liked-by'
import {useResolveUriQuery} from '#/state/queries/resolve-uri'
import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender'
import {
ListFooter,
ListHeaderDesktop,
ListMaybePlaceholder,
} from '#/components/Lists'
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
import {List} from '../util/List'
function renderItem({item}: {item: GetLikes.Like}) {
return <ProfileCardWithFollowBtn key={item.actor.did} profile={item.actor} />
}
function keyExtractor(item: GetLikes.Like) {
return item.actor.did
}
export function PostLikedBy({uri}: {uri: string}) {
const {_} = useLingui()
const initialNumToRender = useInitialNumToRender()
const [isPTRing, setIsPTRing] = useState(false)
const {
data: resolvedUri,
error: resolveError,
isFetching: isFetchingResolvedUri,
isLoading: isLoadingUri,
} = useResolveUriQuery(uri)
const {
data,
isFetching,
isFetched,
isLoading: isLoadingLikes,
isFetchingNextPage,
hasNextPage,
fetchNextPage,
isError,
error,
refetch,
} = useLikedByQuery(resolvedUri?.uri)
const isError = Boolean(resolveError || error)
const likes = useMemo(() => {
if (data?.pages) {
return data.pages.flatMap(page => page.likes)
}
return []
}, [data])
const onRefresh = useCallback(async () => {
@ -46,64 +65,44 @@ export function PostLikedBy({uri}: {uri: string}) {
}, [refetch, setIsPTRing])
const onEndReached = useCallback(async () => {
if (isFetching || !hasNextPage || isError) return
if (isFetchingNextPage || !hasNextPage || isError) return
try {
await fetchNextPage()
} catch (err) {
logger.error('Failed to load more likes', {message: err})
}
}, [isFetching, hasNextPage, isError, fetchNextPage])
}, [isFetchingNextPage, hasNextPage, isError, fetchNextPage])
const renderItem = useCallback(({item}: {item: GetLikes.Like}) => {
if (likes.length < 1) {
return (
<ProfileCardWithFollowBtn key={item.actor.did} profile={item.actor} />
)
}, [])
if (isFetchingResolvedUri || !isFetched) {
return <LoadingScreen />
}
// error
// =
if (resolveError || isError) {
return (
<CenteredView>
<ErrorMessage
message={cleanError(resolveError || error)}
onPressTryAgain={onRefresh}
/>
</CenteredView>
<ListMaybePlaceholder
isLoading={isLoadingUri || isLoadingLikes}
isError={isError}
/>
)
}
// loaded
// =
return (
<List
data={likes}
keyExtractor={item => item.actor.did}
renderItem={renderItem}
keyExtractor={keyExtractor}
refreshing={isPTRing}
onRefresh={onRefresh}
onEndReached={onEndReached}
renderItem={renderItem}
initialNumToRender={15}
// FIXME(dan)
// eslint-disable-next-line react/no-unstable-nested-components
ListFooterComponent={() => (
<View style={styles.footer}>
{(isFetching || isFetchingNextPage) && <ActivityIndicator />}
</View>
)}
onEndReachedThreshold={4}
ListHeaderComponent={<ListHeaderDesktop title={_(msg`Liked By`)} />}
ListFooterComponent={
<ListFooter
isFetchingNextPage={isFetchingNextPage}
error={cleanError(error)}
onRetry={fetchNextPage}
/>
}
// @ts-ignore our .web version only -prf
desktopFixedHeight
initialNumToRender={initialNumToRender}
windowSize={11}
/>
)
}
const styles = StyleSheet.create({
footer: {
height: 200,
paddingTop: 20,
},
})

View File

@ -1,38 +1,57 @@
import React, {useMemo, useCallback, useState} from 'react'
import {ActivityIndicator, StyleSheet, View} from 'react-native'
import React, {useCallback, useMemo, useState} from 'react'
import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {CenteredView} from '../util/Views'
import {List} from '../util/List'
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {logger} from '#/logger'
import {LoadingScreen} from '../util/LoadingScreen'
import {useResolveUriQuery} from '#/state/queries/resolve-uri'
import {usePostRepostedByQuery} from '#/state/queries/post-reposted-by'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {cleanError} from '#/lib/strings/errors'
import {logger} from '#/logger'
import {usePostRepostedByQuery} from '#/state/queries/post-reposted-by'
import {useResolveUriQuery} from '#/state/queries/resolve-uri'
import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender'
import {
ListFooter,
ListHeaderDesktop,
ListMaybePlaceholder,
} from '#/components/Lists'
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
import {List} from '../util/List'
function renderItem({item}: {item: ActorDefs.ProfileViewBasic}) {
return <ProfileCardWithFollowBtn key={item.did} profile={item} />
}
function keyExtractor(item: ActorDefs.ProfileViewBasic) {
return item.did
}
export function PostRepostedBy({uri}: {uri: string}) {
const {_} = useLingui()
const initialNumToRender = useInitialNumToRender()
const [isPTRing, setIsPTRing] = useState(false)
const {
data: resolvedUri,
error: resolveError,
isFetching: isFetchingResolvedUri,
isLoading: isLoadingUri,
} = useResolveUriQuery(uri)
const {
data,
isFetching,
isFetched,
isLoading: isLoadingRepostedBy,
isFetchingNextPage,
hasNextPage,
fetchNextPage,
isError,
error,
refetch,
} = usePostRepostedByQuery(resolvedUri?.uri)
const isError = Boolean(resolveError || error)
const repostedBy = useMemo(() => {
if (data?.pages) {
return data.pages.flatMap(page => page.repostedBy)
}
return []
}, [data])
const onRefresh = useCallback(async () => {
@ -46,35 +65,20 @@ export function PostRepostedBy({uri}: {uri: string}) {
}, [refetch, setIsPTRing])
const onEndReached = useCallback(async () => {
if (isFetching || !hasNextPage || isError) return
if (isFetchingNextPage || !hasNextPage || isError) return
try {
await fetchNextPage()
} catch (err) {
logger.error('Failed to load more reposts', {message: err})
}
}, [isFetching, hasNextPage, isError, fetchNextPage])
}, [isFetchingNextPage, hasNextPage, isError, fetchNextPage])
const renderItem = useCallback(
({item}: {item: ActorDefs.ProfileViewBasic}) => {
return <ProfileCardWithFollowBtn key={item.did} profile={item} />
},
[],
)
if (isFetchingResolvedUri || !isFetched) {
return <LoadingScreen />
}
// error
// =
if (resolveError || isError) {
if (repostedBy.length < 1) {
return (
<CenteredView>
<ErrorMessage
message={cleanError(resolveError || error)}
onPressTryAgain={onRefresh}
/>
</CenteredView>
<ListMaybePlaceholder
isLoading={isLoadingUri || isLoadingRepostedBy}
isError={isError}
/>
)
}
@ -83,28 +87,24 @@ export function PostRepostedBy({uri}: {uri: string}) {
return (
<List
data={repostedBy}
keyExtractor={item => item.did}
renderItem={renderItem}
keyExtractor={keyExtractor}
refreshing={isPTRing}
onRefresh={onRefresh}
onEndReached={onEndReached}
renderItem={renderItem}
initialNumToRender={15}
// FIXME(dan)
// eslint-disable-next-line react/no-unstable-nested-components
ListFooterComponent={() => (
<View style={styles.footer}>
{(isFetching || isFetchingNextPage) && <ActivityIndicator />}
</View>
)}
onEndReachedThreshold={4}
ListHeaderComponent={<ListHeaderDesktop title={_(msg`Reposted By`)} />}
ListFooterComponent={
<ListFooter
isFetchingNextPage={isFetchingNextPage}
error={cleanError(error)}
onRetry={fetchNextPage}
/>
}
// @ts-ignore our .web version only -prf
desktopFixedHeight
initialNumToRender={initialNumToRender}
windowSize={11}
/>
)
}
const styles = StyleSheet.create({
footer: {
height: 200,
paddingTop: 20,
},
})

View File

@ -1,13 +1,14 @@
import React from 'react'
import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {ViewHeader} from '../com/util/ViewHeader'
import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {useSetMinimalShellMode} from '#/state/shell'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useFocusEffect} from '@react-navigation/native'
import {useSetMinimalShellMode} from '#/state/shell'
import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
import {ViewHeader} from '../com/util/ViewHeader'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostLikedBy'>
export const PostLikedByScreen = ({route}: Props) => {
@ -23,7 +24,7 @@ export const PostLikedByScreen = ({route}: Props) => {
)
return (
<View>
<View style={{flex: 1}}>
<ViewHeader title={_(msg`Liked By`)} />
<PostLikedByComponent uri={uri} />
</View>

View File

@ -1,13 +1,14 @@
import React from 'react'
import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {ViewHeader} from '../com/util/ViewHeader'
import {PostRepostedBy as PostRepostedByComponent} from '../com/post-thread/PostRepostedBy'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {useSetMinimalShellMode} from '#/state/shell'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useFocusEffect} from '@react-navigation/native'
import {useSetMinimalShellMode} from '#/state/shell'
import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {PostRepostedBy as PostRepostedByComponent} from '../com/post-thread/PostRepostedBy'
import {ViewHeader} from '../com/util/ViewHeader'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostRepostedBy'>
export const PostRepostedByScreen = ({route}: Props) => {
@ -23,7 +24,7 @@ export const PostRepostedByScreen = ({route}: Props) => {
)
return (
<View>
<View style={{flex: 1}}>
<ViewHeader title={_(msg`Reposted By`)} />
<PostRepostedByComponent uri={uri} />
</View>

View File

@ -1,13 +1,14 @@
import React from 'react'
import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {ViewHeader} from '../com/util/ViewHeader'
import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {useSetMinimalShellMode} from '#/state/shell'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useFocusEffect} from '@react-navigation/native'
import {useSetMinimalShellMode} from '#/state/shell'
import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
import {ViewHeader} from '../com/util/ViewHeader'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeedLikedBy'>
export const ProfileFeedLikedByScreen = ({route}: Props) => {
@ -23,7 +24,7 @@ export const ProfileFeedLikedByScreen = ({route}: Props) => {
)
return (
<View>
<View style={{flex: 1}}>
<ViewHeader title={_(msg`Liked By`)} />
<PostLikedByComponent uri={uri} />
</View>