about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-12-05 18:17:03 -0800
committerGitHub <noreply@github.com>2023-12-05 18:17:03 -0800
commit712cd3fde55cca0444086e4512322832875d4836 (patch)
treecb8b59a4b4e46e5d96e9cba5179a9cd59de62293 /src
parentaccb25ccf2f0a00a82ff54f0659abd46e0ac8284 (diff)
downloadvoidsky-712cd3fde55cca0444086e4512322832875d4836.tar.zst
Perf: Include quote posts in the post-thread placeholder (#2104)
Diffstat (limited to 'src')
-rw-r--r--src/state/queries/notifications/feed.ts5
-rw-r--r--src/state/queries/post-feed.ts5
-rw-r--r--src/state/queries/post-thread.ts39
-rw-r--r--src/state/queries/util.ts48
4 files changed, 96 insertions, 1 deletions
diff --git a/src/state/queries/notifications/feed.ts b/src/state/queries/notifications/feed.ts
index 16025f856..4d4c850ca 100644
--- a/src/state/queries/notifications/feed.ts
+++ b/src/state/queries/notifications/feed.ts
@@ -30,6 +30,7 @@ import {fetchPage} from './util'
 import {FeedPage} from './types'
 import {useMutedThreads} from '#/state/muted-threads'
 import {STALE} from '..'
+import {embedViewRecordToPostView, getEmbeddedPost} from '../util'
 
 export type {NotificationType, FeedNotification, FeedPage} from './types'
 
@@ -119,6 +120,10 @@ export function* findAllPostsInQueryData(
         if (item.subject?.uri === uri) {
           yield item.subject
         }
+        const quotedPost = getEmbeddedPost(item.subject.embed)
+        if (quotedPost?.uri === uri) {
+          yield embedViewRecordToPostView(quotedPost)
+        }
       }
     }
   }
diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts
index 7cdda577c..de18865ea 100644
--- a/src/state/queries/post-feed.ts
+++ b/src/state/queries/post-feed.ts
@@ -23,6 +23,7 @@ import {getAgent} from '#/state/session'
 import {DEFAULT_LOGGED_OUT_PREFERENCES} from '#/state/queries/preferences/const'
 import {getModerationOpts} from '#/state/queries/preferences/moderation'
 import {KnownError} from '#/view/com/posts/FeedErrorMessage'
+import {embedViewRecordToPostView, getEmbeddedPost} from './util'
 
 type ActorDid = string
 type AuthorFilter =
@@ -263,6 +264,10 @@ export function* findAllPostsInQueryData(
         if (item.post.uri === uri) {
           yield item.post
         }
+        const quotedPost = getEmbeddedPost(item.post.embed)
+        if (quotedPost?.uri === uri) {
+          yield embedViewRecordToPostView(quotedPost)
+        }
         if (
           AppBskyFeedDefs.isPostView(item.reply?.parent) &&
           item.reply?.parent?.uri === uri
diff --git a/src/state/queries/post-thread.ts b/src/state/queries/post-thread.ts
index cde45723a..cedbbc9dd 100644
--- a/src/state/queries/post-thread.ts
+++ b/src/state/queries/post-thread.ts
@@ -2,6 +2,7 @@ import {
   AppBskyFeedDefs,
   AppBskyFeedPost,
   AppBskyFeedGetPostThread,
+  AppBskyEmbedRecord,
 } from '@atproto/api'
 import {useQuery, useQueryClient, QueryClient} from '@tanstack/react-query'
 
@@ -10,6 +11,7 @@ import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
 import {findPostInQueryData as findPostInFeedQueryData} from './post-feed'
 import {findPostInQueryData as findPostInNotifsQueryData} from './notifications/feed'
 import {precacheThreadPosts as precacheResolvedUris} from './resolve-uri'
+import {getEmbeddedPost} from './util'
 
 export const RQKEY = (uri: string) => ['post-thread', uri]
 type ThreadViewNode = AppBskyFeedGetPostThread.OutputSchema['thread']
@@ -237,6 +239,10 @@ export function* findAllPostsInQueryData(
       if (item.uri === uri) {
         yield item
       }
+      const quotedPost = getEmbeddedPost(item.post.embed)
+      if (quotedPost?.uri === uri) {
+        yield embedViewRecordToPlaceholderThread(quotedPost)
+      }
     }
   }
 }
