import {useCallback, useState} from 'react' import {View} from 'react-native' import {moderatePost, type ModerationDecision} from '@bsky/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' import {usePostViewTracking} from '#/lib/hooks/usePostViewTracking' import {cleanError} from '#/lib/strings/errors' import {logger} from '#/logger' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {usePostQuotesQuery} from '#/state/queries/post-quotes' import {useResolveUriQuery} from '#/state/queries/resolve-uri' import {Post} from '#/view/com/post/Post' import {atoms as a, useTheme} from '#/alf' import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' import {Text} from '#/components/Typography' import {app} from '#/lexicons' import * as bsky from '#/types/bsky' import {List} from '../util/List' function renderItem({ item, index, }: { item: { post: app.bsky.feed.defs.PostView moderation: ModerationDecision record: app.bsky.feed.post.Main } index: number }) { return } function keyExtractor(item: { post: app.bsky.feed.defs.PostView moderation: ModerationDecision record: app.bsky.feed.post.Main }) { return item.post.uri } function ExtractedQuotedPost({post}: {post: app.bsky.feed.defs.PostView}) { const t = useTheme() return ( The quoted post has been extracted from the following ) } export function PostQuotes({ uri, quotedPost, isQuotedPostExtracted, }: { uri: string quotedPost?: app.bsky.feed.defs.PostView isQuotedPostExtracted: boolean }) { const {_} = useLingui() const initialNumToRender = useInitialNumToRender() const [isPTRing, setIsPTRing] = useState(false) const trackPostView = usePostViewTracking('PostQuotes') const { data: resolvedUri, error: resolveError, isLoading: isLoadingUri, } = useResolveUriQuery(uri) const { data, isLoading: isLoadingQuotes, isFetchingNextPage, hasNextPage, fetchNextPage, error, refetch, } = usePostQuotesQuery(resolvedUri?.uri) const moderationOpts = useModerationOpts() const isError = Boolean(resolveError || error) const quotes = data?.pages .flatMap(page => page.posts.map(post => { if ( !bsky.isType(app.bsky.feed.post, post.record) || !moderationOpts ) { return null } const moderation = moderatePost(post, moderationOpts) return {post, record: post.record, moderation} }), ) .filter(item => item !== null) ?? [] const onRefresh = useCallback(async () => { setIsPTRing(true) try { await refetch() } catch (err) { logger.error('Failed to refresh quotes', {message: err}) } setIsPTRing(false) }, [refetch, setIsPTRing]) const onEndReached = useCallback(async () => { if (isFetchingNextPage || !hasNextPage || isError) return try { await fetchNextPage() } catch (err) { logger.error('Failed to load more quotes', {message: err}) } }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage]) const renderItem = useCallback( ({ item, index, }: { item: { post: app.bsky.feed.defs.PostView moderation: ModerationDecision record: app.bsky.feed.post.Main } index: number }) => ( ), [isQuotedPostExtracted, quotedPost?.uri], ) if (quotes.length < 1) { return ( ) } // loaded // = return ( trackPostView(item.post)} ListHeaderComponent={ isQuotedPostExtracted && quotedPost ? ( ) : undefined } ListFooterComponent={ } desktopFixedHeight initialNumToRender={initialNumToRender} windowSize={11} sideBorders={false} /> ) }