about summary refs log tree commit diff
path: root/src/lib/api
diff options
context:
space:
mode:
authordan <dan.abramov@gmail.com>2024-10-08 09:02:58 +0900
committerGitHub <noreply@github.com>2024-10-07 17:02:58 -0700
commitc06040cc209338fc37980648b31d4d64cc0c5c09 (patch)
tree766e41a310b03bed2e927f468114ca8d14602e5f /src/lib/api
parentdd8be2e939d2879e2bb23b2ccd843a034d19b8dd (diff)
downloadvoidsky-c06040cc209338fc37980648b31d4d64cc0c5c09.tar.zst
Fetch link previews from RQ (#5608)
Co-authored-by: Mary <git@mary.my.id>
Co-authored-by: Hailey <me@haileyok.com>
Diffstat (limited to 'src/lib/api')
-rw-r--r--src/lib/api/index.ts47
-rw-r--r--src/lib/api/resolve.ts49
2 files changed, 81 insertions, 15 deletions
diff --git a/src/lib/api/index.ts b/src/lib/api/index.ts
index e6e8eea3d..6edb111e6 100644
--- a/src/lib/api/index.ts
+++ b/src/lib/api/index.ts
@@ -12,6 +12,7 @@ import {
   ComAtprotoRepoStrongRef,
   RichText,
 } from '@atproto/api'
+import {QueryClient} from '@tanstack/react-query'
 
 import {isNetworkError} from '#/lib/strings/errors'
 import {shortenLinks, stripInvalidMentions} from '#/lib/strings/rich-text-manip'
@@ -19,6 +20,10 @@ import {logger} from '#/logger'
 import {ComposerImage, compressImage} from '#/state/gallery'
 import {writePostgateRecord} from '#/state/queries/postgate'
 import {
+  fetchResolveGifQuery,
+  fetchResolveLinkQuery,
+} from '#/state/queries/resolve-link'
+import {
   createThreadgateRecord,
   ThreadgateAllowUISetting,
   threadgateAllowUISettingToAllowRecordValue,
@@ -27,7 +32,6 @@ import {
 import {ComposerState, EmbedDraft} from '#/view/com/composer/state/composer'
 import {createGIFDescription} from '../gif-alt-text'
 import {LinkMeta} from '../link-meta/link-meta'
-import {resolveGif, resolveLink} from './resolve'
 import {uploadBlob} from './upload-blob'
 
 export {uploadBlob}
@@ -51,7 +55,11 @@ interface PostOpts {
   langs?: string[]
 }
 
-export async function post(agent: BskyAgent, opts: PostOpts) {
+export async function post(
+  agent: BskyAgent,
+  queryClient: QueryClient,
+  opts: PostOpts,
+) {
   let reply
   let rt = new RichText({text: opts.rawText.trimEnd()}, {cleanNewlines: true})
 
@@ -64,6 +72,7 @@ export async function post(agent: BskyAgent, opts: PostOpts) {
 
   const embed = await resolveEmbed(
     agent,
+    queryClient,
     opts.composerState,
     opts.onStateChange,
   )
@@ -178,6 +187,7 @@ export async function post(agent: BskyAgent, opts: PostOpts) {
 
 async function resolveEmbed(
   agent: BskyAgent,
+  queryClient: QueryClient,
   draft: ComposerState,
   onStateChange: ((state: string) => void) | undefined,
 ): Promise<
@@ -190,8 +200,8 @@ async function resolveEmbed(
 > {
   if (draft.embed.quote) {
     const [resolvedMedia, resolvedQuote] = await Promise.all([
-      resolveMedia(agent, draft.embed, onStateChange),
-      resolveRecord(agent, draft.embed.quote.uri),
+      resolveMedia(agent, queryClient, draft.embed, onStateChange),
+      resolveRecord(agent, queryClient, draft.embed.quote.uri),
     ])
     if (resolvedMedia) {
       return {
@@ -208,12 +218,21 @@ async function resolveEmbed(
       record: resolvedQuote,
     }
   }
-  const resolvedMedia = await resolveMedia(agent, draft.embed, onStateChange)
+  const resolvedMedia = await resolveMedia(
+    agent,
+    queryClient,
+    draft.embed,
+    onStateChange,
+  )
   if (resolvedMedia) {
     return resolvedMedia
   }
   if (draft.embed.link) {
-    const resolvedLink = await resolveLink(agent, draft.embed.link.uri)
+    const resolvedLink = await fetchResolveLinkQuery(
+      queryClient,
+      agent,
+      draft.embed.link.uri,
+    )
     if (resolvedLink.type === 'record') {
       return {
         $type: 'app.bsky.embed.record',
@@ -226,6 +245,7 @@ async function resolveEmbed(
 
 async function resolveMedia(
   agent: BskyAgent,
+  queryClient: QueryClient,
   embedDraft: EmbedDraft,
   onStateChange: ((state: string) => void) | undefined,
 ): Promise<
@@ -286,7 +306,11 @@ async function resolveMedia(
   }
   if (embedDraft.media?.type === 'gif') {
     const gifDraft = embedDraft.media
-    const resolvedGif = await resolveGif(agent, gifDraft.gif)
+    const resolvedGif = await fetchResolveGifQuery(
+      queryClient,
+      agent,
+      gifDraft.gif,
+    )
     let blob: BlobRef | undefined
     if (resolvedGif.thumb) {
       onStateChange?.('Uploading link thumbnail...')
@@ -305,7 +329,11 @@ async function resolveMedia(
     }
   }
   if (embedDraft.link) {
-    const resolvedLink = await resolveLink(agent, embedDraft.link.uri)
+    const resolvedLink = await fetchResolveLinkQuery(
+      queryClient,
+      agent,
+      embedDraft.link.uri,
+    )
     if (resolvedLink.type === 'external') {
       let blob: BlobRef | undefined
       if (resolvedLink.thumb) {
@@ -330,9 +358,10 @@ async function resolveMedia(
 
 async function resolveRecord(
   agent: BskyAgent,
+  queryClient: QueryClient,
   uri: string,
 ): Promise<ComAtprotoRepoStrongRef.Main> {
-  const resolvedLink = await resolveLink(agent, uri)
+  const resolvedLink = await fetchResolveLinkQuery(queryClient, agent, uri)
   if (resolvedLink.type !== 'record') {
     throw Error('Expected uri to resolve to a record')
   }
diff --git a/src/lib/api/resolve.ts b/src/lib/api/resolve.ts
index a97a3f31c..4f409e100 100644
--- a/src/lib/api/resolve.ts
+++ b/src/lib/api/resolve.ts
@@ -1,4 +1,4 @@
-import {ComAtprotoRepoStrongRef} from '@atproto/api'
+import {AppBskyActorDefs, ComAtprotoRepoStrongRef} from '@atproto/api'
 import {AtUri} from '@atproto/api'
 import {BskyAgent} from '@atproto/api'
 
@@ -33,12 +33,32 @@ type ResolvedExternalLink = {
   thumb: ComposerImage | undefined
 }
 
-type ResolvedRecord = {
+type ResolvedPostRecord = {
   type: 'record'
   record: ComAtprotoRepoStrongRef.Main
+  kind: 'post'
+  meta: {
+    text: string
+    indexedAt: string
+    author: AppBskyActorDefs.ProfileViewBasic
+  }
 }
 
-type ResolvedLink = ResolvedExternalLink | ResolvedRecord
+type ResolvedOtherRecord = {
+  type: 'record'
+  record: ComAtprotoRepoStrongRef.Main
+  kind: 'other'
+  meta: {
+    // We should replace this with a hydrated record (e.g. feed, list, starter pack)
+    // and change the composer preview to use the actual post embed components:
+    title: string
+  }
+}
+
+export type ResolvedLink =
+  | ResolvedExternalLink
+  | ResolvedPostRecord
+  | ResolvedOtherRecord
 
 export async function resolveLink(
   agent: BskyAgent,
@@ -57,6 +77,8 @@ export async function resolveLink(
         cid: result.cid,
         uri: result.uri,
       },
+      kind: 'post',
+      meta: result,
     }
   }
   if (isBskyCustomFeedUrl(uri)) {
@@ -64,7 +86,12 @@ export async function resolveLink(
     const result = await getFeedAsEmbed(agent, fetchDid, uri)
     return {
       type: 'record',
-      record: result.embed!.record, // TODO: Fix types.
+      record: result.embed!.record,
+      kind: 'other',
+      meta: {
+        // TODO: Include hydrated content instead.
+        title: result.meta!.title!,
+      },
     }
   }
   if (isBskyListUrl(uri)) {
@@ -72,7 +99,12 @@ export async function resolveLink(
     const result = await getListAsEmbed(agent, fetchDid, uri)
     return {
       type: 'record',
-      record: result.embed!.record, // TODO: Fix types.
+      record: result.embed!.record,
+      kind: 'other',
+      meta: {
+        // TODO: Include hydrated content instead.
+        title: result.meta!.title!,
+      },
     }
   }
   if (isBskyStartUrl(uri) || isBskyStarterPackUrl(uri)) {
@@ -80,7 +112,12 @@ export async function resolveLink(
     const result = await getStarterPackAsEmbed(agent, fetchDid, uri)
     return {
       type: 'record',
-      record: result.embed!.record, // TODO: Fix types.
+      record: result.embed!.record,
+      kind: 'other',
+      meta: {
+        // TODO: Include hydrated content instead.
+        title: result.meta!.title!,
+      },
     }
   }
   return resolveExternal(agent, uri)