import {useCallback, useEffect, useMemo, useState} from 'react' import {LayoutAnimation, View} from 'react-native' import { AppBskyFeedPost, AppBskyRichtextFacet, AtUri, moderatePost, RichText as RichTextAPI, } from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {RouteProp, useNavigation, useRoute} from '@react-navigation/native' import {makeProfileLink} from '#/lib/routes/links' import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types' import { convertBskyAppUrlIfNeeded, isBskyPostUrl, makeRecordUri, } from '#/lib/strings/url-helpers' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {usePostQuery} from '#/state/queries/post' import {PostMeta} from '#/view/com/util/PostMeta' import {atoms as a, useTheme} from '#/alf' import {Button, ButtonIcon} from '#/components/Button' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {Loader} from '#/components/Loader' import * as MediaPreview from '#/components/MediaPreview' import {ContentHider} from '#/components/moderation/ContentHider' import {PostAlerts} from '#/components/moderation/PostAlerts' import {RichText} from '#/components/RichText' import {Text} from '#/components/Typography' import * as bsky from '#/types/bsky' export function useMessageEmbed() { const route = useRoute>() const navigation = useNavigation() const embedFromParams = route.params.embed const [embedUri, setEmbed] = useState(embedFromParams) if (embedFromParams && embedUri !== embedFromParams) { setEmbed(embedFromParams) } return { embedUri, setEmbed: useCallback( (embedUrl: string | undefined) => { if (!embedUrl) { navigation.setParams({embed: ''}) setEmbed(undefined) return } if (embedFromParams) return const url = convertBskyAppUrlIfNeeded(embedUrl) const [_0, user, _1, rkey] = url.split('/').filter(Boolean) const uri = makeRecordUri(user, 'app.bsky.feed.post', rkey) setEmbed(uri) }, [embedFromParams, navigation], ), } } export function useExtractEmbedFromFacets( message: string, setEmbed: (embedUrl: string | undefined) => void, ) { const rt = new RichTextAPI({text: message}) rt.detectFacetsWithoutResolution() let uriFromFacet: string | undefined for (const facet of rt.facets ?? []) { for (const feature of facet.features) { if (AppBskyRichtextFacet.isLink(feature) && isBskyPostUrl(feature.uri)) { uriFromFacet = feature.uri break } } } useEffect(() => { if (uriFromFacet) { setEmbed(uriFromFacet) } }, [uriFromFacet, setEmbed]) } export function MessageInputEmbed({ embedUri, setEmbed, }: { embedUri: string | undefined setEmbed: (embedUrl: string | undefined) => void }) { const t = useTheme() const {_} = useLingui() const {data: post, status} = usePostQuery(embedUri) const moderationOpts = useModerationOpts() const moderation = useMemo( () => moderationOpts && post ? moderatePost(post, moderationOpts) : undefined, [moderationOpts, post], ) const {rt, record} = useMemo(() => { if ( post && bsky.dangerousIsType( post.record, AppBskyFeedPost.isRecord, ) ) { return { rt: new RichTextAPI({ text: post.record.text, facets: post.record.facets, }), record: post.record, } } return {rt: undefined, record: undefined} }, [post]) if (!embedUri) { return null } let content = null switch (status) { case 'pending': content = ( ) break case 'error': content = ( Could not fetch post ) break case 'success': const itemUrip = new AtUri(post.uri) const itemHref = makeProfileLink(post.author, 'post', itemUrip.rkey) if (!post || !moderation || !rt || !record) { return null } content = ( {rt.text && ( )} ) break } return ( {content} ) }