Clean up starter packs dialog styles + add optimistic updates (#9469)

This commit is contained in:
Samuel Newman
2026-02-11 17:46:28 +00:00
committed by GitHub
parent 4eca13941a
commit 37e5a0f7a4
4 changed files with 186 additions and 93 deletions
+3 -24
View File
@@ -1,13 +1,4 @@
import {
type AppBskyGraphGetActorStarterPacks,
type AppBskyGraphGetStarterPacksWithMembership,
} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
type QueryKey,
useInfiniteQuery,
} from '@tanstack/react-query'
import {type QueryClient, useInfiniteQuery} from '@tanstack/react-query'
import {useAgent} from '#/state/session'
@@ -28,13 +19,7 @@ export function useActorStarterPacksQuery({
}) {
const agent = useAgent()
return useInfiniteQuery<
AppBskyGraphGetActorStarterPacks.OutputSchema,
Error,
InfiniteData<AppBskyGraphGetActorStarterPacks.OutputSchema>,
QueryKey,
string | undefined
>({
return useInfiniteQuery({
queryKey: RQKEY(did),
queryFn: async ({pageParam}: {pageParam?: string}) => {
const res = await agent.app.bsky.graph.getActorStarterPacks({
@@ -59,13 +44,7 @@ export function useActorStarterPacksWithMembershipsQuery({
}) {
const agent = useAgent()
return useInfiniteQuery<
AppBskyGraphGetStarterPacksWithMembership.OutputSchema,
Error,
InfiniteData<AppBskyGraphGetStarterPacksWithMembership.OutputSchema>,
QueryKey,
string | undefined
>({
return useInfiniteQuery({
queryKey: RQKEY_WITH_MEMBERSHIP(did),
queryFn: async ({pageParam}: {pageParam?: string}) => {
const res = await agent.app.bsky.graph.getStarterPacksWithMembership({
+116 -2
View File
@@ -14,12 +14,23 @@
* -prf
*/
import {AtUri} from '@atproto/api'
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
import {
type AppBskyActorDefs,
type AppBskyGraphGetStarterPacksWithMembership,
AtUri,
} from '@atproto/api'
import {
type InfiniteData,
useMutation,
useQuery,
useQueryClient,
} from '@tanstack/react-query'
import {STALE} from '#/state/queries'
import {RQKEY as LIST_MEMBERS_RQKEY} from '#/state/queries/list-members'
import {useAgent, useSession} from '#/state/session'
import type * as bsky from '#/types/bsky'
import {RQKEY_WITH_MEMBERSHIP as STARTER_PACKS_WITH_MEMBERSHIPS_RKEY} from './actor-starter-packs'
// sanity limit is SANITY_PAGE_LIMIT*PAGE_SIZE total records
const SANITY_PAGE_LIMIT = 1000
@@ -91,9 +102,14 @@ export function getMembership(
}
export function useListMembershipAddMutation({
subject,
onSuccess,
onError,
}: {
/**
* Needed for optimistic update of starter pack query
*/
subject?: bsky.profile.AnyProfileView
onSuccess?: (data: {uri: string; cid: string}) => void
onError?: (error: Error) => void
} = {}) {
@@ -151,6 +167,60 @@ export function useListMembershipAddMutation({
queryKey: LIST_MEMBERS_RQKEY(variables.listUri),
})
}, 1e3)
// update WITH_MEMBERSHIPS query
if (subject) {
queryClient.setQueryData<
InfiniteData<AppBskyGraphGetStarterPacksWithMembership.OutputSchema>
>(STARTER_PACKS_WITH_MEMBERSHIPS_RKEY(variables.actorDid), old => {
if (!old) return old
return {
...old,
pages: old.pages.map(page => ({
...page,
starterPacksWithMembership: page.starterPacksWithMembership.map(
spWithMembership => {
if (
spWithMembership.starterPack.list &&
spWithMembership.starterPack.list?.uri === variables.listUri
) {
return {
...spWithMembership,
starterPack: {
...spWithMembership.starterPack,
listItemsSample: [
{
uri: data.uri,
subject: subject as AppBskyActorDefs.ProfileView,
},
...(spWithMembership.starterPack.listItemsSample?.filter(
item => item.subject.did !== variables.actorDid,
) ?? []),
],
list: {
...spWithMembership.starterPack.list,
listItemCount:
(spWithMembership.starterPack.list.listItemCount ??
0) + 1,
},
},
listItem: {
uri: data.uri,
subject: subject as AppBskyActorDefs.ProfileView,
},
}
}
return spWithMembership
},
),
})),
}
})
}
onSuccess?.(data)
},
onError,
@@ -206,6 +276,50 @@ export function useListMembershipRemoveMutation({
queryKey: LIST_MEMBERS_RQKEY(variables.listUri),
})
}, 1e3)
queryClient.setQueryData<
InfiniteData<AppBskyGraphGetStarterPacksWithMembership.OutputSchema>
>(STARTER_PACKS_WITH_MEMBERSHIPS_RKEY(variables.actorDid), old => {
if (!old) return old
return {
...old,
pages: old.pages.map(page => ({
...page,
starterPacksWithMembership: page.starterPacksWithMembership.map(
spWithMembership => {
if (
spWithMembership.starterPack.list &&
spWithMembership.starterPack.list.uri === variables.listUri
) {
return {
...spWithMembership,
starterPack: {
...spWithMembership.starterPack,
listItemsSample:
spWithMembership.starterPack.listItemsSample?.filter(
item => item.subject.did !== variables.actorDid,
),
list: {
...spWithMembership.starterPack.list,
listItemCount: Math.max(
0,
(spWithMembership.starterPack.list.listItemCount ??
1) - 1,
),
},
},
listItem: undefined,
}
}
return spWithMembership
},
),
})),
}
})
onSuccess?.(data)
},
onError,