diff --git a/src/analytics/metrics/types.ts b/src/analytics/metrics/types.ts
index 78a4574f0f..1639c2a43d 100644
--- a/src/analytics/metrics/types.ts
+++ b/src/analytics/metrics/types.ts
@@ -715,6 +715,10 @@ export type Events = {
count: number
}
'starterPack:delete': {}
+ 'starterPack:optOut': {
+ starterPack: string
+ action: 'optOut' | 'undo'
+ }
'starterPack:create': {
setName: boolean
setDescription: boolean
diff --git a/src/screens/StarterPack/StarterPackScreen.tsx b/src/screens/StarterPack/StarterPackScreen.tsx
index 7d9a11d358..40bc6f31a3 100644
--- a/src/screens/StarterPack/StarterPackScreen.tsx
+++ b/src/screens/StarterPack/StarterPackScreen.tsx
@@ -552,6 +552,12 @@ function OverflowMenu({
const {mutate: setReferenceListOptOut, isPending: isOptOutPending} =
useReferenceListOptOutMutation({
starterPack,
+ onSuccess: action => {
+ ax.metric('starterPack:optOut', {
+ starterPack: starterPack.uri,
+ action,
+ })
+ },
onError: error => {
logger.error('Failed to update starter pack opt-out', {
safeMessage: error,
diff --git a/src/state/queries/__tests__/starter-packs.test.tsx b/src/state/queries/__tests__/starter-packs.test.tsx
index 5f958f7ed2..61a787658f 100644
--- a/src/state/queries/__tests__/starter-packs.test.tsx
+++ b/src/state/queries/__tests__/starter-packs.test.tsx
@@ -34,7 +34,7 @@ const createdOptOut =
const indexedOptOut =
'at://did:plc:viewer/app.bsky.graph.referencelistoptout/indexed'
-function setup() {
+function setup({onSuccess = jest.fn()} = {}) {
const queryClient = new QueryClient({
defaultOptions: {
queries: {gcTime: Infinity, retry: false},
@@ -57,11 +57,11 @@ function setup() {
{children}
)
const hook = renderHook(
- () => useReferenceListOptOutMutation({starterPack, onError}),
+ () => useReferenceListOptOutMutation({starterPack, onError, onSuccess}),
{wrapper},
)
- return {appviewClient, hook, onError, pdsClient, queryClient}
+ return {appviewClient, hook, onError, onSuccess, pdsClient, queryClient}
}
beforeEach(() => {
@@ -76,7 +76,7 @@ beforeAll(() => {
describe('useReferenceListOptOutMutation', () => {
it('keeps the successful PDS write optimistic when AppView has not caught up', async () => {
- const {hook, pdsClient, queryClient} = setup()
+ const {hook, onSuccess, pdsClient, queryClient} = setup()
pdsClient.create.mockResolvedValue({uri: createdOptOut})
jest.mocked(until).mockResolvedValue(false)
@@ -92,6 +92,7 @@ describe('useReferenceListOptOutMutation', () => {
queryClient.getQueryData(queryKey)
?.list?.viewer?.referenceListOptOut,
).toBe(createdOptOut)
+ expect(onSuccess).toHaveBeenCalledWith('optOut')
})
it('uses the indexed viewer-state URI when AppView reports a duplicate', async () => {
@@ -121,7 +122,7 @@ describe('useReferenceListOptOutMutation', () => {
})
it('deletes the viewer-state record URI when undoing', async () => {
- const {hook, pdsClient, queryClient} = setup()
+ const {hook, onSuccess, pdsClient, queryClient} = setup()
queryClient.setQueryData(queryKey, {
...starterPack,
list: {
@@ -148,10 +149,11 @@ describe('useReferenceListOptOutMutation', () => {
queryClient.getQueryData(queryKey)
?.list?.viewer?.referenceListOptOut,
).toBeUndefined()
+ expect(onSuccess).toHaveBeenCalledWith('undo')
})
it('restores viewer state and surfaces PDS write failures', async () => {
- const {hook, onError, pdsClient, queryClient} = setup()
+ const {hook, onError, onSuccess, pdsClient, queryClient} = setup()
const error = new Error('write failed')
pdsClient.create.mockRejectedValue(error)
@@ -162,6 +164,7 @@ describe('useReferenceListOptOutMutation', () => {
})
await waitFor(() => expect(onError).toHaveBeenCalledWith(error))
+ expect(onSuccess).not.toHaveBeenCalled()
expect(
queryClient.getQueryData(queryKey)
?.list?.viewer?.referenceListOptOut,
diff --git a/src/state/queries/starter-packs.ts b/src/state/queries/starter-packs.ts
index 674fe7336d..bbc5d8b4e7 100644
--- a/src/state/queries/starter-packs.ts
+++ b/src/state/queries/starter-packs.ts
@@ -74,9 +74,11 @@ export function useStarterPackQuery({
export function useReferenceListOptOutMutation({
starterPack,
onError,
+ onSuccess,
}: {
starterPack: app.bsky.graph.defs.StarterPackView
onError: (error: Error) => void
+ onSuccess?: (action: 'optOut' | 'undo') => void
}) {
const queryClient = useQueryClient()
const appviewClient = useAppviewClient()
@@ -171,7 +173,7 @@ export function useReferenceListOptOutMutation({
)
return {previous}
},
- onSuccess: ({referenceListOptOut}) => {
+ onSuccess: ({referenceListOptOut}, variables) => {
queryClient.setQueryData(
queryKey,
current =>
@@ -192,6 +194,7 @@ export function useReferenceListOptOutMutation({
queryClient,
uri: starterPack.list!.uri,
})
+ onSuccess?.(variables.referenceListOptOut ? 'undo' : 'optOut')
},
onError: (error, _, context) => {
if (context?.previous) {