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