Fix quote embed clickability in composer on web (#9876)

This commit is contained in:
Samuel Newman
2026-02-14 22:29:59 +00:00
committed by GitHub
parent bc001168f3
commit 1228306309
4 changed files with 67 additions and 50 deletions
+8 -1
View File
@@ -6,7 +6,13 @@ import {useResolveLinkQuery} from '#/state/queries/resolve-link'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {QuoteEmbed} from '#/components/Post/Embed' import {QuoteEmbed} from '#/components/Post/Embed'
export function LazyQuoteEmbed({uri}: {uri: string}) { export function LazyQuoteEmbed({
uri,
linkDisabled,
}: {
uri: string
linkDisabled?: boolean
}) {
const t = useTheme() const t = useTheme()
const {data} = useResolveLinkQuery(uri) const {data} = useResolveLinkQuery(uri)
@@ -21,6 +27,7 @@ export function LazyQuoteEmbed({uri}: {uri: string}) {
type: 'post', type: 'post',
view, view,
}} }}
linkDisabled={linkDisabled}
/> />
) : ( ) : (
<View <View
+57 -45
View File
@@ -225,11 +225,13 @@ export function QuoteEmbed({
embed, embed,
onOpen, onOpen,
style, style,
linkDisabled,
isWithinQuote: parentIsWithinQuote, isWithinQuote: parentIsWithinQuote,
allowNestedQuotes: parentAllowNestedQuotes, allowNestedQuotes: parentAllowNestedQuotes,
}: Omit<CommonProps, 'viewContext'> & { }: Omit<CommonProps, 'viewContext'> & {
embed: EmbedType<'post'> embed: EmbedType<'post'>
viewContext?: QuoteEmbedViewContext viewContext?: QuoteEmbedViewContext
linkDisabled?: boolean
}) { }) {
const moderationOpts = useModerationOpts() const moderationOpts = useModerationOpts()
const quote = useMemo<$Typed<AppBskyFeedDefs.PostView>>( const quote = useMemo<$Typed<AppBskyFeedDefs.PostView>>(
@@ -280,11 +282,48 @@ export function QuoteEmbed({
onIn: onPressIn, onIn: onPressIn,
onOut: onPressOut, onOut: onPressOut,
} = useInteractionState() } = useInteractionState()
const contents = (
<>
<View pointerEvents="none">
<PostMeta
author={quote.author}
moderation={moderation}
showAvatar
postHref={itemHref}
timestamp={quote.indexedAt}
/>
</View>
{moderation ? (
<PostAlerts modui={moderation.ui('contentView')} style={[a.py_xs]} />
) : null}
{richText ? (
<RichText
value={richText}
style={a.text_md}
numberOfLines={20}
disableLinks
/>
) : null}
{quote.embed && (
<Embed
embed={quote.embed}
moderation={moderation}
isWithinQuote={parentIsWithinQuote ?? true}
// already within quote? override nested
allowNestedQuotes={
parentIsWithinQuote ? false : parentAllowNestedQuotes
}
/>
)}
</>
)
return ( return (
<View <View
style={[a.mt_sm]} style={[a.mt_sm]}
onPointerEnter={onPointerEnter} onPointerEnter={linkDisabled ? undefined : onPointerEnter}
onPointerLeave={onPointerLeave}> onPointerLeave={linkDisabled ? undefined : onPointerLeave}>
<ContentHider <ContentHider
modui={moderation?.ui('contentList')} modui={moderation?.ui('contentList')}
style={[a.rounded_md, a.border, t.atoms.border_contrast_low, style]} style={[a.rounded_md, a.border, t.atoms.border_contrast_low, style]}
@@ -292,56 +331,29 @@ export function QuoteEmbed({
childContainerStyle={[a.pt_sm]}> childContainerStyle={[a.pt_sm]}>
{({active}) => ( {({active}) => (
<> <>
{!active && ( {!active && !linkDisabled && (
<SubtleHover <SubtleHover
native native
hover={hover || pressed} hover={hover || pressed}
style={[a.rounded_md]} style={[a.rounded_md]}
/> />
)} )}
<Link {linkDisabled ? (
style={[!active && a.p_md]} <View style={[!active && a.p_md]} pointerEvents="none">
hoverStyle={t.atoms.border_contrast_high} {contents}
href={itemHref}
title={itemTitle}
onBeforePress={onBeforePress}
onPressIn={onPressIn}
onPressOut={onPressOut}>
<View pointerEvents="none">
<PostMeta
author={quote.author}
moderation={moderation}
showAvatar
postHref={itemHref}
timestamp={quote.indexedAt}
/>
</View> </View>
{moderation ? ( ) : (
<PostAlerts <Link
modui={moderation.ui('contentView')} style={[!active && a.p_md]}
style={[a.py_xs]} hoverStyle={t.atoms.border_contrast_high}
/> href={itemHref}
) : null} title={itemTitle}
{richText ? ( onBeforePress={onBeforePress}
<RichText onPressIn={onPressIn}
value={richText} onPressOut={onPressOut}>
style={a.text_md} {contents}
numberOfLines={20} </Link>
disableLinks )}
/>
) : null}
{quote.embed && (
<Embed
embed={quote.embed}
moderation={moderation}
isWithinQuote={parentIsWithinQuote ?? true}
// already within quote? override nested
allowNestedQuotes={
parentIsWithinQuote ? false : parentAllowNestedQuotes
}
/>
)}
</Link>
</> </>
)} )}
</ContentHider> </ContentHider>
+1 -3
View File
@@ -1725,9 +1725,7 @@ function ComposerEmbeds({
<View <View
style={[a.pb_sm, video ? [a.pt_md] : [a.pt_xl], IS_WEB && [a.pb_md]]}> style={[a.pb_sm, video ? [a.pt_md] : [a.pt_xl], IS_WEB && [a.pb_md]]}>
<View style={[a.relative]}> <View style={[a.relative]}>
<View style={{pointerEvents: 'none'}}> <LazyQuoteEmbed uri={embed.quote.uri} linkDisabled />
<LazyQuoteEmbed uri={embed.quote.uri} />
</View>
{canRemoveQuote && ( {canRemoveQuote && (
<ExternalEmbedRemoveBtn <ExternalEmbedRemoveBtn
onRemove={() => dispatch({type: 'embed_remove_quote'})} onRemove={() => dispatch({type: 'embed_remove_quote'})}
+1 -1
View File
@@ -132,7 +132,7 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
)} )}
</View> </View>
{showFull && parsedQuoteEmbed && parsedQuoteEmbed.type === 'post' && ( {showFull && parsedQuoteEmbed && parsedQuoteEmbed.type === 'post' && (
<QuoteEmbed embed={parsedQuoteEmbed} /> <QuoteEmbed embed={parsedQuoteEmbed} linkDisabled />
)} )}
</View> </View>
</Pressable> </Pressable>