mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React, {useEffect} from 'react'
2
3import * as persisted from '#/state/persisted'
4import {useAgent, useSession} from '../session'
5
6type StateContext = Map<string, boolean>
7type SetStateContext = (uri: string, value: boolean) => void
8
9const stateContext = React.createContext<StateContext>(new Map())
10const setStateContext = React.createContext<SetStateContext>(
11 (_: string) => false,
12)
13
14export function Provider({children}: React.PropsWithChildren<{}>) {
15 const [state, setState] = React.useState<StateContext>(() => new Map())
16
17 const setThreadMute = React.useCallback(
18 (uri: string, value: boolean) => {
19 setState(prev => {
20 const next = new Map(prev)
21 next.set(uri, value)
22 return next
23 })
24 },
25 [setState],
26 )
27
28 useMigrateMutes(setThreadMute)
29
30 return (
31 <stateContext.Provider value={state}>
32 <setStateContext.Provider value={setThreadMute}>
33 {children}
34 </setStateContext.Provider>
35 </stateContext.Provider>
36 )
37}
38
39export function useMutedThreads() {
40 return React.useContext(stateContext)
41}
42
43export function useIsThreadMuted(uri: string, defaultValue = false) {
44 const state = React.useContext(stateContext)
45 return state.get(uri) ?? defaultValue
46}
47
48export function useSetThreadMute() {
49 return React.useContext(setStateContext)
50}
51
52function useMigrateMutes(setThreadMute: SetStateContext) {
53 const agent = useAgent()
54 const {currentAccount} = useSession()
55
56 useEffect(() => {
57 if (currentAccount) {
58 if (
59 !persisted
60 .get('mutedThreads')
61 .some(uri => uri.includes(currentAccount.did))
62 ) {
63 return
64 }
65
66 let cancelled = false
67
68 const migrate = async () => {
69 while (!cancelled) {
70 const threads = persisted.get('mutedThreads')
71
72 const root = threads.findLast(uri => uri.includes(currentAccount.did))
73
74 if (!root) break
75
76 persisted.write(
77 'mutedThreads',
78 threads.filter(uri => uri !== root),
79 )
80
81 setThreadMute(root, true)
82
83 await agent.api.app.bsky.graph
84 .muteThread({root})
85 // not a big deal if this fails, since the post might have been deleted
86 .catch(console.error)
87 }
88 }
89
90 migrate()
91
92 return () => {
93 cancelled = true
94 }
95 }
96 }, [agent, currentAccount, setThreadMute])
97}