Files
bsky-social-app/src/components/Post/Embed/JoinRequestEmbed.tsx
T
2026-06-13 00:57:16 +03:00

84 lines
2.1 KiB
TypeScript

import {type StyleProp, View, type ViewStyle} from 'react-native'
import {
type ChatInvitePreview,
isKnownJoinLinkPreview,
} from '#/state/queries/join-links'
import {atoms as a, useTheme} from '#/alf'
import * as ChatInvite from '#/components/dms/ChatInvite'
const JOIN_REQUEST_EMBED_HEIGHT = 140
/**
* The "join request" presentation of a chat invite, used as a post embed (in
* feeds and the post composer). Composes the headless `ChatInvite` primitive:
* pass either a `code` to fetch by, or an already-resolved `preview` as the
* initial data to avoid a loading flash.
*/
export function JoinRequestEmbed({
code,
preview,
style,
onOpen,
}: {
code?: string
preview?: ChatInvitePreview
style?: StyleProp<ViewStyle>
onOpen?: () => void
}) {
const resolvedCode =
code ?? (isKnownJoinLinkPreview(preview) ? preview.code : undefined)
if (!resolvedCode) return null
return (
<ChatInvite.Root
code={resolvedCode}
initialPreview={preview}
hasFixedHeight>
<JoinRequestEmbedBody style={style} onOpen={onOpen} />
</ChatInvite.Root>
)
}
/**
* The context-consuming presentation (loading / no-longer-available / card +
* join button). Exported so surfaces that own their own `ChatInvite.Root` (e.g.
* to add an error fallback) can render it without nesting another Root.
*/
export function JoinRequestEmbedBody({
style,
onOpen,
}: {
style?: StyleProp<ViewStyle>
onOpen?: () => void
}) {
const t = useTheme()
const {status} = ChatInvite.useChatInvite()
const box = [
a.border,
a.rounded_lg,
t.atoms.border_contrast_low,
{height: JOIN_REQUEST_EMBED_HEIGHT},
]
if (status === 'loading') {
return <ChatInvite.Loading style={[box, a.p_lg, style]} />
}
if (status !== 'available') {
return (
<ChatInvite.Unavailable
style={[box, a.p_lg, t.atoms.bg_contrast_25, style]}
/>
)
}
return (
<View style={[a.justify_between, a.p_lg, a.gap_lg, box, style]}>
<ChatInvite.Card size="large" />
<ChatInvite.JoinButton onPress={onOpen} />
</View>
)
}