about summary refs log tree commit diff
path: root/src/state
diff options
context:
space:
mode:
Diffstat (limited to 'src/state')
-rw-r--r--src/state/cache/profile-shadow.ts13
-rw-r--r--src/state/cache/thread-mutes.tsx1
-rw-r--r--src/state/messages/convo/agent.ts23
-rw-r--r--src/state/messages/convo/types.ts26
-rw-r--r--src/state/messages/events/agent.ts7
-rw-r--r--src/state/queries/list.ts9
-rw-r--r--src/state/queries/messages/actor-declaration.ts2
-rw-r--r--src/state/queries/messages/list-conversations.tsx50
-rw-r--r--src/state/queries/notifications/feed.ts18
-rw-r--r--src/state/queries/notifications/util.ts18
-rw-r--r--src/state/queries/post-feed.ts2
-rw-r--r--src/state/queries/post-quotes.ts2
-rw-r--r--src/state/queries/post-thread.ts11
-rw-r--r--src/state/queries/postgate/index.ts6
-rw-r--r--src/state/queries/postgate/util.ts11
-rw-r--r--src/state/queries/profile.ts74
-rw-r--r--src/state/queries/resolve-uri.ts19
-rw-r--r--src/state/queries/search-posts.ts2
-rw-r--r--src/state/queries/service-config.ts1
-rw-r--r--src/state/queries/starter-packs.ts11
-rw-r--r--src/state/queries/threadgate/index.ts6
-rw-r--r--src/state/queries/threadgate/types.ts2
-rw-r--r--src/state/queries/threadgate/util.ts21
-rw-r--r--src/state/queries/unstable-profile-cache.ts51
-rw-r--r--src/state/queries/util.ts13
-rw-r--r--src/state/shell/composer/index.tsx3
26 files changed, 246 insertions, 156 deletions
diff --git a/src/state/cache/profile-shadow.ts b/src/state/cache/profile-shadow.ts
index 4d823ec8e..adbff3919 100644
--- a/src/state/cache/profile-shadow.ts
+++ b/src/state/cache/profile-shadow.ts
@@ -1,9 +1,9 @@
 import {useEffect, useMemo, useState} from 'react'
-import {AppBskyActorDefs} from '@atproto/api'
 import {QueryClient} from '@tanstack/react-query'
 import EventEmitter from 'eventemitter3'
 
 import {batchedUpdates} from '#/lib/batchedUpdates'
+import * as bsky from '#/types/bsky'
 import {findAllProfilesInQueryData as findAllProfilesInActorSearchQueryData} from '../queries/actor-search'
 import {findAllProfilesInQueryData as findAllProfilesInKnownFollowersQueryData} from '../queries/known-followers'
 import {findAllProfilesInQueryData as findAllProfilesInListMembersQueryData} from '../queries/list-members'
