Bluesky app fork with some witchin' additions 💫

ALF feed error screen (#9895)

authored by samuel.fm and committed by

GitHub a1cda126 ae115ca1

+25 -78
+25 -78
src/screens/Profile/ProfileFeed/index.tsx
··· 1 - import React, {useCallback, useMemo} from 'react' 2 - import {StyleSheet, View} from 'react-native' 1 + import {useCallback, useEffect, useMemo, useState} from 'react' 3 2 import {useAnimatedRef} from 'react-native-reanimated' 4 3 import {AppBskyFeedDefs} from '@atproto/api' 5 - import {msg, Trans} from '@lingui/macro' 4 + import {msg} from '@lingui/macro' 6 5 import {useLingui} from '@lingui/react' 7 - import {useIsFocused, useNavigation} from '@react-navigation/native' 6 + import {useIsFocused} from '@react-navigation/native' 8 7 import {type NativeStackScreenProps} from '@react-navigation/native-stack' 9 8 import {useQueryClient} from '@tanstack/react-query' 10 9 11 10 import {VIDEO_FEED_URIS} from '#/lib/constants' 12 11 import {useOpenComposer} from '#/lib/hooks/useOpenComposer' 13 - import {usePalette} from '#/lib/hooks/usePalette' 14 12 import {useSetTitle} from '#/lib/hooks/useSetTitle' 15 13 import {ComposeIcon2} from '#/lib/icons' 16 - import { 17 - type CommonNavigatorParams, 18 - type NavigationProp, 19 - } from '#/lib/routes/types' 14 + import {type CommonNavigatorParams} from '#/lib/routes/types' 15 + import {cleanError} from '#/lib/strings/errors' 20 16 import {makeRecordUri} from '#/lib/strings/url-helpers' 21 - import {s} from '#/lib/styles' 22 17 import {listenSoftReset} from '#/state/events' 23 18 import {FeedFeedbackProvider, useFeedFeedback} from '#/state/feed-feedback' 24 19 import { ··· 36 31 import {useSession} from '#/state/session' 37 32 import {PostFeed} from '#/view/com/posts/PostFeed' 38 33 import {EmptyState} from '#/view/com/util/EmptyState' 34 + import {ErrorScreen} from '#/view/com/util/error/ErrorScreen' 39 35 import {FAB} from '#/view/com/util/fab/FAB' 40 - import {Button} from '#/view/com/util/forms/Button' 41 36 import {type ListRef} from '#/view/com/util/List' 42 37 import {LoadLatestBtn} from '#/view/com/util/load-latest/LoadLatestBtn' 43 38 import {PostFeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder' 44 - import {Text} from '#/view/com/util/text/Text' 45 39 import { 46 40 ProfileFeedHeader, 47 41 ProfileFeedHeaderSkeleton, ··· 55 49 const {rkey, name: handleOrDid} = props.route.params 56 50 57 51 const feedParams: FeedParams | undefined = props.route.params.feedCacheKey 58 - ? { 59 - feedCacheKey: props.route.params.feedCacheKey, 60 - } 52 + ? {feedCacheKey: props.route.params.feedCacheKey} 61 53 : undefined 62 - const pal = usePalette('default') 63 54 const {_} = useLingui() 64 - const navigation = useNavigation<NavigationProp>() 65 55 66 56 const uri = useMemo( 67 57 () => makeRecordUri(handleOrDid, 'app.bsky.feed.generator', rkey), 68 58 [rkey, handleOrDid], 69 59 ) 70 - const {error, data: resolvedUri} = useResolveUriQuery(uri) 71 - 72 - const onPressBack = React.useCallback(() => { 73 - if (navigation.canGoBack()) { 74 - navigation.goBack() 75 - } else { 76 - navigation.navigate('Home') 77 - } 78 - }, [navigation]) 60 + let { 61 + error, 62 + data: resolvedUri, 63 + refetch, 64 + isRefetching, 65 + } = useResolveUriQuery(uri) 79 66 80 - if (error) { 67 + if (error && !isRefetching) { 81 68 return ( 82 69 <Layout.Screen testID="profileFeedScreenError"> 83 - <Layout.Content> 84 - <View style={[pal.view, pal.border, styles.notFoundContainer]}> 85 - <Text type="title-lg" style={[pal.text, s.mb10]}> 86 - <Trans>Could not load feed</Trans> 87 - </Text> 88 - <Text type="md" style={[pal.text, s.mb20]}> 89 - {error.toString()} 90 - </Text> 91 - 92 - <View style={{flexDirection: 'row'}}> 93 - <Button 94 - type="default" 95 - accessibilityLabel={_(msg`Go back`)} 96 - accessibilityHint={_(msg`Returns to previous page`)} 97 - onPress={onPressBack} 98 - style={{flexShrink: 1}}> 99 - <Text type="button" style={pal.text}> 100 - <Trans>Go Back</Trans> 101 - </Text> 102 - </Button> 103 - </View> 104 - </View> 105 - </Layout.Content> 70 + <ErrorScreen 71 + showHeader 72 + title={_(msg`Could not load feed`)} 73 + message={cleanError(error)} 74 + onPressTryAgain={() => void refetch()} 75 + /> 106 76 </Layout.Screen> 107 77 ) 108 78 } ··· 169 139 170 140 const feed = `feedgen|${feedInfo.uri}` as FeedDescriptor 171 141 172 - const [hasNew, setHasNew] = React.useState(false) 173 - const [isScrolledDown, setIsScrolledDown] = React.useState(false) 142 + const [hasNew, setHasNew] = useState(false) 143 + const [isScrolledDown, setIsScrolledDown] = useState(false) 174 144 const queryClient = useQueryClient() 175 145 const feedFeedback = useFeedFeedback(feedInfo, hasSession) 176 146 const scrollElRef = useAnimatedRef() as ListRef ··· 180 150 animated: IS_NATIVE, 181 151 offset: 0, // -headerHeight, 182 152 }) 183 - truncateAndInvalidate(queryClient, FEED_RQKEY(feed)) 153 + void truncateAndInvalidate(queryClient, FEED_RQKEY(feed)) 184 154 setHasNew(false) 185 155 }, [scrollElRef, queryClient, feed, setHasNew]) 186 156 187 - React.useEffect(() => { 157 + useEffect(() => { 188 158 if (!isScreenFocused) { 189 159 return 190 160 } ··· 201 171 ) 202 172 }, [_]) 203 173 204 - const isVideoFeed = React.useMemo(() => { 174 + const isVideoFeed = useMemo(() => { 205 175 const isBskyVideoFeed = VIDEO_FEED_URIS.includes(feedInfo.uri) 206 176 const feedIsVideoMode = 207 177 feedInfo.contentMode === AppBskyFeedDefs.CONTENTMODEVIDEO ··· 254 224 </> 255 225 ) 256 226 } 257 - 258 - const styles = StyleSheet.create({ 259 - btn: { 260 - flexDirection: 'row', 261 - alignItems: 'center', 262 - gap: 6, 263 - paddingVertical: 7, 264 - paddingHorizontal: 14, 265 - borderRadius: 50, 266 - marginLeft: 6, 267 - }, 268 - notFoundContainer: { 269 - margin: 10, 270 - paddingHorizontal: 18, 271 - paddingVertical: 14, 272 - borderRadius: 6, 273 - }, 274 - aboutSectionContainer: { 275 - paddingVertical: 4, 276 - paddingHorizontal: 16, 277 - gap: 12, 278 - }, 279 - })