change .value = to .set()
This commit is contained in:
@@ -21,9 +21,8 @@ export function Loader(props: Props) {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
rotation.value = withRepeat(
|
rotation.set(
|
||||||
withTiming(360, {duration: 500, easing: Easing.linear}),
|
withRepeat(withTiming(360, {duration: 500, easing: Easing.linear}), -1),
|
||||||
-1,
|
|
||||||
)
|
)
|
||||||
}, [rotation])
|
}, [rotation])
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {Pressable, useWindowDimensions, View} from 'react-native'
|
|||||||
import Animated, {
|
import Animated, {
|
||||||
Easing,
|
Easing,
|
||||||
runOnJS,
|
runOnJS,
|
||||||
|
runOnUI,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
withTiming,
|
withTiming,
|
||||||
@@ -55,13 +56,15 @@ export const ProgressGuideToast = React.forwardRef<
|
|||||||
|
|
||||||
// animate the opacity then set isOpen to false when done
|
// animate the opacity then set isOpen to false when done
|
||||||
const setIsntOpen = () => setIsOpen(false)
|
const setIsntOpen = () => setIsOpen(false)
|
||||||
opacity.value = withTiming(
|
opacity.set(
|
||||||
0,
|
withTiming(
|
||||||
{
|
0,
|
||||||
duration: 400,
|
{
|
||||||
easing: Easing.out(Easing.cubic),
|
duration: 400,
|
||||||
},
|
easing: Easing.out(Easing.cubic),
|
||||||
() => runOnJS(setIsntOpen)(),
|
},
|
||||||
|
() => runOnJS(setIsntOpen)(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}, [setIsOpen, opacity])
|
}, [setIsOpen, opacity])
|
||||||
|
|
||||||
@@ -71,20 +74,28 @@ export const ProgressGuideToast = React.forwardRef<
|
|||||||
|
|
||||||
// animate the vertical translation, the opacity, and the checkmark
|
// animate the vertical translation, the opacity, and the checkmark
|
||||||
const playCheckmark = () => animatedCheckRef.current?.play()
|
const playCheckmark = () => animatedCheckRef.current?.play()
|
||||||
opacity.value = 0
|
|
||||||
opacity.value = withTiming(
|
runOnUI(() => {
|
||||||
1,
|
'worklet'
|
||||||
{
|
opacity.set(0)
|
||||||
duration: 100,
|
opacity.set(
|
||||||
easing: Easing.out(Easing.cubic),
|
withTiming(
|
||||||
},
|
1,
|
||||||
() => runOnJS(playCheckmark)(),
|
{
|
||||||
)
|
duration: 100,
|
||||||
translateY.value = 0
|
easing: Easing.out(Easing.cubic),
|
||||||
translateY.value = withTiming(insets.top + 10, {
|
},
|
||||||
duration: 500,
|
() => runOnJS(playCheckmark)(),
|
||||||
easing: Easing.out(Easing.cubic),
|
),
|
||||||
})
|
)
|
||||||
|
translateY.set(0)
|
||||||
|
translateY.set(
|
||||||
|
withTiming(insets.top + 10, {
|
||||||
|
duration: 500,
|
||||||
|
easing: Easing.out(Easing.cubic),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})()
|
||||||
|
|
||||||
// start the countdown timer to autoclose
|
// start the countdown timer to autoclose
|
||||||
timeoutRef.current = setTimeout(close, visibleDuration || 5e3)
|
timeoutRef.current = setTimeout(close, visibleDuration || 5e3)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
Easing,
|
Easing,
|
||||||
|
runOnUI,
|
||||||
useAnimatedProps,
|
useAnimatedProps,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
withDelay,
|
withDelay,
|
||||||
@@ -40,14 +41,19 @@ export const AnimatedCheck = React.forwardRef<
|
|||||||
|
|
||||||
const play = React.useCallback(
|
const play = React.useCallback(
|
||||||
(cb?: () => void) => {
|
(cb?: () => void) => {
|
||||||
circleAnim.value = 0
|
runOnUI(() => {
|
||||||
checkAnim.value = 0
|
'worklet'
|
||||||
|
circleAnim.set(0)
|
||||||
|
checkAnim.set(0)
|
||||||
|
|
||||||
circleAnim.value = withTiming(1, {duration: 500, easing: Easing.linear})
|
circleAnim.set(withTiming(1, {duration: 500, easing: Easing.linear}))
|
||||||
checkAnim.value = withDelay(
|
checkAnim.set(
|
||||||
500,
|
withDelay(
|
||||||
withTiming(1, {duration: 300, easing: Easing.linear}, cb),
|
500,
|
||||||
)
|
withTiming(1, {duration: 300, easing: Easing.linear}, cb),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})()
|
||||||
},
|
},
|
||||||
[circleAnim, checkAnim],
|
[circleAnim, checkAnim],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export function ActionsWrapper({
|
|||||||
const shrink = React.useCallback(() => {
|
const shrink = React.useCallback(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
cancelAnimation(scale)
|
cancelAnimation(scale)
|
||||||
scale.value = withTiming(1, {duration: 200})
|
scale.set(withTiming(1, {duration: 200}))
|
||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
const doubleTapGesture = Gesture.Tap()
|
const doubleTapGesture = Gesture.Tap()
|
||||||
@@ -58,11 +58,13 @@ export function ActionsWrapper({
|
|||||||
const pressAndHoldGesture = Gesture.LongPress()
|
const pressAndHoldGesture = Gesture.LongPress()
|
||||||
.onStart(() => {
|
.onStart(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
scale.value = withTiming(1.05, {duration: 200}, finished => {
|
scale.set(
|
||||||
if (!finished) return
|
withTiming(1.05, {duration: 200}, finished => {
|
||||||
runOnJS(open)()
|
if (!finished) return
|
||||||
shrink()
|
runOnJS(open)()
|
||||||
})
|
shrink()
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.onTouchesUp(shrink)
|
.onTouchesUp(shrink)
|
||||||
.onTouchesMove(shrink)
|
.onTouchesMove(shrink)
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ export function ChatEmptyPill() {
|
|||||||
|
|
||||||
const onPressIn = React.useCallback(() => {
|
const onPressIn = React.useCallback(() => {
|
||||||
if (isWeb) return
|
if (isWeb) return
|
||||||
scale.value = withTiming(1.075, {duration: 100})
|
scale.set(withTiming(1.075, {duration: 100}))
|
||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
const onPressOut = React.useCallback(() => {
|
const onPressOut = React.useCallback(() => {
|
||||||
if (isWeb) return
|
if (isWeb) return
|
||||||
scale.value = withTiming(1, {duration: 100})
|
scale.set(withTiming(1, {duration: 100}))
|
||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
const onPress = React.useCallback(() => {
|
const onPress = React.useCallback(() => {
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ export function NewMessagesPill({
|
|||||||
|
|
||||||
const onPressIn = React.useCallback(() => {
|
const onPressIn = React.useCallback(() => {
|
||||||
if (isWeb) return
|
if (isWeb) return
|
||||||
scale.value = withTiming(1.075, {duration: 100})
|
scale.set(withTiming(1.075, {duration: 100}))
|
||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
const onPressOut = React.useCallback(() => {
|
const onPressOut = React.useCallback(() => {
|
||||||
if (isWeb) return
|
if (isWeb) return
|
||||||
scale.value = withTiming(1, {duration: 100})
|
scale.set(withTiming(1, {duration: 100}))
|
||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
const onPress = React.useCallback(() => {
|
const onPress = React.useCallback(() => {
|
||||||
|
|||||||
@@ -75,9 +75,11 @@ export function GestureActionView({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
iconScale.value = withSequence(
|
iconScale.set(
|
||||||
withTiming(1.2, {duration: 175}),
|
withSequence(
|
||||||
withTiming(1, {duration: 100}),
|
withTiming(1.2, {duration: 175}),
|
||||||
|
withTiming(1, {duration: 100}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,11 +121,11 @@ export function GestureActionView({
|
|||||||
.activeOffsetY([-200, 200])
|
.activeOffsetY([-200, 200])
|
||||||
.onStart(() => {
|
.onStart(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
isActive.value = true
|
isActive.set(true)
|
||||||
})
|
})
|
||||||
.onChange(e => {
|
.onChange(e => {
|
||||||
'worklet'
|
'worklet'
|
||||||
transX.value = e.translationX
|
transX.set(e.translationX)
|
||||||
|
|
||||||
if (e.translationX < 0) {
|
if (e.translationX < 0) {
|
||||||
// Left side
|
// Left side
|
||||||
@@ -134,13 +136,13 @@ export function GestureActionView({
|
|||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
runOnJS(haptic)()
|
runOnJS(haptic)()
|
||||||
hitSecond.value = true
|
hitSecond.set(true)
|
||||||
} else if (
|
} else if (
|
||||||
hitSecond.value &&
|
hitSecond.value &&
|
||||||
e.translationX > -actions.leftSecond.threshold
|
e.translationX > -actions.leftSecond.threshold
|
||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
hitSecond.value = false
|
hitSecond.set(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,12 +153,12 @@ export function GestureActionView({
|
|||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
runOnJS(haptic)()
|
runOnJS(haptic)()
|
||||||
hitFirst.value = true
|
hitFirst.set(true)
|
||||||
} else if (
|
} else if (
|
||||||
hitFirst.value &&
|
hitFirst.value &&
|
||||||
e.translationX > -actions.leftFirst.threshold
|
e.translationX > -actions.leftFirst.threshold
|
||||||
) {
|
) {
|
||||||
hitFirst.value = false
|
hitFirst.set(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (e.translationX > 0) {
|
} else if (e.translationX > 0) {
|
||||||
@@ -168,13 +170,13 @@ export function GestureActionView({
|
|||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
runOnJS(haptic)()
|
runOnJS(haptic)()
|
||||||
hitSecond.value = true
|
hitSecond.set(true)
|
||||||
} else if (
|
} else if (
|
||||||
hitSecond.value &&
|
hitSecond.value &&
|
||||||
e.translationX < actions.rightSecond.threshold
|
e.translationX < actions.rightSecond.threshold
|
||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
hitSecond.value = false
|
hitSecond.set(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,12 +187,12 @@ export function GestureActionView({
|
|||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
runOnJS(haptic)()
|
runOnJS(haptic)()
|
||||||
hitFirst.value = true
|
hitFirst.set(true)
|
||||||
} else if (
|
} else if (
|
||||||
hitFirst.value &&
|
hitFirst.value &&
|
||||||
e.translationX < actions.rightFirst.threshold
|
e.translationX < actions.rightFirst.threshold
|
||||||
) {
|
) {
|
||||||
hitFirst.value = false
|
hitFirst.set(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,10 +212,10 @@ export function GestureActionView({
|
|||||||
runOnJS(actions.rightFirst.action)()
|
runOnJS(actions.rightFirst.action)()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
transX.value = withTiming(0, {duration: 200})
|
transX.set(withTiming(0, {duration: 200}))
|
||||||
hitFirst.value = false
|
hitFirst.set(false)
|
||||||
hitSecond.value = false
|
hitSecond.set(false)
|
||||||
isActive.value = false
|
isActive.set(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
const composedGesture = Gesture.Simultaneous(panGesture)
|
const composedGesture = Gesture.Simultaneous(panGesture)
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ export function MessageInput({
|
|||||||
const max = windowHeight - -keyboardHeight.value - topInset - 150
|
const max = windowHeight - -keyboardHeight.value - topInset - 150
|
||||||
const availableSpace = max - measurement.height
|
const availableSpace = max - measurement.height
|
||||||
|
|
||||||
maxHeight.value = max
|
maxHeight.set(max)
|
||||||
isInputScrollable.value = availableSpace < 30
|
isInputScrollable.set(availableSpace < 30)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[windowHeight, topInset],
|
[windowHeight, topInset],
|
||||||
|
|||||||
@@ -217,13 +217,13 @@ export function MessagesList({
|
|||||||
const onScroll = React.useCallback(
|
const onScroll = React.useCallback(
|
||||||
(e: ReanimatedScrollEvent) => {
|
(e: ReanimatedScrollEvent) => {
|
||||||
'worklet'
|
'worklet'
|
||||||
layoutHeight.value = e.layoutMeasurement.height
|
layoutHeight.value.set(e.layoutMeasurement.height)
|
||||||
const bottomOffset = e.contentOffset.y + e.layoutMeasurement.height
|
const bottomOffset = e.contentOffset.y + e.layoutMeasurement.height
|
||||||
|
|
||||||
// Most apps have a little bit of space the user can scroll past while still automatically scrolling ot the bottom
|
// Most apps have a little bit of space the user can scroll past while still automatically scrolling ot the bottom
|
||||||
// when a new message is added, hence the 100 pixel offset
|
// when a new message is added, hence the 100 pixel offset
|
||||||
isAtBottom.value = e.contentSize.height - 100 < bottomOffset
|
isAtBottom.set(e.contentSize.height - 100 < bottomOffset)
|
||||||
isAtTop.value = e.contentOffset.y <= 1
|
isAtTop.set(e.contentOffset.y <= 1)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
newMessagesPill.show &&
|
newMessagesPill.show &&
|
||||||
@@ -256,22 +256,22 @@ export function MessagesList({
|
|||||||
// Immediate updates - like opening the emoji picker - will have a duration of zero. In those cases, we should
|
// Immediate updates - like opening the emoji picker - will have a duration of zero. In those cases, we should
|
||||||
// just update the height here instead of having the `onMove` event do it (that event will not fire!)
|
// just update the height here instead of having the `onMove` event do it (that event will not fire!)
|
||||||
if (e.duration === 0) {
|
if (e.duration === 0) {
|
||||||
layoutScrollWithoutAnimation.value = true
|
layoutScrollWithoutAnimation.set(true)
|
||||||
keyboardHeight.value = e.height
|
keyboardHeight.set(e.height)
|
||||||
} else {
|
} else {
|
||||||
keyboardIsOpening.value = true
|
keyboardIsOpening.set(true)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onMove: e => {
|
onMove: e => {
|
||||||
'worklet'
|
'worklet'
|
||||||
keyboardHeight.value = e.height
|
keyboardHeight.set(e.height)
|
||||||
if (e.height > bottomOffset) {
|
if (e.height > bottomOffset) {
|
||||||
scrollTo(flatListRef, 0, 1e7, false)
|
scrollTo(flatListRef, 0, 1e7, false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onEnd: () => {
|
onEnd: () => {
|
||||||
'worklet'
|
'worklet'
|
||||||
keyboardIsOpening.value = false
|
keyboardIsOpening.set(false)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -363,13 +363,13 @@ export function MessagesList({
|
|||||||
// -- List layout changes (opening emoji keyboard, etc.)
|
// -- List layout changes (opening emoji keyboard, etc.)
|
||||||
const onListLayout = React.useCallback(
|
const onListLayout = React.useCallback(
|
||||||
(e: LayoutChangeEvent) => {
|
(e: LayoutChangeEvent) => {
|
||||||
layoutHeight.value = e.nativeEvent.layout.height
|
layoutHeight.set(e.nativeEvent.layout.height)
|
||||||
|
|
||||||
if (isWeb || !keyboardIsOpening.value) {
|
if (isWeb || !keyboardIsOpening.value) {
|
||||||
flatListRef.current?.scrollToEnd({
|
flatListRef.current?.scrollToEnd({
|
||||||
animated: !layoutScrollWithoutAnimation.value,
|
animated: !layoutScrollWithoutAnimation.value,
|
||||||
})
|
})
|
||||||
layoutScrollWithoutAnimation.value = false
|
layoutScrollWithoutAnimation.set(false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -44,13 +44,17 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
'worklet'
|
'worklet'
|
||||||
// Cancel any existing animation
|
// Cancel any existing animation
|
||||||
cancelAnimation(headerMode)
|
cancelAnimation(headerMode)
|
||||||
headerMode.value = withSpring(v ? 1 : 0, {
|
headerMode.set(
|
||||||
overshootClamping: true,
|
withSpring(v ? 1 : 0, {
|
||||||
})
|
overshootClamping: true,
|
||||||
|
}),
|
||||||
|
)
|
||||||
cancelAnimation(footerMode)
|
cancelAnimation(footerMode)
|
||||||
footerMode.value = withSpring(v ? 1 : 0, {
|
footerMode.set(
|
||||||
overshootClamping: true,
|
withSpring(v ? 1 : 0, {
|
||||||
})
|
overshootClamping: true,
|
||||||
|
}),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
[headerMode, footerMode],
|
[headerMode, footerMode],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1288,11 +1288,11 @@ function useScrollTracker({
|
|||||||
}) => {
|
}) => {
|
||||||
'worklet'
|
'worklet'
|
||||||
if (typeof newContentHeight === 'number')
|
if (typeof newContentHeight === 'number')
|
||||||
contentHeight.value = Math.floor(newContentHeight)
|
contentHeight.value.set(Math.floor(newContentHeight))
|
||||||
if (typeof newContentOffset === 'number')
|
if (typeof newContentOffset === 'number')
|
||||||
contentOffset.value = Math.floor(newContentOffset)
|
contentOffset.value.set(Math.floor(newContentOffset))
|
||||||
if (typeof newScrollViewHeight === 'number')
|
if (typeof newScrollViewHeight === 'number')
|
||||||
scrollViewHeight.value = Math.floor(newScrollViewHeight)
|
scrollViewHeight.set(Math.floor(newScrollViewHeight))
|
||||||
},
|
},
|
||||||
[contentHeight, contentOffset, scrollViewHeight],
|
[contentHeight, contentOffset, scrollViewHeight],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ function HomeHeaderLayoutDesktopAndTablet({
|
|||||||
{tabBarAnchor}
|
{tabBarAnchor}
|
||||||
<Animated.View
|
<Animated.View
|
||||||
onLayout={e => {
|
onLayout={e => {
|
||||||
headerHeight.value = e.nativeEvent.layout.height
|
headerHeight.set(e.nativeEvent.layout.height)
|
||||||
}}
|
}}
|
||||||
style={[
|
style={[
|
||||||
t.atoms.bg,
|
t.atoms.bg,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export function HomeHeaderLayoutMobile({
|
|||||||
<Animated.View
|
<Animated.View
|
||||||
style={[pal.view, pal.border, styles.tabBar, headerMinimalShellTransform]}
|
style={[pal.view, pal.border, styles.tabBar, headerMinimalShellTransform]}
|
||||||
onLayout={e => {
|
onLayout={e => {
|
||||||
headerHeight.value = e.nativeEvent.layout.height
|
headerHeight.set(e.nativeEvent.layout.height)
|
||||||
}}>
|
}}>
|
||||||
<View style={[pal.view, styles.topBar]}>
|
<View style={[pal.view, styles.topBar]}>
|
||||||
<View style={[pal.view, {width: 100}]}>
|
<View style={[pal.view, {width: 100}]}>
|
||||||
|
|||||||
@@ -147,10 +147,10 @@ const ImageItem = ({
|
|||||||
.onStart(e => {
|
.onStart(e => {
|
||||||
'worklet'
|
'worklet'
|
||||||
const screenSize = measureSafeArea()
|
const screenSize = measureSafeArea()
|
||||||
pinchOrigin.value = {
|
pinchOrigin.set({
|
||||||
x: e.focalX - screenSize.width / 2,
|
x: e.focalX - screenSize.width / 2,
|
||||||
y: e.focalY - screenSize.height / 2,
|
y: e.focalY - screenSize.height / 2,
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
.onChange(e => {
|
.onChange(e => {
|
||||||
'worklet'
|
'worklet'
|
||||||
@@ -171,7 +171,7 @@ const ImageItem = ({
|
|||||||
Math.max(minPinchScale, e.scale),
|
Math.max(minPinchScale, e.scale),
|
||||||
maxPinchScale,
|
maxPinchScale,
|
||||||
)
|
)
|
||||||
pinchScale.value = nextPinchScale
|
pinchScale.set(nextPinchScale)
|
||||||
|
|
||||||
// Zooming out close to the corner could push us out of bounds, which we don't want on Android.
|
// Zooming out close to the corner could push us out of bounds, which we don't want on Android.
|
||||||
// Calculate where we'll end up so we know how much to translate back to stay in bounds.
|
// Calculate where we'll end up so we know how much to translate back to stay in bounds.
|
||||||
@@ -181,10 +181,10 @@ const ImageItem = ({
|
|||||||
prependTransform(t, committedTransform.value)
|
prependTransform(t, committedTransform.value)
|
||||||
const [dx, dy] = getExtraTranslationToStayInBounds(t, screenSize)
|
const [dx, dy] = getExtraTranslationToStayInBounds(t, screenSize)
|
||||||
if (dx !== 0 || dy !== 0) {
|
if (dx !== 0 || dy !== 0) {
|
||||||
pinchTranslation.value = {
|
pinchTranslation.set({
|
||||||
x: pinchTranslation.value.x + dx,
|
x: pinchTranslation.value.x + dx,
|
||||||
y: pinchTranslation.value.y + dy,
|
y: pinchTranslation.value.y + dy,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.onEnd(() => {
|
.onEnd(() => {
|
||||||
@@ -199,12 +199,12 @@ const ImageItem = ({
|
|||||||
)
|
)
|
||||||
prependTransform(t, committedTransform.value)
|
prependTransform(t, committedTransform.value)
|
||||||
applyRounding(t)
|
applyRounding(t)
|
||||||
committedTransform.value = t
|
committedTransform.set(t)
|
||||||
|
|
||||||
// Reset just the pinch.
|
// Reset just the pinch.
|
||||||
pinchScale.value = 1
|
pinchScale.set(1)
|
||||||
pinchOrigin.value = {x: 0, y: 0}
|
pinchOrigin.set({x: 0, y: 0})
|
||||||
pinchTranslation.value = {x: 0, y: 0}
|
pinchTranslation.set({x: 0, y: 0})
|
||||||
})
|
})
|
||||||
|
|
||||||
const pan = Gesture.Pan()
|
const pan = Gesture.Pan()
|
||||||
@@ -233,7 +233,7 @@ const ImageItem = ({
|
|||||||
const [dx, dy] = getExtraTranslationToStayInBounds(t, screenSize)
|
const [dx, dy] = getExtraTranslationToStayInBounds(t, screenSize)
|
||||||
nextPanTranslation.x += dx
|
nextPanTranslation.x += dx
|
||||||
nextPanTranslation.y += dy
|
nextPanTranslation.y += dy
|
||||||
panTranslation.value = nextPanTranslation
|
panTranslation.set(nextPanTranslation)
|
||||||
})
|
})
|
||||||
.onEnd(() => {
|
.onEnd(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
@@ -242,10 +242,10 @@ const ImageItem = ({
|
|||||||
prependPan(t, panTranslation.value)
|
prependPan(t, panTranslation.value)
|
||||||
prependTransform(t, committedTransform.value)
|
prependTransform(t, committedTransform.value)
|
||||||
applyRounding(t)
|
applyRounding(t)
|
||||||
committedTransform.value = t
|
committedTransform.set(t)
|
||||||
|
|
||||||
// Reset just the pan.
|
// Reset just the pan.
|
||||||
panTranslation.value = {x: 0, y: 0}
|
panTranslation.set({x: 0, y: 0})
|
||||||
})
|
})
|
||||||
|
|
||||||
const singleTap = Gesture.Tap().onEnd(() => {
|
const singleTap = Gesture.Tap().onEnd(() => {
|
||||||
@@ -265,7 +265,7 @@ const ImageItem = ({
|
|||||||
if (committedScale !== 1) {
|
if (committedScale !== 1) {
|
||||||
// Go back to 1:1 using the identity vector.
|
// Go back to 1:1 using the identity vector.
|
||||||
let t = createTransform()
|
let t = createTransform()
|
||||||
committedTransform.value = withClampedSpring(t)
|
committedTransform.set(withClampedSpring(t))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ const ImageItem = ({
|
|||||||
)
|
)
|
||||||
const finalTransform = createTransform()
|
const finalTransform = createTransform()
|
||||||
prependPinch(finalTransform, scale, origin, {x: dx, y: dy})
|
prependPinch(finalTransform, scale, origin, {x: dx, y: dy})
|
||||||
committedTransform.value = withClampedSpring(finalTransform)
|
committedTransform.set(withClampedSpring(finalTransform))
|
||||||
})
|
})
|
||||||
|
|
||||||
const composedGesture = isScrollViewBeingDragged
|
const composedGesture = isScrollViewBeingDragged
|
||||||
|
|||||||
@@ -98,12 +98,12 @@ export default function ImageViewRoot({
|
|||||||
|
|
||||||
// https://github.com/software-mansion/react-native-reanimated/issues/6677
|
// https://github.com/software-mansion/react-native-reanimated/issues/6677
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
openProgress.value = canAnimate ? withClampedSpring(1, SLOW_SPRING) : 1
|
openProgress.set(canAnimate ? withClampedSpring(1, SLOW_SPRING) : 1)
|
||||||
})
|
})
|
||||||
return () => {
|
return () => {
|
||||||
// https://github.com/software-mansion/react-native-reanimated/issues/6677
|
// https://github.com/software-mansion/react-native-reanimated/issues/6677
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
openProgress.value = canAnimate ? withClampedSpring(0, SLOW_SPRING) : 0
|
openProgress.set(canAnimate ? withClampedSpring(0, SLOW_SPRING) : 0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [nextLightbox, openProgress])
|
}, [nextLightbox, openProgress])
|
||||||
@@ -119,7 +119,7 @@ export default function ImageViewRoot({
|
|||||||
|
|
||||||
const onFlyAway = React.useCallback(() => {
|
const onFlyAway = React.useCallback(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
openProgress.value = 0
|
openProgress.set(0)
|
||||||
runOnJS(onRequestClose)()
|
runOnJS(onRequestClose)()
|
||||||
}, [onRequestClose, openProgress])
|
}, [onRequestClose, openProgress])
|
||||||
|
|
||||||
@@ -426,7 +426,7 @@ function LightboxImage({
|
|||||||
if (openProgress.value !== 1 || isFlyingAway.value) {
|
if (openProgress.value !== 1 || isFlyingAway.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dismissSwipeTranslateY.value = e.translationY
|
dismissSwipeTranslateY.set(e.translationY)
|
||||||
})
|
})
|
||||||
.onEnd(e => {
|
.onEnd(e => {
|
||||||
'worklet'
|
'worklet'
|
||||||
@@ -434,22 +434,26 @@ function LightboxImage({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (Math.abs(e.velocityY) > 1000) {
|
if (Math.abs(e.velocityY) > 1000) {
|
||||||
isFlyingAway.value = true
|
isFlyingAway.set(true)
|
||||||
if (dismissSwipeTranslateY.value === 0) {
|
if (dismissSwipeTranslateY.value === 0) {
|
||||||
// HACK: If the initial value is 0, withDecay() animation doesn't start.
|
// HACK: If the initial value is 0, withDecay() animation doesn't start.
|
||||||
// This is a bug in Reanimated, but for now we'll work around it like this.
|
// This is a bug in Reanimated, but for now we'll work around it like this.
|
||||||
dismissSwipeTranslateY.value = 1
|
dismissSwipeTranslateY.set(1)
|
||||||
}
|
}
|
||||||
dismissSwipeTranslateY.value = withDecay({
|
dismissSwipeTranslateY.set(
|
||||||
velocity: e.velocityY,
|
withDecay({
|
||||||
velocityFactor: Math.max(3000 / Math.abs(e.velocityY), 1), // Speed up if it's too slow.
|
velocity: e.velocityY,
|
||||||
deceleration: 1, // Danger! This relies on the reaction below stopping it.
|
velocityFactor: Math.max(3000 / Math.abs(e.velocityY), 1), // Speed up if it's too slow.
|
||||||
})
|
deceleration: 1, // Danger! This relies on the reaction below stopping it.
|
||||||
|
}),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
dismissSwipeTranslateY.value = withSpring(0, {
|
dismissSwipeTranslateY.set(
|
||||||
stiffness: 700,
|
withSpring(0, {
|
||||||
damping: 50,
|
stiffness: 700,
|
||||||
})
|
damping: 50,
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
|
|||||||
const currentScrollY = scrollY.value
|
const currentScrollY = scrollY.value
|
||||||
const forcedScrollY = Math.min(currentScrollY, headerOnlyHeight)
|
const forcedScrollY = Math.min(currentScrollY, headerOnlyHeight)
|
||||||
if (lastForcedScrollY.value !== forcedScrollY) {
|
if (lastForcedScrollY.value !== forcedScrollY) {
|
||||||
lastForcedScrollY.value = forcedScrollY
|
lastForcedScrollY.set(forcedScrollY)
|
||||||
const refs = scrollRefs.value
|
const refs = scrollRefs.value
|
||||||
for (let i = 0; i < refs.length; i++) {
|
for (let i = 0; i < refs.length; i++) {
|
||||||
const scollRef = refs[i]
|
const scollRef = refs[i]
|
||||||
@@ -167,7 +167,7 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
|
|||||||
const isPossiblyInvalid =
|
const isPossiblyInvalid =
|
||||||
headerHeight > 0 && Math.round(nextScrollY * 2) / 2 === -headerHeight
|
headerHeight > 0 && Math.round(nextScrollY * 2) / 2 === -headerHeight
|
||||||
if (!isPossiblyInvalid) {
|
if (!isPossiblyInvalid) {
|
||||||
scrollY.value = nextScrollY
|
scrollY.set(nextScrollY)
|
||||||
runOnJS(queueThrottledOnScroll)()
|
runOnJS(queueThrottledOnScroll)()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ function ListImpl<ItemT>(
|
|||||||
|
|
||||||
const didScrollDown = e.contentOffset.y > SCROLLED_DOWN_LIMIT
|
const didScrollDown = e.contentOffset.y > SCROLLED_DOWN_LIMIT
|
||||||
if (isScrolledDown.value !== didScrollDown) {
|
if (isScrolledDown.value !== didScrollDown) {
|
||||||
isScrolledDown.value = didScrollDown
|
isScrolledDown.set(didScrollDown)
|
||||||
if (onScrolledDownChange != null) {
|
if (onScrolledDownChange != null) {
|
||||||
runOnJS(handleScrolledDownChange)(didScrollDown)
|
runOnJS(handleScrolledDownChange)(didScrollDown)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
|
|||||||
(v: boolean) => {
|
(v: boolean) => {
|
||||||
'worklet'
|
'worklet'
|
||||||
cancelAnimation(headerMode)
|
cancelAnimation(headerMode)
|
||||||
headerMode.value = v ? V1.value : V0.value
|
headerMode.set(v ? V1.value : V0.value)
|
||||||
},
|
},
|
||||||
[headerMode],
|
[headerMode],
|
||||||
)
|
)
|
||||||
@@ -52,9 +52,9 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isWeb) {
|
if (isWeb) {
|
||||||
return listenToForcedWindowScroll(() => {
|
return listenToForcedWindowScroll(() => {
|
||||||
startDragOffset.value = null
|
startDragOffset.set(null)
|
||||||
startMode.value = null
|
startMode.set(null)
|
||||||
didJustRestoreScroll.value = true
|
didJustRestoreScroll.set(true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -67,8 +67,8 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const didScrollDown = e.contentOffset.y > startDragOffset.value
|
const didScrollDown = e.contentOffset.y > startDragOffset.value
|
||||||
startDragOffset.value = null
|
startDragOffset.set(null)
|
||||||
startMode.value = null
|
startMode.set(null)
|
||||||
if (e.contentOffset.y < headerHeight.value) {
|
if (e.contentOffset.y < headerHeight.value) {
|
||||||
// If we're close to the top, show the shell.
|
// If we're close to the top, show the shell.
|
||||||
setMode(false)
|
setMode(false)
|
||||||
@@ -88,8 +88,8 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
|
|||||||
(e: NativeScrollEvent) => {
|
(e: NativeScrollEvent) => {
|
||||||
'worklet'
|
'worklet'
|
||||||
if (isNative) {
|
if (isNative) {
|
||||||
startDragOffset.value = e.contentOffset.y
|
startDragOffset.set(e.contentOffset.y)
|
||||||
startMode.value = headerMode.value
|
startMode.set(headerMode.value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[headerMode, startDragOffset, startMode],
|
[headerMode, startDragOffset, startMode],
|
||||||
@@ -148,18 +148,18 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
|
|||||||
// Manually adjust the value. This won't be (and shouldn't be) animated.
|
// Manually adjust the value. This won't be (and shouldn't be) animated.
|
||||||
// Cancel any any existing animation
|
// Cancel any any existing animation
|
||||||
cancelAnimation(headerMode)
|
cancelAnimation(headerMode)
|
||||||
headerMode.value = newValue
|
headerMode.set(newValue)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (didJustRestoreScroll.value) {
|
if (didJustRestoreScroll.value) {
|
||||||
didJustRestoreScroll.value = false
|
didJustRestoreScroll.set(false)
|
||||||
// Don't hide/show navbar based on scroll restoratoin.
|
// Don't hide/show navbar based on scroll restoratoin.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// On the web, we don't try to follow the drag because we don't know when it ends.
|
// On the web, we don't try to follow the drag because we don't know when it ends.
|
||||||
// Instead, show/hide immediately based on whether we're scrolling up or down.
|
// Instead, show/hide immediately based on whether we're scrolling up or down.
|
||||||
const dy = e.contentOffset.y - (startDragOffset.value ?? 0)
|
const dy = e.contentOffset.y - (startDragOffset.value ?? 0)
|
||||||
startDragOffset.value = e.contentOffset.y
|
startDragOffset.set(e.contentOffset.y)
|
||||||
|
|
||||||
if (dy < 0 || e.contentOffset.y < WEB_HIDE_SHELL_THRESHOLD) {
|
if (dy < 0 || e.contentOffset.y < WEB_HIDE_SHELL_THRESHOLD) {
|
||||||
setMode(false)
|
setMode(false)
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
footerMinimalShellTransform,
|
footerMinimalShellTransform,
|
||||||
]}
|
]}
|
||||||
onLayout={e => {
|
onLayout={e => {
|
||||||
footerHeight.value = e.nativeEvent.layout.height
|
footerHeight.set(e.nativeEvent.layout.height)
|
||||||
}}>
|
}}>
|
||||||
{hasSession ? (
|
{hasSession ? (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user