about summary refs log tree commit diff
path: root/src/state/cache/thread-mutes.tsx
blob: 4492977f22e3b22b2646d0d3d5466738bf87a845 (plain) (blame)
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])
}