Resolve chat invites

This commit is contained in:
Eric Bailey
2026-06-08 15:38:18 -05:00
parent e2378f8614
commit 5e0ebcefd2
3 changed files with 38 additions and 2 deletions
@@ -69,7 +69,7 @@ function makeStore() {
return createThreadStore({
agent,
__createId: makeIdGenerator(),
__resolveLink: mockResolveLink as unknown as typeof resolveLink,
__resolveLink: mockResolveLink,
})
}
@@ -118,6 +118,13 @@ const externalLink: ResolvedLink = {
thumb: undefined,
}
const chatInviteLink: ResolvedLink = {
type: 'chat-invite',
uri: 'https://bsky.app/messages/join/abc123',
code: 'abc123',
view: undefined,
}
describe('addUri pre-classifies bsky post URLs to the quote slot', () => {
test('post URL → quote.pending → quote.resolved (with view)', async () => {
const d = deferred<ResolvedLink>()
@@ -258,6 +265,19 @@ describe('addUri pre-classifies non-post URLs to the embed slot', () => {
expect(embed.title).toBe('Example')
})
test('chat-invite → embed["chat-invite"]', async () => {
const d = deferred<ResolvedLink>()
mockResolveLink.mockReturnValueOnce(d.promise)
const store = makeStore()
const root = rootId(store)
store.actions.addUri(root, EXTERNAL_URL)
d.resolve(chatInviteLink)
await flushPromises()
const embed = store.getState().posts[root].embed
if (embed?.state !== 'chat-invite') throw new Error('expected chat-invite')
expect(embed.code).toBe('abc123')
})
test('addUri is a no-op when embed has settled (resolved)', async () => {
const d = deferred<ResolvedLink>()
mockResolveLink.mockReturnValueOnce(d.promise)
+8
View File
@@ -608,6 +608,14 @@ export function createThreadStore(options: {
thumb: link.thumb,
}
}
if (link.type === 'chat-invite') {
return {
state: 'chat-invite',
uri: link.uri,
code: link.code,
view: link.view,
}
}
switch (link.kind) {
case 'feed':
return {state: 'feed', record: link.record, view: link.view}
+9 -1
View File
@@ -2,6 +2,7 @@ import {
type AppBskyFeedDefs,
type AppBskyGraphDefs,
type BlobRef,
type ChatBskyGroupDefs,
type ComAtprotoRepoStrongRef,
} from '@atproto/api'
@@ -97,7 +98,8 @@ export type LinkResolutionFailureCode = 'embedding-disabled' | 'unknown'
* `embedding-disabled`) `retry` is omitted so UI can detect that case and
* surface a non-retryable message. The pending variant is set synchronously
* by addUri while resolution is in flight; the resolved variants
* (external/feed/list/starter-pack) land when the worker reports back.
* (external/feed/list/starter-pack/chat-invite) land when the worker
* reports back.
*
* Note: `retry` is a function reference and won't survive JSON serialization.
* On restore (OS-resume / draft load), the store re-attaches it.
@@ -135,6 +137,12 @@ export type PostEmbed =
record: ComAtprotoRepoStrongRef.Main
view: AppBskyGraphDefs.StarterPackView
}
| {
state: 'chat-invite'
uri: string
code: string
view: ChatBskyGroupDefs.JoinLinkPreviewView | undefined
}
/**
* What's stored on a post's `quote` field. Mirrors `PostEmbed`'s shape: the