forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {
2 createContext,
3 useCallback,
4 useContext,
5 useEffect,
6 useMemo,
7 useState,
8} from 'react'
9import type {PropsWithChildren} from 'react'
10
11import * as persisted from '#/state/persisted'
12
13type SetStateCb = (
14 s: persisted.Schema['hiddenPosts'],
15) => persisted.Schema['hiddenPosts']
16type StateContext = persisted.Schema['hiddenPosts']
17type ApiContext = {
18 hidePost: ({uri}: {uri: string}) => void
19 unhidePost: ({uri}: {uri: string}) => void
20}
21
22const stateContext = createContext<StateContext>(persisted.defaults.hiddenPosts)
23stateContext.displayName = 'HiddenPostsStateContext'
24const apiContext = createContext<ApiContext>({
25 hidePost: () => {},
26 unhidePost: () => {},
27})
28apiContext.displayName = 'HiddenPostsApiContext'
29
30export function Provider({children}: PropsWithChildren<{}>) {
31 const [state, setState] = useState(persisted.get('hiddenPosts'))
32
33 const setStateWrapped = useCallback(
34 (fn: SetStateCb) => {
35 const s = fn(persisted.get('hiddenPosts'))
36 setState(s)
37 persisted.write('hiddenPosts', s)
38 },
39 [setState],
40 )
41
42 const api = useMemo(
43 () => ({
44 hidePost: ({uri}: {uri: string}) => {
45 setStateWrapped(s => [...(s || []), uri])
46 },
47 unhidePost: ({uri}: {uri: string}) => {
48 setStateWrapped(s => (s || []).filter(u => u !== uri))
49 },
50 }),
51 [setStateWrapped],
52 )
53
54 useEffect(() => {
55 return persisted.onUpdate('hiddenPosts', nextHiddenPosts => {
56 setState(nextHiddenPosts)
57 })
58 }, [setStateWrapped])
59
60 return (
61 <stateContext.Provider value={state}>
62 <apiContext.Provider value={api}>{children}</apiContext.Provider>
63 </stateContext.Provider>
64 )
65}
66
67export function useHiddenPosts() {
68 return useContext(stateContext)
69}
70
71export function useHiddenPostsApi() {
72 return useContext(apiContext)
73}