From 0012d1236ffa4f268fb359931d02335b21610fd6 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 18 Jun 2024 22:05:59 +0100 Subject: [PATCH] Migrate local thread mutes (#4523) * migrate thread mutes * don't try and clear if not logged in yet * migrate mutes one at a time * write before mutating * only migrate mutes of self posts * use /** @deprecated */ * shouldLike -> shouldMute --- src/state/cache/thread-mutes.tsx | 55 +++++++++++++++++++++++++++++++- src/state/persisted/schema.ts | 3 +- src/state/queries/post.ts | 4 +-- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/state/cache/thread-mutes.tsx b/src/state/cache/thread-mutes.tsx index b58bd430..dc5104c1 100644 --- a/src/state/cache/thread-mutes.tsx +++ b/src/state/cache/thread-mutes.tsx @@ -1,4 +1,7 @@ -import React from 'react' +import React, {useEffect} from 'react' + +import * as persisted from '#/state/persisted' +import {useAgent, useSession} from '../session' type StateContext = Map type SetStateContext = (uri: string, value: boolean) => void @@ -21,6 +24,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) { }, [setState], ) + + useMigrateMutes(setThreadMute) + return ( @@ -42,3 +48,50 @@ export function useIsThreadMuted(uri: string, defaultValue = false) { export function useSetThreadMute() { return React.useContext(setStateContext) } + +function useMigrateMutes(setThreadMute: SetStateContext) { + const agent = useAgent() + const {currentAccount} = useSession() + + useEffect(() => { + if (currentAccount) { + if ( + !persisted + .get('mutedThreads') + .some(uri => uri.includes(currentAccount.did)) + ) { + return + } + + let cancelled = false + + const migrate = async () => { + while (!cancelled) { + const threads = persisted.get('mutedThreads') + + const root = threads.findLast(uri => uri.includes(currentAccount.did)) + + if (!root) break + + persisted.write( + 'mutedThreads', + threads.filter(uri => uri !== root), + ) + + setThreadMute(root, true) + + await agent.api.app.bsky.graph + .muteThread({root}) + // not a big deal if this fails, since the post might have been deleted + .catch(console.error) + } + } + + migrate() + + return () => { + cancelled = true + } + } + }, [agent, currentAccount, setThreadMute]) +} diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts index b81cf596..9d5b17d3 100644 --- a/src/state/persisted/schema.ts +++ b/src/state/persisted/schema.ts @@ -74,7 +74,6 @@ export const schema = z.object({ flickr: z.enum(externalEmbedOptions).optional(), }) .optional(), - mutedThreads: z.array(z.string()), // should move to server invites: z.object({ copiedInvites: z.array(z.string()), }), @@ -88,6 +87,8 @@ export const schema = z.object({ disableHaptics: z.boolean().optional(), disableAutoplay: z.boolean().optional(), kawaii: z.boolean().optional(), + /** @deprecated */ + mutedThreads: z.array(z.string()), }) export type Schema = z.infer diff --git a/src/state/queries/post.ts b/src/state/queries/post.ts index 8e77bf6b..a511d6b3 100644 --- a/src/state/queries/post.ts +++ b/src/state/queries/post.ts @@ -304,8 +304,8 @@ export function useThreadMuteMutationQueue( const queueToggle = useToggleMutationQueue({ initialState: isThreadMuted, - runMutation: async (_prev, shouldLike) => { - if (shouldLike) { + runMutation: async (_prev, shouldMute) => { + if (shouldMute) { await threadMuteMutation.mutateAsync({ uri: rootUri, })