From 83c2b20c393dec76f1b46645927817ab0acf2f6a Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Thu, 18 Jan 2024 15:45:37 -0600 Subject: [PATCH] Add closeAllDialogs control --- src/App.native.tsx | 17 ++++++---- src/App.web.tsx | 17 ++++++---- src/components/Dialog/context.ts | 12 +++++++ src/state/dialogs/index.tsx | 44 ++++++++++++++++++++++++++ src/view/screens/Storybook/Dialogs.tsx | 16 +++++++++- src/view/screens/Storybook/Forms.tsx | 1 - 6 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 src/state/dialogs/index.tsx diff --git a/src/App.native.tsx b/src/App.native.tsx index 1c3a3f3e74..41b78fc98a 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -27,6 +27,7 @@ import {queryClient} from 'lib/react-query' import {TestCtrls} from 'view/com/testing/TestCtrls' import {Provider as ShellStateProvider} from 'state/shell' import {Provider as ModalStateProvider} from 'state/modals' +import {Provider as DialogStateProvider} from 'state/dialogs' import {Provider as LightboxStateProvider} from 'state/lightbox' import {Provider as MutedThreadsProvider} from 'state/muted-threads' import {Provider as InvitesStateProvider} from 'state/invites' @@ -115,13 +116,15 @@ function App() { - - - - - - - + + + + + + + + + diff --git a/src/App.web.tsx b/src/App.web.tsx index 756d4954eb..1efa0567c7 100644 --- a/src/App.web.tsx +++ b/src/App.web.tsx @@ -17,6 +17,7 @@ import {ThemeProvider} from 'lib/ThemeContext' import {queryClient} from 'lib/react-query' import {Provider as ShellStateProvider} from 'state/shell' import {Provider as ModalStateProvider} from 'state/modals' +import {Provider as DialogStateProvider} from 'state/dialogs' import {Provider as LightboxStateProvider} from 'state/lightbox' import {Provider as MutedThreadsProvider} from 'state/muted-threads' import {Provider as InvitesStateProvider} from 'state/invites' @@ -93,13 +94,15 @@ function App() { - - - - - - - + + + + + + + + + diff --git a/src/components/Dialog/context.ts b/src/components/Dialog/context.ts index 76473aa243..b28b9f5a25 100644 --- a/src/components/Dialog/context.ts +++ b/src/components/Dialog/context.ts @@ -1,4 +1,6 @@ import React from 'react' + +import {useDialogStateContext} from '#/state/dialogs' import {DialogContextProps, DialogControlProps} from '#/components/Dialog/types' export const Context = React.createContext({ @@ -10,10 +12,20 @@ export function useDialogContext() { } export function useDialogControl() { + const id = React.useId() const control = React.useRef({ open: () => {}, close: () => {}, }) + const {activeDialogs} = useDialogStateContext() + + React.useEffect(() => { + activeDialogs.current.set(id, control) + return () => { + // eslint-disable-next-line react-hooks/exhaustive-deps + activeDialogs.current.delete(id) + } + }, [id, activeDialogs]) return { ref: control, diff --git a/src/state/dialogs/index.tsx b/src/state/dialogs/index.tsx new file mode 100644 index 0000000000..4cafaa0861 --- /dev/null +++ b/src/state/dialogs/index.tsx @@ -0,0 +1,44 @@ +import React from 'react' +import {DialogControlProps} from '#/components/Dialog' + +const DialogContext = React.createContext<{ + activeDialogs: React.MutableRefObject< + Map> + > +}>({ + activeDialogs: { + current: new Map(), + }, +}) + +const DialogControlContext = React.createContext<{ + closeAllDialogs(): void +}>({ + closeAllDialogs: () => {}, +}) + +export function useDialogStateContext() { + return React.useContext(DialogContext) +} + +export function useDialogStateControlContext() { + return React.useContext(DialogControlContext) +} + +export function Provider({children}: React.PropsWithChildren<{}>) { + const activeDialogs = React.useRef< + Map> + >(new Map()) + const closeAllDialogs = React.useCallback(() => { + activeDialogs.current.forEach(dialog => dialog.current.close()) + }, []) + const context = React.useMemo(() => ({activeDialogs}), []) + const controls = React.useMemo(() => ({closeAllDialogs}), [closeAllDialogs]) + return ( + + + {children} + + + ) +} diff --git a/src/view/screens/Storybook/Dialogs.tsx b/src/view/screens/Storybook/Dialogs.tsx index d4dcc91938..db568c6bd5 100644 --- a/src/view/screens/Storybook/Dialogs.tsx +++ b/src/view/screens/Storybook/Dialogs.tsx @@ -6,10 +6,12 @@ import {Button} from '#/components/Button' import {H3, P} from '#/components/Typography' import * as Dialog from '#/components/Dialog' import * as Prompt from '#/components/Prompt' +import {useDialogStateControlContext} from '#/state/dialogs' export function Dialogs() { const control = Dialog.useDialogControl() const prompt = Prompt.usePromptControl() + const {closeAllDialogs} = useDialogStateControlContext() return ( @@ -17,7 +19,10 @@ export function Dialogs() { variant="outline" color="secondary" size="small" - onPress={() => control.open()} + onPress={() => { + control.open() + prompt.open() + }} label="Open basic dialog"> Open basic dialog @@ -57,6 +62,15 @@ export function Dialogs() { A scrollable dialog with an input within it.

{}} label="Type here" /> + +