Enrich feed card embed on posts
The feed generator embed on posts only showed the avatar, title, and byline, even though the embed view is fully hydrated with more data. Make the embed a full card matching the feed discovery card: add the feed description (clamped to 3 lines), the "Liked by N users" count, and an interactive Pin/Save button. Also surface video feeds: add a small "Video feed" badge in TitleAndByline when contentMode is the video mode, which the discovery card picks up as well. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011CcnwUeBmYNFzhRGhV4RG5
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import {useCallback, useEffect, useMemo} from 'react'
|
import {useCallback, useEffect, useMemo} from 'react'
|
||||||
import {type GestureResponderEvent, View} from 'react-native'
|
import {type GestureResponderEvent, View} from 'react-native'
|
||||||
import {
|
import {
|
||||||
type AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
type AppBskyGraphDefs,
|
type AppBskyGraphDefs,
|
||||||
AtUri,
|
AtUri,
|
||||||
RichText as RichTextApi,
|
RichText as RichTextApi,
|
||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
} from '#/components/Button'
|
} from '#/components/Button'
|
||||||
import {Live_Stroke2_Corner0_Rounded as LiveIcon} from '#/components/icons/Live'
|
import {Live_Stroke2_Corner0_Rounded as LiveIcon} from '#/components/icons/Live'
|
||||||
import {Pin_Stroke2_Corner0_Rounded as PinIcon} from '#/components/icons/Pin'
|
import {Pin_Stroke2_Corner0_Rounded as PinIcon} from '#/components/icons/Pin'
|
||||||
|
import {VideoClip_Stroke2_Corner0_Rounded as VideoClipIcon} from '#/components/icons/VideoClip'
|
||||||
import {Link as InternalLink, type LinkProps} from '#/components/Link'
|
import {Link as InternalLink, type LinkProps} from '#/components/Link'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
@@ -54,6 +55,7 @@ export function Default(props: Props) {
|
|||||||
title={view.displayName}
|
title={view.displayName}
|
||||||
creator={view.creator}
|
creator={view.creator}
|
||||||
uri={view.uri}
|
uri={view.uri}
|
||||||
|
contentMode={view.contentMode}
|
||||||
/>
|
/>
|
||||||
<SaveButton view={view} pin />
|
<SaveButton view={view} pin />
|
||||||
</Header>
|
</Header>
|
||||||
@@ -124,13 +126,16 @@ export function TitleAndByline({
|
|||||||
title,
|
title,
|
||||||
creator,
|
creator,
|
||||||
uri,
|
uri,
|
||||||
|
contentMode,
|
||||||
}: {
|
}: {
|
||||||
title: string
|
title: string
|
||||||
creator?: bsky.profile.AnyProfileView
|
creator?: bsky.profile.AnyProfileView
|
||||||
uri?: string
|
uri?: string
|
||||||
|
contentMode?: AppBskyFeedDefs.GeneratorView['contentMode']
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const activeLiveEvents = useActiveLiveEventFeedUris()
|
const activeLiveEvents = useActiveLiveEventFeedUris()
|
||||||
|
const isVideoFeed = contentMode === AppBskyFeedDefs.CONTENTMODEVIDEO
|
||||||
const liveColor = useMemo(
|
const liveColor = useMemo(
|
||||||
() =>
|
() =>
|
||||||
select(t.name, {
|
select(t.name, {
|
||||||
@@ -170,6 +175,20 @@ export function TitleAndByline({
|
|||||||
<Trans>Feed by {sanitizeHandle(creator.handle, '@')}</Trans>
|
<Trans>Feed by {sanitizeHandle(creator.handle, '@')}</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
{isVideoFeed && (
|
||||||
|
<View style={[a.flex_row, a.align_center, a.gap_2xs, a.pt_2xs]}>
|
||||||
|
<VideoClipIcon size="xs" fill={t.atoms.text_contrast_medium.color} />
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.text_2xs,
|
||||||
|
a.font_medium,
|
||||||
|
a.leading_snug,
|
||||||
|
t.atoms.text_contrast_medium,
|
||||||
|
]}>
|
||||||
|
<Trans>Video feed</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,15 @@ export function FeedEmbed({
|
|||||||
title={embed.view.displayName}
|
title={embed.view.displayName}
|
||||||
creator={embed.view.creator}
|
creator={embed.view.creator}
|
||||||
uri={embed.view.uri}
|
uri={embed.view.uri}
|
||||||
|
contentMode={embed.view.contentMode}
|
||||||
/>
|
/>
|
||||||
|
<FeedCard.SaveButton view={embed.view} pin />
|
||||||
</FeedCard.Header>
|
</FeedCard.Header>
|
||||||
|
<FeedCard.Description
|
||||||
|
description={embed.view.description}
|
||||||
|
numberOfLines={3}
|
||||||
|
/>
|
||||||
|
<FeedCard.Likes count={embed.view.likeCount || 0} />
|
||||||
</FeedCard.Outer>
|
</FeedCard.Outer>
|
||||||
</FeedCard.Link>
|
</FeedCard.Link>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user