change .value = to .set()

This commit is contained in:
Samuel Newman
2024-11-12 20:41:17 +00:00
parent 427f3a8bd7
commit b29f7b64ac
19 changed files with 153 additions and 125 deletions
+2 -3
View File
@@ -21,9 +21,8 @@ export function Loader(props: Props) {
}))
React.useEffect(() => {
rotation.value = withRepeat(
withTiming(360, {duration: 500, easing: Easing.linear}),
-1,
rotation.set(
withRepeat(withTiming(360, {duration: 500, easing: Easing.linear}), -1),
)
}, [rotation])
+32 -21
View File
@@ -3,6 +3,7 @@ import {Pressable, useWindowDimensions, View} from 'react-native'
import Animated, {
Easing,
runOnJS,
runOnUI,
useAnimatedStyle,
useSharedValue,
withTiming,
@@ -55,13 +56,15 @@ export const ProgressGuideToast = React.forwardRef<
// animate the opacity then set isOpen to false when done
const setIsntOpen = () => setIsOpen(false)
opacity.value = withTiming(
0,
{
duration: 400,
easing: Easing.out(Easing.cubic),
},
() => runOnJS(setIsntOpen)(),
opacity.set(
withTiming(
0,
{
duration: 400,
easing: Easing.out(Easing.cubic),
},
() => runOnJS(setIsntOpen)(),
),
)
}, [setIsOpen, opacity])
@@ -71,20 +74,28 @@ export const ProgressGuideToast = React.forwardRef<
// animate the vertical translation, the opacity, and the checkmark
const playCheckmark = () => animatedCheckRef.current?.play()
opacity.value = 0
opacity.value = withTiming(
1,
{
duration: 100,
easing: Easing.out(Easing.cubic),
},
() => runOnJS(playCheckmark)(),
)
translateY.value = 0
translateY.value = withTiming(insets.top + 10, {
duration: 500,
easing: Easing.out(Easing.cubic),
})
runOnUI(() => {
'worklet'
opacity.set(0)
opacity.set(
withTiming(
1,
{
duration: 100,
easing: Easing.out(Easing.cubic),
},
() => runOnJS(playCheckmark)(),
),
)
translateY.set(0)
translateY.set(
withTiming(insets.top + 10, {
duration: 500,
easing: Easing.out(Easing.cubic),
}),
)
})()
// start the countdown timer to autoclose
timeoutRef.current = setTimeout(close, visibleDuration || 5e3)
+13 -7
View File
@@ -1,6 +1,7 @@
import React from 'react'
import Animated, {
Easing,
runOnUI,
useAnimatedProps,
useSharedValue,
withDelay,
@@ -40,14 +41,19 @@ export const AnimatedCheck = React.forwardRef<
const play = React.useCallback(
(cb?: () => void) => {
circleAnim.value = 0
checkAnim.value = 0
runOnUI(() => {
'worklet'
circleAnim.set(0)
checkAnim.set(0)
circleAnim.value = withTiming(1, {duration: 500, easing: Easing.linear})
checkAnim.value = withDelay(
500,
withTiming(1, {duration: 300, easing: Easing.linear}, cb),
)
circleAnim.set(withTiming(1, {duration: 500, easing: Easing.linear}))
checkAnim.set(
withDelay(
500,
withTiming(1, {duration: 300, easing: Easing.linear}, cb),
),
)
})()
},
[circleAnim, checkAnim],
)
+8 -6
View File
@@ -46,7 +46,7 @@ export function ActionsWrapper({
const shrink = React.useCallback(() => {
'worklet'
cancelAnimation(scale)
scale.value = withTiming(1, {duration: 200})
scale.set(withTiming(1, {duration: 200}))
}, [scale])
const doubleTapGesture = Gesture.Tap()
@@ -58,11 +58,13 @@ export function ActionsWrapper({
const pressAndHoldGesture = Gesture.LongPress()
.onStart(() => {
'worklet'
scale.value = withTiming(1.05, {duration: 200}, finished => {
if (!finished) return
runOnJS(open)()
shrink()
})
scale.set(
withTiming(1.05, {duration: 200}, finished => {
if (!finished) return
runOnJS(open)()
shrink()
}),
)
})
.onTouchesUp(shrink)
.onTouchesMove(shrink)
+2 -2
View File
@@ -42,12 +42,12 @@ export function ChatEmptyPill() {
const onPressIn = React.useCallback(() => {
if (isWeb) return
scale.value = withTiming(1.075, {duration: 100})
scale.set(withTiming(1.075, {duration: 100}))
}, [scale])
const onPressOut = React.useCallback(() => {
if (isWeb) return
scale.value = withTiming(1, {duration: 100})
scale.set(withTiming(1, {duration: 100}))
}, [scale])
const onPress = React.useCallback(() => {
+2 -2
View File
@@ -35,12 +35,12 @@ export function NewMessagesPill({
const onPressIn = React.useCallback(() => {
if (isWeb) return
scale.value = withTiming(1.075, {duration: 100})
scale.set(withTiming(1.075, {duration: 100}))
}, [scale])
const onPressOut = React.useCallback(() => {
if (isWeb) return
scale.value = withTiming(1, {duration: 100})
scale.set(withTiming(1, {duration: 100}))
}, [scale])
const onPress = React.useCallback(() => {
+19 -17
View File
@@ -75,9 +75,11 @@ export function GestureActionView({
return
}
iconScale.value = withSequence(
withTiming(1.2, {duration: 175}),
withTiming(1, {duration: 100}),
iconScale.set(
withSequence(
withTiming(1.2, {duration: 175}),
withTiming(1, {duration: 100}),
),
)
}
@@ -119,11 +121,11 @@ export function GestureActionView({
.activeOffsetY([-200, 200])
.onStart(() => {
'worklet'
isActive.value = true
isActive.set(true)
})
.onChange(e => {
'worklet'
transX.value = e.translationX
transX.set(e.translationX)
if (e.translationX < 0) {
// Left side
@@ -134,13 +136,13 @@ export function GestureActionView({
) {
runPopAnimation()
runOnJS(haptic)()
hitSecond.value = true
hitSecond.set(true)
} else if (
hitSecond.value &&
e.translationX > -actions.leftSecond.threshold
) {
runPopAnimation()
hitSecond.value = false
hitSecond.set(false)
}
}
@@ -151,12 +153,12 @@ export function GestureActionView({
) {
runPopAnimation()
runOnJS(haptic)()
hitFirst.value = true
hitFirst.set(true)
} else if (
hitFirst.value &&
e.translationX > -actions.leftFirst.threshold
) {
hitFirst.value = false
hitFirst.set(false)
}
}
} else if (e.translationX > 0) {
@@ -168,13 +170,13 @@ export function GestureActionView({
) {
runPopAnimation()
runOnJS(haptic)()
hitSecond.value = true
hitSecond.set(true)
} else if (
hitSecond.value &&
e.translationX < actions.rightSecond.threshold
) {
runPopAnimation()
hitSecond.value = false
hitSecond.set(false)
}
}
@@ -185,12 +187,12 @@ export function GestureActionView({
) {
runPopAnimation()
runOnJS(haptic)()
hitFirst.value = true
hitFirst.set(true)
} else if (
hitFirst.value &&
e.translationX < actions.rightFirst.threshold
) {
hitFirst.value = false
hitFirst.set(false)
}
}
}
@@ -210,10 +212,10 @@ export function GestureActionView({
runOnJS(actions.rightFirst.action)()
}
}
transX.value = withTiming(0, {duration: 200})
hitFirst.value = false
hitSecond.value = false
isActive.value = false
transX.set(withTiming(0, {duration: 200}))
hitFirst.set(false)
hitSecond.set(false)
isActive.set(false)
})
const composedGesture = Gesture.Simultaneous(panGesture)
@@ -111,8 +111,8 @@ export function MessageInput({
const max = windowHeight - -keyboardHeight.value - topInset - 150
const availableSpace = max - measurement.height
maxHeight.value = max
isInputScrollable.value = availableSpace < 30
maxHeight.set(max)
isInputScrollable.set(availableSpace < 30)
},
},
[windowHeight, topInset],
@@ -217,13 +217,13 @@ export function MessagesList({
const onScroll = React.useCallback(
(e: ReanimatedScrollEvent) => {
'worklet'
layoutHeight.value = e.layoutMeasurement.height
layoutHeight.value.set(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
// when a new message is added, hence the 100 pixel offset
isAtBottom.value = e.contentSize.height - 100 < bottomOffset
isAtTop.value = e.contentOffset.y <= 1
isAtBottom.set(e.contentSize.height - 100 < bottomOffset)
isAtTop.set(e.contentOffset.y <= 1)
if (
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
// just update the height here instead of having the `onMove` event do it (that event will not fire!)
if (e.duration === 0) {
layoutScrollWithoutAnimation.value = true
keyboardHeight.value = e.height
layoutScrollWithoutAnimation.set(true)
keyboardHeight.set(e.height)
} else {
keyboardIsOpening.value = true
keyboardIsOpening.set(true)
}
},
onMove: e => {
'worklet'
keyboardHeight.value = e.height
keyboardHeight.set(e.height)
if (e.height > bottomOffset) {
scrollTo(flatListRef, 0, 1e7, false)
}
},
onEnd: () => {
'worklet'
keyboardIsOpening.value = false
keyboardIsOpening.set(false)
},
})
@@ -363,13 +363,13 @@ export function MessagesList({
// -- List layout changes (opening emoji keyboard, etc.)
const onListLayout = React.useCallback(
(e: LayoutChangeEvent) => {
layoutHeight.value = e.nativeEvent.layout.height
layoutHeight.set(e.nativeEvent.layout.height)
if (isWeb || !keyboardIsOpening.value) {
flatListRef.current?.scrollToEnd({
animated: !layoutScrollWithoutAnimation.value,
})
layoutScrollWithoutAnimation.value = false
layoutScrollWithoutAnimation.set(false)
}
},
[
+10 -6
View File
@@ -44,13 +44,17 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
'worklet'
// Cancel any existing animation
cancelAnimation(headerMode)
headerMode.value = withSpring(v ? 1 : 0, {
overshootClamping: true,
})
headerMode.set(
withSpring(v ? 1 : 0, {
overshootClamping: true,
}),
)
cancelAnimation(footerMode)
footerMode.value = withSpring(v ? 1 : 0, {
overshootClamping: true,
})
footerMode.set(
withSpring(v ? 1 : 0, {
overshootClamping: true,
}),
)
},
[headerMode, footerMode],
)
+3 -3
View File
@@ -1288,11 +1288,11 @@ function useScrollTracker({
}) => {
'worklet'
if (typeof newContentHeight === 'number')
contentHeight.value = Math.floor(newContentHeight)
contentHeight.value.set(Math.floor(newContentHeight))
if (typeof newContentOffset === 'number')
contentOffset.value = Math.floor(newContentOffset)
contentOffset.value.set(Math.floor(newContentOffset))
if (typeof newScrollViewHeight === 'number')
scrollViewHeight.value = Math.floor(newScrollViewHeight)
scrollViewHeight.set(Math.floor(newScrollViewHeight))
},
[contentHeight, contentOffset, scrollViewHeight],
)
+1 -1
View File
@@ -93,7 +93,7 @@ function HomeHeaderLayoutDesktopAndTablet({
{tabBarAnchor}
<Animated.View
onLayout={e => {
headerHeight.value = e.nativeEvent.layout.height
headerHeight.set(e.nativeEvent.layout.height)
}}
style={[
t.atoms.bg,
+1 -1
View File
@@ -43,7 +43,7 @@ export function HomeHeaderLayoutMobile({
<Animated.View
style={[pal.view, pal.border, styles.tabBar, headerMinimalShellTransform]}
onLayout={e => {
headerHeight.value = e.nativeEvent.layout.height
headerHeight.set(e.nativeEvent.layout.height)
}}>
<View style={[pal.view, styles.topBar]}>
<View style={[pal.view, {width: 100}]}>
@@ -147,10 +147,10 @@ const ImageItem = ({
.onStart(e => {
'worklet'
const screenSize = measureSafeArea()
pinchOrigin.value = {
pinchOrigin.set({
x: e.focalX - screenSize.width / 2,
y: e.focalY - screenSize.height / 2,
}
})
})
.onChange(e => {
'worklet'
@@ -171,7 +171,7 @@ const ImageItem = ({
Math.max(minPinchScale, e.scale),
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.
// 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)
const [dx, dy] = getExtraTranslationToStayInBounds(t, screenSize)
if (dx !== 0 || dy !== 0) {
pinchTranslation.value = {
pinchTranslation.set({
x: pinchTranslation.value.x + dx,
y: pinchTranslation.value.y + dy,
}
})
}
})
.onEnd(() => {
@@ -199,12 +199,12 @@ const ImageItem = ({
)
prependTransform(t, committedTransform.value)
applyRounding(t)
committedTransform.value = t
committedTransform.set(t)
// Reset just the pinch.
pinchScale.value = 1
pinchOrigin.value = {x: 0, y: 0}
pinchTranslation.value = {x: 0, y: 0}
pinchScale.set(1)
pinchOrigin.set({x: 0, y: 0})
pinchTranslation.set({x: 0, y: 0})
})
const pan = Gesture.Pan()
@@ -233,7 +233,7 @@ const ImageItem = ({
const [dx, dy] = getExtraTranslationToStayInBounds(t, screenSize)
nextPanTranslation.x += dx
nextPanTranslation.y += dy
panTranslation.value = nextPanTranslation
panTranslation.set(nextPanTranslation)
})
.onEnd(() => {
'worklet'
@@ -242,10 +242,10 @@ const ImageItem = ({
prependPan(t, panTranslation.value)
prependTransform(t, committedTransform.value)
applyRounding(t)
committedTransform.value = t
committedTransform.set(t)
// Reset just the pan.
panTranslation.value = {x: 0, y: 0}
panTranslation.set({x: 0, y: 0})
})
const singleTap = Gesture.Tap().onEnd(() => {
@@ -265,7 +265,7 @@ const ImageItem = ({
if (committedScale !== 1) {
// Go back to 1:1 using the identity vector.
let t = createTransform()
committedTransform.value = withClampedSpring(t)
committedTransform.set(withClampedSpring(t))
return
}
@@ -299,7 +299,7 @@ const ImageItem = ({
)
const finalTransform = createTransform()
prependPinch(finalTransform, scale, origin, {x: dx, y: dy})
committedTransform.value = withClampedSpring(finalTransform)
committedTransform.set(withClampedSpring(finalTransform))
})
const composedGesture = isScrollViewBeingDragged
+19 -15
View File
@@ -98,12 +98,12 @@ export default function ImageViewRoot({
// https://github.com/software-mansion/react-native-reanimated/issues/6677
requestAnimationFrame(() => {
openProgress.value = canAnimate ? withClampedSpring(1, SLOW_SPRING) : 1
openProgress.set(canAnimate ? withClampedSpring(1, SLOW_SPRING) : 1)
})
return () => {
// https://github.com/software-mansion/react-native-reanimated/issues/6677
requestAnimationFrame(() => {
openProgress.value = canAnimate ? withClampedSpring(0, SLOW_SPRING) : 0
openProgress.set(canAnimate ? withClampedSpring(0, SLOW_SPRING) : 0)
})
}
}, [nextLightbox, openProgress])
@@ -119,7 +119,7 @@ export default function ImageViewRoot({
const onFlyAway = React.useCallback(() => {
'worklet'
openProgress.value = 0
openProgress.set(0)
runOnJS(onRequestClose)()
}, [onRequestClose, openProgress])
@@ -426,7 +426,7 @@ function LightboxImage({
if (openProgress.value !== 1 || isFlyingAway.value) {
return
}
dismissSwipeTranslateY.value = e.translationY
dismissSwipeTranslateY.set(e.translationY)
})
.onEnd(e => {
'worklet'
@@ -434,22 +434,26 @@ function LightboxImage({
return
}
if (Math.abs(e.velocityY) > 1000) {
isFlyingAway.value = true
isFlyingAway.set(true)
if (dismissSwipeTranslateY.value === 0) {
// 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.
dismissSwipeTranslateY.value = 1
dismissSwipeTranslateY.set(1)
}
dismissSwipeTranslateY.value = withDecay({
velocity: e.velocityY,
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.
})
dismissSwipeTranslateY.set(
withDecay({
velocity: e.velocityY,
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 {
dismissSwipeTranslateY.value = withSpring(0, {
stiffness: 700,
damping: 50,
})
dismissSwipeTranslateY.set(
withSpring(0, {
stiffness: 700,
damping: 50,
}),
)
}
})
+2 -2
View File
@@ -134,7 +134,7 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
const currentScrollY = scrollY.value
const forcedScrollY = Math.min(currentScrollY, headerOnlyHeight)
if (lastForcedScrollY.value !== forcedScrollY) {
lastForcedScrollY.value = forcedScrollY
lastForcedScrollY.set(forcedScrollY)
const refs = scrollRefs.value
for (let i = 0; i < refs.length; i++) {
const scollRef = refs[i]
@@ -167,7 +167,7 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
const isPossiblyInvalid =
headerHeight > 0 && Math.round(nextScrollY * 2) / 2 === -headerHeight
if (!isPossiblyInvalid) {
scrollY.value = nextScrollY
scrollY.set(nextScrollY)
runOnJS(queueThrottledOnScroll)()
}
},
+1 -1
View File
@@ -78,7 +78,7 @@ function ListImpl<ItemT>(
const didScrollDown = e.contentOffset.y > SCROLLED_DOWN_LIMIT
if (isScrolledDown.value !== didScrollDown) {
isScrolledDown.value = didScrollDown
isScrolledDown.set(didScrollDown)
if (onScrolledDownChange != null) {
runOnJS(handleScrolledDownChange)(didScrollDown)
}
+11 -11
View File
@@ -44,7 +44,7 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
(v: boolean) => {
'worklet'
cancelAnimation(headerMode)
headerMode.value = v ? V1.value : V0.value
headerMode.set(v ? V1.value : V0.value)
},
[headerMode],
)
@@ -52,9 +52,9 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
useEffect(() => {
if (isWeb) {
return listenToForcedWindowScroll(() => {
startDragOffset.value = null
startMode.value = null
didJustRestoreScroll.value = true
startDragOffset.set(null)
startMode.set(null)
didJustRestoreScroll.set(true)
})
}
})
@@ -67,8 +67,8 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
return
}
const didScrollDown = e.contentOffset.y > startDragOffset.value
startDragOffset.value = null
startMode.value = null
startDragOffset.set(null)
startMode.set(null)
if (e.contentOffset.y < headerHeight.value) {
// If we're close to the top, show the shell.
setMode(false)
@@ -88,8 +88,8 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
(e: NativeScrollEvent) => {
'worklet'
if (isNative) {
startDragOffset.value = e.contentOffset.y
startMode.value = headerMode.value
startDragOffset.set(e.contentOffset.y)
startMode.set(headerMode.value)
}
},
[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.
// Cancel any any existing animation
cancelAnimation(headerMode)
headerMode.value = newValue
headerMode.set(newValue)
}
} else {
if (didJustRestoreScroll.value) {
didJustRestoreScroll.value = false
didJustRestoreScroll.set(false)
// Don't hide/show navbar based on scroll restoratoin.
return
}
// 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.
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) {
setMode(false)
+1 -1
View File
@@ -134,7 +134,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
footerMinimalShellTransform,
]}
onLayout={e => {
footerHeight.value = e.nativeEvent.layout.height
footerHeight.set(e.nativeEvent.layout.height)
}}>
{hasSession ? (
<>