@@ -20,6 +20,7 @@ import {findAllProfilesInQueryData as findAllProfilesInProfileFollowersQueryData
 import {findAllProfilesInQueryData as findAllProfilesInProfileFollowsQueryData} from '../queries/profile-follows'
 import {findAllProfilesInQueryData as findAllProfilesInSuggestedFollowsQueryData} from '../queries/suggested-follows'
 import {castAsShadow, Shadow} from './types'
+
 export type {Shadow} from './types'
 
 export interface ProfileShadow {
@@ -29,13 +30,13 @@ export interface ProfileShadow {
 }
 
 const shadows: WeakMap<
-  AppBskyActorDefs.ProfileView,
+  bsky.profile.AnyProfileView,
   Partial<ProfileShadow>
 > = new WeakMap()
 const emitter = new EventEmitter()
 
 export function useProfileShadow<
-  TProfileView extends AppBskyActorDefs.ProfileView,
+  TProfileView extends bsky.profile.AnyProfileView,
 >(profile: TProfileView): Shadow<TProfileView> {
   const [shadow, setShadow] = useState(() => shadows.get(profile))
   const [prevPost, setPrevPost] = useState(profile)
@@ -68,7 +69,7 @@ export function useProfileShadow<
  * This is useful for when the profile is not guaranteed to be loaded yet.
  */
 export function useMaybeProfileShadow<
-  TProfileView extends AppBskyActorDefs.ProfileView,
+  TProfileView extends bsky.profile.AnyProfileView,
 >(profile?: TProfileView): Shadow<TProfileView> | undefined {
   const [shadow, setShadow] = useState(() =>
     profile ? shadows.get(profile) : undefined,
@@ -115,7 +116,7 @@ export function updateProfileShadow(
   })
 }
 
-function mergeShadow<TProfileView extends AppBskyActorDefs.ProfileView>(
+function mergeShadow<TProfileView extends bsky.profile.AnyProfileView>(
   profile: TProfileView,
   shadow: Partial<ProfileShadow>,
 ): Shadow<TProfileView> {
@@ -137,7 +138,7 @@ function mergeShadow<TProfileView extends AppBskyActorDefs.ProfileView>(
 function* findProfilesInCache(
   queryClient: QueryClient,
   did: string,
-): Generator<AppBskyActorDefs.ProfileView, void> {
+): Generator<bsky.profile.AnyProfileView, void> {
   yield* findAllProfilesInListMembersQueryData(queryClient, did)
   yield* findAllProfilesInMyBlockedAccountsQueryData(queryClient, did)
   yield* findAllProfilesInMyMutedAccountsQueryData(queryClient, did)
diff --git a/src/state/cache/thread-mutes.tsx b/src/state/cache/thread-mutes.tsx
index dc5104c14..4492977f2 100644
--- a/src/state/cache/thread-mutes.tsx
+++ b/src/state/cache/thread-mutes.tsx
@@ -69,6 +69,7 @@ function useMigrateMutes(setThreadMute: SetStateContext) {
         while (!cancelled) {
           const threads = persisted.get('mutedThreads')
 
+          // @ts-ignore findLast is polyfilled - esb
           const root = threads.findLast(uri => uri.includes(currentAccount.did))
 
           if (!root) break
diff --git a/src/state/messages/convo/agent.ts b/src/state/messages/convo/agent.ts
index 91dd59813..eed44c757 100644
--- a/src/state/messages/convo/agent.ts
+++ b/src/state/messages/convo/agent.ts
@@ -1,6 +1,6 @@
 import {
-  AppBskyActorDefs,
   BskyAgent,
+  ChatBskyActorDefs,
   ChatBskyConvoDefs,
   ChatBskyConvoGetLog,
   ChatBskyConvoSendMessage,
@@ -80,8 +80,8 @@ export class Convo {
 
   convoId: string
   convo: ChatBskyConvoDefs.ConvoView | undefined
-  sender: AppBskyActorDefs.ProfileViewBasic | undefined
-  recipients: AppBskyActorDefs.ProfileViewBasic[] | undefined
+  sender: ChatBskyActorDefs.ProfileViewBasic | undefined
+  recipients: ChatBskyActorDefs.ProfileViewBasic[] | undefined
   snapshot: ConvoState | undefined
 
   constructor(params: ConvoParams) {
@@ -463,7 +463,7 @@ export class Convo {
         throw new Error('Convo: could not find recipients in convo')
       }
 
-      const userIsDisabled = this.sender.chatDisabled as boolean
+      const userIsDisabled = Boolean(this.sender.chatDisabled)
 
       if (userIsDisabled) {
         this.dispatch({event: ConvoDispatchEvent.Disable})
@@ -529,8 +529,8 @@ export class Convo {
   private pendingFetchConvo:
     | Promise<{
         convo: ChatBskyConvoDefs.ConvoView
-        sender: AppBskyActorDefs.ProfileViewBasic | undefined
-        recipients: AppBskyActorDefs.ProfileViewBasic[]
+        sender: ChatBskyActorDefs.ProfileViewBasic | undefined
+        recipients: ChatBskyActorDefs.ProfileViewBasic[]
       }>
     | undefined
   async fetchConvo() {
@@ -538,8 +538,8 @@ export class Convo {
 
     this.pendingFetchConvo = new Promise<{
       convo: ChatBskyConvoDefs.ConvoView
-      sender: AppBskyActorDefs.ProfileViewBasic | undefined
-      recipients: AppBskyActorDefs.ProfileViewBasic[]
+      sender: ChatBskyActorDefs.ProfileViewBasic | undefined
+      recipients: ChatBskyActorDefs.ProfileViewBasic[]
     }>(async (resolve, reject) => {
       try {
         const response = await networkRetry(2, () => {
@@ -704,7 +704,7 @@ export class Convo {
        * If there's a rev, we should handle it. If there's not a rev, we don't
        * know what it is.
        */
-      if (typeof ev.rev === 'string') {
+      if ('rev' in ev && typeof ev.rev === 'string') {
         const isUninitialized = !this.latestRev
         const isNewEvent = this.latestRev && ev.rev > this.latestRev
 
@@ -1049,7 +1049,10 @@ export class Convo {
            * `getItems` is only run in "active" status states, where
            * `this.sender` is defined
            */
-          sender: this.sender!,
+          sender: {
+            $type: 'chat.bsky.convo.defs#messageViewSender',
+            did: this.sender!.did,
+          },
         },
         nextMessage: null,
         prevMessage: null,
diff --git a/src/state/messages/convo/types.ts b/src/state/messages/convo/types.ts
index 9f1707c71..69e15acc4 100644
--- a/src/state/messages/convo/types.ts
+++ b/src/state/messages/convo/types.ts
@@ -1,6 +1,6 @@
 import {
-  AppBskyActorDefs,
   BskyAgent,
+  ChatBskyActorDefs,
   ChatBskyConvoDefs,
   ChatBskyConvoSendMessage,
 } from '@atproto/api'
@@ -147,8 +147,8 @@ export type ConvoStateUninitialized = {
   items: []
   convo: ChatBskyConvoDefs.ConvoView | undefined
   error: undefined
-  sender: AppBskyActorDefs.ProfileViewBasic | undefined
-  recipients: AppBskyActorDefs.ProfileViewBasic[] | undefined
+  sender: ChatBskyActorDefs.ProfileViewBasic | undefined
+  recipients: ChatBskyActorDefs.ProfileViewBasic[] | undefined
   isFetchingHistory: false
   deleteMessage: undefined
   sendMessage: undefined
@@ -159,8 +159,8 @@ export type ConvoStateInitializing = {
   items: []
   convo: ChatBskyConvoDefs.ConvoView | undefined
   error: undefined
-  sender: AppBskyActorDefs.ProfileViewBasic | undefined
-  recipients: AppBskyActorDefs.ProfileViewBasic[] | undefined
+  sender: ChatBskyActorDefs.ProfileViewBasic | undefined
+  recipients: ChatBskyActorDefs.ProfileViewBasic[] | undefined
   isFetchingHistory: boolean
   deleteMessage: undefined
   sendMessage: undefined
@@ -171,8 +171,8 @@ export type ConvoStateReady = {
   items: ConvoItem[]
   convo: ChatBskyConvoDefs.ConvoView
   error: undefined
-  sender: AppBskyActorDefs.ProfileViewBasic
-  recipients: AppBskyActorDefs.ProfileViewBasic[]
+  sender: ChatBskyActorDefs.ProfileViewBasic
+  recipients: ChatBskyActorDefs.ProfileViewBasic[]
   isFetchingHistory: boolean
   deleteMessage: DeleteMessage
   sendMessage: SendMessage
@@ -183,8 +183,8 @@ export type ConvoStateBackgrounded = {
   items: ConvoItem[]
   convo: ChatBskyConvoDefs.ConvoView
   error: undefined
-  sender: AppBskyActorDefs.ProfileViewBasic
-  recipients: AppBskyActorDefs.ProfileViewBasic[]
+  sender: ChatBskyActorDefs.ProfileViewBasic
+  recipients: ChatBskyActorDefs.ProfileViewBasic[]
   isFetchingHistory: boolean
   deleteMessage: DeleteMessage
   sendMessage: SendMessage
@@ -195,8 +195,8 @@ export type ConvoStateSuspended = {
   items: ConvoItem[]
   convo: ChatBskyConvoDefs.ConvoView
   error: undefined
-  sender: AppBskyActorDefs.ProfileViewBasic
-  recipients: AppBskyActorDefs.ProfileViewBasic[]
+  sender: ChatBskyActorDefs.ProfileViewBasic
+  recipients: ChatBskyActorDefs.ProfileViewBasic[]
   isFetchingHistory: boolean
   deleteMessage: DeleteMessage
   sendMessage: SendMessage
@@ -219,8 +219,8 @@ export type ConvoStateDisabled = {
   items: ConvoItem[]
   convo: ChatBskyConvoDefs.ConvoView
   error: undefined
-  sender: AppBskyActorDefs.ProfileViewBasic
-  recipients: AppBskyActorDefs.ProfileViewBasic[]
+  sender: ChatBskyActorDefs.ProfileViewBasic
+  recipients: ChatBskyActorDefs.ProfileViewBasic[]
   isFetchingHistory: boolean
   deleteMessage: DeleteMessage
   sendMessage: SendMessage
diff --git a/src/state/messages/events/agent.ts b/src/state/messages/events/agent.ts
index 01165256a..9244a4fa5 100644
--- a/src/state/messages/events/agent.ts
+++ b/src/state/messages/events/agent.ts
@@ -65,10 +65,7 @@ export class MessagesEventBus {
     const handle = (event: MessagesEventBusEvent) => {
       if (event.type === 'logs' && options.convoId) {
         const filteredLogs = event.logs.filter(log => {
-          if (
-            typeof log.convoId === 'string' &&
-            log.convoId === options.convoId
-          ) {
+          if ('convoId' in log && log.convoId === options.convoId) {
             return log.convoId === options.convoId
           }
           return false
@@ -355,7 +352,7 @@ export class MessagesEventBus {
          * If there's a rev, we should handle it. If there's not a rev, we don't
          * know what it is.
          */
-        if (typeof ev.rev === 'string') {
+        if ('rev' in ev && typeof ev.rev === 'string') {
           /*
            * We only care about new events
            */
diff --git a/src/state/queries/list.ts b/src/state/queries/list.ts
index be7542880..260a0bf2c 100644
--- a/src/state/queries/list.ts
+++ b/src/state/queries/list.ts
@@ -1,11 +1,14 @@
 import {Image as RNImage} from 'react-native-image-crop-picker'
 import {
+  $Typed,
   AppBskyGraphDefs,
   AppBskyGraphGetList,
   AppBskyGraphList,
   AtUri,
   BskyAgent,
+  ComAtprotoRepoApplyWrites,
   Facet,
+  Un$Typed,
 } from '@atproto/api'
 import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
 import chunk from 'lodash.chunk'
@@ -68,7 +71,7 @@ export function useListCreateMutation() {
         ) {
           throw new Error('Invalid list purpose: must be curatelist or modlist')
         }
-        const record: AppBskyGraphList.Record = {
+        const record: Un$Typed<AppBskyGraphList.Record> = {
           purpose,
           name,
           description,
@@ -212,7 +215,9 @@ export function useListDeleteMutation() {
       }
 
       // batch delete the list and listitem records
-      const createDel = (uri: string) => {
+      const createDel = (
+        uri: string,
+      ): $Typed<ComAtprotoRepoApplyWrites.Delete> => {
         const urip = new AtUri(uri)
         return {
           $type: 'com.atproto.repo.applyWrites#delete',
diff --git a/src/state/queries/messages/actor-declaration.ts b/src/state/queries/messages/actor-declaration.ts
index 828b85d9e..34fb10935 100644
--- a/src/state/queries/messages/actor-declaration.ts
+++ b/src/state/queries/messages/actor-declaration.ts
@@ -69,12 +69,10 @@ export function useDeleteActorDeclaration() {
   return useMutation({
     mutationFn: async () => {
       if (!currentAccount) throw new Error('Not signed in')
-      // TODO(sam): remove validate: false once PDSes have the new lexicon
       const result = await agent.api.com.atproto.repo.deleteRecord({
         repo: currentAccount.did,
         collection: 'chat.bsky.actor.declaration',
         rkey: 'self',
-        validate: false,
       })
       return result
     },
diff --git a/src/state/queries/messages/list-conversations.tsx b/src/state/queries/messages/list-conversations.tsx
index ae379f962..8c9d6c429 100644
--- a/src/state/queries/messages/list-conversations.tsx
+++ b/src/state/queries/messages/list-conversations.tsx
@@ -101,7 +101,7 @@ export function ListConvosProviderInner({
       events => {
         if (events.type !== 'logs') return
 
-        events.logs.forEach(log => {
+        for (const log of events.logs) {
           if (ChatBskyConvoDefs.isLogBeginConvo(log)) {
             debouncedRefetch()
           } else if (ChatBskyConvoDefs.isLogLeaveConvo(log)) {
@@ -110,30 +110,40 @@ export function ListConvosProviderInner({
             )
           } else if (ChatBskyConvoDefs.isLogDeleteMessage(log)) {
             queryClient.setQueryData(RQKEY, (old: ConvoListQueryData) =>
-              optimisticUpdate(log.convoId, old, convo =>
-                log.message.id === convo.lastMessage?.id
-                  ? {
-                      ...convo,
-                      rev: log.rev,
-                      lastMessage: log.message,
-                    }
-                  : convo,
-              ),
+              optimisticUpdate(log.convoId, old, convo => {
+                if (
+                  (ChatBskyConvoDefs.isDeletedMessageView(log.message) ||
+                    ChatBskyConvoDefs.isMessageView(log.message)) &&
+                  (ChatBskyConvoDefs.isDeletedMessageView(convo.lastMessage) ||
+                    ChatBskyConvoDefs.isMessageView(convo.lastMessage))
+                ) {
+                  return log.message.id === convo.lastMessage.id
+                    ? {
+                        ...convo,
+                        rev: log.rev,
+                        lastMessage: log.message,
+                      }
+                    : convo
+                } else {
+                  return convo
+                }
+              }),
             )
           } else if (ChatBskyConvoDefs.isLogCreateMessage(log)) {
+            // Store in a new var to avoid TS errors due to closures.
+            const logRef: ChatBskyConvoDefs.LogCreateMessage = log
+
             queryClient.setQueryData(RQKEY, (old: ConvoListQueryData) => {
               if (!old) return old
 
               function updateConvo(convo: ChatBskyConvoDefs.ConvoView) {
-                if (!ChatBskyConvoDefs.isLogCreateMessage(log)) return convo
-
                 let unreadCount = convo.unreadCount
                 if (convo.id !== currentConvoId) {
                   if (
-                    ChatBskyConvoDefs.isMessageView(log.message) ||
-                    ChatBskyConvoDefs.isDeletedMessageView(log.message)
+                    ChatBskyConvoDefs.isMessageView(logRef.message) ||
+                    ChatBskyConvoDefs.isDeletedMessageView(logRef.message)
                   ) {
-                    if (log.message.sender.did !== currentAccount?.did) {
+                    if (logRef.message.sender.did !== currentAccount?.did) {
                       unreadCount++
                     }
                   }
@@ -143,8 +153,8 @@ export function ListConvosProviderInner({
 
                 return {
                   ...convo,
-                  rev: log.rev,
-                  lastMessage: log.message,
+                  rev: logRef.rev,
+                  lastMessage: logRef.message,
                   unreadCount,
                 }
               }
@@ -152,10 +162,10 @@ export function ListConvosProviderInner({
               function filterConvoFromPage(
                 convo: ChatBskyConvoDefs.ConvoView[],
               ) {
-                return convo.filter(c => c.id !== log.convoId)
+                return convo.filter(c => c.id !== logRef.convoId)
               }
 
-              const existingConvo = getConvoFromQueryData(log.convoId, old)
+              const existingConvo = getConvoFromQueryData(logRef.convoId, old)
 
               if (existingConvo) {
                 return {
@@ -186,7 +196,7 @@ export function ListConvosProviderInner({
               }
             })
           }
-        })
+        }
       },
       {
         // get events for all chats
diff --git a/src/state/queries/notifications/feed.ts b/src/state/queries/notifications/feed.ts
index 72100a624..396994110 100644
--- a/src/state/queries/notifications/feed.ts
+++ b/src/state/queries/notifications/feed.ts
@@ -295,9 +295,11 @@ export function* findAllPostsInQueryData(
           }
         }
 
-        const quotedPost = getEmbeddedPost(item.subject?.embed)
-        if (quotedPost && didOrHandleUriMatches(atUri, quotedPost)) {
-          yield embedViewRecordToPostView(quotedPost!)
+        if (AppBskyFeedDefs.isPostView(item.subject)) {
+          const quotedPost = getEmbeddedPost(item.subject?.embed)
+          if (quotedPost && didOrHandleUriMatches(atUri, quotedPost)) {
+            yield embedViewRecordToPostView(quotedPost!)
+          }
         }
       }
     }
@@ -307,7 +309,7 @@ export function* findAllPostsInQueryData(
 export function* findAllProfilesInQueryData(
   queryClient: QueryClient,
   did: string,
-): Generator<AppBskyActorDefs.ProfileView, void> {
+): Generator<AppBskyActorDefs.ProfileViewBasic, void> {
   const queryDatas = queryClient.getQueriesData<InfiniteData<FeedPage>>({
     queryKey: [RQKEY_ROOT],
   })
@@ -323,9 +325,11 @@ export function* findAllProfilesInQueryData(
         ) {
           yield item.subject.author
         }
-        const quotedPost = getEmbeddedPost(item.subject?.embed)
-        if (quotedPost?.author.did === did) {
-          yield quotedPost.author
+        if (AppBskyFeedDefs.isPostView(item.subject)) {
+          const quotedPost = getEmbeddedPost(item.subject?.embed)
+          if (quotedPost?.author.did === did) {
+            yield quotedPost.author
+          }
         }
       }
     }
diff --git a/src/state/queries/notifications/util.ts b/src/state/queries/notifications/util.ts
index 0d72e9e92..f6f53f58f 100644
--- a/src/state/queries/notifications/util.ts
+++ b/src/state/queries/notifications/util.ts
@@ -14,6 +14,7 @@ import {QueryClient} from '@tanstack/react-query'
 import chunk from 'lodash.chunk'
 
 import {labelIsHideableOffense} from '#/lib/moderation'
+import * as bsky from '#/types/bsky'
 import {precacheProfile} from '../profile'
 import {FeedNotification, FeedPage, NotificationType} from './types'
 
@@ -205,12 +206,9 @@ async function fetchSubjects(
     ),
   )
   const postsMap = new Map<string, AppBskyFeedDefs.PostView>()
-  const packsMap = new Map<string, AppBskyGraphDefs.StarterPackView>()
+  const packsMap = new Map<string, AppBskyGraphDefs.StarterPackViewBasic>()
   for (const post of postsChunks.flat()) {
-    if (
-      AppBskyFeedPost.isRecord(post.record) &&
-      AppBskyFeedPost.validateRecord(post.record).success
-    ) {
+    if (AppBskyFeedPost.isRecord(post.record)) {
       postsMap.set(post.uri, post)
     }
   }
@@ -255,8 +253,14 @@ function getSubjectUri(
     return notif.uri
   } else if (type === 'post-like' || type === 'repost') {
     if (
-      AppBskyFeedRepost.isRecord(notif.record) ||
-      AppBskyFeedLike.isRecord(notif.record)
+      bsky.dangerousIsType<AppBskyFeedRepost.Record>(
+        notif.record,
+        AppBskyFeedRepost.isRecord,
+      ) ||
+      bsky.dangerousIsType<AppBskyFeedLike.Record>(
+        notif.record,
+        AppBskyFeedLike.isRecord,
+      )
     ) {
       return typeof notif.record.subject?.uri === 'string'
         ? notif.record.subject?.uri
diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts
index 350970ffd..b29384e03 100644
--- a/src/state/queries/post-feed.ts
+++ b/src/state/queries/post-feed.ts
@@ -547,7 +547,7 @@ export function* findAllPostsInQueryData(
 export function* findAllProfilesInQueryData(
   queryClient: QueryClient,
   did: string,
-): Generator<AppBskyActorDefs.ProfileView, undefined> {
+): Generator<AppBskyActorDefs.ProfileViewBasic, undefined> {
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<FeedPageUnselected>
   >({
diff --git a/src/state/queries/post-quotes.ts b/src/state/queries/post-quotes.ts
index be51eaab0..af9699d2b 100644
--- a/src/state/queries/post-quotes.ts
+++ b/src/state/queries/post-quotes.ts
@@ -70,7 +70,7 @@ export function usePostQuotesQuery(resolvedUri: string | undefined) {
 export function* findAllProfilesInQueryData(
   queryClient: QueryClient,
   did: string,
-): Generator<AppBskyActorDefs.ProfileView, void> {
+): Generator<AppBskyActorDefs.ProfileViewBasic, void> {
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyFeedGetQuotes.OutputSchema>
   >({
diff --git a/src/state/queries/post-thread.ts b/src/state/queries/post-thread.ts
index 79350c119..b1cd626cf 100644
--- a/src/state/queries/post-thread.ts
+++ b/src/state/queries/post-thread.ts
@@ -18,6 +18,7 @@ import {
   findAllProfilesInQueryData as findAllProfilesInSearchQueryData,
 } from '#/state/queries/search-posts'
 import {useAgent} from '#/state/session'
+import * as bsky from '#/types/bsky'
 import {
   findAllPostsInQueryData as findAllPostsInNotifsQueryData,
   findAllProfilesInQueryData as findAllProfilesInNotifsQueryData,
@@ -332,8 +333,10 @@ function responseToThreadNodes(
 ): ThreadNode {
   if (
     AppBskyFeedDefs.isThreadViewPost(node) &&
-    AppBskyFeedPost.isRecord(node.post.record) &&
-    AppBskyFeedPost.validateRecord(node.post.record).success
+    bsky.dangerousIsType<AppBskyFeedPost.Record>(
+      node.post.record,
+      AppBskyFeedPost.isRecord,
+    )
   ) {
     const post = node.post
     // These should normally be present. They're missing only for
@@ -364,7 +367,7 @@ function responseToThreadNodes(
         depth,
         isHighlightedPost: depth === 0,
         hasMore:
-          direction === 'down' && !node.replies?.length && !!node.replyCount,
+          direction === 'down' && !node.replies?.length && !!post.replyCount,
         isSelfThread: false, // populated `annotateSelfThread`
         hasMoreSelfThread: false, // populated in `annotateSelfThread`
       },
@@ -497,7 +500,7 @@ export function* findAllPostsInQueryData(
 export function* findAllProfilesInQueryData(
   queryClient: QueryClient,
   did: string,
-): Generator<AppBskyActorDefs.ProfileView, void> {
+): Generator<AppBskyActorDefs.ProfileViewBasic, void> {
   const queryDatas = queryClient.getQueriesData<PostThreadQueryData>({
     queryKey: [RQKEY_ROOT],
   })
diff --git a/src/state/queries/postgate/index.ts b/src/state/queries/postgate/index.ts
index 149b9cbe9..346e7bfe2 100644
--- a/src/state/queries/postgate/index.ts
+++ b/src/state/queries/postgate/index.ts
@@ -21,6 +21,7 @@ import {
   POSTGATE_COLLECTION,
 } from '#/state/queries/postgate/util'
 import {useAgent} from '#/state/session'
+import * as bsky from '#/types/bsky'
 
 export async function getPostgateRecord({
   agent,
@@ -60,7 +61,10 @@ export async function getPostgateRecord({
         }),
     )
 
-    if (data.value && AppBskyFeedPostgate.isRecord(data.value)) {
+    if (
+      data.value &&
+      bsky.validate(data.value, AppBskyFeedPostgate.validateRecord)
+    ) {
       return data.value
     } else {
       return undefined
diff --git a/src/state/queries/postgate/util.ts b/src/state/queries/postgate/util.ts
index 96762d38c..c1955cc74 100644
--- a/src/state/queries/postgate/util.ts
+++ b/src/state/queries/postgate/util.ts
@@ -1,4 +1,5 @@
 import {
+  $Typed,
   AppBskyEmbedRecord,
   AppBskyEmbedRecordWithMedia,
   AppBskyFeedDefs,
@@ -45,8 +46,12 @@ export function mergePostgateRecords(
   })
 }
 
-export function createEmbedViewDetachedRecord({uri}: {uri: string}) {
-  const record: AppBskyEmbedRecord.ViewDetached = {
+export function createEmbedViewDetachedRecord({
+  uri,
+}: {
+  uri: string
+}): $Typed<AppBskyEmbedRecord.View> {
+  const record: $Typed<AppBskyEmbedRecord.ViewDetached> = {
     $type: 'app.bsky.embed.record#viewDetached',
     uri,
     detached: true,
@@ -95,7 +100,7 @@ export function createMaybeDetachedQuoteEmbed({
 
 export function createEmbedViewRecordFromPost(
   post: AppBskyFeedDefs.PostView,
-): AppBskyEmbedRecord.ViewRecord {
+): $Typed<AppBskyEmbedRecord.ViewRecord> {
   return {
     $type: 'app.bsky.embed.record#viewRecord',
     uri: post.uri,
diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts
index 291999ae1..2c98df634 100644
--- a/src/state/queries/profile.ts
+++ b/src/state/queries/profile.ts
@@ -8,6 +8,7 @@ import {
   AtUri,
   BskyAgent,
   ComAtprotoRepoUploadBlob,
+  Un$Typed,
 } from '@atproto/api'
 import {
   keepPreviousData,
@@ -24,7 +25,12 @@ import {logEvent, LogEvents, toClout} from '#/lib/statsig/statsig'
 import {Shadow} from '#/state/cache/types'
 import {STALE} from '#/state/queries'
 import {resetProfilePostsQueries} from '#/state/queries/post-feed'
+import {
+  unstableCacheProfileView,
+  useUnstableProfileViewCache,
+} from '#/state/queries/unstable-profile-cache'
 import * as userActionHistory from '#/state/userActionHistory'
+import * as bsky from '#/types/bsky'
 import {updateProfileShadow} from '../cache/profile-shadow'
 import {useAgent, useSession} from '../session'
 import {
@@ -35,6 +41,12 @@ import {RQKEY as RQKEY_LIST_CONVOS} from './messages/list-conversations'
 import {RQKEY as RQKEY_MY_BLOCKED} from './my-blocked-accounts'
 import {RQKEY as RQKEY_MY_MUTED} from './my-muted-accounts'
 
+export * from '#/state/queries/unstable-profile-cache'
+/**
+ * @deprecated use {@link unstableCacheProfileView} instead
+ */
+export const precacheProfile = unstableCacheProfileView
+
 const RQKEY_ROOT = 'profile'
 export const RQKEY = (did: string) => [RQKEY_ROOT, did]
 
@@ -44,12 +56,6 @@ export const profilesQueryKey = (handles: string[]) => [
   handles,
 ]
 
-const profileBasicQueryKeyRoot = 'profileBasic'
-export const profileBasicQueryKey = (didOrHandle: string) => [
-  profileBasicQueryKeyRoot,
-  didOrHandle,
-]
-
 export function useProfileQuery({
   did,
   staleTime = STALE.SECONDS.FIFTEEN,
@@ -57,8 +63,8 @@ export function useProfileQuery({
   did: string | undefined
   staleTime?: number
 }) {
-  const queryClient = useQueryClient()
   const agent = useAgent()
+  const {getUnstableProfile} = useUnstableProfileViewCache()
   return useQuery<AppBskyActorDefs.ProfileViewDetailed>({
     // WARNING
     // this staleTime is load-bearing
@@ -73,10 +79,7 @@ export function useProfileQuery({
     },
     placeholderData: () => {
       if (!did) return
-
-      return queryClient.getQueryData<AppBskyActorDefs.ProfileViewBasic>(
-        profileBasicQueryKey(did),
-      )
+      return getUnstableProfile(did) as AppBskyActorDefs.ProfileViewDetailed
     },
     enabled: !!did,
   })
@@ -121,10 +124,12 @@ export function usePrefetchProfileQuery() {
 }
 
 interface ProfileUpdateParams {
-  profile: AppBskyActorDefs.ProfileView
+  profile: AppBskyActorDefs.ProfileViewDetailed
   updates:
-    | AppBskyActorProfile.Record
-    | ((existing: AppBskyActorProfile.Record) => AppBskyActorProfile.Record)
+    | Un$Typed<AppBskyActorProfile.Record>
+    | ((
+        existing: Un$Typed<AppBskyActorProfile.Record>,
+      ) => Un$Typed<AppBskyActorProfile.Record>)
   newUserAvatar?: RNImage | undefined | null
   newUserBanner?: RNImage | undefined | null
   checkCommitted?: (res: AppBskyActorGetProfile.Response) => boolean
@@ -161,29 +166,29 @@ export function useProfileUpdateMutation() {
         )
       }
       await agent.upsertProfile(async existing => {
-        existing = existing || {}
+        let next: Un$Typed<AppBskyActorProfile.Record> = existing || {}
         if (typeof updates === 'function') {
-          existing = updates(existing)
+          next = updates(next)
         } else {
-          existing.displayName = updates.displayName
-          existing.description = updates.description
+          next.displayName = updates.displayName
+          next.description = updates.description
           if ('pinnedPost' in updates) {
-            existing.pinnedPost = updates.pinnedPost
+            next.pinnedPost = updates.pinnedPost
           }
         }
         if (newUserAvatarPromise) {
           const res = await newUserAvatarPromise
-          existing.avatar = res.data.blob
+          next.avatar = res.data.blob
         } else if (newUserAvatar === null) {
-          existing.avatar = undefined
+          next.avatar = undefined
         }
         if (newUserBannerPromise) {
           const res = await newUserBannerPromise
-          existing.banner = res.data.blob
+          next.banner = res.data.blob
         } else if (newUserBanner === null) {
-          existing.banner = undefined
+          next.banner = undefined
         }
-        return existing
+        return next
       })
       await whenAppViewReady(
         agent,
@@ -228,7 +233,7 @@ export function useProfileUpdateMutation() {
 }
 
 export function useProfileFollowMutationQueue(
-  profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>,
+  profile: Shadow<bsky.profile.AnyProfileView>,
   logContext: LogEvents['profile:follow']['logContext'] &
     LogEvents['profile:follow']['logContext'],
 ) {
@@ -302,7 +307,7 @@ export function useProfileFollowMutationQueue(
 
 function useProfileFollowMutation(
   logContext: LogEvents['profile:follow']['logContext'],
-  profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>,
+  profile: Shadow<bsky.profile.AnyProfileView>,
 ) {
   const {currentAccount} = useSession()
   const agent = useAgent()
@@ -321,7 +326,10 @@ function useProfileFollowMutation(
         didBecomeMutual: profile.viewer
           ? Boolean(profile.viewer.followedBy)
           : undefined,
-        followeeClout: toClout(profile.followersCount),
+        followeeClout:
+          'followersCount' in profile
+            ? toClout(profile.followersCount)
+            : undefined,
         followerClout: toClout(ownProfile?.followersCount),
       })
       return await agent.follow(did)
@@ -342,7 +350,7 @@ function useProfileUnfollowMutation(
 }
 
 export function useProfileMuteMutationQueue(
-  profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>,
+  profile: Shadow<bsky.profile.AnyProfileView>,
 ) {
   const queryClient = useQueryClient()
   const did = profile.did
@@ -417,7 +425,7 @@ function useProfileUnmuteMutation() {
 }
 
 export function useProfileBlockMutationQueue(
-  profile: Shadow<AppBskyActorDefs.ProfileViewBasic>,
+  profile: Shadow<bsky.profile.AnyProfileView>,
 ) {
   const queryClient = useQueryClient()
   const did = profile.did
@@ -513,14 +521,6 @@ function useProfileUnblockMutation() {
   })
 }
 
-export function precacheProfile(
-  queryClient: QueryClient,
-  profile: AppBskyActorDefs.ProfileViewBasic,
-) {
-  queryClient.setQueryData(profileBasicQueryKey(profile.handle), profile)
-  queryClient.setQueryData(profileBasicQueryKey(profile.did), profile)
-}
-
 async function whenAppViewReady(
   agent: BskyAgent,
   actor: string,
diff --git a/src/state/queries/resolve-uri.ts b/src/state/queries/resolve-uri.ts
index c1fd8e240..1422a2dae 100644
--- a/src/state/queries/resolve-uri.ts
+++ b/src/state/queries/resolve-uri.ts
@@ -1,14 +1,9 @@
-import {AppBskyActorDefs, AtUri} from '@atproto/api'
-import {
-  QueryClient,
-  useQuery,
-  useQueryClient,
-  UseQueryResult,
-} from '@tanstack/react-query'
+import {AtUri} from '@atproto/api'
+import {QueryClient, useQuery, UseQueryResult} from '@tanstack/react-query'
 
 import {STALE} from '#/state/queries'
 import {useAgent} from '#/state/session'
-import {profileBasicQueryKey as RQKEY_PROFILE_BASIC} from './profile'
+import {useUnstableProfileViewCache} from './profile'
 
 const RQKEY_ROOT = 'resolved-did'
 export const RQKEY = (didOrHandle: string) => [RQKEY_ROOT, didOrHandle]
@@ -28,8 +23,8 @@ export function useResolveUriQuery(uri: string | undefined): UriUseQueryResult {
 }
 
 export function useResolveDidQuery(didOrHandle: string | undefined) {
-  const queryClient = useQueryClient()
   const agent = useAgent()
+  const {getUnstableProfile} = useUnstableProfileViewCache()
 
   return useQuery<string, Error>({
     staleTime: STALE.HOURS.ONE,
@@ -45,11 +40,7 @@ export function useResolveDidQuery(didOrHandle: string | undefined) {
     initialData: () => {
       // Return undefined if no did or handle
       if (!didOrHandle) return
-
-      const profile =
-        queryClient.getQueryData<AppBskyActorDefs.ProfileViewBasic>(
-          RQKEY_PROFILE_BASIC(didOrHandle),
-        )
+      const profile = getUnstableProfile(didOrHandle)
       return profile?.did
     },
     enabled: !!didOrHandle,
diff --git a/src/state/queries/search-posts.ts b/src/state/queries/search-posts.ts
index 8a8a3fa52..d0bfd55df 100644
--- a/src/state/queries/search-posts.ts
+++ b/src/state/queries/search-posts.ts
@@ -174,7 +174,7 @@ export function* findAllPostsInQueryData(
 export function* findAllProfilesInQueryData(
   queryClient: QueryClient,
   did: string,
-): Generator<AppBskyActorDefs.ProfileView, undefined> {
+): Generator<AppBskyActorDefs.ProfileViewBasic, undefined> {
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyFeedSearchPosts.OutputSchema>
   >({
diff --git a/src/state/queries/service-config.ts b/src/state/queries/service-config.ts
index 9a9db7865..12d2cc6be 100644
--- a/src/state/queries/service-config.ts
+++ b/src/state/queries/service-config.ts
@@ -19,6 +19,7 @@ export function useServiceConfigQuery() {
         const {data} = await agent.api.app.bsky.unspecced.getConfig()
         return {
           checkEmailConfirmed: Boolean(data.checkEmailConfirmed),
+          // @ts-expect-error not included in types atm
           topicsEnabled: Boolean(data.topicsEnabled),
         }
       } catch (e) {
diff --git a/src/state/queries/starter-packs.ts b/src/state/queries/starter-packs.ts
index b90a57037..5b39fa45f 100644
--- a/src/state/queries/starter-packs.ts
+++ b/src/state/queries/starter-packs.ts
@@ -1,5 +1,4 @@
 import {
-  AppBskyActorDefs,
   AppBskyFeedDefs,
   AppBskyGraphDefs,
   AppBskyGraphGetStarterPack,
@@ -29,6 +28,7 @@ import {invalidateActorStarterPacksQuery} from '#/state/queries/actor-starter-pa
 import {STALE} from '#/state/queries/index'
 import {invalidateListMembersQuery} from '#/state/queries/list-members'
 import {useAgent} from '#/state/session'
+import * as bsky from '#/types/bsky'
 
 const RQKEY_ROOT = 'starter-pack'
 const RQKEY = ({
@@ -93,7 +93,7 @@ export async function invalidateStarterPack({
 interface UseCreateStarterPackMutationParams {
   name: string
   description?: string
-  profiles: AppBskyActorDefs.ProfileViewBasic[]
+  profiles: bsky.profile.AnyProfileView[]
   feeds?: AppBskyFeedDefs.GeneratorView[]
 }
 
@@ -131,7 +131,7 @@ export function useCreateStarterPackMutation({
 
       return await agent.app.bsky.graph.starterpack.create(
         {
-          repo: agent.session?.did,
+          repo: agent.assertDid,
         },
         {
           name,
@@ -366,7 +366,10 @@ export async function precacheStarterPack(
   let starterPackView: AppBskyGraphDefs.StarterPackView | undefined
   if (AppBskyGraphDefs.isStarterPackView(starterPack)) {
     starterPackView = starterPack
-  } else if (AppBskyGraphDefs.isStarterPackViewBasic(starterPack)) {
+  } else if (
+    AppBskyGraphDefs.isStarterPackViewBasic(starterPack) &&
+    bsky.validate(starterPack.record, AppBskyGraphStarterpack.validateRecord)
+  ) {
     const listView: AppBskyGraphDefs.ListViewBasic = {
       uri: starterPack.record.list,
       // This will be populated once the data from server is fetched
diff --git a/src/state/queries/threadgate/index.ts b/src/state/queries/threadgate/index.ts
index 8aa932081..478658fe8 100644
--- a/src/state/queries/threadgate/index.ts
+++ b/src/state/queries/threadgate/index.ts
@@ -20,6 +20,7 @@ import {
 } from '#/state/queries/threadgate/util'
 import {useAgent} from '#/state/session'
 import {useThreadgateHiddenReplyUrisAPI} from '#/state/threadgate-hidden-replies'
+import * as bsky from '#/types/bsky'
 
 export * from '#/state/queries/threadgate/types'
 export * from '#/state/queries/threadgate/util'
@@ -138,7 +139,10 @@ export async function getThreadgateRecord({
         }),
     )
 
-    if (data.value && AppBskyFeedThreadgate.isRecord(data.value)) {
+    if (
+      data.value &&
+      bsky.validate(data.value, AppBskyFeedThreadgate.validateRecord)
+    ) {
       return data.value
     } else {
       return null
diff --git a/src/state/queries/threadgate/types.ts b/src/state/queries/threadgate/types.ts
index 56eadabcd..bbe677ad4 100644
--- a/src/state/queries/threadgate/types.ts
+++ b/src/state/queries/threadgate/types.ts
@@ -4,4 +4,4 @@ export type ThreadgateAllowUISetting =
   | {type: 'mention'}
   | {type: 'following'}
   | {type: 'followers'}
-  | {type: 'list'; list: unknown}
+  | {type: 'list'; list: string}
diff --git a/src/state/queries/threadgate/util.ts b/src/state/queries/threadgate/util.ts
index 4459eddbe..cbe8d4695 100644
--- a/src/state/queries/threadgate/util.ts
+++ b/src/state/queries/threadgate/util.ts
@@ -1,14 +1,15 @@
 import {AppBskyFeedDefs, AppBskyFeedThreadgate} from '@atproto/api'
 
 import {ThreadgateAllowUISetting} from '#/state/queries/threadgate/types'
+import * as bsky from '#/types/bsky'
 
 export function threadgateViewToAllowUISetting(
   threadgateView: AppBskyFeedDefs.ThreadgateView | undefined,
 ): ThreadgateAllowUISetting[] {
+  // Validate the record for clarity, since backwards compat code is a little confusing
   const threadgate =
     threadgateView &&
-    AppBskyFeedThreadgate.isRecord(threadgateView.record) &&
-    AppBskyFeedThreadgate.validateRecord(threadgateView.record).success
+    bsky.validate(threadgateView.record, AppBskyFeedThreadgate.validateRecord)
       ? threadgateView.record
       : undefined
   return threadgateRecordToAllowUISetting(threadgate)
@@ -39,14 +40,14 @@ export function threadgateRecordToAllowUISetting(
   const settings: ThreadgateAllowUISetting[] = threadgate.allow
     .map(allow => {
       let setting: ThreadgateAllowUISetting | undefined
-      if (allow.$type === 'app.bsky.feed.threadgate#mentionRule') {
+      if (AppBskyFeedThreadgate.isMentionRule(allow)) {
         setting = {type: 'mention'}
-      } else if (allow.$type === 'app.bsky.feed.threadgate#followingRule') {
+      } else if (AppBskyFeedThreadgate.isFollowingRule(allow)) {
         setting = {type: 'following'}
-      } else if (allow.$type === 'app.bsky.feed.threadgate#followerRule') {
-        setting = {type: 'followers'}
-      } else if (allow.$type === 'app.bsky.feed.threadgate#listRule') {
+      } else if (AppBskyFeedThreadgate.isListRule(allow)) {
         setting = {type: 'list', list: allow.list}
+      } else if (AppBskyFeedThreadgate.isFollowerRule(allow)) {
+        setting = {type: 'followers'}
       }
       return setting
     })
@@ -69,11 +70,7 @@ export function threadgateAllowUISettingToAllowRecordValue(
     return undefined
   }
 
-  let allow: (
-    | AppBskyFeedThreadgate.MentionRule
-    | AppBskyFeedThreadgate.FollowingRule
-    | AppBskyFeedThreadgate.ListRule
-  )[] = []
+  let allow: Exclude<AppBskyFeedThreadgate.Record['allow'], undefined> = []
 
   if (!threadgate.find(v => v.type === 'nobody')) {
     for (const rule of threadgate) {
diff --git a/src/state/queries/unstable-profile-cache.ts b/src/state/queries/unstable-profile-cache.ts
new file mode 100644
index 000000000..4ac5001b7
--- /dev/null
+++ b/src/state/queries/unstable-profile-cache.ts
@@ -0,0 +1,51 @@
+import {useCallback} from 'react'
+import {QueryClient, useQueryClient} from '@tanstack/react-query'
+
+import * as bsky from '#/types/bsky'
+
+const unstableProfileViewCacheQueryKeyRoot = 'unstableProfileViewCache'
+export const unstableProfileViewCacheQueryKey = (didOrHandle: string) => [
+  unstableProfileViewCacheQueryKeyRoot,
+  didOrHandle,
+]
+
+/**
+ * Used as a rough cache of profile views to make loading snappier. This method
+ * accepts and stores any profile view type by both handle and DID.
+ *
+ * Access the cache via {@link useUnstableProfileViewCache}.
+ */
+export function unstableCacheProfileView(
+  queryClient: QueryClient,
+  profile: bsky.profile.AnyProfileView,
+) {
+  queryClient.setQueryData(
+    unstableProfileViewCacheQueryKey(profile.handle),
+    profile,
+  )
+  queryClient.setQueryData(
+    unstableProfileViewCacheQueryKey(profile.did),
+    profile,
+  )
+}
+
+/**
+ * Hook to access the unstable profile view cache. This cache can return ANY
+ * profile view type, so if the object shape is important, you need to use the
+ * identity validators shipped in the atproto SDK e.g.
+ * `AppBskyActorDefs.isValidProfileViewBasic` to confirm before using.
+ *
+ * To cache a profile, use {@link unstableCacheProfileView}.
+ */
+export function useUnstableProfileViewCache() {
+  const qc = useQueryClient()
+  const getUnstableProfile = useCallback(
+    (didOrHandle: string) => {
+      return qc.getQueryData<bsky.profile.AnyProfileView>(
+        unstableProfileViewCacheQueryKey(didOrHandle),
+      )
+    },
+    [qc],
+  )
+  return {getUnstableProfile}
+}
diff --git a/src/state/queries/util.ts b/src/state/queries/util.ts
index 887c1df0a..71d185bec 100644
--- a/src/state/queries/util.ts
+++ b/src/state/queries/util.ts
@@ -8,6 +8,8 @@ import {
 } from '@atproto/api'
 import {InfiniteData, QueryClient, QueryKey} from '@tanstack/react-query'
 
+import * as bsky from '#/types/bsky'
+
 export async function truncateAndInvalidate<T = any>(
   queryClient: QueryClient,
   queryKey: QueryKey,
@@ -44,7 +46,9 @@ export function didOrHandleUriMatches(
 export function getEmbeddedPost(
   v: unknown,
 ): AppBskyEmbedRecord.ViewRecord | undefined {
-  if (AppBskyEmbedRecord.isView(v)) {
+  if (
+    bsky.dangerousIsType<AppBskyEmbedRecord.View>(v, AppBskyEmbedRecord.isView)
+  ) {
     if (
       AppBskyEmbedRecord.isViewRecord(v.record) &&
       AppBskyFeedPost.isRecord(v.record.value)
@@ -52,7 +56,12 @@ export function getEmbeddedPost(
       return v.record
     }
   }
-  if (AppBskyEmbedRecordWithMedia.isView(v)) {
+  if (
+    bsky.dangerousIsType<AppBskyEmbedRecordWithMedia.View>(
+      v,
+      AppBskyEmbedRecordWithMedia.isView,
+    )
+  ) {
     if (
       AppBskyEmbedRecord.isViewRecord(v.record.record) &&
       AppBskyFeedPost.isRecord(v.record.record.value)
diff --git a/src/state/shell/composer/index.tsx b/src/state/shell/composer/index.tsx
index f1ea41c64..33634c047 100644
--- a/src/state/shell/composer/index.tsx
+++ b/src/state/shell/composer/index.tsx
@@ -1,7 +1,6 @@
 import React from 'react'
 import {
   AppBskyActorDefs,
-  AppBskyEmbedRecord,
   AppBskyFeedDefs,
   ModerationDecision,
 } from '@atproto/api'
@@ -21,7 +20,7 @@ export interface ComposerOptsPostRef {
   cid: string
   text: string
   author: AppBskyActorDefs.ProfileViewBasic
-  embed?: AppBskyEmbedRecord.ViewRecord['embed']
+  embed?: AppBskyFeedDefs.PostView['embed']
   moderation?: ModerationDecision
 }