diff --git a/app/components/post_list/post_list.tsx b/app/components/post_list/post_list.tsx index cd7ae4ed912..f2ad16facd1 100644 --- a/app/components/post_list/post_list.tsx +++ b/app/components/post_list/post_list.tsx @@ -4,7 +4,7 @@ import {FlatList} from '@stream-io/flat-list-mvcp'; import React, {type ReactElement, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {DeviceEventEmitter, type ListRenderItemInfo, type NativeScrollEvent, type NativeSyntheticEvent, Platform, type StyleProp, StyleSheet, type ViewStyle} from 'react-native'; -import Animated from 'react-native-reanimated'; +import Animated, {type AnimatedStyle} from 'react-native-reanimated'; import {fetchPosts, fetchPostThread} from '@actions/remote/post'; import CombinedUserActivity from '@components/post_list/combined_user_activity'; @@ -27,7 +27,7 @@ import type PostModel from '@typings/database/models/servers/post'; type Props = { appsEnabled: boolean; channelId: string; - contentContainerStyle?: StyleProp; + contentContainerStyle?: StyleProp>; currentTimezone: string | null; currentUserId: string; currentUsername: string; @@ -354,6 +354,8 @@ const PostList = ({ onScroll={onScroll} onScrollToIndexFailed={onScrollToIndexFailed} onViewableItemsChanged={onViewableItemsChanged} + + // @ts-expect-error old style ref ref={listRef} removeClippedSubviews={true} renderItem={renderItem} diff --git a/app/components/profile_picture/image.tsx b/app/components/profile_picture/image.tsx index 623b1b0f280..9791f218e18 100644 --- a/app/components/profile_picture/image.tsx +++ b/app/components/profile_picture/image.tsx @@ -92,6 +92,8 @@ const Image = ({author, forwardRef, iconSize, size, source, url}: Props) => { return ( diff --git a/app/context/gallery/index.tsx b/app/context/gallery/index.tsx index c766f1e93cc..df99e40982e 100644 --- a/app/context/gallery/index.tsx +++ b/app/context/gallery/index.tsx @@ -1,14 +1,14 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useEffect, useLayoutEffect} from 'react'; -import Animated, {makeMutable, runOnUI} from 'react-native-reanimated'; +import {useEffect, useLayoutEffect} from 'react'; +import Animated, {makeMutable, runOnUI, type AnimatedRef} from 'react-native-reanimated'; import type {GalleryManagerSharedValues} from '@typings/screens/gallery'; export interface GalleryManagerItem { index: number; - ref: React.RefObject; + ref: AnimatedRef; } export interface GalleryManagerItems { @@ -79,7 +79,7 @@ class Gallery { })(); } - public registerItem(index: number, ref: React.RefObject) { + public registerItem(index: number, ref: AnimatedRef) { if (this.items.has(index)) { return; } diff --git a/app/hooks/header.ts b/app/hooks/header.ts index cbfde035722..1f029fa948b 100644 --- a/app/hooks/header.ts +++ b/app/hooks/header.ts @@ -95,7 +95,7 @@ export const useCollapsibleHeader = (isLargeTitle: boolean, onSnap?: (offset: return; } - if (ctx.dragging || autoScroll.value || snapping.value) { + if (ctx?.dragging || autoScroll.value || snapping.value) { scrollValue.value = e.contentOffset.y; } else { // here we want to ensure that the scroll position @@ -105,25 +105,29 @@ export const useCollapsibleHeader = (isLargeTitle: boolean, onSnap?: (offset: } }, onEndDrag: (e, ctx) => { - if (ctx.start !== undefined) { + if (ctx?.start !== undefined) { const dir = e.contentOffset.y < ctx.start ? 'down' : 'up'; const offset = Math.abs(e.contentOffset.y); snapIfNeeded(dir, offset); } }, onMomentumBegin: (e, ctx) => { - ctx.momentum = e.contentOffset.y < (ctx.start || 0) ? 'down' : 'up'; + if (ctx) { + ctx.momentum = e.contentOffset.y < (ctx.start || 0) ? 'down' : 'up'; + } }, onMomentumEnd: (e, ctx) => { - ctx.start = undefined; - ctx.dragging = false; - if (ctx.momentum === 'down') { - const offset = Math.abs(e.contentOffset.y); - - if (onSnap && offset < largeHeight) { - runOnJS(onSnap)(0); + if (ctx) { + ctx.start = undefined; + ctx.dragging = false; + if (ctx.momentum === 'down') { + const offset = Math.abs(e.contentOffset.y); + + if (onSnap && offset < largeHeight) { + runOnJS(onSnap)(0); + } + ctx.momentum = undefined; } - ctx.momentum = undefined; } }, }, [insets, defaultHeight, largeHeight, animatedRef]); diff --git a/app/screens/channel/channel_post_list/channel_post_list.tsx b/app/screens/channel/channel_post_list/channel_post_list.tsx index 87dd035d896..9d43581df3a 100644 --- a/app/screens/channel/channel_post_list/channel_post_list.tsx +++ b/app/screens/channel/channel_post_list/channel_post_list.tsx @@ -19,10 +19,11 @@ import EphemeralStore from '@store/ephemeral_store'; import Intro from './intro'; import type PostModel from '@typings/database/models/servers/post'; +import type {AnimatedStyle} from 'react-native-reanimated'; type Props = { channelId: string; - contentContainerStyle?: StyleProp; + contentContainerStyle?: StyleProp>; isCRTEnabled: boolean; lastViewedAt: number; nativeID: string; diff --git a/app/screens/gallery/gallery.tsx b/app/screens/gallery/gallery.tsx index 23984406ae6..815595f63bc 100644 --- a/app/screens/gallery/gallery.tsx +++ b/app/screens/gallery/gallery.tsx @@ -4,7 +4,7 @@ import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; import {BackHandler} from 'react-native'; import FastImage, {type ImageStyle} from 'react-native-fast-image'; -import Animated, {runOnJS, runOnUI, useAnimatedReaction} from 'react-native-reanimated'; +import Animated, {runOnJS, runOnUI, useAnimatedReaction, type AnimatedStyle} from 'react-native-reanimated'; import {useGallery} from '@context/gallery'; import {freezeOtherScreens, measureItem} from '@utils/gallery'; @@ -148,7 +148,7 @@ const Gallery = forwardRef(({ return ( } /> ); } diff --git a/app/screens/gallery/header/index.tsx b/app/screens/gallery/header/index.tsx index 4645a640b29..f67787f5032 100644 --- a/app/screens/gallery/header/index.tsx +++ b/app/screens/gallery/header/index.tsx @@ -4,7 +4,7 @@ import React, {useMemo} from 'react'; import {type StyleProp, StyleSheet, useWindowDimensions, View, type ViewStyle} from 'react-native'; import {TouchableOpacity} from 'react-native-gesture-handler'; -import Animated from 'react-native-reanimated'; +import Animated, {type AnimatedStyle} from 'react-native-reanimated'; import {SafeAreaView, type Edge, useSafeAreaInsets} from 'react-native-safe-area-context'; import CompassIcon from '@components/compass_icon'; @@ -16,7 +16,7 @@ import {typography} from '@utils/typography'; type Props = { index: number; onClose: () => void; - style: StyleProp; + style: StyleProp>; total: number; } diff --git a/app/screens/gallery/video_renderer/index.tsx b/app/screens/gallery/video_renderer/index.tsx index f61ed59668b..e45c7457045 100644 --- a/app/screens/gallery/video_renderer/index.tsx +++ b/app/screens/gallery/video_renderer/index.tsx @@ -170,6 +170,8 @@ const VideoRenderer = ({height, index, initialIndex, item, isPageActive, onShoul return ( <> { handleSearch(newTeamId, lastSearchedValue); }, [lastSearchedValue, handleSearch]); - const initialContainerStyle: ViewStyle = useMemo(() => { + const initialContainerStyle: AnimatedStyle = useMemo(() => { return { paddingTop: scrollPaddingTop, flexGrow: 1, @@ -396,6 +396,8 @@ const SearchScreen = ({teamId, teams}: Props) => { removeClippedSubviews={false} scrollToOverflowEnabled={true} overScrollMode='always' + + // @ts-expect-error old style ref ref={scrollRef} renderItem={renderInitialOrLoadingItem} /> diff --git a/app/screens/user_profile/title/avatar.tsx b/app/screens/user_profile/title/avatar.tsx index 41e7be25697..1dfbe52a9f8 100644 --- a/app/screens/user_profile/title/avatar.tsx +++ b/app/screens/user_profile/title/avatar.tsx @@ -42,6 +42,8 @@ const UserProfileAvatar = ({enablePostIconOverride, forwardRef, imageSize, user, return ( , sharedValues: GalleryManagerSharedValues) { +export function measureItem(ref: AnimatedRef, sharedValues: GalleryManagerSharedValues) { 'worklet'; try { diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ac6311b7ec3..97bb3097682 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -528,7 +528,7 @@ PODS: - React-Core - RNReactNativeHapticFeedback (2.0.3): - React-Core - - RNReanimated (3.3.0): + - RNReanimated (3.4.2): - DoubleConversion - FBLazyVector - FBReactNativeSpec @@ -987,7 +987,7 @@ SPEC CHECKSUMS: RNLocalize: 5944c97d2fe8150913a51ddd5eab4e23a82bd80d RNPermissions: cf3a9da0e6e6772e66282ca7338e198885ac70e7 RNReactNativeHapticFeedback: afa5bf2794aecbb2dba2525329253da0d66656df - RNReanimated: 9976fbaaeb8a188c36026154c844bf374b3b7eeb + RNReanimated: 49cdb63e767bb7e743ff4c12f7d85722c0d008f2 RNRudderSdk: 70865f8d0746d7e78e27df98c148d1ca0205c551 RNScreens: d037903436160a4b039d32606668350d2a808806 RNSentry: 9f0447b3ce13806f544903748de423259ead8552 diff --git a/package-lock.json b/package-lock.json index 17c7d6ad73b..7ce1a6666ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -81,7 +81,7 @@ "react-native-navigation": "7.33.4", "react-native-notifications": "4.3.5", "react-native-permissions": "3.8.0", - "react-native-reanimated": "3.3.0", + "react-native-reanimated": "3.4.2", "react-native-safe-area-context": "4.5.3", "react-native-screens": "3.21.0", "react-native-section-list-get-item-layout": "2.2.3", @@ -18452,9 +18452,9 @@ } }, "node_modules/react-native-reanimated": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.3.0.tgz", - "integrity": "sha512-LzfpPZ1qXBGy5BcUHqw3pBC0qSd22qXS3t8hWSbozXNrBkzMhhOrcILE/nEg/PHpNNp1xvGOW8NwpAMF006roQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.4.2.tgz", + "integrity": "sha512-FbtG+f1PB005vDTJSv4zAnTK7nNXi+FjFgbAM5gOzIZDajfph2BFMSUstzIsN8T77+OKuugUBmcTqLnQ24EBVg==", "dependencies": { "@babel/plugin-transform-object-assign": "^7.16.7", "@babel/preset-typescript": "^7.16.7", @@ -35422,9 +35422,9 @@ } }, "react-native-reanimated": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.3.0.tgz", - "integrity": "sha512-LzfpPZ1qXBGy5BcUHqw3pBC0qSd22qXS3t8hWSbozXNrBkzMhhOrcILE/nEg/PHpNNp1xvGOW8NwpAMF006roQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.4.2.tgz", + "integrity": "sha512-FbtG+f1PB005vDTJSv4zAnTK7nNXi+FjFgbAM5gOzIZDajfph2BFMSUstzIsN8T77+OKuugUBmcTqLnQ24EBVg==", "requires": { "@babel/plugin-transform-object-assign": "^7.16.7", "@babel/preset-typescript": "^7.16.7", diff --git a/package.json b/package.json index 397fdd4fb1a..0a663d36d76 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "react-native-navigation": "7.33.4", "react-native-notifications": "4.3.5", "react-native-permissions": "3.8.0", - "react-native-reanimated": "3.3.0", + "react-native-reanimated": "3.4.2", "react-native-safe-area-context": "4.5.3", "react-native-screens": "3.21.0", "react-native-section-list-get-item-layout": "2.2.3", diff --git a/patches/react-native-reanimated+3.3.0.patch b/patches/react-native-reanimated+3.4.2.patch similarity index 59% rename from patches/react-native-reanimated+3.3.0.patch rename to patches/react-native-reanimated+3.4.2.patch index 5f4cf2898ac..7163469aef5 100644 --- a/patches/react-native-reanimated+3.3.0.patch +++ b/patches/react-native-reanimated+3.4.2.patch @@ -1,8 +1,25 @@ +diff --git a/node_modules/react-native-reanimated/lib/typescript/reanimated2/hook/utils.d.ts b/node_modules/react-native-reanimated/lib/typescript/reanimated2/hook/utils.d.ts +index 67c921b..cbb6f83 100644 +--- a/node_modules/react-native-reanimated/lib/typescript/reanimated2/hook/utils.d.ts ++++ b/node_modules/react-native-reanimated/lib/typescript/reanimated2/hook/utils.d.ts +@@ -9,7 +9,11 @@ interface Handlers { + [key: string]: Handler | undefined; + } + type useEventType = (handler: (e: T) => void, eventNames?: string[], rebuild?: boolean) => (e: NativeSyntheticEvent) => void; +-export declare const useEvent: useEventType; ++export declare function useEvent( ++ handler: T, ++ events: string[], ++ rebuild: boolean, ++): K; + type useHandlerType = >(handlers: Handlers, deps?: DependencyList) => { + context: TContext; + doDependenciesDiffer: boolean; diff --git a/node_modules/react-native-reanimated/src/reanimated2/mutables.ts b/node_modules/react-native-reanimated/src/reanimated2/mutables.ts -index 90de1f1..ae59355 100644 +index 6c4213d..e3cc49c 100644 --- a/node_modules/react-native-reanimated/src/reanimated2/mutables.ts +++ b/node_modules/react-native-reanimated/src/reanimated2/mutables.ts -@@ -95,25 +95,25 @@ export function makeMutable( +@@ -94,25 +94,25 @@ export function makeMutable( } return value; }, diff --git a/types/modules/react-native-reanimated.d.ts b/types/modules/react-native-reanimated.d.ts deleted file mode 100644 index d9fc066d830..00000000000 --- a/types/modules/react-native-reanimated.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -declare module 'react-native-reanimated' { - function makeRemote(value: T): T; - - function useEvent( - handler: T, - events: string[], - rebuild: boolean, - ): K; -}