Small logic cleanups (#3449)

* Small logic cleanups

* Small logic cleanups (#3451)

* remove a few things

* oops

* stop swallowing the error

* queue callbacks

* oops

* log error if caught

* no need to be nullable

* move isClosing=true up

* reset `isClosing` and `closeCallbacks` on close completion and open

* run queued callbacks on `open` if there are any pending

* rm unnecessary ref and check

* ensure order of calls is always correct

* call `snapToIndex()` on open

* add tester to storybook

---------

Co-authored-by: Hailey <me@haileyok.com>
This commit is contained in:
Eric Bailey 2024-04-09 17:08:02 -05:00 committed by GitHub
parent a49a5a351d
commit c96bc92042
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 213 additions and 54 deletions

View file

@ -33,40 +33,41 @@ export function Outer({
const t = useTheme()
const {gtMobile} = useBreakpoints()
const [isOpen, setIsOpen] = React.useState(false)
const [isVisible, setIsVisible] = React.useState(true)
const {setDialogIsOpen} = useDialogStateControlContext()
const open = React.useCallback(() => {
setIsOpen(true)
setDialogIsOpen(control.id, true)
setIsOpen(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<DialogControlProps['close']>(
cb => {
setDialogIsOpen(control.id, false)
setIsOpen(false)
try {
if (cb && typeof cb === 'function') {
cb()
// This timeout ensures that the callback runs at the same time as it would on native. I.e.
// console.log('Step 1') -> close(() => console.log('Step 3')) -> console.log('Step 2')
// This should always output 'Step 1', 'Step 2', 'Step 3', but without the timeout it would output
// 'Step 1', 'Step 3', 'Step 2'.
setTimeout(cb)
}
} catch (e: any) {
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 +104,7 @@ export function Outer({
<TouchableWithoutFeedback
accessibilityHint={undefined}
accessibilityLabel={_(msg`Close active dialog`)}
onPress={onCloseInner}>
onPress={handleBackgroundPress}>
<View
style={[
web(a.fixed),
@ -113,17 +114,15 @@ export function Outer({
gtMobile ? a.p_lg : a.p_md,
{overflowY: 'auto'},
]}>
{isVisible && (
<Animated.View
entering={FadeIn.duration(150)}
// exiting={FadeOut.duration(150)}
style={[
web(a.fixed),
a.inset_0,
{opacity: 0.8, backgroundColor: t.palette.black},
]}
/>
)}
<Animated.View
entering={FadeIn.duration(150)}
// exiting={FadeOut.duration(150)}
style={[
web(a.fixed),
a.inset_0,
{opacity: 0.8, backgroundColor: t.palette.black},
]}
/>
<View
style={[
@ -135,7 +134,7 @@ export function Outer({
minHeight: web('calc(90vh - 36px)') || undefined,
},
]}>
{isVisible ? children : null}
{children}
</View>
</View>
</TouchableWithoutFeedback>