Add closeAllDialogs control

This commit is contained in:
Eric Bailey
2024-01-18 15:45:37 -06:00
parent 6d3f19c695
commit 83c2b20c39
6 changed files with 91 additions and 16 deletions
+10 -7
View File
@@ -27,6 +27,7 @@ import {queryClient} from 'lib/react-query'
import {TestCtrls} from 'view/com/testing/TestCtrls' import {TestCtrls} from 'view/com/testing/TestCtrls'
import {Provider as ShellStateProvider} from 'state/shell' import {Provider as ShellStateProvider} from 'state/shell'
import {Provider as ModalStateProvider} from 'state/modals' import {Provider as ModalStateProvider} from 'state/modals'
import {Provider as DialogStateProvider} from 'state/dialogs'
import {Provider as LightboxStateProvider} from 'state/lightbox' import {Provider as LightboxStateProvider} from 'state/lightbox'
import {Provider as MutedThreadsProvider} from 'state/muted-threads' import {Provider as MutedThreadsProvider} from 'state/muted-threads'
import {Provider as InvitesStateProvider} from 'state/invites' import {Provider as InvitesStateProvider} from 'state/invites'
@@ -115,13 +116,15 @@ function App() {
<MutedThreadsProvider> <MutedThreadsProvider>
<InvitesStateProvider> <InvitesStateProvider>
<ModalStateProvider> <ModalStateProvider>
<LightboxStateProvider> <DialogStateProvider>
<I18nProvider> <LightboxStateProvider>
<PortalProvider> <I18nProvider>
<InnerApp /> <PortalProvider>
</PortalProvider> <InnerApp />
</I18nProvider> </PortalProvider>
</LightboxStateProvider> </I18nProvider>
</LightboxStateProvider>
</DialogStateProvider>
</ModalStateProvider> </ModalStateProvider>
</InvitesStateProvider> </InvitesStateProvider>
</MutedThreadsProvider> </MutedThreadsProvider>
+10 -7
View File
@@ -17,6 +17,7 @@ import {ThemeProvider} from 'lib/ThemeContext'
import {queryClient} from 'lib/react-query' import {queryClient} from 'lib/react-query'
import {Provider as ShellStateProvider} from 'state/shell' import {Provider as ShellStateProvider} from 'state/shell'
import {Provider as ModalStateProvider} from 'state/modals' import {Provider as ModalStateProvider} from 'state/modals'
import {Provider as DialogStateProvider} from 'state/dialogs'
import {Provider as LightboxStateProvider} from 'state/lightbox' import {Provider as LightboxStateProvider} from 'state/lightbox'
import {Provider as MutedThreadsProvider} from 'state/muted-threads' import {Provider as MutedThreadsProvider} from 'state/muted-threads'
import {Provider as InvitesStateProvider} from 'state/invites' import {Provider as InvitesStateProvider} from 'state/invites'
@@ -93,13 +94,15 @@ function App() {
<MutedThreadsProvider> <MutedThreadsProvider>
<InvitesStateProvider> <InvitesStateProvider>
<ModalStateProvider> <ModalStateProvider>
<LightboxStateProvider> <DialogStateProvider>
<I18nProvider> <LightboxStateProvider>
<PortalProvider> <I18nProvider>
<InnerApp /> <PortalProvider>
</PortalProvider> <InnerApp />
</I18nProvider> </PortalProvider>
</LightboxStateProvider> </I18nProvider>
</LightboxStateProvider>
</DialogStateProvider>
</ModalStateProvider> </ModalStateProvider>
</InvitesStateProvider> </InvitesStateProvider>
</MutedThreadsProvider> </MutedThreadsProvider>
+12
View File
@@ -1,4 +1,6 @@
import React from 'react' import React from 'react'
import {useDialogStateContext} from '#/state/dialogs'
import {DialogContextProps, DialogControlProps} from '#/components/Dialog/types' import {DialogContextProps, DialogControlProps} from '#/components/Dialog/types'
export const Context = React.createContext<DialogContextProps>({ export const Context = React.createContext<DialogContextProps>({
@@ -10,10 +12,20 @@ export function useDialogContext() {
} }
export function useDialogControl() { export function useDialogControl() {
const id = React.useId()
const control = React.useRef<DialogControlProps>({ const control = React.useRef<DialogControlProps>({
open: () => {}, open: () => {},
close: () => {}, 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 { return {
ref: control, ref: control,
+44
View File
@@ -0,0 +1,44 @@
import React from 'react'
import {DialogControlProps} from '#/components/Dialog'
const DialogContext = React.createContext<{
activeDialogs: React.MutableRefObject<
Map<string, React.MutableRefObject<DialogControlProps>>
>
}>({
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<string, React.MutableRefObject<DialogControlProps>>
>(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 (
<DialogContext.Provider value={context}>
<DialogControlContext.Provider value={controls}>
{children}
</DialogControlContext.Provider>
</DialogContext.Provider>
)
}
+15 -1
View File
@@ -6,10 +6,12 @@ import {Button} from '#/components/Button'
import {H3, P} from '#/components/Typography' import {H3, P} from '#/components/Typography'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import * as Prompt from '#/components/Prompt' import * as Prompt from '#/components/Prompt'
import {useDialogStateControlContext} from '#/state/dialogs'
export function Dialogs() { export function Dialogs() {
const control = Dialog.useDialogControl() const control = Dialog.useDialogControl()
const prompt = Prompt.usePromptControl() const prompt = Prompt.usePromptControl()
const {closeAllDialogs} = useDialogStateControlContext()
return ( return (
<View style={[a.gap_md]}> <View style={[a.gap_md]}>
@@ -17,7 +19,10 @@ export function Dialogs() {
variant="outline" variant="outline"
color="secondary" color="secondary"
size="small" size="small"
onPress={() => control.open()} onPress={() => {
control.open()
prompt.open()
}}
label="Open basic dialog"> label="Open basic dialog">
Open basic dialog Open basic dialog
</Button> </Button>
@@ -57,6 +62,15 @@ export function Dialogs() {
A scrollable dialog with an input within it. A scrollable dialog with an input within it.
</P> </P>
<Dialog.Input value="" onChangeText={() => {}} label="Type here" /> <Dialog.Input value="" onChangeText={() => {}} label="Type here" />
<Button
variant="outline"
color="secondary"
size="small"
onPress={closeAllDialogs}
label="Close all dialogs">
Close all dialogs
</Button>
<View style={{height: 1000}} /> <View style={{height: 1000}} />
<View style={[a.flex_row, a.justify_end]}> <View style={[a.flex_row, a.justify_end]}>
<Button <Button
-1
View File
@@ -70,7 +70,6 @@ export function Forms() {
<View style={[a.w_full]}> <View style={[a.w_full]}>
<Label>Date</Label> <Label>Date</Label>
<DateField <DateField
isInvalid
testID="date" testID="date"
value={date} value={date}
onChangeDate={date => { onChangeDate={date => {