From d8c1354e967fa7b9c51198c3ab72c70f0aec4752 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Sat, 2 Nov 2024 02:52:35 +0000 Subject: [PATCH] Make flying away nice --- src/view/com/lightbox/ImageViewing/index.tsx | 27 +++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/view/com/lightbox/ImageViewing/index.tsx b/src/view/com/lightbox/ImageViewing/index.tsx index 762a3604be..fb0aff8e18 100644 --- a/src/view/com/lightbox/ImageViewing/index.tsx +++ b/src/view/com/lightbox/ImageViewing/index.tsx @@ -19,6 +19,7 @@ import { import {Gesture} from 'react-native-gesture-handler' import PagerView from 'react-native-pager-view' import { + cancelAnimation, interpolate, SharedValue, useAnimatedReaction, @@ -52,12 +53,14 @@ const SCREEN_HEIGHT = Dimensions.get('window').height function ImageViewing({ lightbox, openProgress, + onFlyAway, onRequestClose, onPressSave, onPressShare, }: { lightbox: Lightbox openProgress: SharedValue + onFlyAway: () => void onRequestClose: () => void onPressSave: (uri: string) => void onPressShare: (uri: string) => void @@ -95,7 +98,7 @@ function ImageViewing({ }) const activeImageStyle = useAnimatedStyle(() => { - if (openProgress.value === 1) { + if (openProgress.value === 1 || dismissSwipeTranslateY.value !== 0) { return { transform: [{translateY: dismissSwipeTranslateY.value}], } @@ -127,8 +130,11 @@ function ImageViewing({ .onEnd(e => { 'worklet' if (Math.abs(e.velocityY) > 1000) { - dismissSwipeTranslateY.value = withDecay({velocity: e.velocityY}) - runOnJS(onRequestClose)() + dismissSwipeTranslateY.value = withDecay({ + velocity: e.velocityY, + velocityFactor: 2, + deceleration: 1, // Danger! This relies on the reaction below stopping it. + }) } else { dismissSwipeTranslateY.value = withSpring(0, { stiffness: 700, @@ -136,6 +142,16 @@ function ImageViewing({ }) } }) + useAnimatedReaction( + () => Math.abs(dismissSwipeTranslateY.value) > SCREEN_HEIGHT, + (isOut, wasOut) => { + if (isOut && !wasOut) { + // Stop the animation from blocking the screen forever. + cancelAnimation(dismissSwipeTranslateY) + onFlyAway() + } + }, + ) const onTap = useCallback(() => { setShowControls(show => !show) @@ -428,6 +444,11 @@ function ImageViewingRoot({ lightbox={activeLightbox} openProgress={openProgress} onRequestClose={onRequestClose} + onFlyAway={() => { + 'worklet' + openProgress.value = 0 + runOnJS(onRequestClose)() + }} onPressSave={onPressSave} onPressShare={onPressShare} />