forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import React from 'react'
2import {type AppBskyFeedThreadgate} from '@atproto/api'
3
4type StateContext = {
5 uris: Set<string>
6 recentlyUnhiddenUris: Set<string>
7}
8type ApiContext = {
9 addHiddenReplyUri: (uri: string) => void
10 removeHiddenReplyUri: (uri: string) => void
11}
12
13const StateContext = React.createContext<StateContext>({
14 uris: new Set(),
15 recentlyUnhiddenUris: new Set(),
16})
17StateContext.displayName = 'ThreadgateHiddenRepliesStateContext'
18
19const ApiContext = React.createContext<ApiContext>({
20 addHiddenReplyUri: () => {},
21 removeHiddenReplyUri: () => {},
22})
23ApiContext.displayName = 'ThreadgateHiddenRepliesApiContext'
24
25export function Provider({children}: {children: React.ReactNode}) {
26 const [uris, setHiddenReplyUris] = React.useState<Set<string>>(new Set())
27 const [recentlyUnhiddenUris, setRecentlyUnhiddenUris] = React.useState<
28 Set<string>
29 >(new Set())
30
31 const stateCtx = React.useMemo(
32 () => ({
33 uris,
34 recentlyUnhiddenUris,
35 }),
36 [uris, recentlyUnhiddenUris],
37 )
38
39 const apiCtx = React.useMemo(
40 () => ({
41 addHiddenReplyUri(uri: string) {
42 setHiddenReplyUris(prev => new Set(prev.add(uri)))
43 setRecentlyUnhiddenUris(prev => {
44 prev.delete(uri)
45 return new Set(prev)
46 })
47 },
48 removeHiddenReplyUri(uri: string) {
49 setHiddenReplyUris(prev => {
50 prev.delete(uri)
51 return new Set(prev)
52 })
53 setRecentlyUnhiddenUris(prev => new Set(prev.add(uri)))
54 },
55 }),
56 [setHiddenReplyUris],
57 )
58
59 return (
60 <ApiContext.Provider value={apiCtx}>
61 <StateContext.Provider value={stateCtx}>{children}</StateContext.Provider>
62 </ApiContext.Provider>
63 )
64}
65
66export function useThreadgateHiddenReplyUris() {
67 return React.useContext(StateContext)
68}
69
70export function useThreadgateHiddenReplyUrisAPI() {
71 return React.useContext(ApiContext)
72}
73
74export function useMergedThreadgateHiddenReplies({
75 threadgateRecord,
76}: {
77 threadgateRecord?: AppBskyFeedThreadgate.Record
78}) {
79 const {uris, recentlyUnhiddenUris} = useThreadgateHiddenReplyUris()
80 return React.useMemo(() => {
81 const set = new Set([...(threadgateRecord?.hiddenReplies || []), ...uris])
82 for (const uri of recentlyUnhiddenUris) {
83 set.delete(uri)
84 }
85 return set
86 }, [uris, recentlyUnhiddenUris, threadgateRecord])
87}
88
89export function useMergeThreadgateHiddenReplies() {
90 const {uris, recentlyUnhiddenUris} = useThreadgateHiddenReplyUris()
91 return React.useCallback(
92 (threadgate?: AppBskyFeedThreadgate.Record) => {
93 const set = new Set([...(threadgate?.hiddenReplies || []), ...uris])
94 for (const uri of recentlyUnhiddenUris) {
95 set.delete(uri)
96 }
97 return set
98 },
99 [uris, recentlyUnhiddenUris],
100 )
101}