mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at rn-stack-repro 165 lines 4.9 kB view raw
1import React from 'react' 2import {ListRenderItemInfo, Pressable} from 'react-native' 3import {useFocusEffect} from '@react-navigation/native' 4import {useSetMinimalShellMode} from 'state/shell' 5import {ViewHeader} from 'view/com/util/ViewHeader' 6import {NativeStackScreenProps} from '@react-navigation/native-stack' 7import {CommonNavigatorParams} from 'lib/routes/types' 8import {useSearchPostsQuery} from 'state/queries/search-posts' 9import {Post} from 'view/com/post/Post' 10import {PostView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' 11import {enforceLen} from 'lib/strings/helpers' 12import { 13 ListFooter, 14 ListHeaderDesktop, 15 ListMaybePlaceholder, 16} from '#/components/Lists' 17import {List} from 'view/com/util/List' 18import {msg} from '@lingui/macro' 19import {useLingui} from '@lingui/react' 20import {sanitizeHandle} from 'lib/strings/handles' 21import {ArrowOutOfBox_Stroke2_Corner0_Rounded} from '#/components/icons/ArrowOutOfBox' 22import {shareUrl} from 'lib/sharing' 23import {HITSLOP_10} from 'lib/constants' 24import {isNative} from 'platform/detection' 25import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' 26 27const renderItem = ({item}: ListRenderItemInfo<PostView>) => { 28 return <Post post={item} /> 29} 30 31const keyExtractor = (item: PostView, index: number) => { 32 return `${item.uri}-${index}` 33} 34 35export default function HashtagScreen({ 36 route, 37}: NativeStackScreenProps<CommonNavigatorParams, 'Hashtag'>) { 38 const {tag, author} = route.params 39 const setMinimalShellMode = useSetMinimalShellMode() 40 const {_} = useLingui() 41 const initialNumToRender = useInitialNumToRender() 42 const [isPTR, setIsPTR] = React.useState(false) 43 44 const fullTag = React.useMemo(() => { 45 return `#${tag.replaceAll('%23', '#')}` 46 }, [tag]) 47 48 const queryParam = React.useMemo(() => { 49 if (!author) return fullTag 50 return `${fullTag} from:${sanitizeHandle(author)}` 51 }, [fullTag, author]) 52 53 const headerTitle = React.useMemo(() => { 54 return enforceLen(fullTag.toLowerCase(), 24, true, 'middle') 55 }, [fullTag]) 56 57 const sanitizedAuthor = React.useMemo(() => { 58 if (!author) return 59 return sanitizeHandle(author) 60 }, [author]) 61 62 const { 63 data, 64 isFetching, 65 isLoading, 66 isRefetching, 67 isError, 68 error, 69 refetch, 70 fetchNextPage, 71 hasNextPage, 72 } = useSearchPostsQuery({query: queryParam}) 73 74 const posts = React.useMemo(() => { 75 return data?.pages.flatMap(page => page.posts) || [] 76 }, [data]) 77 78 useFocusEffect( 79 React.useCallback(() => { 80 setMinimalShellMode(false) 81 }, [setMinimalShellMode]), 82 ) 83 84 const onShare = React.useCallback(() => { 85 const url = new URL('https://bsky.app') 86 url.pathname = `/hashtag/${tag}` 87 if (author) { 88 url.searchParams.set('author', author) 89 } 90 shareUrl(url.toString()) 91 }, [tag, author]) 92 93 const onRefresh = React.useCallback(async () => { 94 setIsPTR(true) 95 await refetch() 96 setIsPTR(false) 97 }, [refetch]) 98 99 const onEndReached = React.useCallback(() => { 100 if (isFetching || !hasNextPage || error) return 101 fetchNextPage() 102 }, [isFetching, hasNextPage, error, fetchNextPage]) 103 104 return ( 105 <> 106 <ViewHeader 107 title={headerTitle} 108 subtitle={author ? _(msg`From @${sanitizedAuthor}`) : undefined} 109 canGoBack 110 renderButton={ 111 isNative 112 ? () => ( 113 <Pressable 114 accessibilityRole="button" 115 onPress={onShare} 116 hitSlop={HITSLOP_10}> 117 <ArrowOutOfBox_Stroke2_Corner0_Rounded 118 size="lg" 119 onPress={onShare} 120 /> 121 </Pressable> 122 ) 123 : undefined 124 } 125 /> 126 <ListMaybePlaceholder 127 isLoading={isLoading || isRefetching} 128 isError={isError} 129 isEmpty={posts.length < 1} 130 onRetry={refetch} 131 notFoundType="results" 132 empty={_(msg`We couldn't find any results for that hashtag.`)} 133 /> 134 {!isLoading && posts.length > 0 && ( 135 <List<PostView> 136 data={posts} 137 renderItem={renderItem} 138 keyExtractor={keyExtractor} 139 refreshing={isPTR} 140 onRefresh={onRefresh} 141 onEndReached={onEndReached} 142 onEndReachedThreshold={4} 143 // @ts-ignore web only -prf 144 desktopFixedHeight 145 ListHeaderComponent={ 146 <ListHeaderDesktop 147 title={headerTitle} 148 subtitle={author ? _(msg`From @${sanitizedAuthor}`) : undefined} 149 /> 150 } 151 ListFooterComponent={ 152 <ListFooter 153 isFetching={isFetching && !isRefetching} 154 isError={isError} 155 error={error?.name} 156 onRetry={fetchNextPage} 157 /> 158 } 159 initialNumToRender={initialNumToRender} 160 windowSize={11} 161 /> 162 )} 163 </> 164 ) 165}