@@ -301,7 +307,38 @@ function postViewToPlaceholderThread(
       showChildReplyLine: false,
       showParentReplyLine: false,
       isParentLoading: !!(post.record as AppBskyFeedPost.Record).reply,
-      isChildLoading: !!post.replyCount,
+      isChildLoading: true, // assume yes (show the spinner) just in case
+    },
+  }
+}
+
+function embedViewRecordToPlaceholderThread(
+  record: AppBskyEmbedRecord.ViewRecord,
+): ThreadNode {
+  return {
+    type: 'post',
+    _reactKey: record.uri,
+    uri: record.uri,
+    post: {
+      uri: record.uri,
+      cid: record.cid,
+      author: record.author,
+      record: record.value,
+      indexedAt: record.indexedAt,
+      labels: record.labels,
+    },
+    record: record.value as AppBskyFeedPost.Record, // validated in getEmbeddedPost
+    parent: undefined,
+    replies: undefined,
+    viewer: undefined, // not available
+    ctx: {
+      depth: 0,
+      isHighlightedPost: true,
+      hasMore: false,
+      showChildReplyLine: false,
+      showParentReplyLine: false,
+      isParentLoading: !!(record.value as AppBskyFeedPost.Record).reply,
+      isChildLoading: true, // not available, so assume yes (to show the spinner)
     },
   }
 }
diff --git a/src/state/queries/util.ts b/src/state/queries/util.ts
index ed91a8f2a..b259b1922 100644
--- a/src/state/queries/util.ts
+++ b/src/state/queries/util.ts
@@ -1,4 +1,10 @@
 import {QueryClient, QueryKey, InfiniteData} from '@tanstack/react-query'
+import {
+  AppBskyEmbedRecord,
+  AppBskyEmbedRecordWithMedia,
+  AppBskyFeedDefs,
+  AppBskyFeedPost,
+} from '@atproto/api'
 
 export function truncateAndInvalidate<T = any>(
   queryClient: QueryClient,
@@ -15,3 +21,45 @@ export function truncateAndInvalidate<T = any>(
   })
   queryClient.invalidateQueries({queryKey})
 }
+
+export function getEmbeddedPost(
+  v: unknown,
+): AppBskyEmbedRecord.ViewRecord | undefined {
+  if (
+    AppBskyEmbedRecord.isView(v) &&
+    AppBskyEmbedRecord.validateView(v).success
+  ) {
+    if (
+      AppBskyEmbedRecord.isViewRecord(v.record) &&
+      AppBskyFeedPost.isRecord(v.record.value) &&
+      AppBskyFeedPost.validateRecord(v.record.value).success
+    ) {
+      return v.record
+    }
+  }
+  if (
+    AppBskyEmbedRecordWithMedia.isView(v) &&
+    AppBskyEmbedRecordWithMedia.validateView(v).success
+  ) {
+    if (
+      AppBskyEmbedRecord.isViewRecord(v.record.record) &&
+      AppBskyFeedPost.isRecord(v.record.record.value) &&
+      AppBskyFeedPost.validateRecord(v.record.record.value).success
+    ) {
+      return v.record.record
+    }
+  }
+}
+
+export function embedViewRecordToPostView(
+  v: AppBskyEmbedRecord.ViewRecord,
+): AppBskyFeedDefs.PostView {
+  return {
+    uri: v.uri,
+    cid: v.cid,
+    author: v.author,
+    record: v.value,
+    indexedAt: v.indexedAt,
+    labels: v.labels,
+  }
+}