diff --git a/src/components/Dialog/context.ts b/src/components/Dialog/context.ts index df8bbb0810..859f8edd77 100644 --- a/src/components/Dialog/context.ts +++ b/src/components/Dialog/context.ts @@ -39,8 +39,7 @@ export function useDialogControl(): DialogOuterProps['control'] { control.current.open() }, close: cb => { - control.current.close() - cb?.() + control.current.close(cb) }, }), [id, control], diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index 07e101f85c..1249897b2b 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -107,8 +107,14 @@ export function Outer({ const close = React.useCallback(cb => { if (cb && typeof cb === 'function') { + if (closeCallback.current) { + logger.error( + `Dialog close was passed multiple callbacks, you shouldn't do that`, + ) + } closeCallback.current = cb } + // initiates a close animation, the actual "close" happens in `onCloseInner` sheet.current?.close() }, []) @@ -122,7 +128,10 @@ export function Outer({ ) const onCloseInner = React.useCallback(() => { + setDialogIsOpen(control.id, false) + setOpenIndex(-1) try { + logger.debug(`Dialog closeCallback`, {controlId: control.id}) closeCallback.current?.() } catch (e: any) { logger.error(`Dialog closeCallback failed`, { @@ -131,9 +140,7 @@ export function Outer({ } finally { closeCallback.current = undefined } - setDialogIsOpen(control.id, false) onClose?.() - setOpenIndex(-1) }, [control.id, onClose, setDialogIsOpen]) const context = React.useMemo(() => ({close}), [close]) diff --git a/src/components/Dialog/index.web.tsx b/src/components/Dialog/index.web.tsx index 8383979b3c..8187c16f1a 100644 --- a/src/components/Dialog/index.web.tsx +++ b/src/components/Dialog/index.web.tsx @@ -41,17 +41,13 @@ export function Outer({ setDialogIsOpen(control.id, true) }, [setIsOpen, setDialogIsOpen, control.id]) - const onCloseInner = React.useCallback(async () => { - setIsVisible(false) - await new Promise(resolve => setTimeout(resolve, 150)) - setIsOpen(false) - setIsVisible(true) - setDialogIsOpen(control.id, false) - onClose?.() - }, [control.id, onClose, setDialogIsOpen]) - const close = React.useCallback( cb => { + setDialogIsOpen(control.id, false) + setIsVisible(false) + setIsOpen(false) + setIsVisible(true) + try { if (cb && typeof cb === 'function') { cb() @@ -60,13 +56,17 @@ export function Outer({ logger.error(`Dialog closeCallback failed`, { message: e.message, }) - } finally { - onCloseInner() } + + onClose?.() }, - [onCloseInner], + [control.id, onClose, setDialogIsOpen], ) + const handleBackgroundPress = React.useCallback(async () => { + close() + }, [close]) + useImperativeHandle( control.ref, () => ({ @@ -103,7 +103,7 @@ export function Outer({ + onPress={handleBackgroundPress}> void color?: ButtonColor /** @@ -165,6 +172,13 @@ export function Basic({ description: string cancelButtonCta?: string confirmButtonCta?: string + /** + * Callback to run when the Confirm button is pressed. The method is called + * _after_ the dialog closes. + * + * Note: The dialog will close automatically when the action is pressed, you + * should NOT close the dialog as a side effect of this method. + */ onConfirm: () => void confirmButtonColor?: ButtonColor }>) { diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index a3ee97a2ed..24f61a2ee1 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -507,9 +507,7 @@ export const ComposePost = observer(function ComposePost({ control={discardPromptControl} title={_(msg`Discard draft?`)} description={_(msg`Are you sure you'd like to discard this draft?`)} - onConfirm={() => { - discardPromptControl.close(onClose) - }} + onConfirm={onClose} confirmButtonCta={_(msg`Discard`)} confirmButtonColor="negative" />