From 30c23942715405e4d2ab3985bed104c7283e3534 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Fri, 12 Sep 2025 13:11:52 +0300 Subject: [PATCH] temp rm pagerview --- package.json | 1 - src/view/com/lightbox/ImageViewing/index.tsx | 313 +------------------ src/view/com/pager/Pager.tsx | 111 +------ yarn.lock | 5 - 4 files changed, 13 insertions(+), 417 deletions(-) diff --git a/package.json b/package.json index b816b1c4a1..40b0f800be 100644 --- a/package.json +++ b/package.json @@ -192,7 +192,6 @@ "react-native-get-random-values": "~1.11.0", "react-native-keyboard-controller": "1.18.5", "react-native-mmkv": "^2.12.2", - "react-native-pager-view": "6.8.0", "react-native-progress": "bluesky-social/react-native-progress", "react-native-qrcode-styled": "^0.3.3", "react-native-reanimated": "^3.19.1", diff --git a/src/view/com/lightbox/ImageViewing/index.tsx b/src/view/com/lightbox/ImageViewing/index.tsx index bb3c39f594..6c1531ea36 100644 --- a/src/view/com/lightbox/ImageViewing/index.tsx +++ b/src/view/com/lightbox/ImageViewing/index.tsx @@ -8,37 +8,27 @@ // Original code copied and simplified from the link below as the codebase is currently not maintained: // https://github.com/jobtoday/react-native-image-viewing -import React, {useCallback, useEffect, useMemo, useState} from 'react' -import {LayoutAnimation, PixelRatio, StyleSheet, View} from 'react-native' +import React, {useEffect, useMemo, useState} from 'react' +import {LayoutAnimation, StyleSheet, View} from 'react-native' import {SystemBars} from 'react-native-edge-to-edge' -import {Gesture} from 'react-native-gesture-handler' -import PagerView from 'react-native-pager-view' import Animated, { type AnimatedRef, cancelAnimation, - interpolate, measure, runOnJS, type SharedValue, useAnimatedReaction, useAnimatedRef, useAnimatedStyle, - useDerivedValue, useSharedValue, - withDecay, withSpring, type WithSpringConfig, } from 'react-native-reanimated' -import { - SafeAreaView, - useSafeAreaFrame, - useSafeAreaInsets, -} from 'react-native-safe-area-context' +import {SafeAreaView} from 'react-native-safe-area-context' import * as ScreenOrientation from 'expo-screen-orientation' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {Trans} from '@lingui/macro' -import {type Dimensions} from '#/lib/media/types' import {colors, s} from '#/lib/styles' import {isIOS} from '#/platform/detection' import {type Lightbox} from '#/state/lightbox' @@ -48,14 +38,10 @@ import {ScrollView} from '#/view/com/util/Views' import {useTheme} from '#/alf' import {setSystemUITheme} from '#/alf/util/systemUI' import {PlatformInfo} from '../../../../../modules/expo-bluesky-swiss-army' -import {type ImageSource, type Transform} from './@types' +import {type ImageSource} from './@types' import ImageDefaultHeader from './components/ImageDefaultHeader' -import ImageItem from './components/ImageItem/ImageItem' - -type Rect = {x: number; y: number; width: number; height: number} const PORTRAIT_UP = ScreenOrientation.OrientationLock.PORTRAIT_UP -const PIXEL_RATIO = PixelRatio.get() const SLOW_SPRING: WithSpringConfig = { mass: isIOS ? 1.25 : 0.75, @@ -210,10 +196,9 @@ function ImageView({ }) { const {images, index: initialImageIndex} = lightbox const isAnimated = useMemo(() => canAnimate(lightbox), [lightbox]) - const [isScaled, setIsScaled] = useState(false) - const [isDragging, setIsDragging] = useState(false) - const [imageIndex, setImageIndex] = useState(initialImageIndex) - const [showControls, setShowControls] = useState(true) + const [isScaled] = useState(false) + const [imageIndex] = useState(initialImageIndex) + const [showControls] = useState(true) const [isAltExpanded, setAltExpanded] = React.useState(false) const dismissSwipeTranslateY = useSharedValue(0) const isFlyingAway = useSharedValue(false) @@ -285,17 +270,6 @@ function ImageView({ } }) - const onTap = useCallback(() => { - setShowControls(show => !show) - }, []) - - const onZoom = useCallback((nextIsScaled: boolean) => { - setIsScaled(nextIsScaled) - if (nextIsScaled) { - setShowControls(false) - } - }, []) - useAnimatedReaction( () => { const screenSize = measure(safeAreaRef) @@ -335,37 +309,6 @@ function ImageView({ style={[styles.backdrop, backdropStyle]} renderToHardwareTextureAndroid /> - { - setImageIndex(e.nativeEvent.position) - setIsScaled(false) - }} - onPageScrollStateChanged={e => { - setIsDragging(e.nativeEvent.pageScrollState !== 'idle') - }} - overdrag={true} - style={styles.pager}> - {images.map((imageSrc, i) => ( - - - - ))} - void - onTap: () => void - onZoom: (scaled: boolean) => void - isScrollViewBeingDragged: boolean - isScaled: boolean - isActive: boolean - isFlyingAway: SharedValue - showControls: boolean - safeAreaRef: AnimatedRef - openProgress: SharedValue - dismissSwipeTranslateY: SharedValue -}) { - const [fetchedDims, setFetchedDims] = React.useState(null) - const dims = fetchedDims ?? imageSrc.dimensions ?? imageSrc.thumbDimensions - let imageAspect: number | undefined - if (dims) { - imageAspect = dims.width / dims.height - if (Number.isNaN(imageAspect)) { - imageAspect = undefined - } - } - - const safeFrameDelayedForJSThreadOnly = useSafeAreaFrame() - const safeInsetsDelayedForJSThreadOnly = useSafeAreaInsets() - const measureSafeArea = React.useCallback(() => { - 'worklet' - let safeArea: Rect | null = measure(safeAreaRef) - if (!safeArea) { - if (_WORKLET) { - console.error('Expected to always be able to measure safe area.') - } - const frame = safeFrameDelayedForJSThreadOnly - const insets = safeInsetsDelayedForJSThreadOnly - safeArea = { - x: frame.x + insets.left, - y: frame.y + insets.top, - width: frame.width - insets.left - insets.right, - height: frame.height - insets.top - insets.bottom, - } - } - return safeArea - }, [ - safeFrameDelayedForJSThreadOnly, - safeInsetsDelayedForJSThreadOnly, - safeAreaRef, - ]) - - const {thumbRect} = imageSrc - const transforms = useDerivedValue(() => { - 'worklet' - const safeArea = measureSafeArea() - const openProgressValue = openProgress.get() - const dismissTranslateY = - isActive && openProgressValue === 1 ? dismissSwipeTranslateY.get() : 0 - - if (openProgressValue === 0 && isFlyingAway.get()) { - return { - isHidden: true, - isResting: false, - scaleAndMoveTransform: [], - cropFrameTransform: [], - cropContentTransform: [], - } - } - - if (isActive && thumbRect && imageAspect && openProgressValue < 1) { - return interpolateTransform( - openProgressValue, - thumbRect, - safeArea, - imageAspect, - ) - } - return { - isHidden: false, - isResting: dismissTranslateY === 0, - scaleAndMoveTransform: [{translateY: dismissTranslateY}], - cropFrameTransform: [], - cropContentTransform: [], - } - }) - - const dismissSwipePan = Gesture.Pan() - .enabled(isActive && !isScaled) - .activeOffsetY([-10, 10]) - .failOffsetX([-10, 10]) - .maxPointers(1) - .onUpdate(e => { - 'worklet' - if (openProgress.get() !== 1 || isFlyingAway.get()) { - return - } - dismissSwipeTranslateY.set(e.translationY) - }) - .onEnd(e => { - 'worklet' - if (openProgress.get() !== 1 || isFlyingAway.get()) { - return - } - if (Math.abs(e.velocityY) > 200) { - isFlyingAway.set(true) - if (dismissSwipeTranslateY.get() === 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.set(1) - } - dismissSwipeTranslateY.set(() => { - 'worklet' - return withDecay({ - velocity: e.velocityY, - velocityFactor: Math.max(3500 / 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.set(() => { - 'worklet' - return withSpring(0, { - stiffness: 700, - damping: 50, - }) - }) - } - }) - - return ( - - ) -} - function LightboxFooter({ images, index, @@ -698,90 +483,6 @@ const styles = StyleSheet.create({ }, }) -function interpolatePx( - px: number, - inputRange: readonly number[], - outputRange: readonly number[], -) { - 'worklet' - const value = interpolate(px, inputRange, outputRange) - return Math.round(value * PIXEL_RATIO) / PIXEL_RATIO -} - -function interpolateTransform( - progress: number, - thumbnailDims: { - pageX: number - width: number - pageY: number - height: number - }, - safeArea: {width: number; height: number; x: number; y: number}, - imageAspect: number, -): { - scaleAndMoveTransform: Transform - cropFrameTransform: Transform - cropContentTransform: Transform - isResting: boolean - isHidden: boolean -} { - 'worklet' - const thumbAspect = thumbnailDims.width / thumbnailDims.height - let uncroppedInitialWidth - let uncroppedInitialHeight - if (imageAspect > thumbAspect) { - uncroppedInitialWidth = thumbnailDims.height * imageAspect - uncroppedInitialHeight = thumbnailDims.height - } else { - uncroppedInitialWidth = thumbnailDims.width - uncroppedInitialHeight = thumbnailDims.width / imageAspect - } - const safeAreaAspect = safeArea.width / safeArea.height - let finalWidth - let finalHeight - if (safeAreaAspect > imageAspect) { - finalWidth = safeArea.height * imageAspect - finalHeight = safeArea.height - } else { - finalWidth = safeArea.width - finalHeight = safeArea.width / imageAspect - } - const initialScale = Math.min( - uncroppedInitialWidth / finalWidth, - uncroppedInitialHeight / finalHeight, - ) - const croppedFinalWidth = thumbnailDims.width / initialScale - const croppedFinalHeight = thumbnailDims.height / initialScale - const screenCenterX = safeArea.width / 2 - const screenCenterY = safeArea.height / 2 - const thumbnailSafeAreaX = thumbnailDims.pageX - safeArea.x - const thumbnailSafeAreaY = thumbnailDims.pageY - safeArea.y - const thumbnailCenterX = thumbnailSafeAreaX + thumbnailDims.width / 2 - const thumbnailCenterY = thumbnailSafeAreaY + thumbnailDims.height / 2 - const initialTranslateX = thumbnailCenterX - screenCenterX - const initialTranslateY = thumbnailCenterY - screenCenterY - const scale = interpolate(progress, [0, 1], [initialScale, 1]) - const translateX = interpolatePx(progress, [0, 1], [initialTranslateX, 0]) - const translateY = interpolatePx(progress, [0, 1], [initialTranslateY, 0]) - const cropScaleX = interpolate( - progress, - [0, 1], - [croppedFinalWidth / finalWidth, 1], - ) - const cropScaleY = interpolate( - progress, - [0, 1], - [croppedFinalHeight / finalHeight, 1], - ) - return { - isHidden: false, - isResting: progress === 1, - scaleAndMoveTransform: [{translateX}, {translateY}, {scale}], - cropFrameTransform: [{scaleX: cropScaleX}, {scaleY: cropScaleY}], - cropContentTransform: [{scaleX: 1 / cropScaleX}, {scaleY: 1 / cropScaleY}], - } -} - function withClampedSpring(value: any, config: WithSpringConfig) { 'worklet' return withSpring(value, {...config, overshootClamping: true}) diff --git a/src/view/com/pager/Pager.tsx b/src/view/com/pager/Pager.tsx index 6d0982ad8d..e4ba5cea44 100644 --- a/src/view/com/pager/Pager.tsx +++ b/src/view/com/pager/Pager.tsx @@ -1,6 +1,5 @@ import { type JSX, - memo, useCallback, useContext, useImperativeHandle, @@ -11,25 +10,13 @@ import { import {View} from 'react-native' import {DrawerGestureContext} from 'react-native-drawer-layout' import {Gesture, GestureDetector} from 'react-native-gesture-handler' -import PagerView, { - type PagerViewOnPageScrollEventData, - type PagerViewOnPageSelectedEvent, - type PagerViewOnPageSelectedEventData, - type PageScrollStateChangedNativeEventData, -} from 'react-native-pager-view' -import Animated, { - runOnJS, - type SharedValue, - useEvent, - useHandler, - useSharedValue, -} from 'react-native-reanimated' +import {type SharedValue, useSharedValue} from 'react-native-reanimated' import {useFocusEffect} from '@react-navigation/native' import {useSetDrawerSwipeDisabled} from '#/state/shell' import {atoms as a, native} from '#/alf' -export type PageSelectedEvent = PagerViewOnPageSelectedEvent +export type PageSelectedEvent = any export interface PagerRef { setPage: (index: number) => void @@ -58,23 +45,18 @@ interface Props { testID?: string } -const AnimatedPagerView = Animated.createAnimatedComponent(PagerView) -const MemoizedAnimatedPagerView = memo(AnimatedPagerView) - export function Pager({ ref, children, initialPage = 0, renderTabBar, - onPageSelected: parentOnPageSelected, onTabPressed: parentOnTabPressed, - onPageScrollStateChanged: parentOnPageScrollStateChanged, testID, }: React.PropsWithChildren) { - const [selectedPage, setSelectedPage] = useState(initialPage) - const pagerView = useRef(null) + const [selectedPage] = useState(initialPage) + const pagerView = useRef(null) - const [isIdle, setIsIdle] = useState(true) + const [isIdle] = useState(true) const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled() useFocusEffect( useCallback(() => { @@ -92,14 +74,6 @@ export function Pager({ }, })) - const onPageSelectedJSThread = useCallback( - (nextPosition: number) => { - setSelectedPage(nextPosition) - parentOnPageSelected?.(nextPosition) - }, - [setSelectedPage, parentOnPageSelected], - ) - const onTabBarSelect = useCallback( (index: number) => { parentOnTabPressed?.(index) @@ -110,38 +84,6 @@ export function Pager({ const dragState = useSharedValue<'idle' | 'settling' | 'dragging'>('idle') const dragProgress = useSharedValue(selectedPage) - const didInit = useSharedValue(false) - const handlePageScroll = usePagerHandlers( - { - onPageScroll(e: PagerViewOnPageScrollEventData) { - 'worklet' - if (didInit.get() === false) { - // On iOS, there's a spurious scroll event with 0 position - // even if a different page was supplied as the initial page. - // Ignore it and wait for the first confirmed selection instead. - return - } - dragProgress.set(e.offset + e.position) - }, - onPageScrollStateChanged(e: PageScrollStateChangedNativeEventData) { - 'worklet' - runOnJS(setIsIdle)(e.pageScrollState === 'idle') - if (dragState.get() === 'idle' && e.pageScrollState === 'settling') { - // This is a programmatic scroll on Android. - // Stay "idle" to match iOS and avoid confusing downstream code. - return - } - dragState.set(e.pageScrollState) - parentOnPageScrollStateChanged?.(e.pageScrollState) - }, - onPageSelected(e: PagerViewOnPageSelectedEventData) { - 'worklet' - didInit.set(true) - runOnJS(onPageSelectedJSThread)(e.position) - }, - }, - [parentOnPageScrollStateChanged], - ) return ( @@ -151,15 +93,7 @@ export function Pager({ dragProgress, dragState, })} - - - {children} - - + {children} ) } @@ -177,36 +111,3 @@ function DrawerGestureRequireFail({children}: {children: React.ReactNode}) { return {children} } - -function usePagerHandlers( - handlers: { - onPageScroll: (e: PagerViewOnPageScrollEventData) => void - onPageScrollStateChanged: (e: PageScrollStateChangedNativeEventData) => void - onPageSelected: (e: PagerViewOnPageSelectedEventData) => void - }, - dependencies: unknown[], -) { - const {doDependenciesDiffer} = useHandler(handlers as any, dependencies) - const subscribeForEvents = [ - 'onPageScroll', - 'onPageScrollStateChanged', - 'onPageSelected', - ] - return useEvent( - event => { - 'worklet' - const {onPageScroll, onPageScrollStateChanged, onPageSelected} = handlers - if (event.eventName.endsWith('onPageScroll')) { - onPageScroll(event as any as PagerViewOnPageScrollEventData) - } else if (event.eventName.endsWith('onPageScrollStateChanged')) { - onPageScrollStateChanged( - event as any as PageScrollStateChangedNativeEventData, - ) - } else if (event.eventName.endsWith('onPageSelected')) { - onPageSelected(event as any as PagerViewOnPageSelectedEventData) - } - }, - subscribeForEvents, - doDependenciesDiffer, - ) -} diff --git a/yarn.lock b/yarn.lock index 84c7e2d713..6a3c39187d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16806,11 +16806,6 @@ react-native-mmkv@^2.12.2: resolved "https://registry.yarnpkg.com/react-native-mmkv/-/react-native-mmkv-2.12.2.tgz#4bba0f5f04e2cf222494cce3a9794ba6a4894dee" integrity sha512-6058Aq0p57chPrUutLGe9fYoiDVDNMU2PKV+lLFUJ3GhoHvUrLdsS1PDSCLr00yqzL4WJQ7TTzH+V8cpyrNcfg== -react-native-pager-view@6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.8.0.tgz#5bac05203d911bf9bf039d47db41b1313dbd1a7a" - integrity sha512-/wgFV8nB4TLnQ6j9e3TvNrHbPF5TINMZHaXt86GOV0NSJNMVGkWguniJVKrYLm85LL8KVhRkgdh43Rdu7PvW1A== - react-native-progress@bluesky-social/react-native-progress: version "5.0.0" resolved "https://codeload.github.com/bluesky-social/react-native-progress/tar.gz/5a372f4f2ce5feb26f4f47b6a4d187ab9b923ab4"