defer image rendering to after lightbox has finished opening

This commit is contained in:
Samuel Newman
2026-01-26 14:10:04 +02:00
parent dd1ef4625c
commit 4b34a9eb06
+33 -19
View File
@@ -98,6 +98,8 @@ export default function ImageViewRoot({
'portrait', 'portrait',
) )
const openProgress = useSharedValue(0) const openProgress = useSharedValue(0)
// mirrors `openProgress`, but just a bool, used for deferring rendering other images
const [isCompletelyOpen, setIsCompletelyOpen] = useState(false)
if (!activeLightbox && nextLightbox) { if (!activeLightbox && nextLightbox) {
setActiveLightbox(nextLightbox) setActiveLightbox(nextLightbox)
@@ -135,16 +137,23 @@ export default function ImageViewRoot({
}, },
) )
const onOpenProgressChange = useCallback((isOpen: boolean) => {
setIsCompletelyOpen(isOpen)
if (isOpen) {
ScreenOrientation.unlockAsync()
} else {
// default is PORTRAIT_UP - set via config plugin in app.config.js -sfn
ScreenOrientation.lockAsync(PORTRAIT_UP)
}
}, [])
// Delay the unlock until after we've finished the scale up animation. // Delay the unlock until after we've finished the scale up animation.
// It's complicated to do the same for locking it back so we don't attempt that. // It's complicated to do the same for locking it back so we don't attempt that.
useAnimatedReaction( useAnimatedReaction(
() => openProgress.get() === 1, () => openProgress.get() === 1,
(isOpen, wasOpen) => { (isOpen, wasOpen) => {
if (isOpen && !wasOpen) { if (isOpen !== wasOpen) {
runOnJS(ScreenOrientation.unlockAsync)() runOnJS(onOpenProgressChange)(isOpen)
} else if (!isOpen && wasOpen) {
// default is PORTRAIT_UP - set via config plugin in app.config.js -sfn
runOnJS(ScreenOrientation.lockAsync)(PORTRAIT_UP)
} }
}, },
) )
@@ -183,6 +192,7 @@ export default function ImageViewRoot({
onFlyAway={onFlyAway} onFlyAway={onFlyAway}
safeAreaRef={ref} safeAreaRef={ref}
openProgress={openProgress} openProgress={openProgress}
isCompletelyOpen={isCompletelyOpen}
/> />
)} )}
</Animated.View> </Animated.View>
@@ -199,6 +209,7 @@ function ImageView({
onFlyAway, onFlyAway,
safeAreaRef, safeAreaRef,
openProgress, openProgress,
isCompletelyOpen,
}: { }: {
lightbox: Lightbox lightbox: Lightbox
orientation: 'portrait' | 'landscape' orientation: 'portrait' | 'landscape'
@@ -208,6 +219,7 @@ function ImageView({
onFlyAway: () => void onFlyAway: () => void
safeAreaRef: AnimatedRef<View> safeAreaRef: AnimatedRef<View>
openProgress: SharedValue<number> openProgress: SharedValue<number>
isCompletelyOpen: boolean
}) { }) {
const {images, index: initialImageIndex} = lightbox const {images, index: initialImageIndex} = lightbox
const isAnimated = useMemo(() => canAnimate(lightbox), [lightbox]) const isAnimated = useMemo(() => canAnimate(lightbox), [lightbox])
@@ -350,20 +362,22 @@ function ImageView({
style={styles.pager}> style={styles.pager}>
{images.map((imageSrc, i) => ( {images.map((imageSrc, i) => (
<View key={imageSrc.uri}> <View key={imageSrc.uri}>
<LightboxImage {(isCompletelyOpen || i === imageIndex) && (
onTap={onTap} <LightboxImage
onZoom={onZoom} onTap={onTap}
imageSrc={imageSrc} onZoom={onZoom}
onRequestClose={onRequestClose} imageSrc={imageSrc}
isScrollViewBeingDragged={isDragging} onRequestClose={onRequestClose}
showControls={showControls} isScrollViewBeingDragged={isDragging}
safeAreaRef={safeAreaRef} showControls={showControls}
isScaled={isScaled} safeAreaRef={safeAreaRef}
isFlyingAway={isFlyingAway} isScaled={isScaled}
isActive={i === imageIndex} isFlyingAway={isFlyingAway}
dismissSwipeTranslateY={dismissSwipeTranslateY} isActive={i === imageIndex}
openProgress={openProgress} dismissSwipeTranslateY={dismissSwipeTranslateY}
/> openProgress={openProgress}
/>
)}
</View> </View>
))} ))}
</PagerView> </PagerView>