feat(matrix-mobile): upgrade to Expo SDK 55

- Upgrade all expo packages to SDK 55 (expo 55.0.5, react-native 0.84.1, react 19.2.4)
- Migrate expo-file-system to new File/Paths API (cacheDirectory removed)
- Import SharedValue directly from react-native-reanimated (Animated namespace change)
- Simplify polyfills to use globalThis instead of global
- Remove events import (no longer needed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-07 08:23:56 +01:00
parent 1976c26f19
commit 10b880b6a1
5 changed files with 3804 additions and 2611 deletions

View file

@ -17,31 +17,31 @@
"format": "eslint . --fix"
},
"dependencies": {
"expo": "~53.0.0",
"expo-router": "~5.0.0",
"expo-constants": "~17.1.0",
"expo-status-bar": "~2.2.0",
"expo-system-ui": "~5.0.0",
"expo-linking": "~7.1.0",
"expo-secure-store": "~14.2.0",
"expo-image": "~2.3.0",
"expo-image-picker": "~16.1.0",
"expo-document-picker": "~13.1.0",
"expo-media-library": "~17.1.0",
"expo-file-system": "~18.1.0",
"expo-av": "~15.1.0",
"expo-notifications": "~0.31.0",
"expo-haptics": "~14.1.0",
"expo-web-browser": "~14.1.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "0.79.2",
"react-native-gesture-handler": "~2.24.0",
"react-native-reanimated": "~3.17.0",
"react-native-safe-area-context": "~5.4.0",
"react-native-screens": "~4.10.0",
"react-native-web": "~0.19.13",
"nativewind": "~4.1.0",
"expo": "~55.0.5",
"expo-router": "~55.0.4",
"expo-constants": "~55.0.7",
"expo-status-bar": "~55.0.4",
"expo-system-ui": "~55.0.9",
"expo-linking": "~55.0.7",
"expo-secure-store": "~55.0.8",
"expo-image": "~55.0.6",
"expo-image-picker": "~55.0.11",
"expo-document-picker": "~55.0.8",
"expo-media-library": "~55.0.9",
"expo-file-system": "~55.0.10",
"expo-av": "~16.0.8",
"expo-notifications": "~55.0.11",
"expo-haptics": "~55.0.8",
"expo-web-browser": "~55.0.9",
"react": "19.2.4",
"react-dom": "19.2.4",
"react-native": "0.84.1",
"react-native-gesture-handler": "~2.30.0",
"react-native-reanimated": "~4.2.2",
"react-native-safe-area-context": "~5.7.0",
"react-native-screens": "~4.24.0",
"react-native-web": "~0.21.2",
"nativewind": "~4.2.2",
"zustand": "^4.5.1",
"@react-native-async-storage/async-storage": "2.1.2",
"matrix-js-sdk": "^37.1.0",
@ -52,13 +52,13 @@
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/react": "~18.3.0",
"eslint": "^9.25.1",
"@types/react": "~19.2.14",
"eslint": "^9.39.1",
"eslint-config-expo": "^9.2.0",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11",
"tailwindcss": "^3.4.0",
"typescript": "~5.8.3"
"typescript": "~5.9.3"
},
"private": true
}

View file

@ -1,7 +1,7 @@
import { Modal, View, Pressable, StatusBar, Dimensions } from 'react-native';
import { Image } from 'expo-image';
import { X, DownloadSimple } from 'phosphor-react-native';
import * as FileSystem from 'expo-file-system';
import { File, Paths } from 'expo-file-system';
import * as MediaLibrary from 'expo-media-library';
import { useState } from 'react';
@ -23,9 +23,8 @@ export default function ImageViewer({ uri, onClose }: Props) {
if (status !== 'granted') return;
const filename = `manalink_${Date.now()}.jpg`;
const localUri = FileSystem.cacheDirectory + filename;
await FileSystem.downloadAsync(uri, localUri);
await MediaLibrary.saveToLibraryAsync(localUri);
const downloaded = await File.downloadFileAsync(uri, Paths.cache);
await MediaLibrary.saveToLibraryAsync(downloaded.uri);
} finally {
setSaving(false);
}

View file

@ -11,7 +11,12 @@ import {
ScrollView,
} from 'react-native';
import { Swipeable } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, interpolate, Extrapolation } from 'react-native-reanimated';
import Animated, {
useAnimatedStyle,
interpolate,
Extrapolation,
type SharedValue,
} from 'react-native-reanimated';
import { Image } from 'expo-image';
import { ArrowBendUpLeft } from 'phosphor-react-native';
import type { SimpleMessage, MessageReaction } from '~/src/matrix/types';
@ -69,7 +74,7 @@ function AvatarCircle({
const QUICK_REACTIONS = ['👍', '❤️', '😂', '😮', '😢'];
function SwipeReplyAction({ progress }: { progress: Animated.SharedValue<number> }) {
function SwipeReplyAction({ progress }: { progress: SharedValue<number> }) {
const style = useAnimatedStyle(() => ({
opacity: interpolate(progress.value, [0, 0.5, 1], [0, 0.6, 1], Extrapolation.CLAMP),
transform: [{ scale: interpolate(progress.value, [0, 1], [0.5, 1], Extrapolation.CLAMP) }],
@ -255,10 +260,10 @@ export default function MessageBubble({
const renderLeftActions = isOwn
? undefined
: (progress: Animated.SharedValue<number>) => <SwipeReplyAction progress={progress} />;
: (progress: SharedValue<number>) => <SwipeReplyAction progress={progress} />;
const renderRightActions = isOwn
? (progress: Animated.SharedValue<number>) => <SwipeReplyAction progress={progress} />
? (progress: SharedValue<number>) => <SwipeReplyAction progress={progress} />
: undefined;
// Type assertion needed: react-native-gesture-handler Swipeable types expect old Animated API

View file

@ -1,18 +1,15 @@
// Polyfills required for matrix-js-sdk in React Native
import { Buffer } from 'buffer';
import EventEmitter from 'events';
// @ts-ignore global polyfill
global.Buffer = Buffer;
// @ts-expect-error global polyfill
global.EventEmitter = EventEmitter;
const g = globalThis as any;
g.Buffer = Buffer;
// process stub (Expo provides process.env but not all fields)
if (typeof global.process === 'undefined') {
// @ts-expect-error global polyfill
global.process = { env: {}, nextTick: setImmediate };
} else if (typeof global.process.nextTick === 'undefined') {
global.process.nextTick = setImmediate as unknown as typeof process.nextTick;
if (typeof g.process === 'undefined') {
g.process = { env: {}, nextTick: setImmediate };
} else if (typeof g.process.nextTick === 'undefined') {
g.process.nextTick = setImmediate;
}
export {};

6322
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff