Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

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

at main 174 lines 5.4 kB view raw
1import {type RefObject, useCallback} from 'react' 2import {View} from 'react-native' 3import {type AppBskyFeedDefs} from '@atproto/api' 4import {Trans, useLingui} from '@lingui/react/macro' 5import {useQueryClient} from '@tanstack/react-query' 6 7import {cleanError} from '#/lib/strings/errors' 8import {unstableCacheProfileView} from '#/state/queries/profile' 9import { 10 buildPostSourceKey, 11 setUnstablePostSource, 12} from '#/state/unstable-post-source' 13import {Post} from '#/view/com/post/Post' 14import {PostLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder' 15import {atoms as a, useTheme} from '#/alf' 16import * as Button from '#/components/Button' 17import { 18 ChevronBottom_Stroke2_Corner0_Rounded as ChevronDownIcon, 19 ChevronTop_Stroke2_Corner0_Rounded as ChevronUpIcon, 20} from '#/components/icons/Chevron' 21import {Text} from '#/components/Typography' 22 23export function ThreadAlsoLiked({ 24 posts, 25 visible, 26 collapsed, 27 isLoading: _isLoading, 28 showLoadingState, 29 isFetchingNextPage, 30 error, 31 onRetry, 32 headerRef, 33 onToggleCollapsed, 34 spacerHeight, 35 isTombstoneView, 36}: { 37 posts: AppBskyFeedDefs.PostView[] 38 visible: boolean 39 collapsed: boolean 40 isLoading: boolean 41 showLoadingState: boolean 42 isFetchingNextPage: boolean 43 error: unknown 44 onRetry: () => void 45 headerRef: RefObject<View | null> 46 onToggleCollapsed: () => void 47 spacerHeight: number | undefined 48 isTombstoneView: boolean 49}) { 50 const {t: l} = useLingui() 51 const t = useTheme() 52 const queryClient = useQueryClient() 53 const hasSection = visible 54 const onBeforePress = useCallback( 55 (post: AppBskyFeedDefs.PostView) => { 56 unstableCacheProfileView(queryClient, post.author) 57 setUnstablePostSource(buildPostSourceKey(post.uri, post.author.handle), { 58 post: {post}, 59 }) 60 }, 61 [queryClient], 62 ) 63 64 return ( 65 <View> 66 {hasSection && ( 67 <View style={[a.border_t, t.atoms.border_contrast_low]}> 68 <Button.Button 69 ref={headerRef} 70 label={ 71 collapsed 72 ? l`Expand also liked posts` 73 : l`Collapse also liked posts` 74 } 75 onPress={onToggleCollapsed} 76 style={[a.w_full]}> 77 {({hovered, pressed}) => ( 78 <View 79 style={[ 80 a.w_full, 81 a.flex_row, 82 a.align_center, 83 a.justify_between, 84 a.gap_sm, 85 a.px_lg, 86 a.py_md, 87 (hovered || pressed) && t.atoms.bg_contrast_25, 88 ]}> 89 <View style={[a.flex_1, a.gap_2xs]}> 90 <Text style={[a.text_xl, a.font_bold]}> 91 <Trans>Also liked</Trans> 92 </Text> 93 <Text style={[a.text_sm, t.atoms.text_contrast_medium]}> 94 <Trans>Posts liked by people who liked this post</Trans> 95 </Text> 96 </View> 97 {collapsed ? ( 98 <ChevronDownIcon 99 size="sm" 100 style={t.atoms.text_contrast_medium} 101 /> 102 ) : ( 103 <ChevronUpIcon 104 size="sm" 105 style={t.atoms.text_contrast_medium} 106 /> 107 )} 108 </View> 109 )} 110 </Button.Button> 111 112 {!collapsed && ( 113 <> 114 {posts.map((post, index) => ( 115 <Post 116 key={post.uri} 117 post={post} 118 hideTopBorder={index === 0} 119 onBeforePress={() => onBeforePress(post)} 120 /> 121 ))} 122 123 {showLoadingState && posts.length === 0 && ( 124 <> 125 <PostLoadingPlaceholder 126 style={[a.border_t, t.atoms.border_contrast_low]} 127 /> 128 <PostLoadingPlaceholder 129 style={[a.border_t, t.atoms.border_contrast_low]} 130 /> 131 </> 132 )} 133 134 {isFetchingNextPage && ( 135 <PostLoadingPlaceholder 136 style={[a.border_t, t.atoms.border_contrast_low]} 137 /> 138 )} 139 140 {Boolean(error) && !showLoadingState && !isFetchingNextPage && ( 141 <View style={[a.px_lg, a.pb_xl, a.gap_md]}> 142 <Text style={[a.text_sm, t.atoms.text_contrast_medium]}> 143 {cleanError(error)} 144 </Text> 145 <View style={[a.flex_row]}> 146 <Button.Button 147 label={l`Retry loading also liked posts`} 148 onPress={onRetry} 149 variant="solid" 150 color="secondary_inverted" 151 size="small"> 152 <Button.ButtonText> 153 <Trans>Retry</Trans> 154 </Button.ButtonText> 155 </Button.Button> 156 </View> 157 </View> 158 )} 159 </> 160 )} 161 </View> 162 )} 163 164 <View 165 style={[ 166 a.w_full, 167 !hasSection && 168 !isTombstoneView && [a.border_t, t.atoms.border_contrast_low], 169 {height: spacerHeight ?? 180}, 170 ]} 171 /> 172 </View> 173 ) 174}