Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
117
fork

Configure Feed

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

at a876aae44ea07494ebea9727350aa060b81f317b 145 lines 4.0 kB view raw
1import {useCallback, useState} from 'react' 2import { 3 type AppBskyFeedDefs, 4 AppBskyFeedPost, 5 moderatePost, 6 type ModerationDecision, 7} from '@atproto/api' 8import {msg} from '@lingui/core/macro' 9import {useLingui} from '@lingui/react' 10 11import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' 12import {usePostViewTracking} from '#/lib/hooks/usePostViewTracking' 13import {cleanError} from '#/lib/strings/errors' 14import {logger} from '#/logger' 15import {useModerationOpts} from '#/state/preferences/moderation-opts' 16import {usePostQuotesQuery} from '#/state/queries/post-quotes' 17import {useResolveUriQuery} from '#/state/queries/resolve-uri' 18import {Post} from '#/view/com/post/Post' 19import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' 20import {List} from '../util/List' 21 22function renderItem({ 23 item, 24 index, 25}: { 26 item: { 27 post: AppBskyFeedDefs.PostView 28 moderation: ModerationDecision 29 record: AppBskyFeedPost.Record 30 } 31 index: number 32}) { 33 return <Post post={item.post} hideTopBorder={index === 0} /> 34} 35 36function keyExtractor(item: { 37 post: AppBskyFeedDefs.PostView 38 moderation: ModerationDecision 39 record: AppBskyFeedPost.Record 40}) { 41 return item.post.uri 42} 43 44export function PostQuotes({uri}: {uri: string}) { 45 const {_} = useLingui() 46 const initialNumToRender = useInitialNumToRender() 47 const [isPTRing, setIsPTRing] = useState(false) 48 const trackPostView = usePostViewTracking('PostQuotes') 49 50 const { 51 data: resolvedUri, 52 error: resolveError, 53 isLoading: isLoadingUri, 54 } = useResolveUriQuery(uri) 55 const { 56 data, 57 isLoading: isLoadingQuotes, 58 isFetchingNextPage, 59 hasNextPage, 60 fetchNextPage, 61 error, 62 refetch, 63 } = usePostQuotesQuery(resolvedUri?.uri) 64 65 const moderationOpts = useModerationOpts() 66 67 const isError = Boolean(resolveError || error) 68 69 const quotes = 70 data?.pages 71 .flatMap(page => 72 page.posts.map(post => { 73 if (!AppBskyFeedPost.isRecord(post.record) || !moderationOpts) { 74 return null 75 } 76 const moderation = moderatePost(post, moderationOpts) 77 return {post, record: post.record, moderation} 78 }), 79 ) 80 .filter(item => item !== null) ?? [] 81 82 const onRefresh = useCallback(async () => { 83 setIsPTRing(true) 84 try { 85 await refetch() 86 } catch (err) { 87 logger.error('Failed to refresh quotes', {message: err}) 88 } 89 setIsPTRing(false) 90 }, [refetch, setIsPTRing]) 91 92 const onEndReached = useCallback(async () => { 93 if (isFetchingNextPage || !hasNextPage || isError) return 94 try { 95 await fetchNextPage() 96 } catch (err) { 97 logger.error('Failed to load more quotes', {message: err}) 98 } 99 }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage]) 100 101 if (quotes.length < 1) { 102 return ( 103 <ListMaybePlaceholder 104 isLoading={isLoadingUri || isLoadingQuotes} 105 isError={isError} 106 emptyType="results" 107 emptyTitle={_(msg`No quotes yet`)} 108 emptyMessage={_( 109 msg`Nobody has quoted this yet. Maybe you should be the first!`, 110 )} 111 errorMessage={cleanError(resolveError || error)} 112 sideBorders={false} 113 /> 114 ) 115 } 116 117 // loaded 118 // = 119 return ( 120 <List 121 data={quotes} 122 renderItem={renderItem} 123 keyExtractor={keyExtractor} 124 refreshing={isPTRing} 125 onRefresh={onRefresh} 126 onEndReached={onEndReached} 127 onEndReachedThreshold={4} 128 onItemSeen={item => trackPostView(item.post)} 129 ListFooterComponent={ 130 <ListFooter 131 isFetchingNextPage={isFetchingNextPage} 132 error={cleanError(error)} 133 onRetry={fetchNextPage} 134 showEndMessage 135 endMessageText={_(msg`That's all, folks!`)} 136 /> 137 } 138 // @ts-ignore our .web version only -prf 139 desktopFixedHeight 140 initialNumToRender={initialNumToRender} 141 windowSize={11} 142 sideBorders={false} 143 /> 144 ) 145}