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