Migrate runOnUI/runOnJS to scheduleOnUI/scheduleOnRN (#11249)
This commit is contained in:
+2
-2
@@ -9,13 +9,13 @@ import {
|
|||||||
import Animated, {
|
import Animated, {
|
||||||
Easing,
|
Easing,
|
||||||
interpolate,
|
interpolate,
|
||||||
runOnJS,
|
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
withTiming,
|
withTiming,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import Svg, {Path, type SvgProps} from 'react-native-svg'
|
import Svg, {Path, type SvgProps} from 'react-native-svg'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import * as SplashScreen from 'expo-splash-screen'
|
import * as SplashScreen from 'expo-splash-screen'
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ export function Splash(props: React.PropsWithChildren<Props>) {
|
|||||||
1,
|
1,
|
||||||
{duration: 1200, easing: Easing.in(Easing.cubic)},
|
{duration: 1200, easing: Easing.in(Easing.cubic)},
|
||||||
() => {
|
() => {
|
||||||
runOnJS(onFinish)()
|
scheduleOnRN(onFinish)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import {KeyboardEvents} from 'react-native-keyboard-controller'
|
|||||||
import Animated, {
|
import Animated, {
|
||||||
clamp,
|
clamp,
|
||||||
interpolate,
|
interpolate,
|
||||||
runOnJS,
|
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
@@ -44,6 +43,7 @@ import {
|
|||||||
useSafeAreaInsets,
|
useSafeAreaInsets,
|
||||||
} from 'react-native-safe-area-context'
|
} from 'react-native-safe-area-context'
|
||||||
import {captureRef} from 'react-native-view-shot'
|
import {captureRef} from 'react-native-view-shot'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {Image, type ImageErrorEventData} from 'expo-image'
|
import {Image, type ImageErrorEventData} from 'expo-image'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
@@ -166,7 +166,7 @@ export function Root({children}: {children: React.ReactNode}) {
|
|||||||
// note: return location has to be reset on open,
|
// note: return location has to be reset on open,
|
||||||
// rather than on close, otherwise there's a flicker
|
// rather than on close, otherwise there's a flicker
|
||||||
// where the reanimated update is faster than the react render
|
// where the reanimated update is faster than the react render
|
||||||
runOnJS(onCompletedClose)()
|
scheduleOnRN(onCompletedClose)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -331,7 +331,7 @@ export function Trigger({
|
|||||||
() => hoveredItemSV.get(),
|
() => hoveredItemSV.get(),
|
||||||
(hovered, prev) => {
|
(hovered, prev) => {
|
||||||
if (hovered !== prev) {
|
if (hovered !== prev) {
|
||||||
runOnJS(setHoveredMenuItem)(hovered)
|
scheduleOnRN(setHoveredMenuItem, hovered)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -343,7 +343,7 @@ export function Trigger({
|
|||||||
.averageTouches(true)
|
.averageTouches(true)
|
||||||
.onStart(() => {
|
.onStart(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
runOnJS(open)('full')
|
scheduleOnRN(open, 'full')
|
||||||
})
|
})
|
||||||
.onUpdate(evt => {
|
.onUpdate(evt => {
|
||||||
'worklet'
|
'worklet'
|
||||||
@@ -357,7 +357,7 @@ export function Trigger({
|
|||||||
// as the menu may have slid into place beneath their finger
|
// as the menu may have slid into place beneath their finger
|
||||||
const item = hoveredItemSV.get()
|
const item = hoveredItemSV.get()
|
||||||
if (item) {
|
if (item) {
|
||||||
runOnJS(onTouchUpMenuItem)(item)
|
scheduleOnRN(onTouchUpMenuItem, item)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [open, hoverablesSV, onTouchUpMenuItem, hoveredItemSV, translationSV])
|
}, [open, hoverablesSV, onTouchUpMenuItem, hoveredItemSV, translationSV])
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {useReanimatedKeyboardAnimation} from 'react-native-keyboard-controller'
|
import {useReanimatedKeyboardAnimation} from 'react-native-keyboard-controller'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
runOnJS,
|
|
||||||
type ScrollEvent,
|
type ScrollEvent,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
@@ -299,9 +299,9 @@ export const InnerFlatList = forwardRef<
|
|||||||
}
|
}
|
||||||
const {contentOffset} = e
|
const {contentOffset} = e
|
||||||
if (contentOffset.y > 0 && !disableDrag) {
|
if (contentOffset.y > 0 && !disableDrag) {
|
||||||
runOnJS(setDisableDrag)(true)
|
scheduleOnRN(setDisableDrag, true)
|
||||||
} else if (contentOffset.y <= 1 && disableDrag) {
|
} else if (contentOffset.y <= 1 && disableDrag) {
|
||||||
runOnJS(setDisableDrag)(false)
|
scheduleOnRN(setDisableDrag, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import Animated, {
|
|||||||
type AnimatedRef,
|
type AnimatedRef,
|
||||||
measure,
|
measure,
|
||||||
Reanimated3DefaultSpringConfig,
|
Reanimated3DefaultSpringConfig,
|
||||||
runOnJS,
|
|
||||||
scrollTo,
|
scrollTo,
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedRef,
|
useAnimatedRef,
|
||||||
@@ -14,6 +13,7 @@ import Animated, {
|
|||||||
withSpring,
|
withSpring,
|
||||||
withTiming,
|
withTiming,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
|
|
||||||
import {useHaptics} from '#/lib/haptics'
|
import {useHaptics} from '#/lib/haptics'
|
||||||
import {atoms as a, useTheme, web} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
@@ -26,7 +26,7 @@ import {IS_IOS} from '#/env'
|
|||||||
*
|
*
|
||||||
* All positioning is driven by a `slots` map (key → index) and translateY
|
* All positioning is driven by a `slots` map (key → index) and translateY
|
||||||
* (no discrete `top` changes). On drag end the new slot assignment is
|
* (no discrete `top` changes). On drag end the new slot assignment is
|
||||||
* computed on the UI thread first, then React state is updated via runOnJS.
|
* computed on the UI thread first, then React state is updated via scheduleOnRN.
|
||||||
*
|
*
|
||||||
* See SortableList.web.tsx for the web implementation using pointer events.
|
* See SortableList.web.tsx for the web implementation using pointer events.
|
||||||
*/
|
*/
|
||||||
@@ -265,9 +265,9 @@ function SortableItem<T>({
|
|||||||
measureDone.set(false)
|
measureDone.set(false)
|
||||||
lastHapticSlot.set(mySlot)
|
lastHapticSlot.set(mySlot)
|
||||||
if (onDragStart) {
|
if (onDragStart) {
|
||||||
runOnJS(onDragStart)()
|
scheduleOnRN(onDragStart)
|
||||||
}
|
}
|
||||||
runOnJS(playHaptic)()
|
scheduleOnRN(playHaptic)
|
||||||
})
|
})
|
||||||
.onChange(e => {
|
.onChange(e => {
|
||||||
'worklet'
|
'worklet'
|
||||||
@@ -285,7 +285,7 @@ function SortableItem<T>({
|
|||||||
const clampedSlot = Math.max(0, Math.min(currentSlot, itemCount - 1))
|
const clampedSlot = Math.max(0, Math.min(currentSlot, itemCount - 1))
|
||||||
if (IS_IOS && clampedSlot !== lastHapticSlot.get()) {
|
if (IS_IOS && clampedSlot !== lastHapticSlot.get()) {
|
||||||
lastHapticSlot.set(clampedSlot)
|
lastHapticSlot.set(clampedSlot)
|
||||||
runOnJS(playHaptic)('Light')
|
scheduleOnRN(playHaptic, 'Light')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.onEnd(() => {
|
.onEnd(() => {
|
||||||
@@ -326,13 +326,13 @@ function SortableItem<T>({
|
|||||||
dragStartSlot: -1,
|
dragStartSlot: -1,
|
||||||
})
|
})
|
||||||
dragY.set(0)
|
dragY.set(0)
|
||||||
runOnJS(onCommitReorder)(sorted)
|
scheduleOnRN(onCommitReorder, sorted)
|
||||||
} else {
|
} else {
|
||||||
const s = state.get()
|
const s = state.get()
|
||||||
state.set({...s, activeKey: '', dragStartSlot: -1})
|
state.set({...s, activeKey: '', dragStartSlot: -1})
|
||||||
dragY.set(0)
|
dragY.set(0)
|
||||||
if (onDragEnd) {
|
if (onDragEnd) {
|
||||||
runOnJS(onDragEnd)()
|
scheduleOnRN(onDragEnd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,7 +347,7 @@ function SortableItem<T>({
|
|||||||
const s = state.get()
|
const s = state.get()
|
||||||
state.set({...s, activeKey: '', dragStartSlot: -1})
|
state.set({...s, activeKey: '', dragStartSlot: -1})
|
||||||
if (onDragEnd) {
|
if (onDragEnd) {
|
||||||
runOnJS(onDragEnd)()
|
scheduleOnRN(onDragEnd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import {useRef, useState} from 'react'
|
|||||||
import {Modal, Pressable, StyleSheet, View} from 'react-native'
|
import {Modal, Pressable, StyleSheet, View} from 'react-native'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
interpolate,
|
interpolate,
|
||||||
runOnJS,
|
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
withSpring,
|
withSpring,
|
||||||
withTiming,
|
withTiming,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {useLingui} from '@lingui/react/macro'
|
import {useLingui} from '@lingui/react/macro'
|
||||||
|
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
@@ -52,7 +52,7 @@ export function ImageMenu({onPressShare, onPressSave}: Props) {
|
|||||||
progress.set(
|
progress.set(
|
||||||
withTiming(0, TIMING_OUT, finished => {
|
withTiming(0, TIMING_OUT, finished => {
|
||||||
if (finished) {
|
if (finished) {
|
||||||
runOnJS(setIsMounted)(false)
|
scheduleOnRN(setIsMounted, false)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
import Animated, {
|
import Animated, {
|
||||||
type AnimatableValue,
|
type AnimatableValue,
|
||||||
Reanimated3DefaultSpringConfig,
|
Reanimated3DefaultSpringConfig,
|
||||||
runOnJS,
|
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
useAnimatedRef,
|
useAnimatedRef,
|
||||||
@@ -16,6 +15,7 @@ import Animated, {
|
|||||||
useSharedValue,
|
useSharedValue,
|
||||||
withSpring,
|
withSpring,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -95,7 +95,7 @@ const ImageItem = ({
|
|||||||
},
|
},
|
||||||
(nextIsScaled, prevIsScaled) => {
|
(nextIsScaled, prevIsScaled) => {
|
||||||
if (nextIsScaled !== prevIsScaled) {
|
if (nextIsScaled !== prevIsScaled) {
|
||||||
runOnJS(handleZoom)(nextIsScaled)
|
scheduleOnRN(handleZoom, nextIsScaled)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -245,7 +245,7 @@ const ImageItem = ({
|
|||||||
|
|
||||||
const singleTap = Gesture.Tap().onEnd(() => {
|
const singleTap = Gesture.Tap().onEnd(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
runOnJS(onTap)()
|
scheduleOnRN(onTap)
|
||||||
})
|
})
|
||||||
|
|
||||||
const doubleTap = Gesture.Tap()
|
const doubleTap = Gesture.Tap()
|
||||||
@@ -359,9 +359,9 @@ const ImageItem = ({
|
|||||||
},
|
},
|
||||||
(show, prevShow) => {
|
(show, prevShow) => {
|
||||||
if (!prevShow && show) {
|
if (!prevShow && show) {
|
||||||
runOnJS(setShowLoader)(true)
|
scheduleOnRN(setShowLoader, true)
|
||||||
} else if (prevShow && !show) {
|
} else if (prevShow && !show) {
|
||||||
runOnJS(setShowLoader)(false)
|
scheduleOnRN(setShowLoader, false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
type PanGesture,
|
type PanGesture,
|
||||||
} from 'react-native-gesture-handler'
|
} from 'react-native-gesture-handler'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
runOnJS,
|
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedProps,
|
useAnimatedProps,
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
@@ -24,6 +23,7 @@ import Animated, {
|
|||||||
useSharedValue,
|
useSharedValue,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaFrame} from 'react-native-safe-area-context'
|
import {useSafeAreaFrame} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -84,7 +84,7 @@ const ImageItem = ({
|
|||||||
'worklet'
|
'worklet'
|
||||||
const nextIsScaled = e.zoomScale > 1
|
const nextIsScaled = e.zoomScale > 1
|
||||||
if (scaled !== nextIsScaled) {
|
if (scaled !== nextIsScaled) {
|
||||||
runOnJS(handleZoom)(nextIsScaled)
|
scheduleOnRN(handleZoom, nextIsScaled)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onBeginDrag() {
|
onBeginDrag() {
|
||||||
@@ -118,7 +118,7 @@ const ImageItem = ({
|
|||||||
|
|
||||||
const singleTap = Gesture.Tap().onEnd(() => {
|
const singleTap = Gesture.Tap().onEnd(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
runOnJS(onTap)()
|
scheduleOnRN(onTap)
|
||||||
})
|
})
|
||||||
|
|
||||||
const doubleTap = Gesture.Tap()
|
const doubleTap = Gesture.Tap()
|
||||||
@@ -142,7 +142,7 @@ const ImageItem = ({
|
|||||||
screenSize,
|
screenSize,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
runOnJS(zoomTo)(nextZoomRect)
|
scheduleOnRN(zoomTo, nextZoomRect)
|
||||||
})
|
})
|
||||||
|
|
||||||
const composedGesture = Gesture.Exclusive(
|
const composedGesture = Gesture.Exclusive(
|
||||||
@@ -199,9 +199,9 @@ const ImageItem = ({
|
|||||||
},
|
},
|
||||||
(show, prevShow) => {
|
(show, prevShow) => {
|
||||||
if (!prevShow && show) {
|
if (!prevShow && show) {
|
||||||
runOnJS(setShowLoader)(true)
|
scheduleOnRN(setShowLoader, true)
|
||||||
} else if (prevShow && !show) {
|
} else if (prevShow && !show) {
|
||||||
runOnJS(setShowLoader)(false)
|
scheduleOnRN(setShowLoader, false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ import Animated, {
|
|||||||
measure,
|
measure,
|
||||||
type MeasuredDimensions,
|
type MeasuredDimensions,
|
||||||
ReduceMotion,
|
ReduceMotion,
|
||||||
runOnJS,
|
|
||||||
runOnUI,
|
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
useAnimatedRef,
|
useAnimatedRef,
|
||||||
@@ -32,6 +30,7 @@ import Animated, {
|
|||||||
withSpring,
|
withSpring,
|
||||||
type WithSpringConfig,
|
type WithSpringConfig,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnRN, scheduleOnUI} from 'react-native-worklets'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import * as ScreenOrientation from 'expo-screen-orientation'
|
import * as ScreenOrientation from 'expo-screen-orientation'
|
||||||
|
|
||||||
@@ -136,10 +135,10 @@ export default function ImageViewRoot({
|
|||||||
|
|
||||||
const onFullyClosed = useCallback(() => {
|
const onFullyClosed = useCallback(() => {
|
||||||
setActiveLightbox(null)
|
setActiveLightbox(null)
|
||||||
runOnUI(() => {
|
scheduleOnUI(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
thumbRects.set({})
|
thumbRects.set({})
|
||||||
})()
|
})
|
||||||
requestIdleCallback(() => {
|
requestIdleCallback(() => {
|
||||||
void Image.clearMemoryCache()
|
void Image.clearMemoryCache()
|
||||||
})
|
})
|
||||||
@@ -149,7 +148,7 @@ export default function ImageViewRoot({
|
|||||||
() => openProgress.get() === 0,
|
() => openProgress.get() === 0,
|
||||||
(isGone, wasGone) => {
|
(isGone, wasGone) => {
|
||||||
if (isGone && !wasGone) {
|
if (isGone && !wasGone) {
|
||||||
runOnJS(onFullyClosed)()
|
scheduleOnRN(onFullyClosed)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -160,10 +159,10 @@ export default function ImageViewRoot({
|
|||||||
() => openProgress.get() === 1,
|
() => openProgress.get() === 1,
|
||||||
(isOpen, wasOpen) => {
|
(isOpen, wasOpen) => {
|
||||||
if (isOpen && !wasOpen) {
|
if (isOpen && !wasOpen) {
|
||||||
runOnJS(ScreenOrientation.unlockAsync)()
|
scheduleOnRN(ScreenOrientation.unlockAsync)
|
||||||
} else if (!isOpen && wasOpen) {
|
} else if (!isOpen && wasOpen) {
|
||||||
// default is PORTRAIT_UP - set via config plugin in app.config.js -sfn
|
// default is PORTRAIT_UP - set via config plugin in app.config.js -sfn
|
||||||
runOnJS(ScreenOrientation.lockAsync)(PORTRAIT_UP)
|
scheduleOnRN(ScreenOrientation.lockAsync, PORTRAIT_UP)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -171,7 +170,7 @@ export default function ImageViewRoot({
|
|||||||
const onFlyAway = useCallback(() => {
|
const onFlyAway = useCallback(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
openProgress.set(0)
|
openProgress.set(0)
|
||||||
runOnJS(onRequestClose)()
|
scheduleOnRN(onRequestClose)
|
||||||
}, [onRequestClose, openProgress])
|
}, [onRequestClose, openProgress])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -320,7 +319,7 @@ function ImageView({
|
|||||||
const handleRequestClose = useCallback(() => {
|
const handleRequestClose = useCallback(() => {
|
||||||
const activeRef = images[imageIndex]?.thumbRef
|
const activeRef = images[imageIndex]?.thumbRef
|
||||||
if (isAnimated && activeRef) {
|
if (isAnimated && activeRef) {
|
||||||
runOnUI(() => {
|
scheduleOnUI(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
const rect = measure(activeRef)
|
const rect = measure(activeRef)
|
||||||
thumbRects.modify(rects => {
|
thumbRects.modify(rects => {
|
||||||
@@ -328,8 +327,8 @@ function ImageView({
|
|||||||
rects[imageIndex] = rect
|
rects[imageIndex] = rect
|
||||||
return rects
|
return rects
|
||||||
})
|
})
|
||||||
runOnJS(onRequestClose)()
|
scheduleOnRN(onRequestClose)
|
||||||
})()
|
})
|
||||||
} else {
|
} else {
|
||||||
onRequestClose()
|
onRequestClose()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import {createContext, useContext, useEffect, useMemo, useState} from 'react'
|
import {createContext, useContext, useEffect, useMemo, useState} from 'react'
|
||||||
import {
|
import {measure, type MeasuredDimensions} from 'react-native-reanimated'
|
||||||
measure,
|
import {scheduleOnRN, scheduleOnUI} from 'react-native-worklets'
|
||||||
type MeasuredDimensions,
|
|
||||||
runOnJS,
|
|
||||||
runOnUI,
|
|
||||||
} from 'react-native-reanimated'
|
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
@@ -73,7 +69,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
if (thumbRef) {
|
if (thumbRef) {
|
||||||
// Measure the tapped image on the UI thread, then open with
|
// Measure the tapped image on the UI thread, then open with
|
||||||
// the rect baked in so it's available from the first render.
|
// the rect baked in so it's available from the first render.
|
||||||
// Only the rect (plain data) goes through runOnJS — AnimatedRef
|
// Only the rect (plain data) goes through scheduleOnRN — AnimatedRef
|
||||||
// objects can't survive serialization across threads.
|
// objects can't survive serialization across threads.
|
||||||
const openWithRect = (rect: MeasuredDimensions | null) => {
|
const openWithRect = (rect: MeasuredDimensions | null) => {
|
||||||
doOpen({
|
doOpen({
|
||||||
@@ -83,11 +79,11 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
runOnUI(() => {
|
scheduleOnUI(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
const rect = measure(thumbRef)
|
const rect = measure(thumbRef)
|
||||||
runOnJS(openWithRect)(rect)
|
scheduleOnRN(openWithRect, rect)
|
||||||
})()
|
})
|
||||||
} else {
|
} else {
|
||||||
doOpen(lightbox)
|
doOpen(lightbox)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
measure,
|
measure,
|
||||||
runOnJS,
|
|
||||||
useAnimatedRef,
|
useAnimatedRef,
|
||||||
useFrameCallback,
|
useFrameCallback,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {WebView} from 'react-native-webview'
|
import {WebView} from 'react-native-webview'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import {type AppBskyEmbedExternal} from '@atproto/api'
|
import {type AppBskyEmbedExternal} from '@atproto/api'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
@@ -164,7 +164,7 @@ export function ExternalPlayer({
|
|||||||
const isVisible = top <= realWinHeight - insets.bottom && bot >= insets.top
|
const isVisible = top <= realWinHeight - insets.bottom && bot >= insets.top
|
||||||
|
|
||||||
if (!isVisible) {
|
if (!isVisible) {
|
||||||
runOnJS(setIsPlayerActive)(false)
|
scheduleOnRN(setIsPlayerActive, false)
|
||||||
}
|
}
|
||||||
}, false) // False here disables autostarting the callback
|
}, false) // False here disables autostarting the callback
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import {
|
|||||||
import {Pressable, useWindowDimensions, View} from 'react-native'
|
import {Pressable, useWindowDimensions, View} from 'react-native'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
Easing,
|
Easing,
|
||||||
runOnJS,
|
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
withTiming,
|
withTiming,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ export const ProgressGuideToast = forwardRef<
|
|||||||
duration: 400,
|
duration: 400,
|
||||||
easing: Easing.out(Easing.cubic),
|
easing: Easing.out(Easing.cubic),
|
||||||
},
|
},
|
||||||
() => runOnJS(setIsntOpen)(),
|
() => scheduleOnRN(setIsntOpen),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}, [setIsOpen, opacity])
|
}, [setIsOpen, opacity])
|
||||||
@@ -88,7 +88,7 @@ export const ProgressGuideToast = forwardRef<
|
|||||||
duration: 100,
|
duration: 100,
|
||||||
easing: Easing.out(Easing.cubic),
|
easing: Easing.out(Easing.cubic),
|
||||||
},
|
},
|
||||||
() => runOnJS(playCheckmark)(),
|
() => scheduleOnRN(playCheckmark),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
translateY.set(0)
|
translateY.set(0)
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import {useCallback} from 'react'
|
import {useCallback} from 'react'
|
||||||
import {Pressable, View} from 'react-native'
|
import {Pressable, View} from 'react-native'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
runOnJS,
|
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
withTiming,
|
withTiming,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ScaleAndFadeIn,
|
ScaleAndFadeIn,
|
||||||
@@ -41,7 +41,7 @@ export function NewMessagesPill({
|
|||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
const onPress = useCallback(() => {
|
const onPress = useCallback(() => {
|
||||||
runOnJS(playHaptic)()
|
scheduleOnRN(playHaptic)
|
||||||
onPressInner?.()
|
onPressInner?.()
|
||||||
}, [onPressInner, playHaptic])
|
}, [onPressInner, playHaptic])
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import {Gesture, type GestureType} from 'react-native-gesture-handler'
|
|||||||
import Animated, {
|
import Animated, {
|
||||||
clamp,
|
clamp,
|
||||||
interpolate,
|
interpolate,
|
||||||
runOnJS,
|
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useReducedMotion,
|
useReducedMotion,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
withSequence,
|
withSequence,
|
||||||
withTiming,
|
withTiming,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
|
|
||||||
import {useHaptics} from '#/lib/haptics'
|
import {useHaptics} from '#/lib/haptics'
|
||||||
import {atoms as a, tokens, useTheme} from '#/alf'
|
import {atoms as a, tokens, useTheme} from '#/alf'
|
||||||
@@ -111,7 +111,7 @@ export function SwipeToReply({
|
|||||||
if (pastThreshold && !hit.get()) {
|
if (pastThreshold && !hit.get()) {
|
||||||
hit.set(true)
|
hit.set(true)
|
||||||
runPop()
|
runPop()
|
||||||
runOnJS(playHaptic)('Medium')
|
scheduleOnRN(playHaptic, 'Medium')
|
||||||
} else if (!pastThreshold && hit.get()) {
|
} else if (!pastThreshold && hit.get()) {
|
||||||
hit.set(false)
|
hit.set(false)
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ export function SwipeToReply({
|
|||||||
'worklet'
|
'worklet'
|
||||||
// Only a clean end (finger lifted past threshold) triggers the reply.
|
// Only a clean end (finger lifted past threshold) triggers the reply.
|
||||||
if (hit.get()) {
|
if (hit.get()) {
|
||||||
runOnJS(onReply)()
|
scheduleOnRN(onReply)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.onFinalize(() => {
|
.onFinalize(() => {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import Animated, {
|
|||||||
clamp,
|
clamp,
|
||||||
interpolate,
|
interpolate,
|
||||||
interpolateColor,
|
interpolateColor,
|
||||||
runOnJS,
|
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useDerivedValue,
|
useDerivedValue,
|
||||||
@@ -14,6 +13,7 @@ import Animated, {
|
|||||||
withSequence,
|
withSequence,
|
||||||
withTiming,
|
withTiming,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
|
|
||||||
import {useHaptics} from '#/lib/haptics'
|
import {useHaptics} from '#/lib/haptics'
|
||||||
import {type GestureActions} from './GestureActionView.shared'
|
import {type GestureActions} from './GestureActionView.shared'
|
||||||
@@ -74,17 +74,17 @@ export function GestureActionView({
|
|||||||
() => transX,
|
() => transX,
|
||||||
() => {
|
() => {
|
||||||
if (transX.get() === 0) {
|
if (transX.get() === 0) {
|
||||||
runOnJS(setActiveAction)(null)
|
scheduleOnRN(setActiveAction, null)
|
||||||
} else if (transX.get() < 0) {
|
} else if (transX.get() < 0) {
|
||||||
if (
|
if (
|
||||||
actions.leftSecond &&
|
actions.leftSecond &&
|
||||||
transX.get() <= -actions.leftSecond.threshold
|
transX.get() <= -actions.leftSecond.threshold
|
||||||
) {
|
) {
|
||||||
if (activeAction !== 'leftSecond') {
|
if (activeAction !== 'leftSecond') {
|
||||||
runOnJS(setActiveAction)('leftSecond')
|
scheduleOnRN(setActiveAction, 'leftSecond')
|
||||||
}
|
}
|
||||||
} else if (activeAction !== 'leftFirst') {
|
} else if (activeAction !== 'leftFirst') {
|
||||||
runOnJS(setActiveAction)('leftFirst')
|
scheduleOnRN(setActiveAction, 'leftFirst')
|
||||||
}
|
}
|
||||||
} else if (transX.get() > 0) {
|
} else if (transX.get() > 0) {
|
||||||
if (
|
if (
|
||||||
@@ -92,10 +92,10 @@ export function GestureActionView({
|
|||||||
transX.get() > actions.rightSecond.threshold
|
transX.get() > actions.rightSecond.threshold
|
||||||
) {
|
) {
|
||||||
if (activeAction !== 'rightSecond') {
|
if (activeAction !== 'rightSecond') {
|
||||||
runOnJS(setActiveAction)('rightSecond')
|
scheduleOnRN(setActiveAction, 'rightSecond')
|
||||||
}
|
}
|
||||||
} else if (activeAction !== 'rightFirst') {
|
} else if (activeAction !== 'rightFirst') {
|
||||||
runOnJS(setActiveAction)('rightFirst')
|
scheduleOnRN(setActiveAction, 'rightFirst')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -127,7 +127,7 @@ export function GestureActionView({
|
|||||||
!hitSecond.get()
|
!hitSecond.get()
|
||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
runOnJS(haptic)()
|
scheduleOnRN(haptic)
|
||||||
hitSecond.set(true)
|
hitSecond.set(true)
|
||||||
} else if (
|
} else if (
|
||||||
hitSecond.get() &&
|
hitSecond.get() &&
|
||||||
@@ -144,7 +144,7 @@ export function GestureActionView({
|
|||||||
!hitFirst.get()
|
!hitFirst.get()
|
||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
runOnJS(haptic)()
|
scheduleOnRN(haptic)
|
||||||
hitFirst.set(true)
|
hitFirst.set(true)
|
||||||
} else if (
|
} else if (
|
||||||
hitFirst.get() &&
|
hitFirst.get() &&
|
||||||
@@ -161,7 +161,7 @@ export function GestureActionView({
|
|||||||
!hitSecond.get()
|
!hitSecond.get()
|
||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
runOnJS(haptic)()
|
scheduleOnRN(haptic)
|
||||||
hitSecond.set(true)
|
hitSecond.set(true)
|
||||||
} else if (
|
} else if (
|
||||||
hitSecond.get() &&
|
hitSecond.get() &&
|
||||||
@@ -178,7 +178,7 @@ export function GestureActionView({
|
|||||||
!hitFirst.get()
|
!hitFirst.get()
|
||||||
) {
|
) {
|
||||||
runPopAnimation()
|
runPopAnimation()
|
||||||
runOnJS(haptic)()
|
scheduleOnRN(haptic)
|
||||||
hitFirst.set(true)
|
hitFirst.set(true)
|
||||||
} else if (
|
} else if (
|
||||||
hitFirst.get() &&
|
hitFirst.get() &&
|
||||||
@@ -193,15 +193,15 @@ export function GestureActionView({
|
|||||||
'worklet'
|
'worklet'
|
||||||
if (e.translationX < 0) {
|
if (e.translationX < 0) {
|
||||||
if (hitSecond.get() && actions.leftSecond) {
|
if (hitSecond.get() && actions.leftSecond) {
|
||||||
runOnJS(actions.leftSecond.action)()
|
scheduleOnRN(actions.leftSecond.action)
|
||||||
} else if (hitFirst.get() && actions.leftFirst) {
|
} else if (hitFirst.get() && actions.leftFirst) {
|
||||||
runOnJS(actions.leftFirst.action)()
|
scheduleOnRN(actions.leftFirst.action)
|
||||||
}
|
}
|
||||||
} else if (e.translationX > 0) {
|
} else if (e.translationX > 0) {
|
||||||
if (hitSecond.get() && actions.rightSecond) {
|
if (hitSecond.get() && actions.rightSecond) {
|
||||||
runOnJS(actions.rightSecond.action)()
|
scheduleOnRN(actions.rightSecond.action)
|
||||||
} else if (hitSecond.get() && actions.rightFirst) {
|
} else if (hitSecond.get() && actions.rightFirst) {
|
||||||
runOnJS(actions.rightFirst.action)()
|
scheduleOnRN(actions.rightFirst.action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
transX.set(() => withTiming(0, {duration: 200}))
|
transX.set(() => withTiming(0, {duration: 200}))
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import {
|
|||||||
import Animated, {
|
import Animated, {
|
||||||
Extrapolation,
|
Extrapolation,
|
||||||
interpolate,
|
interpolate,
|
||||||
runOnJS,
|
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {GlassContainer} from 'expo-glass-effect'
|
import {GlassContainer} from 'expo-glass-effect'
|
||||||
import {LinearGradient} from 'expo-linear-gradient'
|
import {LinearGradient} from 'expo-linear-gradient'
|
||||||
import {type $Typed, type ChatBskyConvoDefs} from '@atproto/api'
|
import {type $Typed, type ChatBskyConvoDefs} from '@atproto/api'
|
||||||
@@ -95,7 +95,7 @@ export function MessageComposer({
|
|||||||
onEnd: evt => {
|
onEnd: evt => {
|
||||||
'worklet'
|
'worklet'
|
||||||
if (IS_ANDROID && evt.progress === 0) {
|
if (IS_ANDROID && evt.progress === 0) {
|
||||||
runOnJS(blur)()
|
scheduleOnRN(blur)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
KeyboardGestureArea,
|
KeyboardGestureArea,
|
||||||
} from 'react-native-keyboard-controller'
|
} from 'react-native-keyboard-controller'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
runOnJS,
|
|
||||||
type ScrollEvent,
|
type ScrollEvent,
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
@@ -22,6 +21,7 @@ import Animated, {
|
|||||||
withTiming,
|
withTiming,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {
|
import {
|
||||||
type $Typed,
|
type $Typed,
|
||||||
type AppBskyEmbedRecord,
|
type AppBskyEmbedRecord,
|
||||||
@@ -502,7 +502,7 @@ export function MessagesList({
|
|||||||
(e.contentOffset.y > newMessagesPill.startContentOffset + 200 ||
|
(e.contentOffset.y > newMessagesPill.startContentOffset + 200 ||
|
||||||
isAtBottom.get())
|
isAtBottom.get())
|
||||||
) {
|
) {
|
||||||
runOnJS(setNewMessagesPill)({
|
scheduleOnRN(setNewMessagesPill, {
|
||||||
show: false,
|
show: false,
|
||||||
startContentOffset: 0,
|
startContentOffset: 0,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import Animated, {
|
|||||||
type AnimatedRef,
|
type AnimatedRef,
|
||||||
Extrapolation,
|
Extrapolation,
|
||||||
interpolate,
|
interpolate,
|
||||||
runOnJS,
|
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedProps,
|
useAnimatedProps,
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {BlurView} from 'expo-blur'
|
import {BlurView} from 'expo-blur'
|
||||||
import {useIsFetching} from '@tanstack/react-query'
|
import {useIsFetching} from '@tanstack/react-query'
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ function useShouldAnimateSpinner({
|
|||||||
() => scrollY.get() < -5,
|
() => scrollY.get() < -5,
|
||||||
(value, prevValue) => {
|
(value, prevValue) => {
|
||||||
if (value !== prevValue) {
|
if (value !== prevValue) {
|
||||||
runOnJS(setIsOverscrolled)(value)
|
scheduleOnRN(setIsOverscrolled, value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[scrollY],
|
[scrollY],
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import {memo, useMemo, useState} from 'react'
|
import {memo, useMemo, useState} from 'react'
|
||||||
import {type LayoutChangeEvent, StyleSheet, View} from 'react-native'
|
import {type LayoutChangeEvent, StyleSheet, View} from 'react-native'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
runOnJS,
|
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
withTiming,
|
withTiming,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {
|
import {
|
||||||
type AppBskyActorDefs,
|
type AppBskyActorDefs,
|
||||||
type AppBskyLabelerDefs,
|
type AppBskyLabelerDefs,
|
||||||
@@ -151,7 +151,7 @@ const MinimalHeader = memo(function MinimalHeader({
|
|||||||
() => scrollY.get() > 100,
|
() => scrollY.get() > 100,
|
||||||
(value, prev) => {
|
(value, prev) => {
|
||||||
if (prev !== value) {
|
if (prev !== value) {
|
||||||
runOnJS(setVisible)(value)
|
scheduleOnRN(setVisible, value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import {
|
|||||||
import Animated, {
|
import Animated, {
|
||||||
clamp,
|
clamp,
|
||||||
interpolate,
|
interpolate,
|
||||||
runOnJS,
|
|
||||||
runOnUI,
|
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
@@ -20,6 +18,7 @@ import {
|
|||||||
useSafeAreaFrame,
|
useSafeAreaFrame,
|
||||||
useSafeAreaInsets,
|
useSafeAreaInsets,
|
||||||
} from 'react-native-safe-area-context'
|
} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnRN, scheduleOnUI} from 'react-native-worklets'
|
||||||
import {useEventListener} from 'expo'
|
import {useEventListener} from 'expo'
|
||||||
import {type VideoPlayer} from 'expo-video'
|
import {type VideoPlayer} from 'expo-video'
|
||||||
|
|
||||||
@@ -66,7 +65,7 @@ export function Scrubber({
|
|||||||
() => Math.round(seekProgressSV.get()),
|
() => Math.round(seekProgressSV.get()),
|
||||||
(progress, prevProgress) => {
|
(progress, prevProgress) => {
|
||||||
if (progress !== prevProgress) {
|
if (progress !== prevProgress) {
|
||||||
runOnJS(setCurrentSeekTime)(progress)
|
scheduleOnRN(setCurrentSeekTime, progress)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -76,11 +75,11 @@ export function Scrubber({
|
|||||||
player?.seekBy(time)
|
player?.seekBy(time)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
runOnUI(() => {
|
scheduleOnUI(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
isSeekingSV.set(false)
|
isSeekingSV.set(false)
|
||||||
seekingAnimationSV.set(withTiming(0, {duration: 500}))
|
seekingAnimationSV.set(withTiming(0, {duration: 500}))
|
||||||
})()
|
})
|
||||||
}, 50)
|
}, 50)
|
||||||
},
|
},
|
||||||
[player, isSeekingSV, seekingAnimationSV],
|
[player, isSeekingSV, seekingAnimationSV],
|
||||||
@@ -116,7 +115,7 @@ export function Scrubber({
|
|||||||
|
|
||||||
// it's seek by, so offset by the current time
|
// it's seek by, so offset by the current time
|
||||||
// seekBy sets isSeekingSV back to false, so no need to do that here
|
// seekBy sets isSeekingSV back to false, so no need to do that here
|
||||||
runOnJS(seekBy)(newTime - currentTimeSV.get())
|
scheduleOnRN(seekBy, newTime - currentTimeSV.get())
|
||||||
})
|
})
|
||||||
}, [
|
}, [
|
||||||
scrollGesture,
|
scrollGesture,
|
||||||
@@ -253,7 +252,7 @@ function PlayerListener({
|
|||||||
if (duration !== 0) {
|
if (duration !== 0) {
|
||||||
setDuration(Math.round(duration))
|
setDuration(Math.round(duration))
|
||||||
}
|
}
|
||||||
runOnUI(updateTime)(evt.currentTime, duration)
|
scheduleOnUI(updateTime, evt.currentTime, duration)
|
||||||
})
|
})
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import Animated, {
|
|||||||
interpolateColor,
|
interpolateColor,
|
||||||
LayoutAnimationConfig,
|
LayoutAnimationConfig,
|
||||||
LinearTransition,
|
LinearTransition,
|
||||||
runOnUI,
|
|
||||||
scrollTo,
|
scrollTo,
|
||||||
useAnimatedRef,
|
useAnimatedRef,
|
||||||
useAnimatedScrollHandler,
|
useAnimatedScrollHandler,
|
||||||
@@ -45,6 +44,7 @@ import Animated, {
|
|||||||
ZoomOut,
|
ZoomOut,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
import {scheduleOnUI} from 'react-native-worklets'
|
||||||
import * as FileSystem from 'expo-file-system'
|
import * as FileSystem from 'expo-file-system'
|
||||||
import {type ImagePickerAsset} from 'expo-image-picker'
|
import {type ImagePickerAsset} from 'expo-image-picker'
|
||||||
import {
|
import {
|
||||||
@@ -2382,7 +2382,7 @@ function useScrollTracker({
|
|||||||
|
|
||||||
const onScrollViewContentSizeChange = useCallback(
|
const onScrollViewContentSizeChange = useCallback(
|
||||||
(_width: number, height: number) => {
|
(_width: number, height: number) => {
|
||||||
runOnUI(onScrollViewContentSizeChangeUIThread)(height)
|
scheduleOnUI(onScrollViewContentSizeChangeUIThread, height)
|
||||||
},
|
},
|
||||||
[onScrollViewContentSizeChangeUIThread],
|
[onScrollViewContentSizeChangeUIThread],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ import PagerView, {
|
|||||||
type PageScrollStateChangedNativeEventData,
|
type PageScrollStateChangedNativeEventData,
|
||||||
} from 'react-native-pager-view'
|
} from 'react-native-pager-view'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
runOnJS,
|
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useEvent,
|
useEvent,
|
||||||
useHandler,
|
useHandler,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {useFocusEffect} from '@react-navigation/native'
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
|
|
||||||
import {useSetDrawerSwipeDisabled} from '#/state/shell'
|
import {useSetDrawerSwipeDisabled} from '#/state/shell'
|
||||||
@@ -125,7 +125,7 @@ export function Pager({
|
|||||||
},
|
},
|
||||||
onPageScrollStateChanged(e: PageScrollStateChangedNativeEventData) {
|
onPageScrollStateChanged(e: PageScrollStateChangedNativeEventData) {
|
||||||
'worklet'
|
'worklet'
|
||||||
runOnJS(setIsIdle)(e.pageScrollState === 'idle')
|
scheduleOnRN(setIsIdle, e.pageScrollState === 'idle')
|
||||||
if (dragState.get() === 'idle' && e.pageScrollState === 'settling') {
|
if (dragState.get() === 'idle' && e.pageScrollState === 'settling') {
|
||||||
// This is a programmatic scroll on Android.
|
// This is a programmatic scroll on Android.
|
||||||
// Stay "idle" to match iOS and avoid confusing downstream code.
|
// Stay "idle" to match iOS and avoid confusing downstream code.
|
||||||
@@ -137,7 +137,7 @@ export function Pager({
|
|||||||
onPageSelected(e: PagerViewOnPageSelectedEventData) {
|
onPageSelected(e: PagerViewOnPageSelectedEventData) {
|
||||||
'worklet'
|
'worklet'
|
||||||
didInit.set(true)
|
didInit.set(true)
|
||||||
runOnJS(onPageSelectedJSThread)(e.position)
|
scheduleOnRN(onPageSelectedJSThread, e.position)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[parentOnPageScrollStateChanged],
|
[parentOnPageScrollStateChanged],
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
type AnimatedRef,
|
type AnimatedRef,
|
||||||
runOnUI,
|
|
||||||
scrollTo,
|
scrollTo,
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedRef,
|
useAnimatedRef,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnUI} from 'react-native-worklets'
|
||||||
|
|
||||||
import {ScrollProvider} from '#/lib/ScrollContext'
|
import {ScrollProvider} from '#/lib/ScrollContext'
|
||||||
import {
|
import {
|
||||||
@@ -181,7 +181,7 @@ export function PagerWithHeader({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const onTabPressed = useCallback(() => {
|
const onTabPressed = useCallback(() => {
|
||||||
runOnUI(adjustScrollForOtherPages)('dragging')
|
scheduleOnUI(adjustScrollForOtherPages, 'dragging')
|
||||||
}, [adjustScrollForOtherPages])
|
}, [adjustScrollForOtherPages])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
interpolate,
|
interpolate,
|
||||||
runOnJS,
|
|
||||||
runOnUI,
|
|
||||||
scrollTo,
|
scrollTo,
|
||||||
type SharedValue,
|
type SharedValue,
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
@@ -16,6 +14,7 @@ import Animated, {
|
|||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnRN, scheduleOnUI} from 'react-native-worklets'
|
||||||
|
|
||||||
import {PressableWithHover} from '#/view/com/util/PressableWithHover'
|
import {PressableWithHover} from '#/view/com/util/PressableWithHover'
|
||||||
import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture'
|
import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture'
|
||||||
@@ -126,7 +125,7 @@ export function TabBar({
|
|||||||
const progress = dragProgress.get()
|
const progress = dragProgress.get()
|
||||||
const offset = progressToOffset(progress)
|
const offset = progressToOffset(progress)
|
||||||
// It's unclear why we need to go back to JS here. It seems iOS-specific.
|
// It's unclear why we need to go back to JS here. It seems iOS-specific.
|
||||||
runOnJS(scrollToOffsetJS)(offset)
|
scheduleOnRN(scrollToOffsetJS, offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -303,7 +302,7 @@ export function TabBar({
|
|||||||
|
|
||||||
const onPressItem = useCallback(
|
const onPressItem = useCallback(
|
||||||
(index: number) => {
|
(index: number) => {
|
||||||
runOnUI(onPressUIThread)(index)
|
scheduleOnUI(onPressUIThread, index)
|
||||||
onSelect?.(index)
|
onSelect?.(index)
|
||||||
if (index === selectedPage) {
|
if (index === selectedPage) {
|
||||||
onPressSelected?.(index)
|
onPressSelected?.(index)
|
||||||
@@ -409,14 +408,14 @@ function TabBarItem({
|
|||||||
|
|
||||||
const handleLayout = useCallback(
|
const handleLayout = useCallback(
|
||||||
(e: LayoutChangeEvent) => {
|
(e: LayoutChangeEvent) => {
|
||||||
runOnUI(onItemLayout)(index, e.nativeEvent.layout)
|
scheduleOnUI(onItemLayout, index, e.nativeEvent.layout)
|
||||||
},
|
},
|
||||||
[index, onItemLayout],
|
[index, onItemLayout],
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleTextLayout = useCallback(
|
const handleTextLayout = useCallback(
|
||||||
(e: LayoutChangeEvent) => {
|
(e: LayoutChangeEvent) => {
|
||||||
runOnUI(onTextLayout)(index, e.nativeEvent.layout)
|
scheduleOnUI(onTextLayout, index, e.nativeEvent.layout)
|
||||||
},
|
},
|
||||||
[index, onTextLayout],
|
[index, onTextLayout],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import {forwardRef, memo, useDeferredValue, useMemo} from 'react'
|
|||||||
import {RefreshControl, type ViewToken} from 'react-native'
|
import {RefreshControl, type ViewToken} from 'react-native'
|
||||||
import {
|
import {
|
||||||
type FlatListPropsWithLayout,
|
type FlatListPropsWithLayout,
|
||||||
runOnJS,
|
|
||||||
useAnimatedScrollHandler,
|
useAnimatedScrollHandler,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
|
import {scheduleOnRN} from 'react-native-worklets'
|
||||||
import {updateActiveVideoViewAsync} from '@bsky.app/video'
|
import {updateActiveVideoViewAsync} from '@bsky.app/video'
|
||||||
|
|
||||||
import {useDedupe} from '#/lib/hooks/useDedupe'
|
import {useDedupe} from '#/lib/hooks/useDedupe'
|
||||||
@@ -85,7 +85,7 @@ let List = forwardRef<ListMethods, ListProps>(
|
|||||||
onBeginDragFromContext?.(e, ctx)
|
onBeginDragFromContext?.(e, ctx)
|
||||||
},
|
},
|
||||||
onEndDrag(e, ctx) {
|
onEndDrag(e, ctx) {
|
||||||
runOnJS(updateActiveVideoViewAsync)()
|
scheduleOnRN(updateActiveVideoViewAsync)
|
||||||
onEndDragFromContext?.(e, ctx)
|
onEndDragFromContext?.(e, ctx)
|
||||||
},
|
},
|
||||||
onScroll(e, ctx) {
|
onScroll(e, ctx) {
|
||||||
@@ -95,18 +95,18 @@ let List = forwardRef<ListMethods, ListProps>(
|
|||||||
if (isScrolledDown.get() !== didScrollDown) {
|
if (isScrolledDown.get() !== didScrollDown) {
|
||||||
isScrolledDown.set(didScrollDown)
|
isScrolledDown.set(didScrollDown)
|
||||||
if (onScrolledDownChange != null) {
|
if (onScrolledDownChange != null) {
|
||||||
runOnJS(handleScrolledDownChange)(didScrollDown)
|
scheduleOnRN(handleScrolledDownChange, didScrollDown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_IOS) {
|
if (IS_IOS) {
|
||||||
runOnJS(dedupe)(updateActiveVideoViewAsync)
|
scheduleOnRN(dedupe, updateActiveVideoViewAsync)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Note: adding onMomentumBegin here makes simulator scroll
|
// Note: adding onMomentumBegin here makes simulator scroll
|
||||||
// lag on Android. So either don't add it, or figure out why.
|
// lag on Android. So either don't add it, or figure out why.
|
||||||
onMomentumEnd(e, ctx) {
|
onMomentumEnd(e, ctx) {
|
||||||
runOnJS(updateActiveVideoViewAsync)()
|
scheduleOnRN(updateActiveVideoViewAsync)
|
||||||
onMomentumEndFromContext?.(e, ctx)
|
onMomentumEndFromContext?.(e, ctx)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user