flip the state layer type imports to the generated lexicons

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-08-04 04:20:35 +03:00
parent 541a82c2dd
commit dd957dd123
83 changed files with 819 additions and 900 deletions
+17 -17
View File
@@ -1,12 +1,9 @@
import {useEffect, useMemo, useState} from 'react'
import {
AppBskyEmbedRecord,
AppBskyEmbedRecordWithMedia,
type AppBskyFeedDefs,
} from '@atproto/api'
import {type QueryClient} from '@tanstack/react-query'
import {EventEmitter} from 'eventemitter3'
import * as bsky from '#/types/bsky'
import {app} from '#/lexicons'
import {batchedUpdates} from '#/lib/batchedUpdates'
import {findAllPostsInQueryData as findAllPostsInBookmarksQueryData} from '#/state/queries/bookmarks/useBookmarksQuery'
import {findAllPostsInQueryData as findAllPostsInExploreFeedPreviewsQueryData} from '#/state/queries/explore-feed-previews'
@@ -22,7 +19,10 @@ export interface PostShadow {
likeUri: string | undefined
repostUri: string | undefined
isDeleted: boolean
embed: AppBskyEmbedRecord.View | AppBskyEmbedRecordWithMedia.View | undefined
embed:
| app.bsky.embed.record.View
| app.bsky.embed.recordWithMedia.View
| undefined
pinned: boolean
optimisticReplyCount: number | undefined
bookmarked: boolean | undefined
@@ -32,7 +32,7 @@ export const POST_TOMBSTONE = Symbol('PostTombstone')
const emitter = new EventEmitter()
const shadows: WeakMap<
AppBskyFeedDefs.PostView,
app.bsky.feed.defs.PostView,
Partial<PostShadow>
> = new WeakMap()
@@ -40,13 +40,13 @@ const shadows: WeakMap<
* Use with caution! This function returns the raw shadow data for a post.
* Prefer using `usePostShadow`.
*/
export function dangerousGetPostShadow(post: AppBskyFeedDefs.PostView) {
export function dangerousGetPostShadow(post: app.bsky.feed.defs.PostView) {
return shadows.get(post)
}
export function usePostShadow(
post: AppBskyFeedDefs.PostView,
): Shadow<AppBskyFeedDefs.PostView> | typeof POST_TOMBSTONE {
post: app.bsky.feed.defs.PostView,
): Shadow<app.bsky.feed.defs.PostView> | typeof POST_TOMBSTONE {
const [shadow, setShadow] = useState(() => shadows.get(post))
const [prevPost, setPrevPost] = useState(post)
if (post !== prevPost) {
@@ -74,9 +74,9 @@ export function usePostShadow(
}
function mergeShadow(
post: AppBskyFeedDefs.PostView,
post: app.bsky.feed.defs.PostView,
shadow: Partial<PostShadow>,
): Shadow<AppBskyFeedDefs.PostView> | typeof POST_TOMBSTONE {
): Shadow<app.bsky.feed.defs.PostView> | typeof POST_TOMBSTONE {
if (shadow.isDeleted) {
return POST_TOMBSTONE
}
@@ -125,10 +125,10 @@ function mergeShadow(
let embed: typeof post.embed
if ('embed' in shadow) {
if (
(AppBskyEmbedRecord.isView(post.embed) &&
AppBskyEmbedRecord.isView(shadow.embed)) ||
(AppBskyEmbedRecordWithMedia.isView(post.embed) &&
AppBskyEmbedRecordWithMedia.isView(shadow.embed))
(bsky.isType(app.bsky.embed.record.view, post.embed) &&
bsky.isType(app.bsky.embed.record.view, shadow.embed)) ||
(bsky.isType(app.bsky.embed.recordWithMedia.view, post.embed) &&
bsky.isType(app.bsky.embed.recordWithMedia.view, shadow.embed))
) {
embed = shadow.embed
}
@@ -169,7 +169,7 @@ export function updatePostShadow(
function* findPostsInCache(
queryClient: QueryClient,
uri: string,
): Generator<AppBskyFeedDefs.PostView, void> {
): Generator<app.bsky.feed.defs.PostView, void> {
for (let post of findAllPostsInFeedQueryData(queryClient, uri)) {
yield post
}
+6 -4
View File
@@ -1,8 +1,8 @@
import {useEffect, useMemo, useState} from 'react'
import {type AppBskyActorDefs, type AppBskyNotificationDefs} from '@atproto/api'
import {type QueryClient} from '@tanstack/react-query'
import {EventEmitter} from 'eventemitter3'
import {app} from '#/lexicons'
import {batchedUpdates} from '#/lib/batchedUpdates'
import {findAllProfilesInQueryData as findAllProfilesInActivitySubscriptionsQueryData} from '#/state/queries/activity-subscriptions'
import {findAllProfilesInQueryData as findAllProfilesInActorSearchQueryData} from '#/state/queries/actor-search'
@@ -43,9 +43,11 @@ export interface ProfileShadow {
muted: boolean | undefined
mutedOnlyReposts: boolean | undefined
blockingUri: string | undefined
verification: AppBskyActorDefs.VerificationState
status: AppBskyActorDefs.StatusView | undefined
activitySubscription: AppBskyNotificationDefs.ActivitySubscription | undefined
verification: app.bsky.actor.defs.VerificationState
status: app.bsky.actor.defs.StatusView | undefined
activitySubscription:
| app.bsky.notification.defs.ActivitySubscription
| undefined
}
const shadows: WeakMap<
+8 -9
View File
@@ -7,7 +7,6 @@ import {
useRef,
} from 'react'
import {AppState, type AppStateStatus} from 'react-native'
import {type AppBskyFeedDefs} from '@atproto/api'
import {type AtUriString, type DidString} from '@atproto/syntax'
import throttle from 'lodash.throttle'
@@ -29,7 +28,7 @@ import {useAppviewClient} from './session'
export const FEEDBACK_FEEDS = [...PROD_FEEDS, ...STAGING_FEEDS]
export const THIRD_PARTY_ALLOWED_INTERACTIONS = new Set<
AppBskyFeedDefs.Interaction['event']
app.bsky.feed.defs.Interaction['event']
>([
// These are explicit actions and are therefore fine to send.
'app.bsky.feed.defs#requestLess',
@@ -47,7 +46,7 @@ export const THIRD_PARTY_ALLOWED_INTERACTIONS = new Set<
export type StateContext = {
enabled: boolean
onItemSeen: (item: any) => void
sendInteraction: (interaction: AppBskyFeedDefs.Interaction) => void
sendInteraction: (interaction: app.bsky.feed.defs.Interaction) => void
feedDescriptor: FeedDescriptor | undefined
feedSourceInfo: FeedSourceInfo | undefined
}
@@ -55,7 +54,7 @@ export type StateContext = {
const stateContext = createContext<StateContext>({
enabled: false,
onItemSeen: (_item: any) => {},
sendInteraction: (_interaction: AppBskyFeedDefs.Interaction) => {},
sendInteraction: (_interaction: app.bsky.feed.defs.Interaction) => {},
feedDescriptor: undefined,
feedSourceInfo: undefined,
})
@@ -84,7 +83,7 @@ export function useFeedFeedback(
const history = useRef<
// Use a WeakSet so that we don't need to clear it.
// This assumes that referential identity of slice items maps 1:1 to feed (re)fetches.
WeakSet<FeedPostSliceItem | AppBskyFeedDefs.Interaction>
WeakSet<FeedPostSliceItem | app.bsky.feed.defs.Interaction>
>(new WeakSet())
const flushEvents = useCallback(
@@ -225,7 +224,7 @@ export function useFeedFeedback(
)
const sendInteraction = useCallback(
(interaction: AppBskyFeedDefs.Interaction) => {
(interaction: app.bsky.feed.defs.Interaction) => {
if (!enabled) {
return
}
@@ -273,7 +272,7 @@ export function isDiscoverFeed(feed?: FeedDescriptor) {
function isInteractionAllowed(
enabled: boolean,
feed: FeedSourceFeedInfo | undefined,
interaction: AppBskyFeedDefs.Interaction['event'],
interaction: app.bsky.feed.defs.Interaction['event'],
) {
if (!enabled || !feed) {
return false
@@ -282,7 +281,7 @@ function isInteractionAllowed(
return isDiscover ? true : THIRD_PARTY_ALLOWED_INTERACTIONS.has(interaction)
}
function toString(interaction: AppBskyFeedDefs.Interaction): string {
function toString(interaction: app.bsky.feed.defs.Interaction): string {
return `${interaction.item}|${interaction.event}|${
interaction.feedContext || ''
}|${interaction.reqId || ''}`
@@ -313,7 +312,7 @@ function createAggregatedStats(): AggregatedStats {
function sendOrAggregateInteractionsForStats(
stats: AggregatedStats,
interactions: AppBskyFeedDefs.Interaction[],
interactions: app.bsky.feed.defs.Interaction[],
) {
for (let interaction of interactions) {
switch (interaction.event) {
+64 -72
View File
@@ -1,16 +1,8 @@
import {
type $Typed,
type AppBskyEmbedRecord,
type ChatBskyActorDefs,
ChatBskyConvoDefs,
type ChatBskyConvoGetLog,
type ChatBskyEmbedJoinLink,
type ChatBskyGroupDefs,
} from '@atproto/api'
import {type Client, XrpcResponseError} from '@atproto/lex'
import {type Client, XrpcResponseError, type $Typed} from '@atproto/lex'
import {EventEmitter} from 'eventemitter3'
import {nanoid} from 'nanoid/non-secure'
import * as bsky from '#/types/bsky'
import {networkRetry} from '#/lib/async/retry'
import {
isErrorMaybeAppPasswordPermissions,
@@ -49,7 +41,7 @@ import {
parseConvoView,
} from '#/components/dms/util'
import {IS_NATIVE} from '#/env'
import {chat} from '#/lexicons'
import {app, chat} from '#/lexicons'
const logger = Logger.create(Logger.Context.ConversationAgent)
@@ -65,21 +57,21 @@ export function isConvoItemMessage(
}
function toSystemMessageView(
ev: ChatBskyConvoGetLog.OutputSchema['logs'][number],
): ChatBskyConvoDefs.SystemMessageView | null {
ev: chat.bsky.convo.getLog.$OutputBody['logs'][number],
): chat.bsky.convo.defs.SystemMessageView | null {
const isSystem =
ChatBskyConvoDefs.isLogAddMember(ev) ||
ChatBskyConvoDefs.isLogRemoveMember(ev) ||
ChatBskyConvoDefs.isLogMemberJoin(ev) ||
ChatBskyConvoDefs.isLogMemberLeave(ev) ||
ChatBskyConvoDefs.isLogLockConvo(ev) ||
ChatBskyConvoDefs.isLogUnlockConvo(ev) ||
ChatBskyConvoDefs.isLogLockConvoPermanently(ev) ||
ChatBskyConvoDefs.isLogEditGroup(ev) ||
ChatBskyConvoDefs.isLogCreateJoinLink(ev) ||
ChatBskyConvoDefs.isLogEditJoinLink(ev) ||
ChatBskyConvoDefs.isLogEnableJoinLink(ev) ||
ChatBskyConvoDefs.isLogDisableJoinLink(ev)
bsky.isType(chat.bsky.convo.defs.logAddMember, ev) ||
bsky.isType(chat.bsky.convo.defs.logRemoveMember, ev) ||
bsky.isType(chat.bsky.convo.defs.logMemberJoin, ev) ||
bsky.isType(chat.bsky.convo.defs.logMemberLeave, ev) ||
bsky.isType(chat.bsky.convo.defs.logLockConvo, ev) ||
bsky.isType(chat.bsky.convo.defs.logUnlockConvo, ev) ||
bsky.isType(chat.bsky.convo.defs.logLockConvoPermanently, ev) ||
bsky.isType(chat.bsky.convo.defs.logEditGroup, ev) ||
bsky.isType(chat.bsky.convo.defs.logCreateJoinLink, ev) ||
bsky.isType(chat.bsky.convo.defs.logEditJoinLink, ev) ||
bsky.isType(chat.bsky.convo.defs.logEnableJoinLink, ev) ||
bsky.isType(chat.bsky.convo.defs.logDisableJoinLink, ev)
if (!isSystem) return null
return ev.message
}
@@ -89,8 +81,8 @@ function toSystemMessageView(
* the fields the deleted view carries so a reply can render it as deleted.
*/
function toDeletedMessageView(
m: ChatBskyConvoDefs.MessageView,
): $Typed<ChatBskyConvoDefs.DeletedMessageView> {
m: chat.bsky.convo.defs.MessageView,
): $Typed<chat.bsky.convo.defs.DeletedMessageView> {
return {
$type: 'chat.bsky.convo.defs#deletedMessageView',
id: m.id,
@@ -115,15 +107,15 @@ export class Convo {
private pastMessages: Map<
string,
| ChatBskyConvoDefs.MessageView
| ChatBskyConvoDefs.DeletedMessageView
| ChatBskyConvoDefs.SystemMessageView
| chat.bsky.convo.defs.MessageView
| chat.bsky.convo.defs.DeletedMessageView
| chat.bsky.convo.defs.SystemMessageView
> = new Map()
private newMessages: Map<
string,
| ChatBskyConvoDefs.MessageView
| ChatBskyConvoDefs.DeletedMessageView
| ChatBskyConvoDefs.SystemMessageView
| chat.bsky.convo.defs.MessageView
| chat.bsky.convo.defs.DeletedMessageView
| chat.bsky.convo.defs.SystemMessageView
> = new Map()
private pendingMessages: Map<
string,
@@ -131,13 +123,13 @@ export class Convo {
id: string
message: chat.bsky.convo.defs.MessageInput
optimisticEmbedView?:
| $Typed<AppBskyEmbedRecord.View>
| $Typed<ChatBskyEmbedJoinLink.View>
optimisticReplyTo?: $Typed<ChatBskyConvoDefs.MessageView>
| $Typed<app.bsky.embed.record.View>
| $Typed<chat.bsky.embed.joinLink.View>
optimisticReplyTo?: $Typed<chat.bsky.convo.defs.MessageView>
}
> = new Map()
private deletedMessages: Set<string> = new Set()
private relatedProfiles: Map<string, ChatBskyActorDefs.ProfileViewBasic> =
private relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic> =
new Map()
/**
* Accumulated profile shadow state, keyed by did. The profiles this agent
@@ -157,8 +149,8 @@ export class Convo {
convoId: string
convo: ConvoWithDetails | undefined
sender: ChatBskyActorDefs.ProfileViewBasic | undefined
recipients: ChatBskyActorDefs.ProfileViewBasic[] | undefined
sender: chat.bsky.actor.defs.ProfileViewBasic | undefined
recipients: chat.bsky.actor.defs.ProfileViewBasic[] | undefined
snapshot: ConvoState | undefined
constructor(params: ConvoParams) {
@@ -596,7 +588,7 @@ export class Convo {
}
}
private setConvo(convo: ChatBskyConvoDefs.ConvoView) {
private setConvo(convo: chat.bsky.convo.defs.ConvoView) {
this.convo = parseConvoView(convo, this.senderUserDid) ?? this.convo
if (this.convo) {
for (const member of this.convo.members) {
@@ -606,7 +598,7 @@ export class Convo {
this.applyProfileShadows()
}
private updateConvo(convo: Partial<ChatBskyConvoDefs.ConvoView>) {
private updateConvo(convo: Partial<chat.bsky.convo.defs.ConvoView>) {
if (this.convo) {
this.convo =
parseConvoView({...this.convo.view, ...convo}, this.senderUserDid) ??
@@ -716,7 +708,7 @@ export class Convo {
}
private pendingFetchConvo:
| Promise<{convo: ChatBskyConvoDefs.ConvoView}>
| Promise<{convo: chat.bsky.convo.defs.ConvoView}>
| undefined
async fetchConvo() {
if (this.pendingFetchConvo) return this.pendingFetchConvo
@@ -836,9 +828,9 @@ export class Convo {
for (const message of messages) {
if (
ChatBskyConvoDefs.isMessageView(message) ||
ChatBskyConvoDefs.isDeletedMessageView(message) ||
ChatBskyConvoDefs.isSystemMessageView(message)
bsky.isType(chat.bsky.convo.defs.messageView, message) ||
bsky.isType(chat.bsky.convo.defs.deletedMessageView, message) ||
bsky.isType(chat.bsky.convo.defs.systemMessageView, message)
) {
/*
* If this message is already in new messages, it was added by the
@@ -913,7 +905,7 @@ export class Convo {
this.commit()
}
ingestFirehose(events: ChatBskyConvoGetLog.OutputSchema['logs']) {
ingestFirehose(events: chat.bsky.convo.getLog.$OutputBody['logs']) {
let needsCommit = false
for (const ev of events) {
@@ -950,8 +942,8 @@ export class Convo {
}
if (
ChatBskyConvoDefs.isLogCreateMessage(ev) &&
ChatBskyConvoDefs.isMessageView(ev.message)
bsky.isType(chat.bsky.convo.defs.logCreateMessage, ev) &&
bsky.isType(chat.bsky.convo.defs.messageView, ev.message)
) {
/*
* If this message is already in past messages, the initial
@@ -976,8 +968,8 @@ export class Convo {
}
needsCommit = true
} else if (
ChatBskyConvoDefs.isLogDeleteMessage(ev) &&
ChatBskyConvoDefs.isDeletedMessageView(ev.message)
bsky.isType(chat.bsky.convo.defs.logDeleteMessage, ev) &&
bsky.isType(chat.bsky.convo.defs.deletedMessageView, ev.message)
) {
/*
* Remove the message itself, and keep its id in `deletedMessages`
@@ -992,9 +984,9 @@ export class Convo {
this.deletedMessages.add(ev.message.id)
needsCommit = true
} else if (
(ChatBskyConvoDefs.isLogAddReaction(ev) ||
ChatBskyConvoDefs.isLogRemoveReaction(ev)) &&
ChatBskyConvoDefs.isMessageView(ev.message)
(bsky.isType(chat.bsky.convo.defs.logAddReaction, ev) ||
bsky.isType(chat.bsky.convo.defs.logRemoveReaction, ev)) &&
bsky.isType(chat.bsky.convo.defs.messageView, ev.message)
) {
/*
* Update if we have this in state - replace message wholesale. If we don't, don't worry about it.
@@ -1033,9 +1025,9 @@ export class Convo {
sendMessage(
message: chat.bsky.convo.defs.MessageInput,
optimisticEmbedView?:
| $Typed<AppBskyEmbedRecord.View>
| $Typed<ChatBskyEmbedJoinLink.View>,
optimisticReplyTo?: $Typed<ChatBskyConvoDefs.MessageView>,
| $Typed<app.bsky.embed.record.View>
| $Typed<chat.bsky.embed.joinLink.View>,
optimisticReplyTo?: $Typed<chat.bsky.convo.defs.MessageView>,
) {
// Ignore empty messages for now since they have no other purpose atm
if (!message.text.trim() && !message.embed) return
@@ -1110,7 +1102,7 @@ export class Convo {
this.commit()
}
updateJoinLink(joinLink: ChatBskyGroupDefs.JoinLinkView | undefined) {
updateJoinLink(joinLink: chat.bsky.group.defs.JoinLinkView | undefined) {
if (this.convo?.kind !== 'group') {
throw new Error('updateJoinLink can only be called on group convo')
}
@@ -1126,7 +1118,7 @@ export class Convo {
}
updateLockStatus(
lockStatus: ChatBskyConvoDefs.ConvoLockStatus,
lockStatus: chat.bsky.convo.defs.ConvoLockStatus,
lockStatusModerationOverride: boolean,
) {
if (this.convo?.kind !== 'group') {
@@ -1340,11 +1332,11 @@ export class Convo {
* matching what the server returns on refresh.
*/
private tombstoneDeletedReplyTo(
m: ChatBskyConvoDefs.MessageView,
): ChatBskyConvoDefs.MessageView {
m: chat.bsky.convo.defs.MessageView,
): chat.bsky.convo.defs.MessageView {
const {replyTo} = m
if (
!ChatBskyConvoDefs.isMessageView(replyTo) ||
!bsky.isType(chat.bsky.convo.defs.messageView, replyTo) ||
!this.deletedMessages.has(replyTo.id)
) {
return m
@@ -1359,19 +1351,19 @@ export class Convo {
const items: ConvoItem[] = []
this.pastMessages.forEach(m => {
if (ChatBskyConvoDefs.isMessageView(m)) {
if (bsky.isType(chat.bsky.convo.defs.messageView, m)) {
items.unshift({
type: 'message',
key: m.id,
message: this.tombstoneDeletedReplyTo(m),
})
} else if (ChatBskyConvoDefs.isDeletedMessageView(m)) {
} else if (bsky.isType(chat.bsky.convo.defs.deletedMessageView, m)) {
items.unshift({
type: 'deleted-message',
key: m.id,
message: m,
})
} else if (ChatBskyConvoDefs.isSystemMessageView(m)) {
} else if (bsky.isType(chat.bsky.convo.defs.systemMessageView, m)) {
items.unshift({
type: 'system-message',
key: m.id,
@@ -1392,19 +1384,19 @@ export class Convo {
}
this.newMessages.forEach(m => {
if (ChatBskyConvoDefs.isMessageView(m)) {
if (bsky.isType(chat.bsky.convo.defs.messageView, m)) {
items.push({
type: 'message',
key: m.id,
message: this.tombstoneDeletedReplyTo(m),
})
} else if (ChatBskyConvoDefs.isDeletedMessageView(m)) {
} else if (bsky.isType(chat.bsky.convo.defs.deletedMessageView, m)) {
items.push({
type: 'deleted-message',
key: m.id,
message: m,
})
} else if (ChatBskyConvoDefs.isSystemMessageView(m)) {
} else if (bsky.isType(chat.bsky.convo.defs.systemMessageView, m)) {
items.push({
type: 'system-message',
key: m.id,
@@ -1479,7 +1471,7 @@ export class Convo {
if (this.pastMessages.has(messageId)) {
const prevMessage = this.pastMessages.get(messageId)
if (
ChatBskyConvoDefs.isMessageView(prevMessage) &&
bsky.isType(chat.bsky.convo.defs.messageView, prevMessage) &&
// skip optimistic update if reaction already exists
!prevMessage.reactions?.find(
reaction =>
@@ -1509,7 +1501,7 @@ export class Convo {
} else if (this.newMessages.has(messageId)) {
const prevMessage = this.newMessages.get(messageId)
if (
ChatBskyConvoDefs.isMessageView(prevMessage) &&
bsky.isType(chat.bsky.convo.defs.messageView, prevMessage) &&
!prevMessage.reactions?.find(reaction => reaction.value === emoji)
) {
if (prevMessage.reactions && prevMessage.reactions.length >= 5)
@@ -1533,7 +1525,7 @@ export class Convo {
value: emoji,
convoId: this.convoId,
})
if (ChatBskyConvoDefs.isMessageView(data.message)) {
if (bsky.isType(chat.bsky.convo.defs.messageView, data.message)) {
if (this.pastMessages.has(messageId)) {
this.pastMessages.set(messageId, data.message)
this.commit()
@@ -1558,7 +1550,7 @@ export class Convo {
let restore: null | (() => void) = null
if (this.pastMessages.has(messageId)) {
const prevMessage = this.pastMessages.get(messageId)
if (ChatBskyConvoDefs.isMessageView(prevMessage)) {
if (bsky.isType(chat.bsky.convo.defs.messageView, prevMessage)) {
this.pastMessages.set(messageId, {
...prevMessage,
reactions: prevMessage.reactions?.filter(
@@ -1575,7 +1567,7 @@ export class Convo {
}
} else if (this.newMessages.has(messageId)) {
const prevMessage = this.newMessages.get(messageId)
if (ChatBskyConvoDefs.isMessageView(prevMessage)) {
if (bsky.isType(chat.bsky.convo.defs.messageView, prevMessage)) {
this.newMessages.set(messageId, {
...prevMessage,
reactions: prevMessage.reactions?.filter(
+11 -9
View File
@@ -6,10 +6,11 @@ import {
useState,
useSyncExternalStore,
} from 'react'
import {ChatBskyConvoDefs} from '@atproto/api'
import {useFocusEffect} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {chat} from '#/lexicons'
import {useAppState} from '#/lib/appState'
import {Convo} from '#/state/messages/convo/agent'
import {
@@ -34,8 +35,8 @@ import {type GroupConvoMember} from '#/components/dms/util'
export * from '#/state/messages/convo/util'
function membersChanged(
a: ChatBskyConvoDefs.ConvoView['members'],
b: ChatBskyConvoDefs.ConvoView['members'],
a: chat.bsky.convo.defs.ConvoView['members'],
b: chat.bsky.convo.defs.ConvoView['members'],
) {
if (a.length !== b.length) return true
const aDids = new Set(a.map(m => m.did))
@@ -83,9 +84,10 @@ export function ConvoProvider({
const chatClient = useChatClient()
const events = useMessagesEventBus()
const [convo] = useState(() => {
const placeholder = queryClient.getQueryData<ChatBskyConvoDefs.ConvoView>(
getConvoKey(convoId),
)
const placeholder =
queryClient.getQueryData<chat.bsky.convo.defs.ConvoView>(
getConvoKey(convoId),
)
return new Convo({
convoId,
chatClient,
@@ -151,14 +153,14 @@ export function ConvoProvider({
const queryKey = event.query.queryKey as string[]
if (queryKey[0] === root && queryKey[1] === id) {
const data = event.query.state.data as
| ChatBskyConvoDefs.ConvoView
| chat.bsky.convo.defs.ConvoView
| undefined
if (data && convo.convo && data.muted !== convo.convo.view.muted) {
convo.updateMuted(data.muted)
}
if (
data &&
ChatBskyConvoDefs.isGroupConvo(data.kind) &&
bsky.isType(chat.bsky.convo.defs.groupConvo, data.kind) &&
convo.convo?.kind === 'group'
) {
if (data.kind.name !== convo.convo.details.name) {
@@ -180,7 +182,7 @@ export function ConvoProvider({
}
if (
data &&
ChatBskyConvoDefs.isGroupConvo(data.kind) &&
bsky.isType(chat.bsky.convo.defs.groupConvo, data.kind) &&
convo.convo?.kind === 'group' &&
(membersChanged(data.members, convo.convo.members) ||
data.kind.memberCount !== convo.convo.details.memberCount)
+14 -21
View File
@@ -1,15 +1,8 @@
import {
type $Typed,
type AppBskyEmbedRecord,
type ChatBskyActorDefs,
type ChatBskyConvoDefs,
type ChatBskyEmbedJoinLink,
} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type Client, type $Typed} from '@atproto/lex'
import {type MessagesEventBus} from '#/state/messages/events/agent'
import {type ConvoWithDetails} from '#/components/dms/util'
import {type chat} from '#/lexicons'
import {app, chat} from '#/lexicons'
export type ConvoParams = {
convoId: string
@@ -17,7 +10,7 @@ export type ConvoParams = {
chatClient: Client
events: MessagesEventBus
placeholderData?: {
convo: ChatBskyConvoDefs.ConvoView
convo: chat.bsky.convo.defs.ConvoView
}
}
@@ -75,12 +68,12 @@ export type ConvoItem =
| {
type: 'message'
key: string
message: ChatBskyConvoDefs.MessageView
message: chat.bsky.convo.defs.MessageView
}
| {
type: 'pending-message'
key: string
message: ChatBskyConvoDefs.MessageView
message: chat.bsky.convo.defs.MessageView
failed: boolean
/**
* Retry sending the message. If present, the message is in a failed state.
@@ -90,12 +83,12 @@ export type ConvoItem =
| {
type: 'deleted-message'
key: string
message: ChatBskyConvoDefs.DeletedMessageView
message: chat.bsky.convo.defs.DeletedMessageView
}
| {
type: 'system-message'
key: string
message: ChatBskyConvoDefs.SystemMessageView
message: chat.bsky.convo.defs.SystemMessageView
}
| {
type: 'error'
@@ -111,10 +104,10 @@ type DeleteMessage = (messageId: string) => Promise<void>
type SendMessage = (
message: chat.bsky.convo.defs.MessageInput,
optimisticEmbedView:
| $Typed<AppBskyEmbedRecord.View>
| $Typed<ChatBskyEmbedJoinLink.View>
| $Typed<app.bsky.embed.record.View>
| $Typed<chat.bsky.embed.joinLink.View>
| undefined,
optimisticReplyTo?: $Typed<ChatBskyConvoDefs.MessageView>,
optimisticReplyTo?: $Typed<chat.bsky.convo.defs.MessageView>,
) => void
type FetchMessageHistory = () => Promise<void>
type MarkConvoAccepted = () => void
@@ -153,7 +146,7 @@ export type ConvoStateReady = {
status: ConvoStatus.Ready
items: ConvoItem[]
convo: ConvoWithDetails
relatedProfiles: Map<string, ChatBskyActorDefs.ProfileViewBasic>
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
error: undefined
isFetchingHistory: boolean
hasAllHistory: boolean
@@ -168,7 +161,7 @@ export type ConvoStateBackgrounded = {
status: ConvoStatus.Backgrounded
items: ConvoItem[]
convo: ConvoWithDetails
relatedProfiles: Map<string, ChatBskyActorDefs.ProfileViewBasic>
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
error: undefined
isFetchingHistory: boolean
hasAllHistory: boolean
@@ -183,7 +176,7 @@ export type ConvoStateSuspended = {
status: ConvoStatus.Suspended
items: ConvoItem[]
convo: ConvoWithDetails
relatedProfiles: Map<string, ChatBskyActorDefs.ProfileViewBasic>
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
error: undefined
isFetchingHistory: boolean
hasAllHistory: boolean
@@ -212,7 +205,7 @@ export type ConvoStateDisabled = {
status: ConvoStatus.Disabled
items: ConvoItem[]
convo: ConvoWithDetails
relatedProfiles: Map<string, ChatBskyActorDefs.ProfileViewBasic>
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
error: undefined
isFetchingHistory: boolean
hasAllHistory: boolean
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type AtIdentifierString} from '@atproto/syntax'
import {t} from '@lingui/core/macro'
import {
@@ -106,7 +105,7 @@ export function useNotificationDeclarationMutation() {
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.notification.listActivitySubscriptions.$OutputBody>
>({
+4 -5
View File
@@ -1,5 +1,4 @@
import {useCallback} from 'react'
import {type AppBskyActorDefs} from '@atproto/api'
import {type ModerationOpts} from '@bsky.app/sdk/moderation'
import {keepPreviousData, useQuery, useQueryClient} from '@tanstack/react-query'
@@ -34,7 +33,7 @@ export function useActorAutocompleteQuery(
prefix = prefix.slice(0, -1)
}
return useQuery<AppBskyActorDefs.ProfileViewBasic[]>({
return useQuery<app.bsky.actor.defs.ProfileViewBasic[]>({
staleTime: STALE.MINUTES.ONE,
queryKey: RQKEY(prefix || ''),
async queryFn() {
@@ -47,7 +46,7 @@ export function useActorAutocompleteQuery(
return data?.actors || []
},
select: useCallback(
(data: AppBskyActorDefs.ProfileViewBasic[]) => {
(data: app.bsky.actor.defs.ProfileViewBasic[]) => {
return computeSuggestions({
q: prefix,
searched: data,
@@ -104,10 +103,10 @@ function computeSuggestions({
moderationOpts,
}: {
q?: string
searched?: AppBskyActorDefs.ProfileViewBasic[]
searched?: app.bsky.actor.defs.ProfileViewBasic[]
moderationOpts: ModerationOpts
}) {
let items: AppBskyActorDefs.ProfileViewBasic[] = []
let items: app.bsky.actor.defs.ProfileViewBasic[] = []
for (const item of searched) {
if (!items.find(item2 => item2.handle === item.handle)) {
items.push(item)
@@ -1,4 +1,3 @@
import {type AppBskyFeedDefs} from '@atproto/api'
import {type AtUriString} from '@atproto/syntax'
import {useMutation, useQueryClient} from '@tanstack/react-query'
@@ -13,7 +12,7 @@ import {useAppviewClient} from '#/state/session'
import {app} from '#/lexicons'
type MutationArgs =
| {action: 'create'; post: AppBskyFeedDefs.PostView}
| {action: 'create'; post: app.bsky.feed.defs.PostView}
| {
action: 'delete'
/**
@@ -1,4 +1,3 @@
import {type $Typed, AppBskyFeedDefs, AtUri} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
@@ -11,6 +10,8 @@ import {
embedViewRecordToPostView,
getEmbeddedPost,
} from '#/state/queries/util'
import {type $Typed} from '@atproto/lex'
import {AtUri} from '@atproto/syntax'
import {useAppviewClient} from '#/state/session'
import {app} from '#/lexicons'
import * as bsky from '#/types/bsky'
@@ -57,7 +58,7 @@ export async function truncateAndInvalidate(qc: QueryClient) {
export async function optimisticallySaveBookmark(
qc: QueryClient,
post: AppBskyFeedDefs.PostView,
post: app.bsky.feed.defs.PostView,
) {
qc.setQueriesData<InfiniteData<app.bsky.bookmark.getBookmarks.$OutputBody>>(
{
@@ -81,7 +82,7 @@ export async function optimisticallySaveBookmark(
uri: post.uri,
cid: post.cid,
},
item: post as $Typed<AppBskyFeedDefs.PostView>,
item: post as $Typed<app.bsky.feed.defs.PostView>,
} as unknown as app.bsky.bookmark.defs.BookmarkView
return {
...page,
@@ -121,7 +122,7 @@ export async function optimisticallyDeleteBookmark(
export function* findAllPostsInQueryData(
queryClient: QueryClient,
uri: string,
): Generator<AppBskyFeedDefs.PostView, undefined> {
): Generator<app.bsky.feed.defs.PostView, undefined> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.bookmark.getBookmarks.$OutputBody>
>({
@@ -135,13 +136,7 @@ export function* findAllPostsInQueryData(
}
for (const page of queryData?.pages) {
for (const bookmark of page.bookmarks) {
if (
!bsky.dangerousIsType<AppBskyFeedDefs.PostView>(
bookmark.item,
AppBskyFeedDefs.isPostView,
)
)
continue
if (!bsky.isType(app.bsky.feed.defs.postView, bookmark.item)) continue
if (didOrHandleUriMatches(atUri, bookmark.item)) {
yield bookmark.item
+18 -17
View File
@@ -1,6 +1,5 @@
import {useMemo, useRef} from 'react'
import {type AppBskyActorDefs, AppBskyFeedDefs, AtUri} from '@atproto/api'
import {type AtUriString} from '@atproto/syntax'
import {type AtUriString, AtUri} from '@atproto/syntax'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {
@@ -9,6 +8,8 @@ import {
useInfiniteQuery,
} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {app} from '#/lexicons'
import {CustomFeedAPI} from '#/lib/api/feed/custom'
import {aggregateUserInterests} from '#/lib/api/feed/utils'
import {FeedTuner} from '#/lib/api/feed-manip'
@@ -82,7 +83,7 @@ export type FeedPreviewItem =
| {
type: 'preview:header'
key: string
feed: AppBskyFeedDefs.GeneratorView
feed: app.bsky.feed.defs.GeneratorView
}
| {
type: 'preview:footer'
@@ -94,7 +95,7 @@ export type FeedPreviewItem =
key: string
slice: FeedPostSlice
indexInSlice: number
feed: AppBskyFeedDefs.GeneratorView
feed: app.bsky.feed.defs.GeneratorView
showReplyTo: boolean
hideTopBorder: boolean
}
@@ -105,7 +106,7 @@ export type FeedPreviewItem =
}
export function useFeedPreviews(
feedsMaybeWithDuplicates: AppBskyFeedDefs.GeneratorView[],
feedsMaybeWithDuplicates: app.bsky.feed.defs.GeneratorView[],
isEnabled: boolean = true,
) {
const feeds = useMemo(
@@ -127,8 +128,8 @@ export function useFeedPreviews(
const processedPageCache = useRef(
new Map<
{
feed: AppBskyFeedDefs.GeneratorView
posts: AppBskyFeedDefs.FeedViewPost[]
feed: app.bsky.feed.defs.GeneratorView
posts: app.bsky.feed.defs.FeedViewPost[]
},
FeedPreviewItem[]
>(),
@@ -346,13 +347,13 @@ export function useFeedPreviews(
export function* findAllPostsInQueryData(
queryClient: QueryClient,
uri: string,
): Generator<AppBskyFeedDefs.PostView, undefined> {
): Generator<app.bsky.feed.defs.PostView, undefined> {
const atUri = new AtUri(uri)
const queryDatas = queryClient.getQueriesData<
InfiniteData<{
feed: AppBskyFeedDefs.GeneratorView
posts: AppBskyFeedDefs.FeedViewPost[]
feed: app.bsky.feed.defs.GeneratorView
posts: app.bsky.feed.defs.FeedViewPost[]
}>
>({
queryKey: [RQKEY_ROOT],
@@ -372,7 +373,7 @@ export function* findAllPostsInQueryData(
yield embedViewRecordToPostView(quotedPost)
}
if (AppBskyFeedDefs.isPostView(item.reply?.parent)) {
if (bsky.isType(app.bsky.feed.defs.postView, item.reply?.parent)) {
if (didOrHandleUriMatches(atUri, item.reply.parent)) {
yield item.reply.parent
}
@@ -386,7 +387,7 @@ export function* findAllPostsInQueryData(
}
}
if (AppBskyFeedDefs.isPostView(item.reply?.root)) {
if (bsky.isType(app.bsky.feed.defs.postView, item.reply?.root)) {
if (didOrHandleUriMatches(atUri, item.reply.root)) {
yield item.reply.root
}
@@ -404,11 +405,11 @@ export function* findAllPostsInQueryData(
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileViewBasic, undefined> {
): Generator<app.bsky.actor.defs.ProfileViewBasic, undefined> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<{
feed: AppBskyFeedDefs.GeneratorView
posts: AppBskyFeedDefs.FeedViewPost[]
feed: app.bsky.feed.defs.GeneratorView
posts: app.bsky.feed.defs.FeedViewPost[]
}>
>({
queryKey: [RQKEY_ROOT],
@@ -427,13 +428,13 @@ export function* findAllProfilesInQueryData(
yield quotedPost.author
}
if (
AppBskyFeedDefs.isPostView(item.reply?.parent) &&
bsky.isType(app.bsky.feed.defs.postView, item.reply?.parent) &&
item.reply?.parent?.author.did === did
) {
yield item.reply.parent.author
}
if (
AppBskyFeedDefs.isPostView(item.reply?.root) &&
bsky.isType(app.bsky.feed.defs.postView, item.reply?.root) &&
item.reply?.root?.author.did === did
) {
yield item.reply.root.author
+19 -23
View File
@@ -1,11 +1,5 @@
import {useCallback, useEffect, useMemo, useRef} from 'react'
import {
type AppBskyActorDefs,
type AppBskyFeedDefs,
type AppBskyGraphDefs,
AtUri,
} from '@atproto/api'
import {type AtUriString} from '@atproto/syntax'
import {type AtUriString, AtUri} from '@atproto/syntax'
import {RichText} from '@bsky.app/sdk/richtext'
import {t} from '@lingui/core/macro'
import {
@@ -36,7 +30,7 @@ import {precacheResolvedUri} from './resolve-uri'
export type FeedSourceFeedInfo = {
type: 'feed'
view?: AppBskyFeedDefs.GeneratorView
view?: app.bsky.feed.defs.GeneratorView
uri: string
feedDescriptor: FeedDescriptor
route: {
@@ -53,12 +47,12 @@ export type FeedSourceFeedInfo = {
likeCount: number | undefined
acceptsInteractions?: boolean
likeUri: string | undefined
contentMode: AppBskyFeedDefs.GeneratorView['contentMode']
contentMode: app.bsky.feed.defs.GeneratorView['contentMode']
}
export type FeedSourceListInfo = {
type: 'list'
view?: AppBskyGraphDefs.ListView
view?: app.bsky.graph.defs.ListView
uri: string
feedDescriptor: FeedDescriptor
route: {
@@ -95,7 +89,7 @@ const feedSourceNSIDs = {
}
export function hydrateFeedGenerator(
view: AppBskyFeedDefs.GeneratorView,
view: app.bsky.feed.defs.GeneratorView,
): FeedSourceInfo {
const urip = new AtUri(view.uri)
const collection =
@@ -137,7 +131,9 @@ export function hydrateFeedGenerator(
}
}
export function hydrateList(view: AppBskyGraphDefs.ListView): FeedSourceInfo {
export function hydrateList(
view: app.bsky.graph.defs.ListView,
): FeedSourceInfo {
const urip = new AtUri(view.uri)
const collection =
urip.collection === 'app.bsky.feed.generator' ? 'feed' : 'lists'
@@ -410,7 +406,7 @@ export function usePopularFeedsSearch({
}
export type SavedFeedSourceInfo = FeedSourceInfo & {
savedFeed: AppBskyActorDefs.SavedFeed
savedFeed: app.bsky.actor.defs.SavedFeed
}
const PWI_DISCOVER_FEED_STUB: SavedFeedSourceInfo = {
@@ -549,17 +545,17 @@ export function usePinnedFeedsInfos() {
export type SavedFeedItem =
| {
type: 'feed'
config: AppBskyActorDefs.SavedFeed
view: AppBskyFeedDefs.GeneratorView
config: app.bsky.actor.defs.SavedFeed
view: app.bsky.feed.defs.GeneratorView
}
| {
type: 'list'
config: AppBskyActorDefs.SavedFeed
view: AppBskyGraphDefs.ListView
config: app.bsky.actor.defs.SavedFeed
view: app.bsky.graph.defs.ListView
}
| {
type: 'timeline'
config: AppBskyActorDefs.SavedFeed
config: app.bsky.actor.defs.SavedFeed
view: undefined
}
@@ -587,8 +583,8 @@ export function useSavedFeeds() {
)
},
queryFn: async () => {
const resolvedFeeds = new Map<string, AppBskyFeedDefs.GeneratorView>()
const resolvedLists = new Map<string, AppBskyGraphDefs.ListView>()
const resolvedFeeds = new Map<string, app.bsky.feed.defs.GeneratorView>()
const resolvedLists = new Map<string, app.bsky.graph.defs.ListView>()
const savedFeeds = savedItems.filter(feed => feed.type === 'feed')
const savedLists = savedItems.filter(feed => feed.type === 'list')
@@ -703,10 +699,10 @@ function precacheFeed(queryClient: QueryClient, hydratedFeed: FeedSourceInfo) {
export function precacheList(
queryClient: QueryClient,
list: AppBskyGraphDefs.ListView,
list: app.bsky.graph.defs.ListView,
) {
precacheResolvedUri(queryClient, list.creator.handle, list.creator.did)
queryClient.setQueryData<AppBskyGraphDefs.ListView>(
queryClient.setQueryData<app.bsky.graph.defs.ListView>(
listQueryKey(list.uri),
list,
)
@@ -714,7 +710,7 @@ export function precacheList(
export function precacheFeedFromGeneratorView(
queryClient: QueryClient,
view: AppBskyFeedDefs.GeneratorView,
view: app.bsky.feed.defs.GeneratorView,
) {
const hydratedFeed = hydrateFeedGenerator(view)
precacheFeed(queryClient, hydratedFeed)
+13 -17
View File
@@ -1,12 +1,8 @@
import {useCallback} from 'react'
import {
type $Typed,
ChatBskyGroupDefs,
type ChatBskyGroupGetJoinLinkPreviews,
} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type Client, type $Typed} from '@atproto/lex'
import {type QueryClient, useQuery, useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {CHAT_SERVICE} from '#/lib/constants'
import {createLexClient} from '#/lib/lexClient'
import {logger} from '#/logger'
@@ -21,9 +17,9 @@ import {chat} from '#/lexicons'
* `ChatInvitePreview` for that.
*/
export type KnownChatInvitePreview =
| $Typed<ChatBskyGroupDefs.JoinLinkPreviewView>
| $Typed<ChatBskyGroupDefs.DisabledJoinLinkPreviewView>
| $Typed<ChatBskyGroupDefs.InvalidJoinLinkPreviewView>
| $Typed<chat.bsky.group.defs.JoinLinkPreviewView>
| $Typed<chat.bsky.group.defs.DisabledJoinLinkPreviewView>
| $Typed<chat.bsky.group.defs.InvalidJoinLinkPreviewView>
/**
* The full open-union shape, including the `{$type: string}` fallback for
@@ -39,9 +35,9 @@ export function isKnownJoinLinkPreview(
preview: unknown,
): preview is KnownChatInvitePreview {
return (
ChatBskyGroupDefs.isJoinLinkPreviewView(preview) ||
ChatBskyGroupDefs.isDisabledJoinLinkPreviewView(preview) ||
ChatBskyGroupDefs.isInvalidJoinLinkPreviewView(preview)
bsky.isType(chat.bsky.group.defs.joinLinkPreviewView, preview) ||
bsky.isType(chat.bsky.group.defs.disabledJoinLinkPreviewView, preview) ||
bsky.isType(chat.bsky.group.defs.invalidJoinLinkPreviewView, preview)
)
}
@@ -90,7 +86,7 @@ export function setJoinLinkPreviewRequestedForCode(
code: string,
requested: boolean,
) {
queryClient.setQueriesData<ChatBskyGroupGetJoinLinkPreviews.OutputSchema>(
queryClient.setQueriesData<chat.bsky.group.getJoinLinkPreviews.$OutputBody>(
{
predicate: query => {
const [root, args] = query.queryKey as Partial<
@@ -109,7 +105,7 @@ export function setJoinLinkPreviewRequestedForCode(
...old,
joinLinkPreviews: old.joinLinkPreviews.map(preview => {
if (
ChatBskyGroupDefs.isJoinLinkPreviewView(preview) &&
bsky.isType(chat.bsky.group.defs.joinLinkPreviewView, preview) &&
preview.code === code
) {
return {
@@ -143,12 +139,12 @@ export function invalidateJoinLinkPreviewsForConvo(
const [root] = query.queryKey
if (root !== joinLinkPreviewQueryKeyRoot) return false
const data = query.state.data as
| ChatBskyGroupGetJoinLinkPreviews.OutputSchema
| chat.bsky.group.getJoinLinkPreviews.$OutputBody
| undefined
return (
data?.joinLinkPreviews.some(
preview =>
ChatBskyGroupDefs.isJoinLinkPreviewView(preview) &&
bsky.isType(chat.bsky.group.defs.joinLinkPreviewView, preview) &&
preview.convoId === convoId,
) ?? false
)
@@ -204,7 +200,7 @@ export function useJoinLinkPreviewsQuery({
* Seed the query with an already-known preview (e.g. a DM message embed
* already carries the resolved view), avoiding a duplicate fetch.
*/
initialData?: ChatBskyGroupGetJoinLinkPreviews.OutputSchema
initialData?: chat.bsky.group.getJoinLinkPreviews.$OutputBody
}) {
const client = useChatClient()
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -43,7 +42,7 @@ export function useProfileKnownFollowersQuery(did: string | undefined) {
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.graph.getKnownFollowers.$OutputBody>
>({
+2 -3
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs, type AppBskyGraphDefs} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type AtUriString} from '@atproto/syntax'
import {
@@ -91,7 +90,7 @@ export async function invalidateListMembersQuery({
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.graph.getList.$OutputBody>
>({
@@ -114,7 +113,7 @@ export function* findAllProfilesInQueryData(
}
const allQueryData = queryClient.getQueriesData<
AppBskyGraphDefs.ListItemView[]
app.bsky.graph.defs.ListItemView[]
>({
queryKey: [RQKEY_ROOT_ALL],
})
+4 -8
View File
@@ -1,7 +1,3 @@
import {
type AppBskyActorDefs,
type AppBskyGraphGetStarterPacksWithMembership,
} from '@atproto/api'
import {
AtUri,
type AtUriString,
@@ -73,7 +69,7 @@ export function useListMembershipAddMutation({
// update WITH_MEMBERSHIPS query for starter packs
if (subject) {
queryClient.setQueryData<
InfiniteData<AppBskyGraphGetStarterPacksWithMembership.OutputSchema>
InfiniteData<app.bsky.graph.getStarterPacksWithMembership.$OutputBody>
>(STARTER_PACKS_WITH_MEMBERSHIPS_RKEY(variables.actorDid), old => {
if (!old) return old
@@ -94,7 +90,7 @@ export function useListMembershipAddMutation({
listItemsSample: [
{
uri: data.uri,
subject: subject as AppBskyActorDefs.ProfileView,
subject: subject as app.bsky.actor.defs.ProfileView,
},
...(spWithMembership.starterPack.listItemsSample?.filter(
item => item.subject.did !== variables.actorDid,
@@ -109,7 +105,7 @@ export function useListMembershipAddMutation({
},
listItem: {
uri: data.uri,
subject: subject as AppBskyActorDefs.ProfileView,
subject: subject as app.bsky.actor.defs.ProfileView,
},
}
}
@@ -167,7 +163,7 @@ export function useListMembershipRemoveMutation({
// update WITH_MEMBERSHIPS query for starter packs
queryClient.setQueryData<
InfiniteData<AppBskyGraphGetStarterPacksWithMembership.OutputSchema>
InfiniteData<app.bsky.graph.getStarterPacksWithMembership.$OutputBody>
>(STARTER_PACKS_WITH_MEMBERSHIPS_RKEY(variables.actorDid), old => {
if (!old) return old
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyGraphDefs} from '@atproto/api'
import {type $Typed, type Client} from '@atproto/lex'
import {
type AtIdentifierString,
@@ -30,7 +29,7 @@ export const RQKEY = (uri: string) => [RQKEY_ROOT, uri]
export function useListQuery(uri?: string) {
const client = useAppviewClient()
return useQuery<AppBskyGraphDefs.ListView, Error>({
return useQuery<app.bsky.graph.defs.ListView, Error>({
staleTime: STALE.MINUTES.ONE,
queryKey: RQKEY(uri || ''),
async queryFn() {
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type AtIdentifierString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -60,7 +59,7 @@ export function updateListMembershipOptimistically({
actor: string
listUri: string
membershipUri: string
subject: AppBskyActorDefs.ProfileView
subject: app.bsky.actor.defs.ProfileView
}) {
queryClient.setQueryData<
InfiniteData<app.bsky.graph.getListsWithMembership.$OutputBody>
@@ -1,7 +1,3 @@
import {
type ChatBskyConvoAcceptConvo,
type ChatBskyConvoDefs,
} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {logger} from '#/logger'
@@ -29,7 +25,7 @@ export function useAcceptConversation(
onError,
}: {
onMutate?: () => void
onSuccess?: (data: ChatBskyConvoAcceptConvo.OutputSchema) => void
onSuccess?: (data: chat.bsky.convo.acceptConvo.$OutputBody) => void
onError?: (error: Error) => void
},
) {
@@ -47,7 +43,7 @@ export function useAcceptConversation(
queryClient.getQueriesData<ConvoListQueryData>({
queryKey: [CONVO_LIST_ROOT_KEY],
})
let convoBeingAccepted: ChatBskyConvoDefs.ConvoView | null = null
let convoBeingAccepted: chat.bsky.convo.defs.ConvoView | null = null
for (const [_key, data] of queryClient.getQueriesData<ConvoListQueryData>(
{queryKey: CONVO_LIST_PARTIAL_KEY('request')},
)) {
@@ -60,7 +56,7 @@ export function useAcceptConversation(
(old?: ConvoListQueryData) => optimisticDelete(convoId, old),
)
if (convoBeingAccepted) {
const acceptedConvo: ChatBskyConvoDefs.ConvoView = {
const acceptedConvo: chat.bsky.convo.defs.ConvoView = {
...convoBeingAccepted,
status: 'accepted',
}
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type DidString} from '@atproto/syntax'
import {useMutation, useQueryClient} from '@tanstack/react-query'
@@ -6,7 +5,7 @@ import {useMutation, useQueryClient} from '@tanstack/react-query'
import {logger} from '#/logger'
import {usePdsClient, useSession} from '#/state/session'
import {resolveAllowGroupInvites} from '#/components/dms/util'
import {chat, com} from '#/lexicons'
import {app, chat, com} from '#/lexicons'
import {RQKEY as PROFILE_RKEY} from '../profile'
export function useUpdateActorDeclaration({
@@ -27,7 +26,7 @@ export function useUpdateActorDeclaration({
}) => {
if (!currentAccount) throw new Error('Not signed in')
const current =
queryClient.getQueryData<AppBskyActorDefs.ProfileViewDetailed>(
queryClient.getQueryData<app.bsky.actor.defs.ProfileViewDetailed>(
PROFILE_RKEY(currentAccount.did),
)
const allowIncoming =
@@ -57,7 +56,7 @@ export function useUpdateActorDeclaration({
if (!currentAccount) return
queryClient.setQueryData(
PROFILE_RKEY(currentAccount?.did),
(old?: AppBskyActorDefs.ProfileViewDetailed) => {
(old?: app.bsky.actor.defs.ProfileViewDetailed) => {
if (!old) return old
const allowIncoming =
update.allowIncoming ??
@@ -81,7 +80,7 @@ export function useUpdateActorDeclaration({
allowGroupInvites,
},
},
} satisfies AppBskyActorDefs.ProfileViewDetailed
} satisfies app.bsky.actor.defs.ProfileViewDetailed
},
)
},
+25 -27
View File
@@ -1,9 +1,3 @@
import {
type ChatBskyActorDefs,
ChatBskyConvoDefs,
type ChatBskyConvoListConvos,
type ChatBskyGroupAddMembers,
} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -15,7 +9,7 @@ import {logger} from '#/logger'
import {useProfileQuery} from '#/state/queries/profile'
import {useChatClient, useSession} from '#/state/session'
import {chat} from '#/lexicons'
import type * as bsky from '#/types/bsky'
import * as bsky from '#/types/bsky'
import {RQKEY as CONVO_KEY} from './conversation'
import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
import {listConvoMembersQueryKey} from './list-convo-members'
@@ -26,7 +20,7 @@ export function useAddGroupMembers(
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupAddMembers.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.addMembers.$OutputBody) => void
onError?: (error: Error) => void
},
) {
@@ -52,24 +46,26 @@ export function useAddGroupMembers(
onMutate: ({profiles}) => {
if (!convoId) return
const prevConvo = queryClient.getQueryData<ChatBskyConvoDefs.ConvoView>(
CONVO_KEY(convoId),
)
const prevConvo =
queryClient.getQueryData<chat.bsky.convo.defs.ConvoView>(
CONVO_KEY(convoId),
)
const prevListEntries = queryClient.getQueriesData<
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
InfiniteData<chat.bsky.convo.listConvos.$OutputBody>
>({queryKey: [CONVO_LIST_KEY]})
const prevMemberList = queryClient.getQueryData<
ChatBskyActorDefs.ProfileViewBasic[]
chat.bsky.actor.defs.ProfileViewBasic[]
>(listConvoMembersQueryKey(convoId))
const addedBy: ChatBskyActorDefs.ProfileViewBasic | undefined = myProfile
? {
...myProfile,
$type: 'chat.bsky.actor.defs#profileViewBasic',
}
: undefined
const addedBy: chat.bsky.actor.defs.ProfileViewBasic | undefined =
myProfile
? {
...myProfile,
$type: 'chat.bsky.actor.defs#profileViewBasic',
}
: undefined
const optimisticMembers: ChatBskyActorDefs.ProfileViewBasic[] =
const optimisticMembers: chat.bsky.actor.defs.ProfileViewBasic[] =
profiles.map(profile => ({
...profile,
$type: 'chat.bsky.actor.defs#profileViewBasic',
@@ -80,11 +76,12 @@ export function useAddGroupMembers(
},
}))
queryClient.setQueryData<ChatBskyConvoDefs.ConvoView>(
queryClient.setQueryData<chat.bsky.convo.defs.ConvoView>(
CONVO_KEY(convoId),
prev => {
if (!prev) return
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) return prev
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind))
return prev
return {
...prev,
members: [...prev.members, ...optimisticMembers],
@@ -97,7 +94,7 @@ export function useAddGroupMembers(
)
queryClient.setQueriesData<
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
InfiniteData<chat.bsky.convo.listConvos.$OutputBody>
>({queryKey: [CONVO_LIST_KEY]}, prev => {
if (!prev?.pages) return
return {
@@ -106,7 +103,8 @@ export function useAddGroupMembers(
...page,
convos: page.convos.map(convo => {
if (convo.id !== convoId) return convo
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) return convo
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind))
return convo
return {
...convo,
members: [...convo.members, ...optimisticMembers],
@@ -121,7 +119,7 @@ export function useAddGroupMembers(
}
})
queryClient.setQueryData<ChatBskyActorDefs.ProfileViewBasic[]>(
queryClient.setQueryData<chat.bsky.actor.defs.ProfileViewBasic[]>(
listConvoMembersQueryKey(convoId),
prev => {
if (!prev) return
@@ -133,13 +131,13 @@ export function useAddGroupMembers(
},
onSuccess: data => {
if (convoId) {
queryClient.setQueryData<ChatBskyConvoDefs.ConvoView>(
queryClient.setQueryData<chat.bsky.convo.defs.ConvoView>(
CONVO_KEY(convoId),
data.convo,
)
queryClient.setQueriesData<
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
InfiniteData<chat.bsky.convo.listConvos.$OutputBody>
>({queryKey: [CONVO_LIST_KEY]}, prev => {
if (!prev?.pages) return
return {
+10 -14
View File
@@ -1,9 +1,3 @@
import {
type ChatBskyActorDefs,
type ChatBskyConvoDefs,
type ChatBskyConvoGetConvo,
type ChatBskyConvoGetUnreadCounts,
} from '@atproto/api'
import {
type QueryClient,
useMutation,
@@ -44,7 +38,7 @@ export function useConvoQuery({convoId}: {convoId: string}) {
export function precacheConvoQuery(
queryClient: QueryClient,
convo: ChatBskyConvoDefs.ConvoView,
convo: chat.bsky.convo.defs.ConvoView,
) {
queryClient.setQueryData(RQKEY(convo.id), convo)
}
@@ -81,7 +75,7 @@ export function useMarkAsReadMutation() {
// find the convo so we know which badge counter (if any) to decrement.
// keep scanning past a stale unreadCount === 0 cache so another cache
// holding the true unread state still drives the decrement
let unreadStatus: ChatBskyConvoDefs.ConvoView['status'] | undefined
let unreadStatus: chat.bsky.convo.defs.ConvoView['status'] | undefined
for (const [, data] of prevListQueries) {
if (!data) continue
const convo = getConvoFromQueryData(convoId, data)
@@ -96,11 +90,13 @@ export function useMarkAsReadMutation() {
// the badge count query is a separate server query that the list caches
// don't feed, so decrement it here to keep the badge in sync
const prevUnreadCountsQueries =
queryClient.getQueriesData<ChatBskyConvoGetUnreadCounts.OutputSchema>({
queryKey: UNREAD_COUNTS_PARTIAL_KEY,
})
queryClient.getQueriesData<chat.bsky.convo.getUnreadCounts.$OutputBody>(
{
queryKey: UNREAD_COUNTS_PARTIAL_KEY,
},
)
if (unreadStatus) {
queryClient.setQueriesData<ChatBskyConvoGetUnreadCounts.OutputSchema>(
queryClient.setQueriesData<chat.bsky.convo.getUnreadCounts.$OutputBody>(
{queryKey: UNREAD_COUNTS_PARTIAL_KEY},
old => {
if (!old) return old
@@ -184,9 +180,9 @@ export function useMarkAsReadMutation() {
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<ChatBskyActorDefs.ProfileViewBasic, void> {
): Generator<chat.bsky.actor.defs.ProfileViewBasic, void> {
const queryDatas = queryClient.getQueriesData<
ChatBskyConvoGetConvo.OutputSchema['convo']
chat.bsky.convo.getConvo.$OutputBody['convo']
>({
queryKey: [RQKEY_ROOT],
})
@@ -1,4 +1,3 @@
import {type ChatBskyGroupCreateGroup} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {useMutation, useQueryClient} from '@tanstack/react-query'
@@ -11,7 +10,7 @@ export function useCreateGroupChat({
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupCreateGroup.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.createGroup.$OutputBody) => void
onError?: (error: Error) => void
}) {
const queryClient = useQueryClient()
@@ -1,10 +1,6 @@
import {
ChatBskyConvoDefs,
type ChatBskyGroupCreateJoinLink,
type ChatBskyGroupDefs,
} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {logger} from '#/logger'
import {useChatClient} from '#/state/session'
import {chat} from '#/lexicons'
@@ -19,7 +15,7 @@ export function useCreateJoinLink(
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupCreateJoinLink.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.createJoinLink.$OutputBody) => void
onError?: (error: Error) => void
},
) {
@@ -31,7 +27,7 @@ export function useCreateJoinLink(
joinRule,
requireApproval,
}: {
joinRule: ChatBskyGroupDefs.JoinRule
joinRule: chat.bsky.group.defs.JoinRule
requireApproval: boolean
}) => {
if (!convoId) throw new Error('No convoId provided')
@@ -44,7 +40,8 @@ export function useCreateJoinLink(
onMutate: ({joinRule, requireApproval}) => {
if (!convoId) return
return updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) return undefined
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind))
return undefined
return {
...prev,
kind: {
@@ -64,7 +61,8 @@ export function useCreateJoinLink(
onSuccess: data => {
if (convoId) {
updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) return undefined
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind))
return undefined
return {
...prev,
kind: {...prev.kind, joinLink: data.joinLink},
@@ -1,9 +1,6 @@
import {
ChatBskyConvoDefs,
type ChatBskyGroupDisableJoinLink,
} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {logger} from '#/logger'
import {invalidateJoinLinkPreviewsForCode} from '#/state/queries/join-links'
import {useChatClient} from '#/state/session'
@@ -19,7 +16,7 @@ export function useDisableJoinLink(
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupDisableJoinLink.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.disableJoinLink.$OutputBody) => void
onError?: (error: Error) => void
},
) {
@@ -34,7 +31,10 @@ export function useDisableJoinLink(
onMutate: () => {
if (!convoId) return
return updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind) || !prev.kind.joinLink) {
if (
!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind) ||
!prev.kind.joinLink
) {
return undefined
}
return {
@@ -49,7 +49,8 @@ export function useDisableJoinLink(
onSuccess: data => {
if (convoId) {
updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) return undefined
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind))
return undefined
return {
...prev,
kind: {...prev.kind, joinLink: data.joinLink},
@@ -1,6 +1,6 @@
import {ChatBskyConvoDefs, type ChatBskyGroupEditGroup} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {logger} from '#/logger'
import {useChatClient} from '#/state/session'
import {chat} from '#/lexicons'
@@ -15,7 +15,7 @@ export function useEditGroupChatName(
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupEditGroup.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.editGroup.$OutputBody) => void
onError?: (error: Error) => void
},
) {
@@ -33,7 +33,8 @@ export function useEditGroupChatName(
onMutate: ({name: groupName}) => {
if (!convoId) return
return updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) return undefined
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind))
return undefined
return {
...prev,
kind: {...prev.kind, name: groupName},
+9 -9
View File
@@ -1,10 +1,6 @@
import {
ChatBskyConvoDefs,
type ChatBskyGroupDefs,
type ChatBskyGroupEditJoinLink,
} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {logger} from '#/logger'
import {useChatClient} from '#/state/session'
import {chat} from '#/lexicons'
@@ -19,7 +15,7 @@ export function useEditJoinLink(
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupEditJoinLink.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.editJoinLink.$OutputBody) => void
onError?: (error: Error) => void
},
) {
@@ -31,7 +27,7 @@ export function useEditJoinLink(
joinRule,
requireApproval,
}: {
joinRule: ChatBskyGroupDefs.JoinRule
joinRule: chat.bsky.group.defs.JoinRule
requireApproval: boolean
}) => {
if (!convoId) throw new Error('No convoId provided')
@@ -44,7 +40,10 @@ export function useEditJoinLink(
onMutate: ({joinRule, requireApproval}) => {
if (!convoId) return
return updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind) || !prev.kind.joinLink) {
if (
!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind) ||
!prev.kind.joinLink
) {
return undefined
}
return {
@@ -59,7 +58,8 @@ export function useEditJoinLink(
onSuccess: data => {
if (convoId) {
updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) return undefined
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind))
return undefined
return {
...prev,
kind: {...prev.kind, joinLink: data.joinLink},
@@ -1,6 +1,6 @@
import {ChatBskyConvoDefs, type ChatBskyGroupEnableJoinLink} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {logger} from '#/logger'
import {invalidateJoinLinkPreviewsForCode} from '#/state/queries/join-links'
import {useChatClient} from '#/state/session'
@@ -16,7 +16,7 @@ export function useEnableJoinLink(
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupEnableJoinLink.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.enableJoinLink.$OutputBody) => void
onError?: (error: Error) => void
},
) {
@@ -31,7 +31,10 @@ export function useEnableJoinLink(
onMutate: () => {
if (!convoId) return
return updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind) || !prev.kind.joinLink) {
if (
!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind) ||
!prev.kind.joinLink
) {
return undefined
}
return {
@@ -46,7 +49,8 @@ export function useEnableJoinLink(
onSuccess: data => {
if (convoId) {
updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) return undefined
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind))
return undefined
return {
...prev,
kind: {...prev.kind, joinLink: data.joinLink},
@@ -1,4 +1,3 @@
import {type ChatBskyConvoGetConvoForMembers} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {useMutation, useQueryClient} from '@tanstack/react-query'
@@ -11,7 +10,7 @@ export function useGetConvoForMembers({
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyConvoGetConvoForMembers.OutputSchema) => void
onSuccess?: (data: chat.bsky.convo.getConvoForMembers.$OutputBody) => void
onError?: (error: Error) => void
}) {
const queryClient = useQueryClient()
+7 -13
View File
@@ -1,9 +1,3 @@
import {
type ChatBskyActorDefs,
type ChatBskyGroupApproveJoinRequest,
type ChatBskyGroupListJoinRequests,
type ChatBskyGroupRejectJoinRequest,
} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -20,8 +14,8 @@ import {createListJoinRequestsQueryKey} from './list-join-requests'
type JoinRequestAction = 'approve' | 'reject'
type JoinRequestOutput<A extends JoinRequestAction> = A extends 'approve'
? ChatBskyGroupApproveJoinRequest.OutputSchema
: ChatBskyGroupRejectJoinRequest.OutputSchema
? chat.bsky.group.approveJoinRequest.$OutputBody
: chat.bsky.group.rejectJoinRequest.$OutputBody
export function useJoinRequestMutation<A extends JoinRequestAction>(
action: A,
@@ -65,7 +59,7 @@ export function useJoinRequestMutation<A extends JoinRequestAction>(
const requestsKey = createListJoinRequestsQueryKey({convoId})
const prevRequests =
queryClient.getQueryData<
InfiniteData<ChatBskyGroupListJoinRequests.OutputSchema>
InfiniteData<chat.bsky.group.listJoinRequests.$OutputBody>
>(requestsKey)
const requestedByProfile = prevRequests?.pages
@@ -73,7 +67,7 @@ export function useJoinRequestMutation<A extends JoinRequestAction>(
.find(request => request.requestedBy.did === member)?.requestedBy
queryClient.setQueryData<
InfiniteData<ChatBskyGroupListJoinRequests.OutputSchema>
InfiniteData<chat.bsky.group.listJoinRequests.$OutputBody>
>(requestsKey, prev => {
if (!prev?.pages) return prev
return {
@@ -87,14 +81,14 @@ export function useJoinRequestMutation<A extends JoinRequestAction>(
}
})
let prevMembers: ChatBskyActorDefs.ProfileViewBasic[] | undefined
let prevMembers: chat.bsky.actor.defs.ProfileViewBasic[] | undefined
if (action === 'approve' && requestedByProfile) {
const membersKey = listConvoMembersQueryKey(convoId)
prevMembers =
queryClient.getQueryData<ChatBskyActorDefs.ProfileViewBasic[]>(
queryClient.getQueryData<chat.bsky.actor.defs.ProfileViewBasic[]>(
membersKey,
)
queryClient.setQueryData<ChatBskyActorDefs.ProfileViewBasic[]>(
queryClient.setQueryData<chat.bsky.actor.defs.ProfileViewBasic[]>(
membersKey,
prev => {
if (!prev) return prev
@@ -1,7 +1,3 @@
import {
type ChatBskyConvoLeaveConvo,
type ChatBskyConvoListConvos,
} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {logger} from '#/logger'
@@ -22,7 +18,7 @@ export function RQKEY(convoId: string | undefined) {
type ConvoListQueryData = {
pageParams: Array<string | undefined>
pages: Array<ChatBskyConvoListConvos.OutputSchema>
pages: Array<chat.bsky.convo.listConvos.$OutputBody>
}
export function useLeaveConvo(
@@ -33,7 +29,7 @@ export function useLeaveConvo(
onError,
}: {
onMutate?: () => void
onSuccess?: (data: ChatBskyConvoLeaveConvo.OutputSchema) => void
onSuccess?: (data: chat.bsky.convo.leaveConvo.$OutputBody) => void
onError?: (error: Error) => void
},
) {
@@ -1,14 +1,10 @@
import {
ChatBskyConvoDefs,
type ChatBskyConvoListConvoRequests,
ChatBskyGroupDefs,
} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
useInfiniteQuery,
} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {useChatClient} from '#/state/session'
import {chat} from '#/lexicons'
@@ -44,16 +40,18 @@ export function useListConvoRequests({
export type ConvoRequestListQueryData = {
pageParams: Array<string | undefined>
pages: Array<ChatBskyConvoListConvoRequests.OutputSchema>
pages: Array<chat.bsky.convo.listConvoRequests.$OutputBody>
}
export type ConvoRequestItem =
ChatBskyConvoListConvoRequests.OutputSchema['requests'][number]
chat.bsky.convo.listConvoRequests.$OutputBody['requests'][number]
export function optimisticUpdate(
chatId: string,
old: ConvoRequestListQueryData | undefined,
updateFn: (convo: ChatBskyConvoDefs.ConvoView) => ChatBskyConvoDefs.ConvoView,
updateFn: (
convo: chat.bsky.convo.defs.ConvoView,
) => chat.bsky.convo.defs.ConvoView,
): ConvoRequestListQueryData | undefined {
if (!old) return old
@@ -62,7 +60,10 @@ export function optimisticUpdate(
pages: old.pages.map(page => ({
...page,
requests: page.requests.map((item): ConvoRequestItem => {
if (ChatBskyConvoDefs.isConvoView(item) && item.id === chatId) {
if (
bsky.isType(chat.bsky.convo.defs.convoView, item) &&
item.id === chatId
) {
return {
...updateFn(item),
$type: 'chat.bsky.convo.defs#convoView',
@@ -85,7 +86,9 @@ export function optimisticDelete(
pages: old.pages.map(page => ({
...page,
requests: page.requests.filter(
item => !ChatBskyConvoDefs.isConvoView(item) || item.id !== chatId,
item =>
!bsky.isType(chat.bsky.convo.defs.convoView, item) ||
item.id !== chatId,
),
})),
}
@@ -101,7 +104,7 @@ export function markAllRead(
pages: old.pages.map(page => ({
...page,
requests: page.requests.map((item): ConvoRequestItem => {
if (ChatBskyConvoDefs.isConvoView(item)) {
if (bsky.isType(chat.bsky.convo.defs.convoView, item)) {
return {
...item,
$type: 'chat.bsky.convo.defs#convoView',
@@ -126,7 +129,7 @@ export function optimisticDeleteJoinRequest(
...page,
requests: page.requests.filter(
item =>
!ChatBskyGroupDefs.isJoinRequestConvoView(item) ||
!bsky.isType(chat.bsky.group.defs.joinRequestConvoView, item) ||
item.convoId !== convoId,
),
})),
@@ -138,7 +141,7 @@ export function* findAllProfilesInQueryData(
did: string,
) {
const queryDatas = queryClient.getQueriesData<
InfiniteData<ChatBskyConvoListConvoRequests.OutputSchema>
InfiniteData<chat.bsky.convo.listConvoRequests.$OutputBody>
>({
queryKey: [RQKEY_ROOT],
})
@@ -147,13 +150,15 @@ export function* findAllProfilesInQueryData(
for (const page of queryData.pages) {
for (const item of page.requests) {
if (ChatBskyConvoDefs.isConvoView(item)) {
if (bsky.isType(chat.bsky.convo.defs.convoView, item)) {
for (const member of item.members) {
if (member.did === did) {
yield member
}
}
} else if (ChatBskyGroupDefs.isJoinRequestConvoView(item)) {
} else if (
bsky.isType(chat.bsky.group.defs.joinRequestConvoView, item)
) {
if (item.owner.did === did) {
yield item.owner
}
+129 -94
View File
@@ -1,9 +1,4 @@
import {useCallback, useEffect, useMemo} from 'react'
import {
type ChatBskyActorDefs,
ChatBskyConvoDefs,
type ChatBskyConvoListConvos,
} from '@atproto/api'
import {
type InfiniteData,
type Query,
@@ -68,7 +63,7 @@ export const RQKEY_PARTIAL = (
* filters client-side or convos leak into lists that should exclude them.
*/
export function convoMatchesQueryKey(
convo: ChatBskyConvoDefs.ConvoView,
convo: chat.bsky.convo.defs.ConvoView,
queryKey: QueryKey,
): boolean {
const [, status, readState, kind, lockStatus] = queryKey as ReturnType<
@@ -76,7 +71,7 @@ export function convoMatchesQueryKey(
>
if (status !== 'all' && status !== convo.status) return false
if (readState === 'unread' && convo.unreadCount === 0) return false
if (ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
if (bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)) {
if (kind === 'direct') return false
if (lockStatus && convo.kind.lockStatus !== lockStatus) return false
} else {
@@ -94,7 +89,7 @@ export function convoMatchesQueryKey(
* longer matches (e.g. unreadCount dropped to 0), mirroring how read/mute
* log events update convos in place everywhere.
*/
export function convoListQueryPredicate(convo: ChatBskyConvoDefs.ConvoView) {
export function convoListQueryPredicate(convo: chat.bsky.convo.defs.ConvoView) {
return (query: Query): boolean => {
const data = query.state.data as ConvoListQueryData | undefined
if (data && getConvoFromQueryData(convo.id, data)) return true
@@ -196,10 +191,10 @@ export function ListConvosProviderInner({
function mutateMembers(
convoId: string,
fn: (
members: ChatBskyActorDefs.ProfileViewBasic[],
) => ChatBskyActorDefs.ProfileViewBasic[],
members: chat.bsky.actor.defs.ProfileViewBasic[],
) => chat.bsky.actor.defs.ProfileViewBasic[],
) {
queryClient.setQueryData<ChatBskyActorDefs.ProfileViewBasic[]>(
queryClient.setQueryData<chat.bsky.actor.defs.ProfileViewBasic[]>(
listConvoMembersQueryKey(convoId),
old => {
if (!old) return // query doesn't exist yet, skip
@@ -211,8 +206,8 @@ export function ListConvosProviderInner({
function updateConvoInAllLists(
convoId: string,
fn: (
convo: ChatBskyConvoDefs.ConvoView,
) => ChatBskyConvoDefs.ConvoView,
convo: chat.bsky.convo.defs.ConvoView,
) => chat.bsky.convo.defs.ConvoView,
) {
queryClient.setQueriesData<ConvoListQueryData>(
{queryKey: [RQKEY_ROOT]},
@@ -227,10 +222,10 @@ export function ListConvosProviderInner({
function mutateConvoView(
convoId: string,
fn: (
convo: ChatBskyConvoDefs.ConvoView,
) => ChatBskyConvoDefs.ConvoView,
convo: chat.bsky.convo.defs.ConvoView,
) => chat.bsky.convo.defs.ConvoView,
) {
queryClient.setQueryData<ChatBskyConvoDefs.ConvoView>(
queryClient.setQueryData<chat.bsky.convo.defs.ConvoView>(
CONVO_KEY(convoId),
old => (old ? fn(old) : old),
)
@@ -251,7 +246,7 @@ export function ListConvosProviderInner({
function handleMemberAdded(
convoId: string,
did: string,
relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[],
relatedProfiles: chat.bsky.actor.defs.ProfileViewBasic[],
rev: string,
) {
const newMember = relatedProfiles.find(r => r.did === did)
@@ -261,7 +256,7 @@ export function ListConvosProviderInner({
const alreadyKnownMember =
queryClient
.getQueryData<
ChatBskyActorDefs.ProfileViewBasic[]
chat.bsky.actor.defs.ProfileViewBasic[]
>(listConvoMembersQueryKey(convoId))
?.some(m => m.did === did) ?? false
mutateMembers(convoId, list =>
@@ -285,7 +280,7 @@ export function ListConvosProviderInner({
const alreadyRemovedMember =
queryClient
.getQueryData<
ChatBskyActorDefs.ProfileViewBasic[]
chat.bsky.actor.defs.ProfileViewBasic[]
>(listConvoMembersQueryKey(convoId))
?.some(m => m.did === did) === false
mutateMembers(convoId, list => list.filter(m => m.did !== did))
@@ -298,24 +293,36 @@ export function ListConvosProviderInner({
}
for (const log of events.logs) {
if (ChatBskyConvoDefs.isLogBeginConvo(log)) {
if (bsky.isType(chat.bsky.convo.defs.logBeginConvo, log)) {
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogLeaveConvo(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logLeaveConvo, log)) {
deleteConvoFromAllLists(log.convoId)
// The viewer is no longer in this convo (they left on another
// device, or were removed - removed members receive a
// logLeaveConvo, not a logRemoveMember). Refetch any cached join
// link preview so its viewer state reflects the lost membership.
void invalidateJoinLinkPreviewsForConvo(queryClient, log.convoId)
} else if (ChatBskyConvoDefs.isLogDeleteMessage(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logDeleteMessage, log)) {
updateConvoInAllLists(
log.convoId,
withRevGuard(log.rev, convo => {
if (
(ChatBskyConvoDefs.isDeletedMessageView(log.message) ||
ChatBskyConvoDefs.isMessageView(log.message)) &&
(ChatBskyConvoDefs.isDeletedMessageView(convo.lastMessage) ||
ChatBskyConvoDefs.isMessageView(convo.lastMessage))
(bsky.isType(
chat.bsky.convo.defs.deletedMessageView,
log.message,
) ||
bsky.isType(
chat.bsky.convo.defs.messageView,
log.message,
)) &&
(bsky.isType(
chat.bsky.convo.defs.deletedMessageView,
convo.lastMessage,
) ||
bsky.isType(
chat.bsky.convo.defs.messageView,
convo.lastMessage,
))
) {
return log.message.id === convo.lastMessage.id
? {
@@ -329,9 +336,9 @@ export function ListConvosProviderInner({
}
}),
)
} else if (ChatBskyConvoDefs.isLogCreateMessage(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logCreateMessage, log)) {
// Store in a new var to avoid TS errors due to closures.
const logRef: ChatBskyConvoDefs.LogCreateMessage = log
const logRef: chat.bsky.convo.defs.LogCreateMessage = log
// Get all matching queries
const queries = queryClient.getQueriesData<ConvoListQueryData>({
@@ -339,7 +346,7 @@ export function ListConvosProviderInner({
})
// Check if convo exists in any query
let foundConvo: ChatBskyConvoDefs.ConvoView | null = null
let foundConvo: chat.bsky.convo.defs.ConvoView | null = null
for (const [_key, query] of queries) {
if (!query) continue
const convo = getConvoFromQueryData(logRef.convoId, query)
@@ -382,15 +389,23 @@ export function ListConvosProviderInner({
lastMessage: logRef.message,
unreadCount:
foundConvo.id !== currentConvoId
? (ChatBskyConvoDefs.isMessageView(logRef.message) ||
ChatBskyConvoDefs.isDeletedMessageView(logRef.message)) &&
? (bsky.isType(
chat.bsky.convo.defs.messageView,
logRef.message,
) ||
bsky.isType(
chat.bsky.convo.defs.deletedMessageView,
logRef.message,
)) &&
logRef.message.sender.did !== currentAccount?.did
? foundConvo.unreadCount + 1
: foundConvo.unreadCount
: 0,
}
function filterConvoFromPage(convo: ChatBskyConvoDefs.ConvoView[]) {
function filterConvoFromPage(
convo: chat.bsky.convo.defs.ConvoView[],
) {
return convo.filter(c => c.id !== logRef.convoId)
}
@@ -453,7 +468,7 @@ export function ListConvosProviderInner({
old => moveConvoToTopInRequests(updatedConvo, old),
)
}
} else if (ChatBskyConvoDefs.isLogReadMessage(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logReadMessage, log)) {
updateConvoInAllLists(
log.convoId,
withRevGuard(log.rev, convo => ({
@@ -462,7 +477,7 @@ export function ListConvosProviderInner({
rev: log.rev,
})),
)
} else if (ChatBskyConvoDefs.isLogReadConvo(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logReadConvo, log)) {
updateConvoInAllLists(
log.convoId,
withRevGuard(log.rev, convo => ({
@@ -471,12 +486,12 @@ export function ListConvosProviderInner({
rev: log.rev,
})),
)
} else if (ChatBskyConvoDefs.isLogAcceptConvo(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logAcceptConvo, log)) {
const requestQueries =
queryClient.getQueriesData<ConvoListQueryData>({
queryKey: RQKEY_PARTIAL('request'),
})
let foundConvo: ChatBskyConvoDefs.ConvoView | null = null
let foundConvo: chat.bsky.convo.defs.ConvoView | null = null
for (const [_key, data] of requestQueries) {
if (!data) continue
foundConvo = getConvoFromQueryData(log.convoId, data)
@@ -492,7 +507,7 @@ export function ListConvosProviderInner({
if (log.rev <= foundConvo.rev) {
continue
}
const acceptedConvo: ChatBskyConvoDefs.ConvoView = {
const acceptedConvo: chat.bsky.convo.defs.ConvoView = {
...foundConvo,
status: 'accepted',
rev: log.rev,
@@ -553,7 +568,7 @@ export function ListConvosProviderInner({
}
},
)
} else if (ChatBskyConvoDefs.isLogMuteConvo(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logMuteConvo, log)) {
mutateConvoView(
log.convoId,
withRevGuard(log.rev, convo => ({
@@ -562,7 +577,7 @@ export function ListConvosProviderInner({
rev: log.rev,
})),
)
} else if (ChatBskyConvoDefs.isLogUnmuteConvo(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logUnmuteConvo, log)) {
mutateConvoView(
log.convoId,
withRevGuard(log.rev, convo => ({
@@ -571,11 +586,11 @@ export function ListConvosProviderInner({
rev: log.rev,
})),
)
} else if (ChatBskyConvoDefs.isLogLockConvo(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logLockConvo, log)) {
mutateConvoView(
log.convoId,
withRevGuard(log.rev, convo => {
if (ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
if (bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)) {
return {
...convo,
kind: {...convo.kind, lockStatus: 'locked'},
@@ -590,11 +605,11 @@ export function ListConvosProviderInner({
void queryClient.invalidateQueries({
queryKey: CONVO_KEY(log.convoId),
})
} else if (ChatBskyConvoDefs.isLogUnlockConvo(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logUnlockConvo, log)) {
mutateConvoView(
log.convoId,
withRevGuard(log.rev, convo => {
if (ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
if (bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)) {
return {
...convo,
kind: {
@@ -609,11 +624,13 @@ export function ListConvosProviderInner({
return {...convo, rev: log.rev}
}),
)
} else if (ChatBskyConvoDefs.isLogLockConvoPermanently(log)) {
} else if (
bsky.isType(chat.bsky.convo.defs.logLockConvoPermanently, log)
) {
mutateConvoView(
log.convoId,
withRevGuard(log.rev, convo => {
if (ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
if (bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)) {
return {
...convo,
kind: {...convo.kind, lockStatus: 'locked-permanently'},
@@ -624,20 +641,20 @@ export function ListConvosProviderInner({
}),
)
} else if (
ChatBskyConvoDefs.isLogCreateJoinLink(log) ||
ChatBskyConvoDefs.isLogEditJoinLink(log) ||
ChatBskyConvoDefs.isLogEnableJoinLink(log) ||
ChatBskyConvoDefs.isLogDisableJoinLink(log)
bsky.isType(chat.bsky.convo.defs.logCreateJoinLink, log) ||
bsky.isType(chat.bsky.convo.defs.logEditJoinLink, log) ||
bsky.isType(chat.bsky.convo.defs.logEnableJoinLink, log) ||
bsky.isType(chat.bsky.convo.defs.logDisableJoinLink, log)
) {
// Join link data not included in the log event, trigger refetch to get it
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogEditGroup(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logEditGroup, log)) {
// Updated group details (name etc.) aren't included in the log
// event, so refetch to pick them up.
debouncedRefetch()
} else if (
ChatBskyConvoDefs.isLogApproveJoinRequest(log) ||
ChatBskyConvoDefs.isLogRejectJoinRequest(log)
bsky.isType(chat.bsky.convo.defs.logApproveJoinRequest, log) ||
bsky.isType(chat.bsky.convo.defs.logRejectJoinRequest, log)
) {
// Route through mutateConvoView (not updateConvoInAllLists) so the
// single-convo cache updates too, keeping the in-convo requests
@@ -648,7 +665,9 @@ export function ListConvosProviderInner({
applyJoinRequestCountDelta(convo, log.rev, -1),
),
)
} else if (ChatBskyConvoDefs.isLogIncomingJoinRequest(log)) {
} else if (
bsky.isType(chat.bsky.convo.defs.logIncomingJoinRequest, log)
) {
// Route through mutateConvoView (not updateConvoInAllLists) so the
// single-convo cache updates too, letting the in-convo requests
// banner appear live.
@@ -658,14 +677,16 @@ export function ListConvosProviderInner({
applyJoinRequestCountDelta(convo, log.rev, 1),
),
)
} else if (ChatBskyConvoDefs.isLogReadJoinRequests(log)) {
} else if (
bsky.isType(chat.bsky.convo.defs.logReadJoinRequests, log)
) {
// The owner marked join requests as read (possibly on another
// device). Zero the unread count but keep the total, mirroring the
// useMarkJoinRequestsRead mutation.
mutateConvoView(
log.convoId,
withRevGuard(log.rev, convo => {
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)) {
return {...convo, rev: log.rev}
}
return {
@@ -675,11 +696,18 @@ export function ListConvosProviderInner({
}
}),
)
} else if (ChatBskyConvoDefs.isLogOutgoingJoinRequest(log)) {
} else if (
bsky.isType(chat.bsky.convo.defs.logOutgoingJoinRequest, log)
) {
// Viewer isn't in the chat yet, but the inbox surfaces outgoing
// requests, so refetch to pick up the new entry.
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogWithdrawIncomingJoinRequest(log)) {
} else if (
bsky.isType(
chat.bsky.convo.defs.logWithdrawIncomingJoinRequest,
log,
)
) {
// A requester rescinded their request to a group the viewer owns.
// Mirror of isLogIncomingJoinRequest: decrement the counts.
mutateConvoView(
@@ -688,14 +716,19 @@ export function ListConvosProviderInner({
applyJoinRequestCountDelta(convo, log.rev, -1),
),
)
} else if (ChatBskyConvoDefs.isLogWithdrawOutgoingJoinRequest(log)) {
} else if (
bsky.isType(
chat.bsky.convo.defs.logWithdrawOutgoingJoinRequest,
log,
)
) {
// The viewer rescinded their own outgoing join request (possibly on
// another device). Remove it from the requests inbox cache.
queryClient.setQueriesData<ConvoRequestListQueryData>(
{queryKey: [REQUESTS_RQKEY_ROOT]},
old => optimisticDeleteJoinRequest(log.convoId, old),
)
} else if (ChatBskyConvoDefs.isLogAddReaction(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logAddReaction, log)) {
updateConvoInAllLists(
log.convoId,
withRevGuard(log.rev, convo => {
@@ -718,13 +751,10 @@ export function ListConvosProviderInner({
}
}),
)
} else if (ChatBskyConvoDefs.isLogAddMember(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logAddMember, log)) {
const data = log.message.data
if (
bsky.dangerousIsType<ChatBskyConvoDefs.SystemMessageDataAddMember>(
data,
ChatBskyConvoDefs.isSystemMessageDataAddMember,
)
bsky.isType(chat.bsky.convo.defs.systemMessageDataAddMember, data)
) {
handleMemberAdded(
log.convoId,
@@ -738,12 +768,12 @@ export function ListConvosProviderInner({
queryKey: CONVO_KEY(log.convoId),
})
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogRemoveMember(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logRemoveMember, log)) {
const data = log.message.data
if (
bsky.dangerousIsType<ChatBskyConvoDefs.SystemMessageDataRemoveMember>(
bsky.isType(
chat.bsky.convo.defs.systemMessageDataRemoveMember,
data,
ChatBskyConvoDefs.isSystemMessageDataRemoveMember,
)
) {
handleMemberRemoved(log.convoId, data.member.did, log.rev)
@@ -753,12 +783,12 @@ export function ListConvosProviderInner({
queryKey: CONVO_KEY(log.convoId),
})
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogMemberJoin(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logMemberJoin, log)) {
const data = log.message.data
if (
bsky.dangerousIsType<ChatBskyConvoDefs.SystemMessageDataMemberJoin>(
bsky.isType(
chat.bsky.convo.defs.systemMessageDataMemberJoin,
data,
ChatBskyConvoDefs.isSystemMessageDataMemberJoin,
)
) {
handleMemberAdded(
@@ -772,12 +802,12 @@ export function ListConvosProviderInner({
queryKey: CONVO_KEY(log.convoId),
})
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogMemberLeave(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logMemberLeave, log)) {
const data = log.message.data
if (
bsky.dangerousIsType<ChatBskyConvoDefs.SystemMessageDataMemberLeave>(
bsky.isType(
chat.bsky.convo.defs.systemMessageDataMemberLeave,
data,
ChatBskyConvoDefs.isSystemMessageDataMemberLeave,
)
) {
handleMemberRemoved(log.convoId, data.member.did, log.rev)
@@ -786,7 +816,7 @@ export function ListConvosProviderInner({
queryKey: CONVO_KEY(log.convoId),
})
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogRemoveReaction(log)) {
} else if (bsky.isType(chat.bsky.convo.defs.logRemoveReaction, log)) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) =>
@@ -797,10 +827,14 @@ export function ListConvosProviderInner({
if (
// if the convo is the same
log.convoId === convo.id &&
ChatBskyConvoDefs.isMessageAndReactionView(
bsky.isType(
chat.bsky.convo.defs.messageAndReactionView,
convo.lastReaction,
) &&
ChatBskyConvoDefs.isMessageView(log.message) &&
bsky.isType(
chat.bsky.convo.defs.messageView,
log.message,
) &&
// ...and the message is the same
convo.lastReaction.message.id === log.message.id &&
// ...and the reaction is the same
@@ -882,7 +916,7 @@ export function useUnreadMessageCount(): {
export type ConvoListQueryData = {
pageParams: Array<string | undefined>
pages: Array<ChatBskyConvoListConvos.OutputSchema>
pages: Array<chat.bsky.convo.listConvos.$OutputBody>
}
export function useOnMarkAsRead() {
@@ -919,8 +953,8 @@ export function useOnMarkAsRead() {
*/
function withRevGuard(
rev: string,
fn: (convo: ChatBskyConvoDefs.ConvoView) => ChatBskyConvoDefs.ConvoView,
): (convo: ChatBskyConvoDefs.ConvoView) => ChatBskyConvoDefs.ConvoView {
fn: (convo: chat.bsky.convo.defs.ConvoView) => chat.bsky.convo.defs.ConvoView,
): (convo: chat.bsky.convo.defs.ConvoView) => chat.bsky.convo.defs.ConvoView {
return convo => (rev <= convo.rev ? convo : fn(convo))
}
@@ -928,8 +962,8 @@ function optimisticUpdate(
chatId: string,
old?: ConvoListQueryData,
updateFn?: (
convo: ChatBskyConvoDefs.ConvoView,
) => ChatBskyConvoDefs.ConvoView,
convo: chat.bsky.convo.defs.ConvoView,
) => chat.bsky.convo.defs.ConvoView,
) {
if (!old || !updateFn) return old
@@ -945,12 +979,12 @@ function optimisticUpdate(
}
function applyJoinRequestCountDelta(
convo: ChatBskyConvoDefs.ConvoView,
convo: chat.bsky.convo.defs.ConvoView,
rev: string,
delta: 1 | -1,
): ChatBskyConvoDefs.ConvoView {
): chat.bsky.convo.defs.ConvoView {
// Join requests are only meaningful for group convos.
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)) {
return {...convo, rev}
}
// Bump the total and unread counts together. Both are clamped at 0 and
@@ -971,7 +1005,7 @@ function applyJoinRequestCountDelta(
}
function moveConvoToTopInRequests(
updatedConvo: ChatBskyConvoDefs.ConvoView,
updatedConvo: chat.bsky.convo.defs.ConvoView,
old: ConvoRequestListQueryData | undefined,
): ConvoRequestListQueryData | undefined {
if (!old) return old
@@ -985,7 +1019,8 @@ function moveConvoToTopInRequests(
pages: old.pages.map((page, i) => {
const filtered = page.requests.filter(
item =>
!ChatBskyConvoDefs.isConvoView(item) || item.id !== updatedConvo.id,
!bsky.isType(chat.bsky.convo.defs.convoView, item) ||
item.id !== updatedConvo.id,
)
if (i === 0) {
return {
@@ -999,13 +1034,13 @@ function moveConvoToTopInRequests(
}
function removeMemberFromConvoView(
convo: ChatBskyConvoDefs.ConvoView,
convo: chat.bsky.convo.defs.ConvoView,
did: string,
rev: string,
alreadyRemovedMember: boolean,
): ChatBskyConvoDefs.ConvoView {
): chat.bsky.convo.defs.ConvoView {
// Member add/remove/join/leave events are only meaningful for group convos.
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) return convo
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)) return convo
const nextMembers = convo.members.filter(m => m.did !== did)
return {
...convo,
@@ -1021,13 +1056,13 @@ function removeMemberFromConvoView(
}
function addMemberToConvoView(
convo: ChatBskyConvoDefs.ConvoView,
member: ChatBskyActorDefs.ProfileViewBasic,
convo: chat.bsky.convo.defs.ConvoView,
member: chat.bsky.actor.defs.ProfileViewBasic,
rev: string,
alreadyKnownMember: boolean,
): ChatBskyConvoDefs.ConvoView {
): chat.bsky.convo.defs.ConvoView {
// Member add/remove/join/leave events are only meaningful for group convos.
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) return convo
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)) return convo
const alreadyInCuratedList = convo.members.some(m => m.did === member.did)
const nextMembers = alreadyInCuratedList
? convo.members
@@ -1073,7 +1108,7 @@ export function* findAllProfilesInQueryData(
did: string,
) {
const queryDatas = queryClient.getQueriesData<
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
InfiniteData<chat.bsky.convo.listConvos.$OutputBody>
>({
queryKey: [RQKEY_ROOT],
})
@@ -1,4 +1,3 @@
import {type ChatBskyActorDefs} from '@atproto/api'
import {type QueryClient, useQuery} from '@tanstack/react-query'
import {STALE} from '#/state/queries'
@@ -18,7 +17,7 @@ export function useListConvoMembersQuery({
placeholderData,
}: {
convoId: string
placeholderData?: ChatBskyActorDefs.ProfileViewBasic[]
placeholderData?: chat.bsky.actor.defs.ProfileViewBasic[]
}) {
const client = useChatClient()
@@ -32,7 +31,7 @@ export function useListConvoMembersQuery({
* `members` with the exported profile type also keeps the hook's result
* type unchanged for consumers.
*/
const members: ChatBskyActorDefs.ProfileViewBasic[] = []
const members: chat.bsky.actor.defs.ProfileViewBasic[] = []
let cursor: string | undefined
do {
@@ -55,9 +54,9 @@ export function useListConvoMembersQuery({
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<ChatBskyActorDefs.ProfileViewBasic, void> {
): Generator<chat.bsky.actor.defs.ProfileViewBasic, void> {
const queryDatas = queryClient.getQueriesData<
ChatBskyActorDefs.ProfileViewBasic[]
chat.bsky.actor.defs.ProfileViewBasic[]
>({
queryKey: [RQKEY_ROOT],
})
@@ -1,7 +1,7 @@
import {useEffect} from 'react'
import {ChatBskyConvoDefs} from '@atproto/api'
import {useInfiniteQuery, useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {useMessagesEventBus} from '#/state/messages/events'
import {createQueryKey} from '#/state/queries/util'
import {useChatClient} from '#/state/session'
@@ -35,9 +35,9 @@ export function useListJoinRequestsQuery({
if (event.type !== 'logs') return
for (const log of event.logs) {
if (
ChatBskyConvoDefs.isLogIncomingJoinRequest(log) ||
ChatBskyConvoDefs.isLogApproveJoinRequest(log) ||
ChatBskyConvoDefs.isLogRejectJoinRequest(log)
bsky.isType(chat.bsky.convo.defs.logIncomingJoinRequest, log) ||
bsky.isType(chat.bsky.convo.defs.logApproveJoinRequest, log) ||
bsky.isType(chat.bsky.convo.defs.logRejectJoinRequest, log)
) {
void queryClient.invalidateQueries({
queryKey: createListJoinRequestsQueryKey({convoId}),
@@ -1,6 +1,6 @@
import {ChatBskyConvoDefs, type ChatBskyConvoLockConvo} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {useChatClient} from '#/state/session'
import {chat} from '#/lexicons'
import {
@@ -15,7 +15,7 @@ export function useLockConvo(
onError,
}: {
onSuccess?: (
data: ChatBskyConvoLockConvo.OutputSchema,
data: chat.bsky.convo.lockConvo.$OutputBody,
variables: {lock: boolean; silent?: boolean},
) => void
onError?: (
@@ -39,7 +39,8 @@ export function useLockConvo(
onMutate: ({lock}) => {
if (!convoId) return
return updateConvoOptimistic(queryClient, convoId, prev => {
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) return undefined
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind))
return undefined
return {
...prev,
kind: {
@@ -1,6 +1,6 @@
import {ChatBskyConvoDefs} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {logger} from '#/logger'
import {useChatClient} from '#/state/session'
import {chat} from '#/lexicons'
@@ -22,13 +22,15 @@ export function useMarkJoinRequestsRead(convoId: string | undefined) {
onMutate: () => {
if (!convoId) return
const prevConvo = queryClient.getQueryData<ChatBskyConvoDefs.ConvoView>(
CONVO_KEY(convoId),
)
queryClient.setQueryData<ChatBskyConvoDefs.ConvoView | undefined>(
const prevConvo =
queryClient.getQueryData<chat.bsky.convo.defs.ConvoView>(
CONVO_KEY(convoId),
)
queryClient.setQueryData<chat.bsky.convo.defs.ConvoView | undefined>(
CONVO_KEY(convoId),
old => {
if (!old || !ChatBskyConvoDefs.isGroupConvo(old.kind)) return old
if (!old || !bsky.isType(chat.bsky.convo.defs.groupConvo, old.kind))
return old
return {
...old,
kind: {...old.kind, unreadJoinRequestCount: 0},
@@ -50,7 +52,7 @@ export function useMarkJoinRequestsRead(convoId: string | undefined) {
convos: page.convos.map(convo => {
if (
convo.id !== convoId ||
!ChatBskyConvoDefs.isGroupConvo(convo.kind)
!bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)
) {
return convo
}
@@ -1,4 +1,3 @@
import {type ChatBskyConvoMuteConvo} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {useChatClient} from '#/state/session'
@@ -14,7 +13,7 @@ export function useMuteConvo(
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyConvoMuteConvo.OutputSchema) => void
onSuccess?: (data: chat.bsky.convo.muteConvo.$OutputBody) => void
onError?: (error: Error) => void
},
) {
+13 -17
View File
@@ -1,9 +1,3 @@
import {
type ChatBskyActorDefs,
ChatBskyConvoDefs,
type ChatBskyConvoListConvos,
type ChatBskyGroupRemoveMembers,
} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -11,6 +5,7 @@ import {
useQueryClient,
} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {logger} from '#/logger'
import {useChatClient} from '#/state/session'
import {chat} from '#/lexicons'
@@ -24,7 +19,7 @@ export function useRemoveFromGroupChat(
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupRemoveMembers.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.removeMembers.$OutputBody) => void
onError?: (error: Error) => void
},
) {
@@ -43,23 +38,24 @@ export function useRemoveFromGroupChat(
onMutate: ({members}) => {
if (!convoId) return
const prevConvo = queryClient.getQueryData<ChatBskyConvoDefs.ConvoView>(
CONVO_KEY(convoId),
)
const prevConvo =
queryClient.getQueryData<chat.bsky.convo.defs.ConvoView>(
CONVO_KEY(convoId),
)
const prevListEntries = queryClient.getQueriesData<
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
InfiniteData<chat.bsky.convo.listConvos.$OutputBody>
>({queryKey: [CONVO_LIST_KEY]})
const prevMemberList = queryClient.getQueryData<
ChatBskyActorDefs.ProfileViewBasic[]
chat.bsky.actor.defs.ProfileViewBasic[]
>(listConvoMembersQueryKey(convoId))
queryClient.setQueryData<ChatBskyConvoDefs.ConvoView>(
queryClient.setQueryData<chat.bsky.convo.defs.ConvoView>(
CONVO_KEY(convoId),
prev => {
if (!prev) return
const nextMembers = prev.members.filter(m => !members.includes(m.did))
const removed = prev.members.length - nextMembers.length
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) {
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, prev.kind)) {
return {...prev, members: nextMembers}
}
return {
@@ -74,7 +70,7 @@ export function useRemoveFromGroupChat(
)
queryClient.setQueriesData<
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
InfiniteData<chat.bsky.convo.listConvos.$OutputBody>
>({queryKey: [CONVO_LIST_KEY]}, prev => {
if (!prev?.pages) return
return {
@@ -87,7 +83,7 @@ export function useRemoveFromGroupChat(
m => !members.includes(m.did),
)
const removed = convo.members.length - nextMembers.length
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
if (!bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind)) {
return {...convo, members: nextMembers}
}
return {
@@ -103,7 +99,7 @@ export function useRemoveFromGroupChat(
}
})
queryClient.setQueryData<ChatBskyActorDefs.ProfileViewBasic[]>(
queryClient.setQueryData<chat.bsky.actor.defs.ProfileViewBasic[]>(
listConvoMembersQueryKey(convoId),
prev => {
if (!prev) return
@@ -1,4 +1,3 @@
import {type ChatBskyGroupRequestJoin} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {logger} from '#/logger'
@@ -10,7 +9,7 @@ export function useRequestJoinGroupChat({
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupRequestJoin.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.requestJoin.$OutputBody) => void
onError?: (error: Error) => void
} = {}) {
const client = useChatClient()
@@ -1,4 +1,3 @@
import {type ChatBskyConvoGetUnreadCounts} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {logger} from '#/logger'
@@ -94,10 +93,12 @@ export function useUpdateAllRead(
// zero out the badge count query that actually drives the unread badge,
// since it's a separate server query that the list caches don't feed
const prevUnreadCountsQueries =
queryClient.getQueriesData<ChatBskyConvoGetUnreadCounts.OutputSchema>({
queryKey: UNREAD_COUNTS_PARTIAL_KEY,
})
queryClient.setQueriesData<ChatBskyConvoGetUnreadCounts.OutputSchema>(
queryClient.getQueriesData<chat.bsky.convo.getUnreadCounts.$OutputBody>(
{
queryKey: UNREAD_COUNTS_PARTIAL_KEY,
},
)
queryClient.setQueriesData<chat.bsky.convo.getUnreadCounts.$OutputBody>(
{queryKey: UNREAD_COUNTS_PARTIAL_KEY},
old => {
if (!old) return old
@@ -1,7 +1,3 @@
import {
type ChatBskyConvoDefs,
type ChatBskyConvoListConvos,
} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
@@ -10,15 +6,16 @@ import {
import {RQKEY as CONVO_KEY} from '../conversation'
import {RQKEY_ROOT as CONVO_LIST_KEY} from '../list-conversations'
import {chat} from '#/lexicons'
type ConvoUpdater = (
prev: ChatBskyConvoDefs.ConvoView,
) => ChatBskyConvoDefs.ConvoView | undefined
prev: chat.bsky.convo.defs.ConvoView,
) => chat.bsky.convo.defs.ConvoView | undefined
export type ConvoCacheSnapshot = {
prevConvo: ChatBskyConvoDefs.ConvoView | undefined
prevConvo: chat.bsky.convo.defs.ConvoView | undefined
prevListEntries: Array<
[QueryKey, InfiniteData<ChatBskyConvoListConvos.OutputSchema> | undefined]
[QueryKey, InfiniteData<chat.bsky.convo.listConvos.$OutputBody> | undefined]
>
}
@@ -34,14 +31,14 @@ export function updateConvoOptimistic(
convoId: string,
updater: ConvoUpdater,
): ConvoCacheSnapshot {
const prevConvo = queryClient.getQueryData<ChatBskyConvoDefs.ConvoView>(
const prevConvo = queryClient.getQueryData<chat.bsky.convo.defs.ConvoView>(
CONVO_KEY(convoId),
)
const prevListEntries = queryClient.getQueriesData<
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
InfiniteData<chat.bsky.convo.listConvos.$OutputBody>
>({queryKey: [CONVO_LIST_KEY]})
queryClient.setQueryData<ChatBskyConvoDefs.ConvoView>(
queryClient.setQueryData<chat.bsky.convo.defs.ConvoView>(
CONVO_KEY(convoId),
prev => {
if (!prev) return
@@ -51,7 +48,7 @@ export function updateConvoOptimistic(
)
queryClient.setQueriesData<
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
InfiniteData<chat.bsky.convo.listConvos.$OutputBody>
>({queryKey: [CONVO_LIST_KEY]}, prev => {
if (!prev?.pages) return
return {
@@ -1,4 +1,3 @@
import {type ChatBskyGroupWithdrawJoinRequest} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {logger} from '#/logger'
@@ -14,7 +13,7 @@ export function useWithdrawJoinGroupChatRequest({
onSuccess,
onError,
}: {
onSuccess?: (data: ChatBskyGroupWithdrawJoinRequest.OutputSchema) => void
onSuccess?: (data: chat.bsky.group.withdrawJoinRequest.$OutputBody) => void
onError?: (error: Error) => void
} = {}) {
const client = useChatClient()
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
@@ -37,7 +36,7 @@ export function useMyBlockedAccountsQuery() {
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.graph.getBlocks.$OutputBody>
>({
+2 -3
View File
@@ -1,4 +1,3 @@
import {type AppBskyGraphDefs} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {type QueryClient, useQuery} from '@tanstack/react-query'
@@ -19,11 +18,11 @@ export const RQKEY = (filter: MyListsFilter) => [RQKEY_ROOT, filter]
export function useMyListsQuery(filter: MyListsFilter) {
const {currentAccount} = useSession()
const client = useAppviewClient()
return useQuery<AppBskyGraphDefs.ListView[]>({
return useQuery<app.bsky.graph.defs.ListView[]>({
staleTime: STALE.MINUTES.ONE,
queryKey: RQKEY(filter),
async queryFn() {
let lists: AppBskyGraphDefs.ListView[] = []
let lists: app.bsky.graph.defs.ListView[] = []
const promises = [
accumulate(cursor =>
client
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
@@ -37,7 +36,7 @@ export function useMyMutedAccountsQuery() {
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.graph.getMutes.$OutputBody>
>({
@@ -1,11 +1,11 @@
import {type AppBskyNotificationListNotifications} from '@atproto/api'
import {describe, expect, it, jest} from '@jest/globals'
import {groupNotifications} from '../util'
import {app} from '#/lexicons'
jest.mock('#/state/queries/profile', () => ({precacheProfile: jest.fn()}))
type Notification = AppBskyNotificationListNotifications.Notification
type Notification = app.bsky.notification.listNotifications.Notification
function makeFollowNotification(
did: string,
+9 -6
View File
@@ -17,7 +17,6 @@
*/
import {useCallback, useEffect, useMemo, useRef} from 'react'
import {AppBskyFeedDefs, AppBskyFeedPost, AtUri} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
@@ -26,12 +25,14 @@ import {
useQueryClient,
} from '@tanstack/react-query'
import {AtUri} from '@atproto/syntax'
import {app} from '#/lexicons'
import {moderatePost} from '#/lib/moderation/subjects'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {STALE} from '#/state/queries'
import {useAppviewClient} from '#/state/session'
import {useThreadgateHiddenReplyUris} from '#/state/threadgate-hidden-replies'
import type * as bsky from '#/types/bsky'
import * as bsky from '#/types/bsky'
import {
didOrHandleUriMatches,
embedViewRecordToPostView,
@@ -195,7 +196,9 @@ export function useNotificationFeedQuery(opts: {
* a `$type` field on the `subject`. But if the nested
* `record` is a post, we know it's a post view.
*/
if (AppBskyFeedPost.isRecord(item.subject?.record)) {
if (
bsky.isType(app.bsky.feed.post, item.subject?.record)
) {
const mod = moderatePost(item.subject, moderationOpts!)
if (mod.ui('contentList').filter) {
return false
@@ -272,7 +275,7 @@ export function useNotificationFeedQuery(opts: {
export function* findAllPostsInQueryData(
queryClient: QueryClient,
uri: string,
): Generator<AppBskyFeedDefs.PostView, void> {
): Generator<app.bsky.feed.defs.PostView, void> {
const atUri = new AtUri(uri)
const queryDatas = queryClient.getQueriesData<InfiniteData<FeedPage>>({
@@ -291,7 +294,7 @@ export function* findAllPostsInQueryData(
}
}
if (AppBskyFeedDefs.isPostView(item.subject)) {
if (bsky.isType(app.bsky.feed.defs.postView, item.subject)) {
const quotedPost = getEmbeddedPost(item.subject?.embed)
if (quotedPost && didOrHandleUriMatches(atUri, quotedPost)) {
yield embedViewRecordToPostView(quotedPost)
@@ -329,7 +332,7 @@ export function* findAllProfilesInQueryData(
) {
yield item.subject.author
}
if (AppBskyFeedDefs.isPostView(item.subject)) {
if (bsky.isType(app.bsky.feed.defs.postView, item.subject)) {
const quotedPost = getEmbeddedPost(item.subject?.embed)
if (quotedPost?.author.did === did) {
yield quotedPost.author
+12 -16
View File
@@ -1,7 +1,3 @@
import {
type AppBskyNotificationDefs,
type ChatBskyNotificationDefs,
} from '@atproto/api'
import {t} from '@lingui/core/macro'
import {
type QueryClient,
@@ -24,18 +20,18 @@ const RQKEY_CHAT = [RQKEY_ROOT, 'chat']
// fetched and cached separately. This combined type names every preference for
// the generic settings dialog, but it is never the shape of a query response.
export type NotificationSettingsPreferences = Omit<
AppBskyNotificationDefs.Preferences,
app.bsky.notification.defs.Preferences,
'chat'
> &
Partial<Pick<ChatBskyNotificationDefs.Preferences, 'chat' | 'chatRequest'>>
Partial<Pick<chat.bsky.notification.defs.Preferences, 'chat' | 'chatRequest'>>
export type AppNotificationSettingsPreferences = Omit<
AppBskyNotificationDefs.Preferences,
app.bsky.notification.defs.Preferences,
'chat'
>
export type ChatNotificationSettingsPreferences = Pick<
ChatBskyNotificationDefs.Preferences,
chat.bsky.notification.defs.Preferences,
'chat' | 'chatRequest'
>
@@ -45,9 +41,9 @@ export type NotificationSettingsPreferenceName = Exclude<
>
export type NotificationSettingsPreference =
| AppBskyNotificationDefs.Preference
| AppBskyNotificationDefs.FilterablePreference
| ChatBskyNotificationDefs.ChatPreference
| app.bsky.notification.defs.Preference
| app.bsky.notification.defs.FilterablePreference
| chat.bsky.notification.defs.ChatPreference
export function isChatPreferenceName(
name: NotificationSettingsPreferenceName,
@@ -58,7 +54,7 @@ export function isChatPreferenceName(
type NotificationSettingsUpdate = Partial<NotificationSettingsPreferences>
type AppNotificationSettingsUpdate = Partial<
Omit<AppBskyNotificationDefs.Preferences, '$type' | 'chat'>
Omit<app.bsky.notification.defs.Preferences, '$type' | 'chat'>
>
type ChatNotificationSettingsUpdate =
@@ -159,15 +155,15 @@ function optimisticUpdateNotificationSettings(
}
function appPreferencesWithoutChat(
preferences: AppBskyNotificationDefs.Preferences,
): Omit<AppBskyNotificationDefs.Preferences, 'chat'> {
preferences: app.bsky.notification.defs.Preferences,
): Omit<app.bsky.notification.defs.Preferences, 'chat'> {
const {chat: _ignoredChat, ...appPreferences} = preferences
return appPreferences
}
function chatPreferencesForSettings(
preferences: ChatBskyNotificationDefs.Preferences,
): Pick<ChatBskyNotificationDefs.Preferences, 'chat' | 'chatRequest'> {
preferences: chat.bsky.notification.defs.Preferences,
): Pick<chat.bsky.notification.defs.Preferences, 'chat' | 'chatRequest'> {
return {
chat: preferences.chat,
chatRequest: preferences.chatRequest,
+8 -10
View File
@@ -1,8 +1,4 @@
import {
type AppBskyFeedDefs,
type AppBskyGraphDefs,
type AppBskyNotificationListNotifications,
} from '@atproto/api'
import {app} from '#/lexicons'
export type NotificationType =
| StarterPackNotificationType
@@ -11,11 +7,11 @@ export type NotificationType =
export type FeedNotification =
| (FeedNotificationBase & {
type: StarterPackNotificationType
subject?: AppBskyGraphDefs.StarterPackViewBasic
subject?: app.bsky.graph.defs.StarterPackViewBasic
})
| (FeedNotificationBase & {
type: OtherNotificationType
subject?: AppBskyFeedDefs.PostView
subject?: app.bsky.feed.defs.PostView
})
export interface FeedPage {
@@ -54,8 +50,10 @@ type OtherNotificationType =
type FeedNotificationBase = {
_reactKey: string
notification: AppBskyNotificationListNotifications.Notification
additional?: AppBskyNotificationListNotifications.Notification[]
notification: app.bsky.notification.listNotifications.Notification
additional?: app.bsky.notification.listNotifications.Notification[]
subjectUri?: string
subject?: AppBskyFeedDefs.PostView | AppBskyGraphDefs.StarterPackViewBasic
subject?:
| app.bsky.feed.defs.PostView
| app.bsky.graph.defs.StarterPackViewBasic
}
+13 -31
View File
@@ -1,12 +1,3 @@
import {
type AppBskyFeedDefs,
AppBskyFeedLike,
AppBskyFeedPost,
AppBskyFeedRepost,
type AppBskyGraphDefs,
AppBskyGraphStarterpack,
type AppBskyNotificationListNotifications,
} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type AtUriString} from '@atproto/syntax'
import {type ModerationOpts} from '@bsky.app/sdk/moderation'
@@ -117,7 +108,7 @@ export async function fetchPage({
// =
export function shouldFilterNotif(
notif: AppBskyNotificationListNotifications.Notification,
notif: app.bsky.notification.listNotifications.Notification,
moderationOpts: ModerationOpts | undefined,
): boolean {
const containsImperative = !!notif.author.labels?.some(labelIsHideableOffense)
@@ -129,10 +120,7 @@ export function shouldFilterNotif(
}
if (
notif.reason === 'subscribed-post' &&
bsky.dangerousIsType<AppBskyFeedPost.Record>(
notif.record,
AppBskyFeedPost.isRecord,
) &&
bsky.isType(app.bsky.feed.post, notif.record) &&
hasMutedWord({
mutedWords: moderationOpts.prefs.mutedWords,
text: notif.record.text,
@@ -151,7 +139,7 @@ export function shouldFilterNotif(
}
export function groupNotifications(
notifs: AppBskyNotificationListNotifications.Notification[],
notifs: app.bsky.notification.listNotifications.Notification[],
): FeedNotification[] {
const groupedNotifs: FeedNotification[] = []
for (const notif of notifs) {
@@ -211,8 +199,8 @@ async function fetchSubjects(
client: Client,
groupedNotifs: FeedNotification[],
): Promise<{
posts: Map<string, AppBskyFeedDefs.PostView>
starterPacks: Map<string, AppBskyGraphDefs.StarterPackViewBasic>
posts: Map<string, app.bsky.feed.defs.PostView>
starterPacks: Map<string, app.bsky.graph.defs.StarterPackViewBasic>
}> {
const postUris = new Set<string>()
const packUris = new Set<string>()
@@ -243,15 +231,15 @@ async function fetchSubjects(
.then(data => data.starterPacks),
),
)
const postsMap = new Map<string, AppBskyFeedDefs.PostView>()
const packsMap = new Map<string, AppBskyGraphDefs.StarterPackViewBasic>()
const postsMap = new Map<string, app.bsky.feed.defs.PostView>()
const packsMap = new Map<string, app.bsky.graph.defs.StarterPackViewBasic>()
for (const post of postsChunks.flat()) {
if (AppBskyFeedPost.isRecord(post.record)) {
if (bsky.isType(app.bsky.feed.post, post.record)) {
postsMap.set(post.uri, post)
}
}
for (const pack of packsChunks.flat()) {
if (AppBskyGraphStarterpack.isRecord(pack.record)) {
if (bsky.isType(app.bsky.graph.starterpack, pack.record)) {
packsMap.set(pack.uri, pack)
}
}
@@ -262,7 +250,7 @@ async function fetchSubjects(
}
function toKnownType(
notif: AppBskyNotificationListNotifications.Notification,
notif: app.bsky.notification.listNotifications.Notification,
): NotificationType {
if (notif.reason === 'like') {
if (notif.reasonSubject?.includes('feed.generator')) {
@@ -291,7 +279,7 @@ function toKnownType(
function getSubjectUri(
type: NotificationType,
notif: AppBskyNotificationListNotifications.Notification,
notif: app.bsky.notification.listNotifications.Notification,
): string | undefined {
if (
type === 'reply' ||
@@ -307,14 +295,8 @@ function getSubjectUri(
type === 'repost-via-repost'
) {
if (
bsky.dangerousIsType<AppBskyFeedRepost.Record>(
notif.record,
AppBskyFeedRepost.isRecord,
) ||
bsky.dangerousIsType<AppBskyFeedLike.Record>(
notif.record,
AppBskyFeedLike.isRecord,
)
bsky.isType(app.bsky.feed.repost, notif.record) ||
bsky.isType(app.bsky.feed.like, notif.record)
) {
return typeof notif.record.subject?.uri === 'string'
? notif.record.subject?.uri
+3 -3
View File
@@ -1,7 +1,7 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {app} from '#/lexicons'
export type Data = Record<string, unknown> | undefined
export type BaseNux<
T extends Pick<AppBskyActorDefs.Nux, 'id' | 'expiresAt'> & {data: Data},
> = Pick<AppBskyActorDefs.Nux, 'id' | 'completed' | 'expiresAt'> & T
T extends Pick<app.bsky.actor.defs.Nux, 'id' | 'expiresAt'> & {data: Data},
> = Pick<app.bsky.actor.defs.Nux, 'id' | 'completed' | 'expiresAt'> & T
+5 -4
View File
@@ -1,4 +1,4 @@
import {type AppBskyActorDefs, nuxSchema} from '@atproto/api'
import {nuxSchema} from '@bsky.app/sdk/utils'
import {
type AppNux,
@@ -6,8 +6,9 @@ import {
nuxNames,
NuxSchemas,
} from '#/state/queries/nuxs/definitions'
import {type app} from '#/lexicons'
export function parseAppNux(nux: AppBskyActorDefs.Nux): AppNux | undefined {
export function parseAppNux(nux: app.bsky.actor.defs.Nux): AppNux | undefined {
if (!nuxNames.has(nux.id as Nux)) return
if (!nuxSchema.safeParse(nux).success) return
@@ -32,11 +33,11 @@ export function parseAppNux(nux: AppBskyActorDefs.Nux): AppNux | undefined {
} as AppNux
}
export function serializeAppNux(nux: AppNux): AppBskyActorDefs.Nux {
export function serializeAppNux(nux: AppNux): app.bsky.actor.defs.Nux {
const {data, ...rest} = nux
const schema = NuxSchemas[nux.id]
const result: AppBskyActorDefs.Nux = {
const result: app.bsky.actor.defs.Nux = {
...rest,
data: undefined,
}
+16 -20
View File
@@ -1,13 +1,7 @@
import {useCallback, useEffect, useMemo, useRef} from 'react'
import {AppState} from 'react-native'
import {
type AppBskyActorDefs,
AppBskyFeedDefs,
type AppBskyFeedPost,
AtUri,
} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type AtIdentifierString, type AtUriString} from '@atproto/syntax'
import {type AtIdentifierString, type AtUriString, AtUri} from '@atproto/syntax'
import {
type ModerationDecision,
type ModerationPrefs,
@@ -19,6 +13,8 @@ import {
useInfiniteQuery,
} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {app} from '#/lexicons'
import {AuthorFeedAPI} from '#/lib/api/feed/author'
import {CustomFeedAPI} from '#/lib/api/feed/custom'
import {DemoFeedAPI} from '#/lib/api/feed/demo'
@@ -83,10 +79,10 @@ export function RQKEY(feedDesc: FeedDescriptor, params?: FeedParams) {
export interface FeedPostSliceItem {
_reactKey: string
uri: string
post: AppBskyFeedDefs.PostView
record: AppBskyFeedPost.Record
post: app.bsky.feed.defs.PostView
record: app.bsky.feed.post.Main
moderation: ModerationDecision
parentAuthor?: AppBskyActorDefs.ProfileViewBasic
parentAuthor?: app.bsky.actor.defs.ProfileViewBasic
isParentBlocked?: boolean
isParentNotFound?: boolean
}
@@ -101,8 +97,8 @@ export interface FeedPostSlice {
reqId: string | undefined
feedPostUri: string
reason?:
| AppBskyFeedDefs.ReasonRepost
| AppBskyFeedDefs.ReasonPin
| app.bsky.feed.defs.ReasonRepost
| app.bsky.feed.defs.ReasonPin
| ReasonFeedSource
| {[k: string]: unknown; $type: string}
}
@@ -110,7 +106,7 @@ export interface FeedPostSlice {
export interface FeedPageUnselected {
api: FeedAPI
cursor: string | undefined
feed: AppBskyFeedDefs.FeedViewPost[]
feed: app.bsky.feed.defs.FeedViewPost[]
fetchedAt: number
}
@@ -515,7 +511,7 @@ function createApi({
export function* findAllPostsInQueryData(
queryClient: QueryClient,
uri: string,
): Generator<AppBskyFeedDefs.PostView, undefined> {
): Generator<app.bsky.feed.defs.PostView, undefined> {
const atUri = new AtUri(uri)
const queryDatas = queryClient.getQueriesData<
@@ -538,7 +534,7 @@ export function* findAllPostsInQueryData(
yield embedViewRecordToPostView(quotedPost)
}
if (AppBskyFeedDefs.isPostView(item.reply?.parent)) {
if (bsky.isType(app.bsky.feed.defs.postView, item.reply?.parent)) {
if (didOrHandleUriMatches(atUri, item.reply.parent)) {
yield item.reply.parent
}
@@ -552,7 +548,7 @@ export function* findAllPostsInQueryData(
}
}
if (AppBskyFeedDefs.isPostView(item.reply?.root)) {
if (bsky.isType(app.bsky.feed.defs.postView, item.reply?.root)) {
if (didOrHandleUriMatches(atUri, item.reply.root)) {
yield item.reply.root
}
@@ -570,7 +566,7 @@ export function* findAllPostsInQueryData(
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileViewBasic, undefined> {
): Generator<app.bsky.actor.defs.ProfileViewBasic, undefined> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<FeedPageUnselected>
>({
@@ -590,13 +586,13 @@ export function* findAllProfilesInQueryData(
yield quotedPost.author
}
if (
AppBskyFeedDefs.isPostView(item.reply?.parent) &&
bsky.isType(app.bsky.feed.defs.postView, item.reply?.parent) &&
item.reply?.parent?.author.did === did
) {
yield item.reply.parent.author
}
if (
AppBskyFeedDefs.isPostView(item.reply?.root) &&
bsky.isType(app.bsky.feed.defs.postView, item.reply?.root) &&
item.reply?.root?.author.did === did
) {
yield item.reply.root.author
@@ -607,7 +603,7 @@ export function* findAllProfilesInQueryData(
}
function assertSomePostsPassModeration(
feed: AppBskyFeedDefs.FeedViewPost[],
feed: app.bsky.feed.defs.FeedViewPost[],
moderationPrefs: ModerationPrefs,
) {
// no posts in this feed
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type AtUriString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -83,7 +82,7 @@ export function useLikedBySampleQuery({uri}: {uri: string | undefined}) {
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.feed.getLikes.$OutputBody>
>({
+14 -11
View File
@@ -1,10 +1,4 @@
import {
type AppBskyActorDefs,
AppBskyEmbedRecord,
type AppBskyFeedDefs,
AtUri,
} from '@atproto/api'
import {type AtUriString} from '@atproto/syntax'
import {type AtUriString, AtUri} from '@atproto/syntax'
import {
type InfiniteData,
type QueryClient,
@@ -12,6 +6,7 @@ import {
useInfiniteQuery,
} from '@tanstack/react-query'
import * as bsky from '#/types/bsky'
import {useAppviewClient} from '#/state/session'
import {app} from '#/lexicons'
import {
@@ -54,8 +49,16 @@ export function usePostQuotesQuery(resolvedUri: string | undefined) {
return {
...page,
posts: page.posts.filter(post => {
if (post.embed && AppBskyEmbedRecord.isView(post.embed)) {
if (AppBskyEmbedRecord.isViewDetached(post.embed.record)) {
if (
post.embed &&
bsky.isType(app.bsky.embed.record.view, post.embed)
) {
if (
bsky.isType(
app.bsky.embed.record.viewDetached,
post.embed.record,
)
) {
return false
}
}
@@ -71,7 +74,7 @@ export function usePostQuotesQuery(resolvedUri: string | undefined) {
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileViewBasic, void> {
): Generator<app.bsky.actor.defs.ProfileViewBasic, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.feed.getQuotes.$OutputBody>
>({
@@ -98,7 +101,7 @@ export function* findAllProfilesInQueryData(
export function* findAllPostsInQueryData(
queryClient: QueryClient,
uri: string,
): Generator<AppBskyFeedDefs.PostView, undefined> {
): Generator<app.bsky.feed.defs.PostView, undefined> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.feed.getQuotes.$OutputBody>
>({
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type AtUriString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -44,7 +43,7 @@ export function usePostRepostedByQuery(resolvedUri: string | undefined) {
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.feed.getRepostedBy.$OutputBody>
>({
+13 -14
View File
@@ -1,7 +1,6 @@
import {useCallback} from 'react'
import {type AppBskyActorDefs, type AppBskyFeedDefs, AtUri} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type AtUriString, type HandleString} from '@atproto/syntax'
import {type AtUriString, type HandleString, AtUri} from '@atproto/syntax'
import {deleteLike, deletePost, deleteRepost, like, repost} from '@bsky.app/sdk'
import {
type QueryClient,
@@ -26,7 +25,7 @@ export const RQKEY = (postUri: string) => [RQKEY_ROOT, postUri]
export function usePostQuery(uri: string | undefined) {
const client = useAppviewClient()
return useQuery<AppBskyFeedDefs.PostView>({
return useQuery<app.bsky.feed.defs.PostView>({
queryKey: RQKEY(uri || ''),
queryFn: async () => {
if (!uri) throw new Error('[unreachable] No URI provided')
@@ -53,7 +52,7 @@ export function usePostQuery(uri: string | undefined) {
async function fetchPost(
client: Client,
uri: string,
): Promise<AppBskyFeedDefs.PostView | undefined> {
): Promise<app.bsky.feed.defs.PostView | undefined> {
const urip = new AtUri(uri)
if (!urip.host.startsWith('did:')) {
@@ -72,7 +71,7 @@ async function fetchPost(
export function precachePost(
queryClient: QueryClient,
uri: string,
post: AppBskyFeedDefs.PostView,
post: app.bsky.feed.defs.PostView,
) {
queryClient.setQueryData(RQKEY(uri), post)
}
@@ -110,7 +109,7 @@ export function useGetPosts() {
uris: uris as AtUriString[],
})
// See the note on `fetchPost` about the view shapes.
return data.posts as AppBskyFeedDefs.PostView[]
return data.posts as app.bsky.feed.defs.PostView[]
},
})
},
@@ -119,7 +118,7 @@ export function useGetPosts() {
}
export function usePostLikeMutationQueue(
post: Shadow<AppBskyFeedDefs.PostView>,
post: Shadow<app.bsky.feed.defs.PostView>,
viaRepost: {uri: string; cid: string} | undefined,
feedDescriptor: string | undefined,
logContext: Metrics['post:like']['logContext'],
@@ -183,7 +182,7 @@ export function usePostLikeMutationQueue(
function usePostLikeMutation(
feedDescriptor: string | undefined,
logContext: Metrics['post:like']['logContext'],
post: Shadow<AppBskyFeedDefs.PostView>,
post: Shadow<app.bsky.feed.defs.PostView>,
) {
const {currentAccount} = useSession()
const queryClient = useQueryClient()
@@ -196,7 +195,7 @@ function usePostLikeMutation(
{uri: string; cid: string; via?: {uri: string; cid: string}} // the post's uri and cid, and the repost uri/cid if present
>({
mutationFn: ({uri, cid, via}) => {
let ownProfile: AppBskyActorDefs.ProfileViewDetailed | undefined
let ownProfile: app.bsky.actor.defs.ProfileViewDetailed | undefined
if (currentAccount) {
ownProfile = findProfileQueryData(queryClient, currentAccount.did)
}
@@ -231,7 +230,7 @@ function usePostLikeMutation(
function usePostUnlikeMutation(
feedDescriptor: string | undefined,
logContext: Metrics['post:unlike']['logContext'],
post: Shadow<AppBskyFeedDefs.PostView>,
post: Shadow<app.bsky.feed.defs.PostView>,
) {
const pdsClient = usePdsClient()
const ax = useAnalytics()
@@ -249,7 +248,7 @@ function usePostUnlikeMutation(
}
export function usePostRepostMutationQueue(
post: Shadow<AppBskyFeedDefs.PostView>,
post: Shadow<app.bsky.feed.defs.PostView>,
viaRepost: {uri: string; cid: string} | undefined,
feedDescriptor: string | undefined,
logContext: Metrics['post:repost']['logContext'],
@@ -315,7 +314,7 @@ export function usePostRepostMutationQueue(
function usePostRepostMutation(
feedDescriptor: string | undefined,
logContext: Metrics['post:repost']['logContext'],
post: Shadow<AppBskyFeedDefs.PostView>,
post: Shadow<app.bsky.feed.defs.PostView>,
) {
const pdsClient = usePdsClient()
const ax = useAnalytics()
@@ -343,7 +342,7 @@ function usePostRepostMutation(
function usePostUnrepostMutation(
feedDescriptor: string | undefined,
logContext: Metrics['post:unrepost']['logContext'],
post: Shadow<AppBskyFeedDefs.PostView>,
post: Shadow<app.bsky.feed.defs.PostView>,
) {
const pdsClient = usePdsClient()
const ax = useAnalytics()
@@ -374,7 +373,7 @@ export function usePostDeleteMutation() {
}
export function useThreadMuteMutationQueue(
post: Shadow<AppBskyFeedDefs.PostView>,
post: Shadow<app.bsky.feed.defs.PostView>,
rootUri: string,
) {
const threadMuteMutation = useThreadMuteMutation()
+4 -9
View File
@@ -1,9 +1,4 @@
import {useRef} from 'react'
import {
AppBskyEmbedRecord,
AppBskyEmbedRecordWithMedia,
type AppBskyFeedDefs,
} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {AtUri, type HandleString} from '@atproto/syntax'
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
@@ -173,7 +168,7 @@ export function useToggleQuoteDetachmentMutation() {
const pdsClient = usePdsClient()
const queryClient = useQueryClient()
const getPosts = useGetPosts()
const prevEmbed = useRef<AppBskyFeedDefs.PostView['embed']>(undefined)
const prevEmbed = useRef<app.bsky.feed.defs.PostView['embed']>(undefined)
return useMutation({
mutationFn: async ({
@@ -181,7 +176,7 @@ export function useToggleQuoteDetachmentMutation() {
quoteUri,
action,
}: {
post: AppBskyFeedDefs.PostView
post: app.bsky.feed.defs.PostView
quoteUri: string
action: 'detach' | 'reattach'
}) => {
@@ -247,8 +242,8 @@ export function useToggleQuoteDetachmentMutation() {
if (action === 'detach' && prevEmbed.current) {
// detach failed, add the embed back
if (
AppBskyEmbedRecord.isView(prevEmbed.current) ||
AppBskyEmbedRecordWithMedia.isView(prevEmbed.current)
bsky.isType(app.bsky.embed.record.view, prevEmbed.current) ||
bsky.isType(app.bsky.embed.recordWithMedia.view, prevEmbed.current)
) {
updatePostShadow(queryClient, post.uri, {
embed: prevEmbed.current,
+34 -32
View File
@@ -1,13 +1,8 @@
import {
type $Typed,
AppBskyEmbedRecord,
AppBskyEmbedRecordWithMedia,
type AppBskyFeedDefs,
AtUri,
} from '@atproto/api'
import {type AtUriString, toDatetimeString} from '@atproto/syntax'
import {type AtUriString, toDatetimeString, AtUri} from '@atproto/syntax'
import {type app} from '#/lexicons'
import {type $Typed} from '@atproto/lex'
import * as bsky from '#/types/bsky'
import {app} from '#/lexicons'
export const POSTGATE_COLLECTION = 'app.bsky.feed.postgate'
@@ -64,8 +59,8 @@ export function createEmbedViewDetachedRecord({
uri,
}: {
uri: string
}): $Typed<AppBskyEmbedRecord.View> {
const record: $Typed<AppBskyEmbedRecord.ViewDetached> = {
}): $Typed<app.bsky.embed.record.View> {
const record: $Typed<app.bsky.embed.record.ViewDetached> = {
$type: 'app.bsky.embed.record#viewDetached',
uri,
detached: true,
@@ -83,24 +78,27 @@ export function createMaybeDetachedQuoteEmbed({
detached,
}:
| {
post: AppBskyFeedDefs.PostView
quote: AppBskyFeedDefs.PostView
post: app.bsky.feed.defs.PostView
quote: app.bsky.feed.defs.PostView
quoteUri: undefined
detached: false
}
| {
post: AppBskyFeedDefs.PostView
post: app.bsky.feed.defs.PostView
quote: undefined
quoteUri: string
detached: true
}): AppBskyEmbedRecord.View | AppBskyEmbedRecordWithMedia.View | undefined {
if (AppBskyEmbedRecord.isView(post.embed)) {
}):
| app.bsky.embed.record.View
| app.bsky.embed.recordWithMedia.View
| undefined {
if (bsky.isType(app.bsky.embed.record.view, post.embed)) {
if (detached) {
return createEmbedViewDetachedRecord({uri: quoteUri})
} else {
return createEmbedRecordView({post: quote})
}
} else if (AppBskyEmbedRecordWithMedia.isView(post.embed)) {
} else if (bsky.isType(app.bsky.embed.recordWithMedia.view, post.embed)) {
if (detached) {
return {
...post.embed,
@@ -113,8 +111,8 @@ export function createMaybeDetachedQuoteEmbed({
}
export function createEmbedViewRecordFromPost(
post: AppBskyFeedDefs.PostView,
): $Typed<AppBskyEmbedRecord.ViewRecord> {
post: app.bsky.feed.defs.PostView,
): $Typed<app.bsky.embed.record.ViewRecord> {
return {
$type: 'app.bsky.embed.record#viewRecord',
uri: post.uri,
@@ -134,8 +132,8 @@ export function createEmbedViewRecordFromPost(
export function createEmbedRecordView({
post,
}: {
post: AppBskyFeedDefs.PostView
}): AppBskyEmbedRecord.View {
post: app.bsky.feed.defs.PostView
}): app.bsky.embed.record.View {
return {
$type: 'app.bsky.embed.record#view',
record: createEmbedViewRecordFromPost(post),
@@ -146,10 +144,10 @@ export function createEmbedRecordWithMediaView({
post,
quote,
}: {
post: AppBskyFeedDefs.PostView
quote: AppBskyFeedDefs.PostView
}): AppBskyEmbedRecordWithMedia.View | undefined {
if (!AppBskyEmbedRecordWithMedia.isView(post.embed)) return
post: app.bsky.feed.defs.PostView
quote: app.bsky.feed.defs.PostView
}): app.bsky.embed.recordWithMedia.View | undefined {
if (!bsky.isType(app.bsky.embed.recordWithMedia.view, post.embed)) return
return {
...(post.embed || {}),
record: {
@@ -163,11 +161,11 @@ export function getMaybeDetachedQuoteEmbed({
post,
}: {
viewerDid: string
post: AppBskyFeedDefs.PostView
post: app.bsky.feed.defs.PostView
}) {
if (AppBskyEmbedRecord.isView(post.embed)) {
if (bsky.isType(app.bsky.embed.record.view, post.embed)) {
// detached
if (AppBskyEmbedRecord.isViewDetached(post.embed.record)) {
if (bsky.isType(app.bsky.embed.record.viewDetached, post.embed.record)) {
const urip = new AtUri(post.embed.record.uri)
return {
embed: post.embed,
@@ -178,7 +176,7 @@ export function getMaybeDetachedQuoteEmbed({
}
// post
if (AppBskyEmbedRecord.isViewRecord(post.embed.record)) {
if (bsky.isType(app.bsky.embed.record.viewRecord, post.embed.record)) {
const urip = new AtUri(post.embed.record.uri)
return {
embed: post.embed,
@@ -187,9 +185,11 @@ export function getMaybeDetachedQuoteEmbed({
isDetached: false,
}
}
} else if (AppBskyEmbedRecordWithMedia.isView(post.embed)) {
} else if (bsky.isType(app.bsky.embed.recordWithMedia.view, post.embed)) {
// detached
if (AppBskyEmbedRecord.isViewDetached(post.embed.record.record)) {
if (
bsky.isType(app.bsky.embed.record.viewDetached, post.embed.record.record)
) {
const urip = new AtUri(post.embed.record.record.uri)
return {
embed: post.embed,
@@ -200,7 +200,9 @@ export function getMaybeDetachedQuoteEmbed({
}
// post
if (AppBskyEmbedRecord.isViewRecord(post.embed.record.record)) {
if (
bsky.isType(app.bsky.embed.record.viewRecord, post.embed.record.record)
) {
const urip = new AtUri(post.embed.record.record.uri)
return {
embed: post.embed,
+8 -9
View File
@@ -1,5 +1,4 @@
import {useCallback} from 'react'
import {type AppBskyActorDefs} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {
addSavedFeeds,
@@ -278,7 +277,7 @@ export function useOverwriteSavedFeedsMutation() {
const queryClient = useQueryClient()
const client = usePdsClient()
return useMutation<void, unknown, AppBskyActorDefs.SavedFeed[]>({
return useMutation<void, unknown, app.bsky.actor.defs.SavedFeed[]>({
mutationFn: async savedFeeds => {
await client.call(overwriteSavedFeeds, savedFeeds)
// triggers a refetch
@@ -296,7 +295,7 @@ export function useAddSavedFeedsMutation() {
return useMutation<
void,
unknown,
Pick<AppBskyActorDefs.SavedFeed, 'type' | 'value' | 'pinned'>[]
Pick<app.bsky.actor.defs.SavedFeed, 'type' | 'value' | 'pinned'>[]
>({
mutationFn: async savedFeeds => {
await client.call(addSavedFeeds, savedFeeds)
@@ -312,7 +311,7 @@ export function useRemoveFeedMutation() {
const queryClient = useQueryClient()
const client = usePdsClient()
return useMutation<void, unknown, Pick<AppBskyActorDefs.SavedFeed, 'id'>>({
return useMutation<void, unknown, Pick<app.bsky.actor.defs.SavedFeed, 'id'>>({
mutationFn: async savedFeed => {
await client.call(removeSavedFeeds, [savedFeed.id])
// triggers a refetch
@@ -332,8 +331,8 @@ export function useReplaceForYouWithDiscoverFeedMutation() {
forYouFeedConfig,
discoverFeedConfig,
}: {
forYouFeedConfig: AppBskyActorDefs.SavedFeed | undefined
discoverFeedConfig: AppBskyActorDefs.SavedFeed | undefined
forYouFeedConfig: app.bsky.actor.defs.SavedFeed | undefined
discoverFeedConfig: app.bsky.actor.defs.SavedFeed | undefined
}) => {
if (forYouFeedConfig) {
await client.call(removeSavedFeeds, [forYouFeedConfig.id])
@@ -366,7 +365,7 @@ export function useUpdateSavedFeedsMutation() {
const queryClient = useQueryClient()
const client = usePdsClient()
return useMutation<void, unknown, AppBskyActorDefs.SavedFeed[]>({
return useMutation<void, unknown, app.bsky.actor.defs.SavedFeed[]>({
mutationFn: async feeds => {
await client.call(updateSavedFeeds, feeds)
@@ -477,7 +476,7 @@ export function useSetActiveProgressGuideMutation() {
return useMutation({
mutationFn: async (
guide: AppBskyActorDefs.BskyAppProgressGuide | undefined,
guide: app.bsky.actor.defs.BskyAppProgressGuide | undefined,
) => {
await client.call(setActiveProgressGuide, guide)
// triggers a refetch
@@ -508,7 +507,7 @@ export function useSetVerificationPrefsMutation() {
const queryClient = useQueryClient()
const client = usePdsClient()
return useMutation<void, unknown, AppBskyActorDefs.VerificationPrefs>({
return useMutation<void, unknown, app.bsky.actor.defs.VerificationPrefs>({
mutationFn: async prefs => {
await client.call(setVerificationPrefs, prefs)
if (prefs.hideBadges) {
@@ -1,8 +1,8 @@
import {useCallback, useMemo, useRef, useState} from 'react'
import {type AppBskyUnspeccedGetPostThreadV2} from '@atproto/api'
import {useFocusEffect} from '@react-navigation/native'
import debounce from 'lodash.debounce'
import {app} from '#/lexicons'
import {useCallOnce} from '#/lib/once'
import {
usePreferencesQuery,
@@ -13,7 +13,7 @@ import {useAnalytics} from '#/analytics'
import {type Literal} from '#/types/utils'
export type ThreadSortOption = Literal<
AppBskyUnspeccedGetPostThreadV2.QueryParams['sort'],
app.bsky.unspecced.getPostThreadV2.$Params['sort'],
string
>
export type ThreadViewOption = 'linear' | 'tree'
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -67,7 +66,7 @@ export function useProfileFollowersQuery(
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.graph.getFollowers.$OutputBody>
>({
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -72,7 +71,7 @@ export function useProfileFollowsQuery(
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.graph.getFollows.$OutputBody>
>({
+15 -22
View File
@@ -1,18 +1,11 @@
import {useCallback} from 'react'
import {
type AppBskyActorDefs,
type AppBskyActorGetProfile,
type AppBskyActorGetProfiles,
type AppBskyGraphGetFollows,
AtUri,
type Un$Typed,
} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type Client, type Un$Typed} from '@atproto/lex'
import {
type AtIdentifierString,
type AtUriString,
type DidString,
toDatetimeString,
AtUri,
} from '@atproto/syntax'
import {
deleteFollow,
@@ -82,7 +75,7 @@ export function useProfileQuery({
}) {
const client = useAppviewClient()
const {getUnstableProfile} = useUnstableProfileViewCache()
return useQuery<AppBskyActorDefs.ProfileViewDetailed>({
return useQuery<app.bsky.actor.defs.ProfileViewDetailed>({
// WARNING
// this staleTime is load-bearing
// if you remove it, the UI infinite-loops
@@ -97,7 +90,7 @@ export function useProfileQuery({
},
placeholderData: () => {
if (!did) return
return getUnstableProfile(did) as AppBskyActorDefs.ProfileViewDetailed
return getUnstableProfile(did) as app.bsky.actor.defs.ProfileViewDetailed
},
enabled: !!did,
})
@@ -145,7 +138,7 @@ export function usePrefetchProfileQuery() {
}
interface ProfileUpdateParams {
profile: AppBskyActorDefs.ProfileViewDetailed
profile: app.bsky.actor.defs.ProfileViewDetailed
updates:
| Un$Typed<app.bsky.actor.profile.Main>
| ((
@@ -153,7 +146,7 @@ interface ProfileUpdateParams {
) => Un$Typed<app.bsky.actor.profile.Main>)
newUserAvatar?: ImageMeta | undefined | null
newUserBanner?: ImageMeta | undefined | null
checkCommitted?: (res: AppBskyActorGetProfile.Response) => boolean
checkCommitted?: (res: app.bsky.actor.getProfile.Response) => boolean
}
export function useProfileUpdateMutation() {
const queryClient = useQueryClient()
@@ -303,7 +296,7 @@ export function useProfileFollowMutationQueue(
// Optimistically update profile follows cache for avatar displays
if (currentAccount?.did) {
type FollowsQueryData =
InfiniteData<AppBskyGraphGetFollows.OutputSchema>
InfiniteData<app.bsky.graph.getFollows.$OutputBody>
queryClient.setQueryData<FollowsQueryData>(
PROFILE_FOLLOWS_RQKEY(currentAccount.did),
old => {
@@ -320,7 +313,7 @@ export function useProfileFollowMutationQueue(
{
...old.pages[0],
follows: [
profile as AppBskyActorDefs.ProfileView,
profile as app.bsky.actor.defs.ProfileView,
...old.pages[0].follows,
],
},
@@ -390,7 +383,7 @@ function useProfileFollowMutation(
return useMutation<{uri: string; cid: string}, Error, {did: string}>({
mutationFn: async ({did}) => {
let ownProfile: AppBskyActorDefs.ProfileViewDetailed | undefined
let ownProfile: app.bsky.actor.defs.ProfileViewDetailed | undefined
if (currentAccount) {
ownProfile = findProfileQueryData(queryClient, currentAccount.did)
}
@@ -686,7 +679,7 @@ function useProfileUnblockMutation() {
async function whenAppViewReady(
client: Client,
actor: string,
fn: (res: AppBskyActorGetProfile.Response) => boolean,
fn: (res: app.bsky.actor.getProfile.Response) => boolean,
) {
await until(
5, // 5 tries
@@ -709,9 +702,9 @@ async function whenAppViewReady(
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileViewDetailed, void> {
): Generator<app.bsky.actor.defs.ProfileViewDetailed, void> {
const profileQueryDatas =
queryClient.getQueriesData<AppBskyActorDefs.ProfileViewDetailed>({
queryClient.getQueriesData<app.bsky.actor.defs.ProfileViewDetailed>({
queryKey: [RQKEY_ROOT],
})
for (const [_queryKey, queryData] of profileQueryDatas) {
@@ -723,7 +716,7 @@ export function* findAllProfilesInQueryData(
}
}
const profilesQueryDatas =
queryClient.getQueriesData<AppBskyActorGetProfiles.OutputSchema>({
queryClient.getQueriesData<app.bsky.actor.getProfiles.$OutputBody>({
queryKey: [profilesQueryKeyRoot],
})
for (const [_queryKey, queryData] of profilesQueryDatas) {
@@ -741,8 +734,8 @@ export function* findAllProfilesInQueryData(
export function findProfileQueryData(
queryClient: QueryClient,
did: string,
): AppBskyActorDefs.ProfileViewDetailed | undefined {
return queryClient.getQueryData<AppBskyActorDefs.ProfileViewDetailed>(
): app.bsky.actor.defs.ProfileViewDetailed | undefined {
return queryClient.getQueryData<app.bsky.actor.defs.ProfileViewDetailed>(
RQKEY(did),
)
}
+1 -2
View File
@@ -1,6 +1,5 @@
import {AtUri} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type HandleString} from '@atproto/syntax'
import {type HandleString, AtUri} from '@atproto/syntax'
import {type QueryClient, queryOptions, useQuery} from '@tanstack/react-query'
import {STALE} from '#/state/queries'
+3 -4
View File
@@ -1,11 +1,10 @@
import {app} from '#/lexicons'
/*
* Pure helpers for lifting structured `app.bsky.feed.searchPosts` params out of
* a free-text query. Kept free of React Native imports so it can be unit
* tested in isolation (the search-posts query hook re-exports these).
*/
import {type AppBskyFeedSearchPostsV2} from '@atproto/api'
import {
filtersToApiParams,
type SearchFilters,
@@ -204,9 +203,9 @@ function mergeList(a?: string[], b?: string[]): string[] | undefined {
export function buildSearchPostsV2Filters(
embedded: Omit<ExtractedSearchParams, 'q'>,
filters?: SearchFilters,
): AppBskyFeedSearchPostsV2.QueryParams {
): app.bsky.feed.searchPostsV2.$Params {
const apiFilters = filters ? filtersToApiParams(filters) : {}
const params: AppBskyFeedSearchPostsV2.QueryParams = {}
const params: app.bsky.feed.searchPostsV2.$Params = {}
const authors = mergeList(
embedded.author ? [embedded.author] : undefined,
+2 -2
View File
@@ -1,5 +1,4 @@
import {useCallback, useMemo, useRef} from 'react'
import {type AppBskyFeedDefs, AtUri} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
@@ -7,6 +6,7 @@ import {
useInfiniteQuery,
} from '@tanstack/react-query'
import {AtUri} from '@atproto/syntax'
import {moderatePost} from '#/lib/moderation/subjects'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useAppviewClient} from '#/state/session'
@@ -180,7 +180,7 @@ export function useSearchPostsV2Query({
export function* findAllPostsInQueryData(
queryClient: QueryClient,
uri: string,
): Generator<AppBskyFeedDefs.PostView, undefined> {
): Generator<app.bsky.feed.defs.PostView, undefined> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.feed.searchPostsV2.$OutputBody>
>({
+14 -19
View File
@@ -1,8 +1,3 @@
import {
AppBskyFeedDefs,
AppBskyGraphDefs,
AppBskyGraphStarterpack,
} from '@atproto/api'
import {type Client, type LexValue} from '@atproto/lex'
import {AtUri, type AtUriString, toDatetimeString} from '@atproto/syntax'
import {RichText} from '@bsky.app/sdk/richtext'
@@ -57,7 +52,7 @@ export function useStarterPackQuery({
}) {
const client = useAppviewClient()
return useQuery<AppBskyGraphDefs.StarterPackView>({
return useQuery<app.bsky.graph.defs.StarterPackView>({
queryKey: RQKEY(uri ? {uri} : {did, rkey}),
queryFn: async () => {
if (!uri) {
@@ -92,7 +87,7 @@ interface UseCreateStarterPackMutationParams {
name: string
description?: string
profiles: bsky.profile.AnyProfileView[]
feeds?: AppBskyFeedDefs.GeneratorView[]
feeds?: app.bsky.feed.defs.GeneratorView[]
}
export function useCreateStarterPackMutation({
@@ -173,8 +168,8 @@ export function useEditStarterPackMutation({
void,
Error,
UseCreateStarterPackMutationParams & {
currentStarterPack: AppBskyGraphDefs.StarterPackView
currentListItems: AppBskyGraphDefs.ListItemView[]
currentStarterPack: app.bsky.graph.defs.StarterPackView
currentListItems: app.bsky.graph.defs.ListItemView[]
}
>({
mutationFn: async ({
@@ -373,33 +368,33 @@ async function whenAppViewReady(
export function precacheStarterPack(
queryClient: QueryClient,
starterPack:
| AppBskyGraphDefs.StarterPackViewBasic
| AppBskyGraphDefs.StarterPackView,
| app.bsky.graph.defs.StarterPackViewBasic
| app.bsky.graph.defs.StarterPackView,
) {
if (!AppBskyGraphStarterpack.isRecord(starterPack.record)) {
if (!bsky.isType(app.bsky.graph.starterpack, starterPack.record)) {
return
}
let starterPackView: AppBskyGraphDefs.StarterPackView | undefined
if (AppBskyGraphDefs.isStarterPackView(starterPack)) {
let starterPackView: app.bsky.graph.defs.StarterPackView | undefined
if (bsky.isType(app.bsky.graph.defs.starterPackView, starterPack)) {
starterPackView = starterPack
} else if (
AppBskyGraphDefs.isStarterPackViewBasic(starterPack) &&
bsky.validate(starterPack.record, AppBskyGraphStarterpack.validateRecord)
bsky.isType(app.bsky.graph.defs.starterPackViewBasic, starterPack) &&
bsky.matches(app.bsky.graph.starterpack, starterPack.record)
) {
let feeds: AppBskyFeedDefs.GeneratorView[] | undefined
let feeds: app.bsky.feed.defs.GeneratorView[] | undefined
if (starterPack.record.feeds) {
feeds = []
for (const feed of starterPack.record.feeds) {
// note: types are wrong? claims to be `FeedItem`, but we actually
// get un$typed `GeneratorView` objects here -sfn
if (bsky.validate(feed, AppBskyFeedDefs.validateGeneratorView)) {
if (bsky.matches(app.bsky.feed.defs.generatorView, feed)) {
feeds.push(feed)
}
}
}
const listView: AppBskyGraphDefs.ListViewBasic = {
const listView: app.bsky.graph.defs.ListViewBasic = {
uri: starterPack.record.list,
// This will be populated once the data from server is fetched
cid: '',
+1 -2
View File
@@ -1,5 +1,4 @@
import {useCallback, useMemo} from 'react'
import {type AppBskyActorDefs} from '@atproto/api'
import {type DidString} from '@atproto/syntax'
import {
type InfiniteData,
@@ -103,7 +102,7 @@ export function useSuggestedFollowsByActorWithDismiss({
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
): Generator<app.bsky.actor.defs.ProfileView, void> {
yield* findAllProfilesInSuggestedFollowsQueryData(queryClient, did)
yield* findAllProfilesInSuggestedFollowsByActorQueryData(queryClient, did)
}
+2 -3
View File
@@ -1,4 +1,3 @@
import {type AppBskyFeedDefs} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {AtUri, type HandleString} from '@atproto/syntax'
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
@@ -67,7 +66,7 @@ export function useThreadgateViewQuery({
initialData,
}: {
postUri?: string
initialData?: AppBskyFeedDefs.ThreadgateView
initialData?: app.bsky.feed.defs.ThreadgateView
} = {}) {
const getPost = useGetPost()
@@ -248,7 +247,7 @@ export function useSetThreadgateAllowMutation() {
})
},
async onSuccess(_, {postUri, allow}) {
const data = await retry<AppBskyFeedDefs.ThreadgateView | undefined>(
const data = await retry<app.bsky.feed.defs.ThreadgateView | undefined>(
5, // 5 tries
_e => true,
async () => {
+1 -2
View File
@@ -1,4 +1,3 @@
import {type AppBskyFeedDefs} from '@atproto/api'
import {type AtUriString, toDatetimeString} from '@atproto/syntax'
import {type ThreadgateAllowUISetting} from '#/state/queries/threadgate/types'
@@ -12,7 +11,7 @@ import * as bsky from '#/types/bsky'
* through `com.atproto.repo.putRecord`, whose body is typed as a lex `LexMap`.
*/
export function threadgateViewToAllowUISetting(
threadgateView: AppBskyFeedDefs.ThreadgateView | undefined,
threadgateView: app.bsky.feed.defs.ThreadgateView | undefined,
): ThreadgateAllowUISetting[] {
// Validate the record for clarity, since backwards compat code is a little confusing
const threadgate =
+6 -6
View File
@@ -1,27 +1,27 @@
import {app} from '#/lexicons'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import {type AppBskyUnspeccedGetPostThreadV2} from '@atproto/api'
/**
* See the `below` param on {@link AppBskyUnspeccedGetPostThreadV2.QueryParams}
* See the `below` param on {@link app.bsky.unspecced.getPostThreadV2.$Params}
*/
export const LINEAR_VIEW_BELOW = 10
/**
* See the `branchingFactor` param on {@link AppBskyUnspeccedGetPostThreadV2.QueryParams}
* See the `branchingFactor` param on {@link app.bsky.unspecced.getPostThreadV2.$Params}
*/
export const LINEAR_VIEW_BF = 1
/**
* See the `below` param on {@link AppBskyUnspeccedGetPostThreadV2.QueryParams}
* See the `below` param on {@link app.bsky.unspecced.getPostThreadV2.$Params}
*/
export const TREE_VIEW_BELOW = 4
/**
* See the `branchingFactor` param on {@link AppBskyUnspeccedGetPostThreadV2.QueryParams}
* See the `branchingFactor` param on {@link app.bsky.unspecced.getPostThreadV2.$Params}
*/
export const TREE_VIEW_BF = undefined
/**
* See the `below` param on {@link AppBskyUnspeccedGetPostThreadV2.QueryParams}
* See the `below` param on {@link app.bsky.unspecced.getPostThreadV2.$Params}
*/
export const TREE_VIEW_BELOW_DESKTOP = 6
+37 -34
View File
@@ -1,19 +1,14 @@
import {useCallback} from 'react'
import {
type $Typed,
type AppBskyActorDefs,
type AppBskyFeedDefs,
AppBskyUnspeccedDefs,
type AppBskyUnspeccedGetPostThreadOtherV2,
type AppBskyUnspeccedGetPostThreadV2,
AtUri,
} from '@atproto/api'
import {type QueryClient, useQueryClient} from '@tanstack/react-query'
import {
dangerousGetPostShadow,
updatePostShadow,
} from '#/state/cache/post-shadow'
import {type $Typed} from '@atproto/lex'
import {AtUri} from '@atproto/syntax'
import * as bsky from '#/types/bsky'
import {app} from '#/lexicons'
import {findAllPostsInQueryData as findAllPostsInBookmarksQueryData} from '#/state/queries/bookmarks/useBookmarksQuery'
import {findAllPostsInQueryData as findAllPostsInExploreFeedPreviewsQueryData} from '#/state/queries/explore-feed-previews'
import {findAllPostsInQueryData as findAllPostsInNotifsQueryData} from '#/state/queries/notifications/feed'
@@ -51,18 +46,18 @@ export function createCacheMutator({
return {
insertReplies(
parentUri: string,
replies: AppBskyUnspeccedGetPostThreadV2.ThreadItem[],
replies: app.bsky.unspecced.getPostThreadV2.ThreadItem[],
) {
/*
* Main thread query mutator.
*/
queryClient.setQueryData<AppBskyUnspeccedGetPostThreadV2.OutputSchema>(
queryClient.setQueryData<app.bsky.unspecced.getPostThreadV2.$OutputBody>(
postThreadQueryKey,
data => {
if (!data) return
return {
...data,
thread: mutator<AppBskyUnspeccedGetPostThreadV2.ThreadItem>([
thread: mutator<app.bsky.unspecced.getPostThreadV2.ThreadItem>([
...data.thread,
]),
}
@@ -72,15 +67,15 @@ export function createCacheMutator({
/*
* Additional replies query mutator.
*/
queryClient.setQueryData<AppBskyUnspeccedGetPostThreadOtherV2.OutputSchema>(
queryClient.setQueryData<app.bsky.unspecced.getPostThreadOtherV2.$OutputBody>(
postThreadOtherQueryKey,
data => {
if (!data) return
return {
...data,
thread: mutator<AppBskyUnspeccedGetPostThreadOtherV2.ThreadItem>([
...data.thread,
]),
thread: mutator<app.bsky.unspecced.getPostThreadOtherV2.ThreadItem>(
[...data.thread],
),
}
},
)
@@ -89,7 +84,10 @@ export function createCacheMutator({
for (let i = 0; i < thread.length; i++) {
const parent = thread[i]
if (!AppBskyUnspeccedDefs.isThreadItemPost(parent.value)) continue
if (
!bsky.isType(app.bsky.unspecced.defs.threadItemPost, parent.value)
)
continue
if (parent.uri !== parentUri) continue
/*
@@ -124,7 +122,8 @@ export function createCacheMutator({
const isParentRoot = parent.depth === 0
const isParentBelowRoot = parent.depth > 0
const optimisticReply = replies.at(0)
const opIsReplier = AppBskyUnspeccedDefs.isThreadItemPost(
const opIsReplier = bsky.isType(
app.bsky.unspecced.defs.threadItemPost,
optimisticReply?.value,
)
? opDid === optimisticReply.value.post.author.did
@@ -172,8 +171,8 @@ export function createCacheMutator({
* Unused atm, post shadow does the trick, but it would be nice to clean up
* the whole sub-tree on deletes.
*/
deletePost(post: AppBskyUnspeccedGetPostThreadV2.ThreadItem) {
queryClient.setQueryData<AppBskyUnspeccedGetPostThreadV2.OutputSchema>(
deletePost(post: app.bsky.unspecced.getPostThreadV2.ThreadItem) {
queryClient.setQueryData<app.bsky.unspecced.getPostThreadV2.$OutputBody>(
postThreadQueryKey,
queryData => {
if (!queryData) return
@@ -182,7 +181,10 @@ export function createCacheMutator({
for (let i = 0; i < thread.length; i++) {
const existingPost = thread[i]
if (!AppBskyUnspeccedDefs.isThreadItemPost(post.value)) continue
if (
!bsky.isType(app.bsky.unspecced.defs.threadItemPost, post.value)
)
continue
if (existingPost.uri === post.uri) {
const branch = getBranch(thread, i, existingPost.depth)
@@ -204,7 +206,7 @@ export function createCacheMutator({
export function getThreadPlaceholder(
queryClient: QueryClient,
uri: string,
): $Typed<AppBskyUnspeccedGetPostThreadV2.ThreadItem> | void {
): $Typed<app.bsky.unspecced.getPostThreadV2.ThreadItem> | void {
let partial
for (let item of getThreadPlaceholderCandidates(queryClient, uri)) {
/*
@@ -231,8 +233,8 @@ export function* getThreadPlaceholderCandidates(
uri: string,
): Generator<
$Typed<
Omit<AppBskyUnspeccedGetPostThreadV2.ThreadItem, 'value'> & {
value: $Typed<AppBskyUnspeccedDefs.ThreadItemPost>
Omit<app.bsky.unspecced.getPostThreadV2.ThreadItem, 'value'> & {
value: $Typed<app.bsky.unspecced.defs.ThreadItemPost>
}
>,
void
@@ -276,10 +278,10 @@ export function* getThreadPlaceholderCandidates(
export function* findAllPostsInQueryData(
queryClient: QueryClient,
uri: string,
): Generator<AppBskyFeedDefs.PostView, void> {
): Generator<app.bsky.feed.defs.PostView, void> {
const atUri = new AtUri(uri)
const queryDatas =
queryClient.getQueriesData<AppBskyUnspeccedGetPostThreadV2.OutputSchema>({
queryClient.getQueriesData<app.bsky.unspecced.getPostThreadV2.$OutputBody>({
queryKey: [postThreadQueryKeyRoot],
})
@@ -289,7 +291,7 @@ export function* findAllPostsInQueryData(
const {thread} = queryData
for (const item of thread) {
if (AppBskyUnspeccedDefs.isThreadItemPost(item.value)) {
if (bsky.isType(app.bsky.unspecced.defs.threadItemPost, item.value)) {
if (didOrHandleUriMatches(atUri, item.value.post)) {
yield item.value.post
}
@@ -306,9 +308,9 @@ export function* findAllPostsInQueryData(
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileViewBasic, void> {
): Generator<app.bsky.actor.defs.ProfileViewBasic, void> {
const queryDatas =
queryClient.getQueriesData<AppBskyUnspeccedGetPostThreadV2.OutputSchema>({
queryClient.getQueriesData<app.bsky.unspecced.getPostThreadV2.$OutputBody>({
queryKey: [postThreadQueryKeyRoot],
})
@@ -318,7 +320,7 @@ export function* findAllProfilesInQueryData(
const {thread} = queryData
for (const item of thread) {
if (AppBskyUnspeccedDefs.isThreadItemPost(item.value)) {
if (bsky.isType(app.bsky.unspecced.defs.threadItemPost, item.value)) {
if (item.value.post.author.did === did) {
yield item.value.post.author
}
@@ -337,14 +339,15 @@ export function useUpdatePostThreadThreadgateQueryCache() {
const context = usePostThreadContext()
return useCallback(
(threadgate: AppBskyFeedDefs.ThreadgateView) => {
(threadgate: app.bsky.feed.defs.ThreadgateView) => {
if (!context) return
function mutator<T>(thread: ApiThreadItem[]): T[] {
for (let i = 0; i < thread.length; i++) {
const item = thread[i]
if (!AppBskyUnspeccedDefs.isThreadItemPost(item.value)) continue
if (!bsky.isType(app.bsky.unspecced.defs.threadItemPost, item.value))
continue
if (item.depth === 0) {
thread.splice(i, 1, {
@@ -363,13 +366,13 @@ export function useUpdatePostThreadThreadgateQueryCache() {
return thread as T[]
}
qc.setQueryData<AppBskyUnspeccedGetPostThreadV2.OutputSchema>(
qc.setQueryData<app.bsky.unspecced.getPostThreadV2.$OutputBody>(
context.postThreadQueryKey,
data => {
if (!data) return
return {
...data,
thread: mutator<AppBskyUnspeccedGetPostThreadV2.ThreadItem>([
thread: mutator<app.bsky.unspecced.getPostThreadV2.ThreadItem>([
...data.thread,
]),
}
+46 -15
View File
@@ -1,4 +1,3 @@
import {AppBskyUnspeccedDefs} from '@atproto/api'
import {type ModerationOpts} from '@bsky.app/sdk/moderation'
import {
@@ -14,6 +13,8 @@ import {
getTraversalMetadata,
storeTraversalMetadata,
} from '#/state/queries/usePostThread/utils'
import * as bsky from '#/types/bsky'
import {app} from '#/lexicons'
import * as views from '#/state/queries/usePostThread/views'
export function sortAndAnnotateThreadItems(
@@ -46,7 +47,7 @@ export function sortAndAnnotateThreadItems(
let parentMetadata: TraversalMetadata | undefined
let metadata: TraversalMetadata | undefined
if (AppBskyUnspeccedDefs.isThreadItemPost(item.value)) {
if (bsky.isType(app.bsky.unspecced.defs.threadItemPost, item.value)) {
parentMetadata = metadatas.get(
getPostRecord(item.value.post).reply?.parent?.uri || '',
)
@@ -65,13 +66,24 @@ export function sortAndAnnotateThreadItems(
* _up_ from there.
*/
} else if (item.depth === 0) {
if (AppBskyUnspeccedDefs.isThreadItemNoUnauthenticated(item.value)) {
if (
bsky.isType(
app.bsky.unspecced.defs.threadItemNoUnauthenticated,
item.value,
)
) {
threadItems.push(views.threadPostNoUnauthenticated(item))
} else if (AppBskyUnspeccedDefs.isThreadItemNotFound(item.value)) {
} else if (
bsky.isType(app.bsky.unspecced.defs.threadItemNotFound, item.value)
) {
threadItems.push(views.threadPostNotFound(item))
} else if (AppBskyUnspeccedDefs.isThreadItemBlocked(item.value)) {
} else if (
bsky.isType(app.bsky.unspecced.defs.threadItemBlocked, item.value)
) {
threadItems.push(views.threadPostBlocked(item))
} else if (AppBskyUnspeccedDefs.isThreadItemPost(item.value)) {
} else if (
bsky.isType(app.bsky.unspecced.defs.threadItemPost, item.value)
) {
const post = views.threadPost({
uri: item.uri,
depth: item.depth,
@@ -85,7 +97,10 @@ export function sortAndAnnotateThreadItems(
const parent = thread[pi]
if (
AppBskyUnspeccedDefs.isThreadItemNoUnauthenticated(parent.value)
bsky.isType(
app.bsky.unspecced.defs.threadItemNoUnauthenticated,
parent.value,
)
) {
const post = views.threadPostNoUnauthenticated(parent)
post.ui = getThreadPostNoUnauthenticatedUI({
@@ -97,13 +112,22 @@ export function sortAndAnnotateThreadItems(
threadItems.unshift(post)
// for now, break parent traversal at first no-unauthed
break parentTraversal
} else if (AppBskyUnspeccedDefs.isThreadItemNotFound(parent.value)) {
} else if (
bsky.isType(
app.bsky.unspecced.defs.threadItemNotFound,
parent.value,
)
) {
threadItems.unshift(views.threadPostNotFound(parent))
break parentTraversal
} else if (AppBskyUnspeccedDefs.isThreadItemBlocked(parent.value)) {
} else if (
bsky.isType(app.bsky.unspecced.defs.threadItemBlocked, parent.value)
) {
threadItems.unshift(views.threadPostBlocked(parent))
break parentTraversal
} else if (AppBskyUnspeccedDefs.isThreadItemPost(parent.value)) {
} else if (
bsky.isType(app.bsky.unspecced.defs.threadItemPost, parent.value)
) {
threadItems.unshift(
views.threadPost({
uri: parent.uri,
@@ -123,16 +147,21 @@ export function sortAndAnnotateThreadItems(
* we could.
*/
const shouldBreak =
AppBskyUnspeccedDefs.isThreadItemNoUnauthenticated(item.value) ||
AppBskyUnspeccedDefs.isThreadItemNotFound(item.value) ||
AppBskyUnspeccedDefs.isThreadItemBlocked(item.value)
bsky.isType(
app.bsky.unspecced.defs.threadItemNoUnauthenticated,
item.value,
) ||
bsky.isType(app.bsky.unspecced.defs.threadItemNotFound, item.value) ||
bsky.isType(app.bsky.unspecced.defs.threadItemBlocked, item.value)
if (shouldBreak) {
const branch = getBranch(thread, i, item.depth)
// could insert tombstone
i = branch.end
continue traversal
} else if (AppBskyUnspeccedDefs.isThreadItemPost(item.value)) {
} else if (
bsky.isType(app.bsky.unspecced.defs.threadItemPost, item.value)
) {
if (parentMetadata) {
/*
* Set this value before incrementing the `repliesSeenCounter` later
@@ -180,7 +209,9 @@ export function sortAndAnnotateThreadItems(
for (let ci = startIndex; ci <= branch.end; ci++) {
const child = thread[ci]
if (AppBskyUnspeccedDefs.isThreadItemPost(child.value)) {
if (
bsky.isType(app.bsky.unspecced.defs.threadItemPost, child.value)
) {
const childParentMetadata = metadatas.get(
getPostRecord(child.value.post).reply?.parent?.uri || '',
)
+14 -21
View File
@@ -1,16 +1,9 @@
import {
type AppBskyFeedDefs,
type AppBskyFeedPost,
type AppBskyFeedThreadgate,
type AppBskyUnspeccedDefs,
type AppBskyUnspeccedGetPostThreadOtherV2,
type AppBskyUnspeccedGetPostThreadV2,
} from '@atproto/api'
import {type ModerationDecision} from '@bsky.app/sdk/moderation'
import {app} from '#/lexicons'
export type ApiThreadItem =
| AppBskyUnspeccedGetPostThreadV2.ThreadItem
| AppBskyUnspeccedGetPostThreadOtherV2.ThreadItem
| app.bsky.unspecced.getPostThreadV2.ThreadItem
| app.bsky.unspecced.getPostThreadOtherV2.ThreadItem
export const postThreadQueryKeyRoot = 'post-thread-v2' as const
@@ -18,13 +11,13 @@ export const createPostThreadQueryKey = (props: PostThreadParams) =>
[postThreadQueryKeyRoot, props] as const
export const createPostThreadOtherQueryKey = (
props: Omit<AppBskyUnspeccedGetPostThreadOtherV2.QueryParams, 'anchor'> & {
props: Omit<app.bsky.unspecced.getPostThreadOtherV2.$Params, 'anchor'> & {
anchor?: string
},
) => [postThreadQueryKeyRoot, 'other', props] as const
export type PostThreadParams = Pick<
AppBskyUnspeccedGetPostThreadV2.QueryParams,
app.bsky.unspecced.getPostThreadV2.$Params,
'sort'
> & {
anchor?: string
@@ -33,9 +26,9 @@ export type PostThreadParams = Pick<
export type UsePostThreadQueryResult = {
hasOtherReplies: boolean
thread: AppBskyUnspeccedGetPostThreadV2.ThreadItem[]
threadgate?: Omit<AppBskyFeedDefs.ThreadgateView, 'record'> & {
record: AppBskyFeedThreadgate.Record
thread: app.bsky.unspecced.getPostThreadV2.ThreadItem[]
threadgate?: Omit<app.bsky.feed.defs.ThreadgateView, 'record'> & {
record: app.bsky.feed.threadgate.Main
}
}
@@ -45,9 +38,9 @@ export type ThreadItem =
key: string
uri: string
depth: number
value: Omit<AppBskyUnspeccedDefs.ThreadItemPost, 'post'> & {
post: Omit<AppBskyFeedDefs.PostView, 'record'> & {
record: AppBskyFeedPost.Record
value: Omit<app.bsky.unspecced.defs.ThreadItemPost, 'post'> & {
post: Omit<app.bsky.feed.defs.PostView, 'record'> & {
record: app.bsky.feed.post.Main
}
}
isBlurred: boolean
@@ -67,7 +60,7 @@ export type ThreadItem =
key: string
uri: string
depth: number
value: AppBskyUnspeccedDefs.ThreadItemNoUnauthenticated
value: app.bsky.unspecced.defs.ThreadItemNoUnauthenticated
ui: {
showParentReplyLine: boolean
showChildReplyLine: boolean
@@ -78,14 +71,14 @@ export type ThreadItem =
key: string
uri: string
depth: number
value: AppBskyUnspeccedDefs.ThreadItemNotFound
value: app.bsky.unspecced.defs.ThreadItemNotFound
}
| {
type: 'threadPostBlocked'
key: string
uri: string
depth: number
value: AppBskyUnspeccedDefs.ThreadItemBlocked
value: app.bsky.unspecced.defs.ThreadItemBlocked
}
| {
type: 'replyComposer'
+9 -24
View File
@@ -1,38 +1,23 @@
import {
type AppBskyFeedDefs,
AppBskyFeedPost,
AppBskyFeedThreadgate,
AppBskyUnspeccedDefs,
type AppBskyUnspeccedGetPostThreadV2,
AtUri,
} from '@atproto/api'
import {
type ApiThreadItem,
type ThreadItem,
type TraversalMetadata,
} from '#/state/queries/usePostThread/types'
import {AtUri} from '@atproto/syntax'
import {app} from '#/lexicons'
import {isDevMode} from '#/storage/hooks/dev-mode'
import * as bsky from '#/types/bsky'
export function getThreadgateRecord(
view: AppBskyUnspeccedGetPostThreadV2.OutputSchema['threadgate'],
view: app.bsky.unspecced.getPostThreadV2.$OutputBody['threadgate'],
) {
return bsky.dangerousIsType<AppBskyFeedThreadgate.Record>(
view?.record,
AppBskyFeedThreadgate.isRecord,
)
return bsky.isType(app.bsky.feed.threadgate, view?.record)
? view?.record
: undefined
}
export function getRootPostAtUri(post: AppBskyFeedDefs.PostView) {
if (
bsky.dangerousIsType<AppBskyFeedPost.Record>(
post.record,
AppBskyFeedPost.isRecord,
)
) {
export function getRootPostAtUri(post: app.bsky.feed.defs.PostView) {
if (bsky.isType(app.bsky.feed.post, post.record)) {
/**
* If the record has no `reply` field, it is a root post.
*/
@@ -45,8 +30,8 @@ export function getRootPostAtUri(post: AppBskyFeedDefs.PostView) {
}
}
export function getPostRecord(post: AppBskyFeedDefs.PostView) {
return post.record as AppBskyFeedPost.Record
export function getPostRecord(post: app.bsky.feed.defs.PostView) {
return post.record as app.bsky.feed.post.Main
}
export function getTraversalMetadata({
@@ -60,7 +45,7 @@ export function getTraversalMetadata({
nextItem?: ApiThreadItem
parentMetadata?: TraversalMetadata
}): TraversalMetadata {
if (!AppBskyUnspeccedDefs.isThreadItemPost(item.value)) {
if (!bsky.isType(app.bsky.unspecced.defs.threadItemPost, item.value)) {
throw new Error(`Expected thread item to be a post`)
}
const repliesCount = item.value.post.replyCount || 0
+12 -17
View File
@@ -1,13 +1,8 @@
import {
type $Typed,
type AppBskyFeedDefs,
type AppBskyFeedPost,
type AppBskyUnspeccedDefs,
type AppBskyUnspeccedGetPostThreadV2,
AtUri,
} from '@atproto/api'
import {type ModerationOpts} from '@bsky.app/sdk/moderation'
import {type $Typed} from '@atproto/lex'
import {AtUri} from '@atproto/syntax'
import {app} from '#/lexicons'
import {moderatePost} from '#/lib/moderation/subjects'
import {makeProfileLink} from '#/lib/routes/links'
import {
@@ -26,7 +21,7 @@ export function threadPostNoUnauthenticated({
key: uri,
uri,
depth,
value: value as AppBskyUnspeccedDefs.ThreadItemNoUnauthenticated,
value: value as app.bsky.unspecced.defs.ThreadItemNoUnauthenticated,
// @ts-ignore populated by the traversal
ui: {},
}
@@ -42,7 +37,7 @@ export function threadPostNotFound({
key: uri,
uri,
depth,
value: value as AppBskyUnspeccedDefs.ThreadItemNotFound,
value: value as app.bsky.unspecced.defs.ThreadItemNotFound,
}
}
@@ -56,7 +51,7 @@ export function threadPostBlocked({
key: uri,
uri,
depth,
value: value as AppBskyUnspeccedDefs.ThreadItemBlocked,
value: value as app.bsky.unspecced.defs.ThreadItemBlocked,
}
}
@@ -69,7 +64,7 @@ export function threadPost({
}: {
uri: string
depth: number
value: $Typed<AppBskyUnspeccedDefs.ThreadItemPost>
value: $Typed<app.bsky.unspecced.defs.ThreadItemPost>
moderationOpts: ModerationOpts
threadgateHiddenReplies: Set<string>
}): Extract<ThreadItem, {type: 'threadPost'}> {
@@ -91,8 +86,8 @@ export function threadPost({
* Do not spread anything here, load bearing for post shadow strict
* equality reference checks.
*/
post: value.post as Omit<AppBskyFeedDefs.PostView, 'record'> & {
record: AppBskyFeedPost.Record
post: value.post as Omit<app.bsky.feed.defs.PostView, 'record'> & {
record: app.bsky.feed.post.Main
},
},
isBlurred,
@@ -161,10 +156,10 @@ export function skeleton({
}
export function postViewToThreadPlaceholder(
post: AppBskyFeedDefs.PostView,
post: app.bsky.feed.defs.PostView,
): $Typed<
Omit<AppBskyUnspeccedGetPostThreadV2.ThreadItem, 'value'> & {
value: $Typed<AppBskyUnspeccedDefs.ThreadItemPost>
Omit<app.bsky.unspecced.getPostThreadV2.ThreadItem, 'value'> & {
value: $Typed<app.bsky.unspecced.defs.ThreadItemPost>
}
> {
return {
+12 -25
View File
@@ -1,17 +1,11 @@
import {
type AppBskyActorDefs,
AppBskyEmbedRecord,
AppBskyEmbedRecordWithMedia,
type AppBskyFeedDefs,
AppBskyFeedPost,
type AtUri,
} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
type QueryKey,
} from '@tanstack/react-query'
import {type AtUri} from '@atproto/syntax'
import {app} from '#/lexicons'
import * as bsky from '#/types/bsky'
export type StructuredQueryKey<T extends Record<string, unknown>> = readonly [
@@ -93,7 +87,7 @@ export async function truncateAndInvalidate<T = any>(
// of the currentUri that is being checked.
export function didOrHandleUriMatches(
atUri: AtUri,
record: {uri: string; author: AppBskyActorDefs.ProfileViewBasic},
record: {uri: string; author: app.bsky.actor.defs.ProfileViewBasic},
) {
if (atUri.host.startsWith('did:')) {
return atUri.href === record.uri
@@ -104,26 +98,19 @@ export function didOrHandleUriMatches(
export function getEmbeddedPost(
v: unknown,
): AppBskyEmbedRecord.ViewRecord | undefined {
if (
bsky.dangerousIsType<AppBskyEmbedRecord.View>(v, AppBskyEmbedRecord.isView)
) {
): app.bsky.embed.record.ViewRecord | undefined {
if (bsky.isType(app.bsky.embed.record.view, v)) {
if (
AppBskyEmbedRecord.isViewRecord(v.record) &&
AppBskyFeedPost.isRecord(v.record.value)
bsky.isType(app.bsky.embed.record.viewRecord, v.record) &&
bsky.isType(app.bsky.feed.post, v.record.value)
) {
return v.record
}
}
if (
bsky.dangerousIsType<AppBskyEmbedRecordWithMedia.View>(
v,
AppBskyEmbedRecordWithMedia.isView,
)
) {
if (bsky.isType(app.bsky.embed.recordWithMedia.view, v)) {
if (
AppBskyEmbedRecord.isViewRecord(v.record.record) &&
AppBskyFeedPost.isRecord(v.record.record.value)
bsky.isType(app.bsky.embed.record.viewRecord, v.record.record) &&
bsky.isType(app.bsky.feed.post, v.record.record.value)
) {
return v.record.record
}
@@ -131,8 +118,8 @@ export function getEmbeddedPost(
}
export function embedViewRecordToPostView(
v: AppBskyEmbedRecord.ViewRecord,
): AppBskyFeedDefs.PostView {
v: app.bsky.embed.record.ViewRecord,
): app.bsky.feed.defs.PostView {
return {
uri: v.uri,
cid: v.cid,
@@ -1,4 +1,3 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type AtIdentifierString, AtUri} from '@atproto/syntax'
import {useMutation} from '@tanstack/react-query'
@@ -22,7 +21,7 @@ export function useVerificationsRemoveMutation() {
verifications,
}: {
profile: bsky.profile.AnyProfileView
verifications: AppBskyActorDefs.VerificationView[]
verifications: app.bsky.actor.defs.VerificationView[]
}) {
if (!currentAccount) {
throw new Error('User not logged in')
+5 -9
View File
@@ -1,14 +1,10 @@
import {createContext, useContext, useMemo, useState} from 'react'
import {
type AppBskyActorDefs,
type AppBskyFeedDefs,
type AppBskyUnspeccedGetPostThreadV2,
} from '@atproto/api'
import {type ModerationDecision} from '@bsky.app/sdk/moderation'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query'
import {app} from '#/lexicons'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {postUriToRelativePath, toBskyAppUrl} from '#/lib/strings/url-helpers'
import {purgeTemporaryImageFiles} from '#/state/gallery'
@@ -24,15 +20,15 @@ export interface ComposerOptsPostRef {
cid: string
text: string
langs?: string[]
author: AppBskyActorDefs.ProfileViewBasic
embed?: AppBskyFeedDefs.PostView['embed']
author: app.bsky.actor.defs.ProfileViewBasic
embed?: app.bsky.feed.defs.PostView['embed']
moderation?: ModerationDecision
}
export type OnPostSuccessData =
| {
replyToUri?: string
posts: AppBskyUnspeccedGetPostThreadV2.ThreadItem[]
posts: app.bsky.unspecced.getPostThreadV2.ThreadItem[]
}
| undefined
@@ -48,7 +44,7 @@ export interface ComposerOpts {
replyTo?: ComposerOptsPostRef
onPost?: (postUri: string | undefined) => void
onPostSuccess?: (data: OnPostSuccessData) => void
quote?: AppBskyFeedDefs.PostView
quote?: app.bsky.feed.defs.PostView
mention?: string // handle of user to mention
text?: string
imageUris?: {uri: string; width: number; height: number; altText?: string}[]
+3 -3
View File
@@ -1,5 +1,5 @@
import {createContext, useCallback, useContext, useMemo, useState} from 'react'
import {type AppBskyFeedThreadgate} from '@atproto/api'
import {app} from '#/lexicons'
type StateContext = {
uris: Set<string>
@@ -74,7 +74,7 @@ export function useThreadgateHiddenReplyUrisAPI() {
export function useMergedThreadgateHiddenReplies({
threadgateRecord,
}: {
threadgateRecord?: AppBskyFeedThreadgate.Record
threadgateRecord?: app.bsky.feed.threadgate.Main
}) {
const {uris, recentlyUnhiddenUris} = useThreadgateHiddenReplyUris()
return useMemo(() => {
@@ -89,7 +89,7 @@ export function useMergedThreadgateHiddenReplies({
export function useMergeThreadgateHiddenReplies() {
const {uris, recentlyUnhiddenUris} = useThreadgateHiddenReplyUris()
return useCallback(
(threadgate?: AppBskyFeedThreadgate.Record) => {
(threadgate?: app.bsky.feed.threadgate.Main) => {
const set = new Set([...(threadgate?.hiddenReplies || []), ...uris])
for (const uri of recentlyUnhiddenUris) {
set.delete(uri)
+3 -2
View File
@@ -1,6 +1,7 @@
import {useEffect, useId, useState} from 'react'
import {type AppBskyFeedDefs, AtUri} from '@atproto/api'
import {AtUri} from '@atproto/syntax'
import {app} from '#/lexicons'
import {Logger} from '#/logger'
import {type FeedSourceInfo} from '#/state/queries/feed'
@@ -10,7 +11,7 @@ import {type FeedSourceInfo} from '#/state/queries/feed'
const logger = Logger.create(Logger.Context.PostSource)
export type PostSource = {
post: AppBskyFeedDefs.FeedViewPost
post: app.bsky.feed.defs.FeedViewPost
feedSourceInfo?: FeedSourceInfo
}