diff --git a/src/state/lightbox.tsx b/src/state/lightbox.tsx index 67a450991d..3e01d7ef7b 100644 --- a/src/state/lightbox.tsx +++ b/src/state/lightbox.tsx @@ -31,7 +31,15 @@ export function Provider({children}: React.PropsWithChildren<{}>) { const openLightbox = useNonReactiveCallback( (lightbox: Omit) => { - setActiveLightbox({...lightbox, id: nanoid()}) + setActiveLightbox(prevLightbox => { + if (prevLightbox) { + // Ignore duplicate open requests. If it's already open, + // the user has to explicitly close the previous one first. + return prevLightbox + } else { + return {...lightbox, id: nanoid()} + } + }) }, ) diff --git a/src/view/com/lightbox/ImageViewing/index.tsx b/src/view/com/lightbox/ImageViewing/index.tsx index e7d158d034..ce59b4b9d3 100644 --- a/src/view/com/lightbox/ImageViewing/index.tsx +++ b/src/view/com/lightbox/ImageViewing/index.tsx @@ -111,14 +111,14 @@ export default function ImageViewRoot({ ) // https://github.com/software-mansion/react-native-reanimated/issues/6677 - requestAnimationFrame(() => { + rAF_FIXED(() => { openProgress.set(() => canAnimate ? withClampedSpring(1, SLOW_SPRING) : 1, ) }) return () => { // https://github.com/software-mansion/react-native-reanimated/issues/6677 - requestAnimationFrame(() => { + rAF_FIXED(() => { openProgress.set(() => canAnimate ? withClampedSpring(0, SLOW_SPRING) : 0, ) @@ -752,3 +752,32 @@ function withClampedSpring(value: any, config: WithSpringConfig) { 'worklet' return withSpring(value, {...config, overshootClamping: true}) } + +// We have to do this because we can't trust RN's rAF to fire in order. +// https://github.com/facebook/react-native/issues/48005 +let isFrameScheduled = false +let pendingFrameCallbacks: Array<() => void> = [] +function rAF_FIXED(callback: () => void) { + pendingFrameCallbacks.push(callback) + if (!isFrameScheduled) { + isFrameScheduled = true + requestAnimationFrame(() => { + const callbacks = pendingFrameCallbacks.slice() + isFrameScheduled = false + pendingFrameCallbacks = [] + let hasError = false + let error + for (let i = 0; i < callbacks.length; i++) { + try { + callbacks[i]() + } catch (e) { + hasError = true + error = e + } + } + if (hasError) { + throw error + } + }) + } +}