Add LazyQuoteEmbed for composer use

This commit is contained in:
Eric Bailey
2025-06-11 10:58:08 -05:00
parent c20f0319a7
commit 54c531a4da
4 changed files with 60 additions and 12 deletions
@@ -0,0 +1,37 @@
import {useMemo} from 'react'
import {View} from 'react-native'
import {createEmbedViewRecordFromPost} from '#/state/queries/postgate/util'
import {useResolveLinkQuery} from '#/state/queries/resolve-link'
import {atoms as a, useTheme} from '#/alf'
import {QuoteEmbed} from '#/components/Post/Embed'
export function LazyQuoteEmbed({uri}: {uri: string}) {
const t = useTheme()
const {data} = useResolveLinkQuery(uri)
const view = useMemo(() => {
if (!data || data.type !== 'record' || data.kind !== 'post') return
return createEmbedViewRecordFromPost(data.view)
}, [data])
return view ? (
<QuoteEmbed
embed={{
type: 'post',
view,
}}
/>
) : (
<View
style={[
a.w_full,
a.rounded_md,
t.atoms.bg_contrast_25,
{
height: 68,
},
]}
/>
)
}
+4 -3
View File
@@ -1,9 +1,9 @@
import { import {
$Typed, type $Typed,
AppBskyEmbedRecord, AppBskyEmbedRecord,
AppBskyEmbedRecordWithMedia, AppBskyEmbedRecordWithMedia,
AppBskyFeedDefs, type AppBskyFeedDefs,
AppBskyFeedPostgate, type AppBskyFeedPostgate,
AtUri, AtUri,
} from '@atproto/api' } from '@atproto/api'
@@ -113,6 +113,7 @@ export function createEmbedViewRecordFromPost(
likeCount: post.likeCount, likeCount: post.likeCount,
quoteCount: post.quoteCount, quoteCount: post.quoteCount,
indexedAt: post.indexedAt, indexedAt: post.indexedAt,
embeds: post.embed ? [post.embed] : [],
} }
} }
+10 -5
View File
@@ -71,7 +71,7 @@ import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {mimeToExt} from '#/lib/media/video/util' import {mimeToExt} from '#/lib/media/video/util'
import {logEvent} from '#/lib/statsig/statsig' import {logEvent} from '#/lib/statsig/statsig'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
import {colors, s} from '#/lib/styles' import {colors} from '#/lib/styles'
import {logger} from '#/logger' import {logger} from '#/logger'
import {isAndroid, isIOS, isNative, isWeb} from '#/platform/detection' import {isAndroid, isIOS, isNative, isWeb} from '#/platform/detection'
import {useDialogStateControlContext} from '#/state/dialogs' import {useDialogStateControlContext} from '#/state/dialogs'
@@ -96,6 +96,7 @@ import {
ExternalEmbedGif, ExternalEmbedGif,
ExternalEmbedLink, ExternalEmbedLink,
} from '#/view/com/composer/ExternalEmbed' } from '#/view/com/composer/ExternalEmbed'
import {ExternalEmbedRemoveBtn} from '#/view/com/composer/ExternalEmbedRemoveBtn'
import {GifAltTextDialog} from '#/view/com/composer/GifAltText' import {GifAltTextDialog} from '#/view/com/composer/GifAltText'
import {LabelsBtn} from '#/view/com/composer/labels/LabelsBtn' import {LabelsBtn} from '#/view/com/composer/labels/LabelsBtn'
import {Gallery} from '#/view/com/composer/photos/Gallery' import {Gallery} from '#/view/com/composer/photos/Gallery'
@@ -115,7 +116,6 @@ import {SelectVideoBtn} from '#/view/com/composer/videos/SelectVideoBtn'
import {SubtitleDialogBtn} from '#/view/com/composer/videos/SubtitleDialog' import {SubtitleDialogBtn} from '#/view/com/composer/videos/SubtitleDialog'
import {VideoPreview} from '#/view/com/composer/videos/VideoPreview' import {VideoPreview} from '#/view/com/composer/videos/VideoPreview'
import {VideoTranscodeProgress} from '#/view/com/composer/videos/VideoTranscodeProgress' import {VideoTranscodeProgress} from '#/view/com/composer/videos/VideoTranscodeProgress'
import {LazyQuoteEmbed, QuoteX} from '#/view/com/util/post-embeds/QuoteEmbed'
import {Text} from '#/view/com/util/text/Text' import {Text} from '#/view/com/util/text/Text'
import * as Toast from '#/view/com/util/Toast' import * as Toast from '#/view/com/util/Toast'
import {UserAvatar} from '#/view/com/util/UserAvatar' import {UserAvatar} from '#/view/com/util/UserAvatar'
@@ -124,6 +124,7 @@ import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji' import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji'
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
import {LazyQuoteEmbed} from '#/components/Post/Embed/LazyQuoteEmbed'
import * as Prompt from '#/components/Prompt' import * as Prompt from '#/components/Prompt'
import {Text as NewText} from '#/components/Typography' import {Text as NewText} from '#/components/Typography'
import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet' import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet'
@@ -1146,13 +1147,17 @@ function ComposerEmbeds({
)} )}
</LayoutAnimationConfig> </LayoutAnimationConfig>
{embed.quote?.uri ? ( {embed.quote?.uri ? (
<View style={!video ? [a.mt_md] : []}> <View
<View style={[s.mt5, s.mb2, isWeb && s.mb10]}> style={[a.pb_sm, video ? [a.pt_md] : [a.pt_xl], isWeb && [a.pb_md]]}>
<View style={[a.relative]}>
<View style={{pointerEvents: 'none'}}> <View style={{pointerEvents: 'none'}}>
<LazyQuoteEmbed uri={embed.quote.uri} /> <LazyQuoteEmbed uri={embed.quote.uri} />
</View> </View>
{canRemoveQuote && ( {canRemoveQuote && (
<QuoteX onRemove={() => dispatch({type: 'embed_remove_quote'})} /> <ExternalEmbedRemoveBtn
onRemove={() => dispatch({type: 'embed_remove_quote'})}
style={{top: 16}}
/>
)} )}
</View> </View>
</View> </View>
@@ -2,22 +2,27 @@ import {View} from 'react-native'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {atoms as a} from '#/alf' import {atoms as a, useTheme, type ViewStyleProp} from '#/alf'
import {Button, ButtonIcon} from '#/components/Button' import {Button, ButtonIcon} from '#/components/Button'
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
export function ExternalEmbedRemoveBtn({onRemove}: {onRemove: () => void}) { export function ExternalEmbedRemoveBtn({
onRemove,
style,
}: {onRemove: () => void} & ViewStyleProp) {
const t = useTheme()
const {_} = useLingui() const {_} = useLingui()
return ( return (
<View style={[a.absolute, {top: 8, right: 8}, a.z_50]}> <View style={[a.absolute, {top: 8, right: 8}, a.z_50, style]}>
<Button <Button
label={_(msg`Remove attachment`)} label={_(msg`Remove attachment`)}
onPress={onRemove} onPress={onRemove}
size="small" size="small"
variant="solid" variant="solid"
color="secondary" color="secondary"
shape="round"> shape="round"
style={[t.atoms.shadow_sm]}>
<ButtonIcon icon={X} size="sm" /> <ButtonIcon icon={X} size="sm" />
</Button> </Button>
</View> </View>