ALF feed error screen (#9895)

This commit is contained in:
Samuel Newman
2026-02-18 08:16:12 +00:00
committed by GitHub
parent ae115ca17e
commit a1cda126e6
+25 -78
View File
@@ -1,24 +1,19 @@
import React, {useCallback, useMemo} from 'react'
import {StyleSheet, View} from 'react-native'
import {useCallback, useEffect, useMemo, useState} from 'react'
import {useAnimatedRef} from 'react-native-reanimated'
import {AppBskyFeedDefs} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useIsFocused, useNavigation} from '@react-navigation/native'
import {useIsFocused} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {useQueryClient} from '@tanstack/react-query'
import {VIDEO_FEED_URIS} from '#/lib/constants'
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
import {usePalette} from '#/lib/hooks/usePalette'
import {useSetTitle} from '#/lib/hooks/useSetTitle'
import {ComposeIcon2} from '#/lib/icons'
import {
type CommonNavigatorParams,
type NavigationProp,
} from '#/lib/routes/types'
import {type CommonNavigatorParams} from '#/lib/routes/types'
import {cleanError} from '#/lib/strings/errors'
import {makeRecordUri} from '#/lib/strings/url-helpers'
import {s} from '#/lib/styles'
import {listenSoftReset} from '#/state/events'
import {FeedFeedbackProvider, useFeedFeedback} from '#/state/feed-feedback'
import {
@@ -36,12 +31,11 @@ import {truncateAndInvalidate} from '#/state/queries/util'
import {useSession} from '#/state/session'
import {PostFeed} from '#/view/com/posts/PostFeed'
import {EmptyState} from '#/view/com/util/EmptyState'
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
import {FAB} from '#/view/com/util/fab/FAB'
import {Button} from '#/view/com/util/forms/Button'
import {type ListRef} from '#/view/com/util/List'
import {LoadLatestBtn} from '#/view/com/util/load-latest/LoadLatestBtn'
import {PostFeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
import {Text} from '#/view/com/util/text/Text'
import {
ProfileFeedHeader,
ProfileFeedHeaderSkeleton,
@@ -55,54 +49,30 @@ export function ProfileFeedScreen(props: Props) {
const {rkey, name: handleOrDid} = props.route.params
const feedParams: FeedParams | undefined = props.route.params.feedCacheKey
? {
feedCacheKey: props.route.params.feedCacheKey,
}
? {feedCacheKey: props.route.params.feedCacheKey}
: undefined
const pal = usePalette('default')
const {_} = useLingui()
const navigation = useNavigation<NavigationProp>()
const uri = useMemo(
() => makeRecordUri(handleOrDid, 'app.bsky.feed.generator', rkey),
[rkey, handleOrDid],
)
const {error, data: resolvedUri} = useResolveUriQuery(uri)
let {
error,
data: resolvedUri,
refetch,
isRefetching,
} = useResolveUriQuery(uri)
const onPressBack = React.useCallback(() => {
if (navigation.canGoBack()) {
navigation.goBack()
} else {
navigation.navigate('Home')
}
}, [navigation])
if (error) {
if (error && !isRefetching) {
return (
<Layout.Screen testID="profileFeedScreenError">
<Layout.Content>
<View style={[pal.view, pal.border, styles.notFoundContainer]}>
<Text type="title-lg" style={[pal.text, s.mb10]}>
<Trans>Could not load feed</Trans>
</Text>
<Text type="md" style={[pal.text, s.mb20]}>
{error.toString()}
</Text>
<View style={{flexDirection: 'row'}}>
<Button
type="default"
accessibilityLabel={_(msg`Go back`)}
accessibilityHint={_(msg`Returns to previous page`)}
onPress={onPressBack}
style={{flexShrink: 1}}>
<Text type="button" style={pal.text}>
<Trans>Go Back</Trans>
</Text>
</Button>
</View>
</View>
</Layout.Content>
<ErrorScreen
showHeader
title={_(msg`Could not load feed`)}
message={cleanError(error)}
onPressTryAgain={() => void refetch()}
/>
</Layout.Screen>
)
}
@@ -169,8 +139,8 @@ export function ProfileFeedScreenInner({
const feed = `feedgen|${feedInfo.uri}` as FeedDescriptor
const [hasNew, setHasNew] = React.useState(false)
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
const [hasNew, setHasNew] = useState(false)
const [isScrolledDown, setIsScrolledDown] = useState(false)
const queryClient = useQueryClient()
const feedFeedback = useFeedFeedback(feedInfo, hasSession)
const scrollElRef = useAnimatedRef() as ListRef
@@ -180,11 +150,11 @@ export function ProfileFeedScreenInner({
animated: IS_NATIVE,
offset: 0, // -headerHeight,
})
truncateAndInvalidate(queryClient, FEED_RQKEY(feed))
void truncateAndInvalidate(queryClient, FEED_RQKEY(feed))
setHasNew(false)
}, [scrollElRef, queryClient, feed, setHasNew])
React.useEffect(() => {
useEffect(() => {
if (!isScreenFocused) {
return
}
@@ -201,7 +171,7 @@ export function ProfileFeedScreenInner({
)
}, [_])
const isVideoFeed = React.useMemo(() => {
const isVideoFeed = useMemo(() => {
const isBskyVideoFeed = VIDEO_FEED_URIS.includes(feedInfo.uri)
const feedIsVideoMode =
feedInfo.contentMode === AppBskyFeedDefs.CONTENTMODEVIDEO
@@ -254,26 +224,3 @@ export function ProfileFeedScreenInner({
</>
)
}
const styles = StyleSheet.create({
btn: {
flexDirection: 'row',
alignItems: 'center',
gap: 6,
paddingVertical: 7,
paddingHorizontal: 14,
borderRadius: 50,
marginLeft: 6,
},
notFoundContainer: {
margin: 10,
paddingHorizontal: 18,
paddingVertical: 14,
borderRadius: 6,
},
aboutSectionContainer: {
paddingVertical: 4,
paddingHorizontal: 16,
gap: 12,
},
})