1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
import React, {useEffect} from 'react'
import * as persisted from '#/state/persisted'
import {useAgent, useSession} from '../session'
type StateContext = Map<string, boolean>
type SetStateContext = (uri: string, value: boolean) => void
const stateContext = React.createContext<StateContext>(new Map())
const setStateContext = React.createContext<SetStateContext>(
(_: string) => false,
)
export function Provider({children}: React.PropsWithChildren<{}>) {
const [state, setState] = React.useState<StateContext>(() => new Map())
const setThreadMute = React.useCallback(
(uri: string, value: boolean) => {
setState(prev => {
const next = new Map(prev)
next.set(uri, value)
return next
})
},
[setState],
)
useMigrateMutes(setThreadMute)
return (
<stateContext.Provider value={state}>
<setStateContext.Provider value={setThreadMute}>
{children}
</setStateContext.Provider>
</stateContext.Provider>
)
}
export function useMutedThreads() {
return React.useContext(stateContext)
}
export function useIsThreadMuted(uri: string, defaultValue = false) {
const state = React.useContext(stateContext)
return state.get(uri) ?? defaultValue
}
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')
// @ts-ignore findLast is polyfilled - esb
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])
}
|