Handle live event in feed card
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, {useMemo} from 'react'
|
||||
import {type GestureResponderEvent, View} from 'react-native'
|
||||
import {
|
||||
type AppBskyFeedDefs,
|
||||
@@ -21,19 +21,21 @@ import {
|
||||
import {useSession} from '#/state/session'
|
||||
import * as Toast from '#/view/com/util/Toast'
|
||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {atoms as a, select, useTheme} from '#/alf'
|
||||
import {
|
||||
Button,
|
||||
ButtonIcon,
|
||||
type ButtonProps,
|
||||
ButtonText,
|
||||
} from '#/components/Button'
|
||||
import {Live_Stroke2_Corner0_Rounded as LiveIcon} from '#/components/icons/Live'
|
||||
import {Pin_Stroke2_Corner0_Rounded as PinIcon} from '#/components/icons/Pin'
|
||||
import {Link as InternalLink, type LinkProps} from '#/components/Link'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import {RichText, type RichTextProps} from '#/components/RichText'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useActiveLiveEventFeedUris} from '#/features/liveEvents/context'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from './icons/Trash'
|
||||
|
||||
@@ -49,7 +51,11 @@ export function Default(props: Props) {
|
||||
<Outer>
|
||||
<Header>
|
||||
<Avatar src={view.avatar} />
|
||||
<TitleAndByline title={view.displayName} creator={view.creator} />
|
||||
<TitleAndByline
|
||||
title={view.displayName}
|
||||
creator={view.creator}
|
||||
uri={view.uri}
|
||||
/>
|
||||
<SaveButton view={view} pin />
|
||||
</Header>
|
||||
<Description description={view.description} />
|
||||
@@ -118,14 +124,40 @@ export function AvatarPlaceholder({size = 40}: Omit<AvatarProps, 'src'>) {
|
||||
export function TitleAndByline({
|
||||
title,
|
||||
creator,
|
||||
uri,
|
||||
}: {
|
||||
title: string
|
||||
creator?: bsky.profile.AnyProfileView
|
||||
uri?: string
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const activeLiveEvents = useActiveLiveEventFeedUris()
|
||||
const liveColor = useMemo(
|
||||
() =>
|
||||
select(t.name, {
|
||||
dark: t.palette.negative_600,
|
||||
dim: t.palette.negative_600,
|
||||
light: t.palette.negative_500,
|
||||
}),
|
||||
[t],
|
||||
)
|
||||
|
||||
return (
|
||||
<View style={[a.flex_1]}>
|
||||
{uri && activeLiveEvents.has(uri) && (
|
||||
<View style={[a.flex_row, a.align_center, a.gap_2xs]}>
|
||||
<LiveIcon size="xs" fill={liveColor} />
|
||||
<Text
|
||||
style={[
|
||||
a.text_2xs,
|
||||
a.font_medium,
|
||||
a.leading_snug,
|
||||
{color: liveColor},
|
||||
]}>
|
||||
<Trans>Happening now</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
<Text
|
||||
emoji
|
||||
style={[a.text_md, a.font_semi_bold, a.leading_snug]}
|
||||
|
||||
@@ -842,6 +842,7 @@ export function SuggestedFeeds() {
|
||||
<FeedCard.TitleAndByline
|
||||
title={feed.displayName}
|
||||
creator={feed.creator}
|
||||
uri={feed.uri}
|
||||
/>
|
||||
</FeedCard.Header>
|
||||
<FeedCard.Description
|
||||
|
||||
@@ -17,16 +17,16 @@ export function FeedEmbed({
|
||||
return (
|
||||
<FeedCard.Link
|
||||
view={embed.view}
|
||||
style={[a.border, t.atoms.border_contrast_low, a.p_md, a.rounded_sm]}>
|
||||
style={[a.border, t.atoms.border_contrast_low, a.p_sm, a.rounded_md]}>
|
||||
<FeedCard.Outer>
|
||||
<FeedCard.Header>
|
||||
<FeedCard.Avatar src={embed.view.avatar} />
|
||||
<FeedCard.Avatar src={embed.view.avatar} size={48} />
|
||||
<FeedCard.TitleAndByline
|
||||
title={embed.view.displayName}
|
||||
creator={embed.view.creator}
|
||||
uri={embed.view.uri}
|
||||
/>
|
||||
</FeedCard.Header>
|
||||
<FeedCard.Likes count={embed.view.likeCount || 0} />
|
||||
</FeedCard.Outer>
|
||||
</FeedCard.Link>
|
||||
)
|
||||
|
||||
@@ -2,6 +2,11 @@ import {createContext, useContext} from 'react'
|
||||
import {QueryClient, useQuery} from '@tanstack/react-query'
|
||||
|
||||
import {useIsBskyTeam} from '#/lib/hooks/useIsBskyTeam'
|
||||
import {
|
||||
convertBskyAppUrlIfNeeded,
|
||||
isBskyCustomFeedUrl,
|
||||
makeRecordUri,
|
||||
} from '#/lib/strings/url-helpers'
|
||||
import {IS_DEV, LIVE_EVENTS_URL} from '#/env'
|
||||
import {useLiveEventPreferences} from '#/features/liveEvents/preferences'
|
||||
import {type LiveEventsWorkerResponse} from '#/features/liveEvents/types'
|
||||
@@ -88,3 +93,19 @@ export function useUserPreferencedLiveEvents() {
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
export function useActiveLiveEventFeedUris() {
|
||||
const {feeds} = useLiveEvents()
|
||||
|
||||
return new Set(
|
||||
feeds
|
||||
// insurance
|
||||
.filter(f => isBskyCustomFeedUrl(f.url))
|
||||
.map(f => {
|
||||
const uri = convertBskyAppUrlIfNeeded(f.url)
|
||||
const [_0, did, _1, rkey] = uri.split('/').filter(Boolean)
|
||||
const urip = makeRecordUri(did, 'app.bsky.feed.generator', rkey)
|
||||
return urip.toString()
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user