Bluesky app fork with some witchin' additions 馃挮
at post-text-option 100 lines 2.6 kB view raw
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()) 10stateContext.displayName = 'ThreadMutesStateContext' 11const setStateContext = React.createContext<SetStateContext>( 12 (_: string) => false, 13) 14setStateContext.displayName = 'ThreadMutesSetStateContext' 15 16export function Provider({children}: React.PropsWithChildren<{}>) { 17 const [state, setState] = React.useState<StateContext>(() => new Map()) 18 19 const setThreadMute = React.useCallback( 20 (uri: string, value: boolean) => { 21 setState(prev => { 22 const next = new Map(prev) 23 next.set(uri, value) 24 return next 25 }) 26 }, 27 [setState], 28 ) 29 30 useMigrateMutes(setThreadMute) 31 32 return ( 33 <stateContext.Provider value={state}> 34 <setStateContext.Provider value={setThreadMute}> 35 {children} 36 </setStateContext.Provider> 37 </stateContext.Provider> 38 ) 39} 40 41export function useMutedThreads() { 42 return React.useContext(stateContext) 43} 44 45export function useIsThreadMuted(uri: string, defaultValue = false) { 46 const state = React.useContext(stateContext) 47 return state.get(uri) ?? defaultValue 48} 49 50export function useSetThreadMute() { 51 return React.useContext(setStateContext) 52} 53 54function useMigrateMutes(setThreadMute: SetStateContext) { 55 const agent = useAgent() 56 const {currentAccount} = useSession() 57 58 useEffect(() => { 59 if (currentAccount) { 60 if ( 61 !persisted 62 .get('mutedThreads') 63 .some(uri => uri.includes(currentAccount.did)) 64 ) { 65 return 66 } 67 68 let cancelled = false 69 70 const migrate = async () => { 71 while (!cancelled) { 72 const threads = persisted.get('mutedThreads') 73 74 // @ts-ignore findLast is polyfilled - esb 75 const root = threads.findLast(uri => uri.includes(currentAccount.did)) 76 77 if (!root) break 78 79 persisted.write( 80 'mutedThreads', 81 threads.filter(uri => uri !== root), 82 ) 83 84 setThreadMute(root, true) 85 86 await agent.api.app.bsky.graph 87 .muteThread({root}) 88 // not a big deal if this fails, since the post might have been deleted 89 .catch(console.error) 90 } 91 } 92 93 migrate() 94 95 return () => { 96 cancelled = true 97 } 98 } 99 }, [agent, currentAccount, setThreadMute]) 100}