Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 129 lines 3.7 kB view raw
1import { 2 createContext, 3 useCallback, 4 useContext, 5 useMemo, 6 useRef, 7 useState, 8} from 'react' 9 10import {useHotkeysContext} from '#/lib/hotkeys' 11import {type DialogControlRefProps} from '#/components/Dialog' 12import {Provider as GlobalDialogsProvider} from '#/components/dialogs/Context' 13import {IS_WEB} from '#/env' 14import {BottomSheetNativeComponent} from '../../../modules/bottom-sheet' 15 16interface IDialogContext { 17 /** 18 * The currently active `useDialogControl` hooks. 19 */ 20 activeDialogs: React.MutableRefObject< 21 Map<string, React.MutableRefObject<DialogControlRefProps>> 22 > 23 /** 24 * The currently open dialogs, referenced by their IDs, generated from 25 * `useId`. 26 */ 27 openDialogs: React.MutableRefObject<Set<string>> 28} 29 30interface IDialogControlContext { 31 closeAllDialogs(): boolean 32 setDialogIsOpen(id: string, isOpen: boolean): void 33 setFullyExpandedCount: React.Dispatch<React.SetStateAction<number>> 34} 35 36const DialogContext = createContext<IDialogContext>({} as IDialogContext) 37DialogContext.displayName = 'DialogContext' 38 39const DialogControlContext = createContext<IDialogControlContext>( 40 {} as IDialogControlContext, 41) 42DialogControlContext.displayName = 'DialogControlContext' 43 44/** 45 * The number of dialogs that are fully expanded. This is used to determine the background color of the status bar 46 * on iOS. 47 */ 48const DialogFullyExpandedCountContext = createContext<number>(0) 49DialogFullyExpandedCountContext.displayName = 'DialogFullyExpandedCountContext' 50 51export function useDialogStateContext() { 52 return useContext(DialogContext) 53} 54 55export function useDialogStateControlContext() { 56 return useContext(DialogControlContext) 57} 58 59/** The number of dialogs that are fully expanded */ 60export function useDialogFullyExpandedCountContext() { 61 return useContext(DialogFullyExpandedCountContext) 62} 63 64export function Provider({children}: React.PropsWithChildren<{}>) { 65 const [fullyExpandedCount, setFullyExpandedCount] = useState(0) 66 const {disableScope, enableScope} = useHotkeysContext() 67 68 const activeDialogs = useRef< 69 Map<string, React.MutableRefObject<DialogControlRefProps>> 70 >(new Map()) 71 const openDialogs = useRef<Set<string>>(new Set()) 72 73 const closeAllDialogs = useCallback(() => { 74 if (IS_WEB) { 75 openDialogs.current.forEach(id => { 76 const dialog = activeDialogs.current.get(id) 77 if (dialog) dialog.current.close() 78 }) 79 80 return openDialogs.current.size > 0 81 } else { 82 void BottomSheetNativeComponent.dismissAll() 83 return false 84 } 85 }, []) 86 87 const setDialogIsOpen = useCallback( 88 (id: string, isOpen: boolean) => { 89 if (isOpen) { 90 openDialogs.current.add(id) 91 } else { 92 openDialogs.current.delete(id) 93 } 94 if (openDialogs.current.size > 0) { 95 disableScope('global') 96 } else { 97 enableScope('global') 98 } 99 }, 100 [disableScope, enableScope], 101 ) 102 103 const context = useMemo<IDialogContext>( 104 () => ({ 105 activeDialogs, 106 openDialogs, 107 }), 108 [activeDialogs, openDialogs], 109 ) 110 const controls = useMemo( 111 () => ({ 112 closeAllDialogs, 113 setDialogIsOpen, 114 setFullyExpandedCount, 115 }), 116 [closeAllDialogs, setDialogIsOpen, setFullyExpandedCount], 117 ) 118 119 return ( 120 <DialogContext.Provider value={context}> 121 <DialogControlContext.Provider value={controls}> 122 <DialogFullyExpandedCountContext.Provider value={fullyExpandedCount}> 123 <GlobalDialogsProvider>{children}</GlobalDialogsProvider> 124 </DialogFullyExpandedCountContext.Provider> 125 </DialogControlContext.Provider> 126 </DialogContext.Provider> 127 ) 128} 129Provider.displayName = 'DialogsProvider'