chore(mobile): upgrade to Expo SDK 57 and refresh dependencies (#14166)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
SubashMohanandClaude Opus 5 authored and GitHub committed 2026-08-22 06:07:53 +00:00
1 parent d721efe3f9
commit a7d66a8b77
11 files changed
+482 -518

No files matched your search

+2 -3
View File
@@ -6,9 +6,8 @@ const store = new Map<string, string>();
// Readable sentinel; the mock ignores the options arg.
export const WHEN_UNLOCKED_THIS_DEVICE_ONLY = "WHEN_UNLOCKED_THIS_DEVICE_ONLY";
export const getItemAsync = jest.fn(
(key: string): Promise<string | null> =>
Promise.resolve(store.get(key) ?? null),
export const getItemAsync = jest.fn((key: string): Promise<string | null> =>
Promise.resolve(store.get(key) ?? null),
);
export const setItemAsync = jest.fn(
+409 -436
View File
File diff suppressed because it is too large. Load diff
+46 -43
View File
@@ -7,65 +7,65 @@
"@expo-google-fonts/hanken-grotesk": "^0.4.3",
"@onyx-ai/shared": "file:../web/lib/shared",
"@react-native-community/netinfo": "12.0.1",
"@rn-primitives/portal": "^1.4.0",
"@rn-primitives/separator": "^1.4.0",
"@rn-primitives/slot": "^1.4.0",
"@rn-primitives/portal": "^1.5.3",
"@rn-primitives/separator": "^1.5.2",
"@rn-primitives/slot": "^1.5.2",
"@shopify/flash-list": "2.0.2",
"@tanstack/query-sync-storage-persister": "^5.101.0",
"@tanstack/react-query": "^5.101.0",
"@tanstack/react-query-persist-client": "^5.101.0",
"@tanstack/query-sync-storage-persister": "^5.101.4",
"@tanstack/react-query": "^5.101.4",
"@tanstack/react-query-persist-client": "^5.101.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"expo": "~56.0.9",
"expo-build-properties": "~56.0.17",
"expo-clipboard": "~56.0.4",
"expo-constants": "~56.0.17",
"expo-crypto": "~56.0.4",
"expo-dev-client": "~56.0.19",
"expo-document-picker": "~56.0.4",
"expo-file-system": "~56.0.8",
"expo-font": "~56.0.5",
"expo-image": "~56.0.11",
"expo-image-picker": "~56.0.19",
"expo-linking": "~56.0.13",
"expo-router": "~56.2.9",
"expo-secure-store": "~56.0.4",
"expo-splash-screen": "~56.0.10",
"expo-status-bar": "~56.0.4",
"expo-system-ui": "~56.0.5",
"expo-web-browser": "~56.0.5",
"nativewind": "^4.2.5",
"expo": "~57.0.15",
"expo-build-properties": "~57.0.13",
"expo-clipboard": "~57.0.1",
"expo-constants": "~57.0.13",
"expo-crypto": "~57.0.1",
"expo-dev-client": "~57.0.14",
"expo-document-picker": "~57.0.1",
"expo-file-system": "~57.0.5",
"expo-font": "~57.0.1",
"expo-image": "~57.0.3",
"expo-image-picker": "~57.0.12",
"expo-linking": "~57.0.7",
"expo-router": "~57.0.15",
"expo-secure-store": "~57.0.1",
"expo-splash-screen": "~57.0.7",
"expo-status-bar": "~57.0.1",
"expo-system-ui": "~57.0.2",
"expo-web-browser": "~57.0.2",
"nativewind": "^4.2.6",
"react": "19.2.3",
"react-dom": "19.2.3",
"react-hook-form": "^7.54.2",
"react-native": "0.85.3",
"react-hook-form": "^7.86.0",
"react-native": "0.86.2",
"react-native-enriched-markdown": "^0.6.0",
"react-native-gesture-handler": "~2.31.1",
"react-native-keyboard-controller": "1.21.6",
"react-native-mmkv": "^4.3.1",
"react-native-reanimated": "4.3.1",
"react-native-gesture-handler": "~2.32.0",
"react-native-keyboard-controller": "1.21.9",
"react-native-mmkv": "^4.3.2",
"react-native-reanimated": "4.5.1",
"react-native-safe-area-context": "~5.7.0",
"react-native-screens": "4.25.2",
"react-native-screens": "~4.26.0",
"react-native-streamdown": "^0.2.0",
"react-native-svg": "15.15.4",
"react-native-web": "~0.21.0",
"react-native-worklets": "0.8.3",
"react-native-worklets": "0.10.1",
"remend": "^1.3.0",
"tailwind-merge": "^3.6.0",
"zustand": "^5.0.14"
"zustand": "^5.0.15"
},
"devDependencies": {
"@testing-library/react-native": "^13.0.0",
"@testing-library/react-native": "^13.3.3",
"@types/jest": "^29.5.14",
"@types/react": "~19.2.2",
"eslint": "^9.39.4",
"eslint-config-expo": "^56.0.4",
"@types/react": "~19.2.18",
"eslint": "^9.39.5",
"eslint-config-expo": "~57.0.1",
"eslint-config-prettier": "^10.1.8",
"jest-expo": "~56.0.0",
"prettier": "^3.8.4",
"prettier-plugin-tailwindcss": "^0.8.0",
"jest-expo": "~57.0.4",
"prettier": "3.9.6",
"prettier-plugin-tailwindcss": "0.8.1",
"react-test-renderer": "19.2.3",
"tailwindcss": "3.4.17",
"tailwindcss": "3.4.19",
"typescript": "~6.0.3"
},
"scripts": {
@@ -85,6 +85,9 @@
},
"private": true,
"patchedDependencies": {
"metro@0.84.4": "patches/metro@0.84.4.patch"
"metro@0.84.5": "patches/metro@0.84.5.patch"
},
"overrides": {
"metro": "0.84.5"
}
}
+10 -2
View File
@@ -2,7 +2,11 @@
Applied via bun's `patchedDependencies` (see `package.json`); bun re-applies them on every `bun install`.
## `metro@0.84.4.patch` — Bundle Mode `.worklets` SHA-1 fix
Both keys name an **exact** version. If the package drifts off that version, bun applies **nothing and
prints no warning**, so `package.json` `overrides` pins each patched package to the version its patch was
cut for. Bump the override, the `patchedDependencies` key, and the patch filename together.
## `metro@0.84.5.patch` — Bundle Mode `.worklets` SHA-1 fix
This is **Software Mansion's official react-native-worklets Bundle Mode patch**, copied verbatim for our
metro version (only the diff paths are rewritten from patch-package's `node_modules/metro/...` to bun's
@@ -19,7 +23,11 @@ The patch short-circuits `getOrComputeSha1` for `.worklets` paths and returns a
throwing. SWM calls this "a temporary workaround until necessary changes are merged into Metro" — no metro
release through 0.85.0 fixes it.
Metro reaches us through `@expo/metro`, which is a re-export shim (`module.exports = require("metro/...")`),
so patching the bare `metro` package is what takes effect. `@expo/metro` itself contains no metro source.
**On a metro version bump** (e.g. an Expo SDK upgrade): grab the matching `metro+<version>.patch` from the
SWM link above, re-cut it for the new version (`bun patch metro` → apply the change → `bun patch --commit`),
and re-check [metro#330](https://github.com/facebook/metro/issues/330) — if it's fixed in the metro your SDK
pulls, drop this patch entirely.
pulls, drop this patch entirely. `src/node-haste/DependencyGraph.js` was byte-identical from 0.84.4 to
0.84.5, so that re-cut needed no content change.
File renamed without changes.
+5 -21
View File
@@ -362,17 +362,10 @@ export type FetchToolObj =
| PacketError;
export type CustomToolObj =
| CustomToolStart
| CustomToolArgs
| CustomToolDelta
| SectionEnd
| PacketError;
CustomToolStart | CustomToolArgs | CustomToolDelta | SectionEnd | PacketError;
export type FileReaderToolObj =
| FileReaderStart
| FileReaderResult
| SectionEnd
| PacketError;
FileReaderStart | FileReaderResult | SectionEnd | PacketError;
export type MemoryToolObj =
| MemoryToolStart
@@ -391,22 +384,13 @@ export type NewToolObj =
| MemoryToolObj;
export type ReasoningObj =
| ReasoningStart
| ReasoningDelta
| ReasoningDone
| SectionEnd
| PacketError;
ReasoningStart | ReasoningDelta | ReasoningDone | SectionEnd | PacketError;
export type CitationObj =
| CitationStart
| CitationInfo
| SectionEnd
| PacketError;
CitationStart | CitationInfo | SectionEnd | PacketError;
export type DeepResearchPlanObj =
| DeepResearchPlanStart
| DeepResearchPlanDelta
| SectionEnd;
DeepResearchPlanStart | DeepResearchPlanDelta | SectionEnd;
export type ResearchAgentObj =
| ResearchAgentStart
@@ -1,5 +1,6 @@
import { describe, expect, it, jest } from "@jest/globals";
import {
act,
fireEvent,
render,
renderHook,
@@ -113,7 +114,11 @@ describe("TextInputField", () => {
fireEvent.press(screen.getByLabelText("submit"));
await waitFor(() => expect(screen.getByRole("alert")).toBeTruthy());
fireEvent.changeText(screen.getByPlaceholderText("email"), "a@b.com");
// react-hook-form revalidates asynchronously; flush it so the assertion doesn't
// race waitFor's 1s default.
await act(async () => {
fireEvent.changeText(screen.getByPlaceholderText("email"), "a@b.com");
});
await waitFor(() => expect(screen.queryByRole("alert")).toBeNull());
});
+1 -2
View File
@@ -21,8 +21,7 @@ import {
// RN TextInput only handles strings; binding a number/boolean field would corrupt form state.
type StringFieldPath<TFieldValues extends FieldValues> = {
[K in FieldPath<TFieldValues>]: FieldPathValue<TFieldValues, K> extends
| string
| undefined
string | undefined
? K
: never;
}[FieldPath<TFieldValues>];
+1 -5
View File
@@ -11,11 +11,7 @@ import type { IconFunctionComponent } from "@/icons/types";
// editing, tag/aux, responsive grid) throw rather than render wrong.
type ContentSizePreset =
| "headline"
| "section"
| "main-content"
| "main-ui"
| "secondary";
"headline" | "section" | "main-content" | "main-ui" | "secondary";
type ContentVariant = "heading" | "section" | "body";
type ContentColor = "default" | "muted" | "danger";
@@ -28,9 +28,7 @@ const CONNECTOR_ROWS = [
* `isPending` goes false, and stubbing above that layer can't tell an outage from a `true` answer.
*/
type SettingsOutcome =
| { kind: "ok"; vectorDb: boolean }
| { kind: "pending" }
| { kind: "error" };
{ kind: "ok"; vectorDb: boolean } | { kind: "pending" } | { kind: "error" };
function mockApi(settings: SettingsOutcome, federated: unknown[] = []): void {
apiFetchMock.mockImplementation((path: string) => {
+1 -2
View File
@@ -14,8 +14,7 @@ import { UserFileStatus, type ProjectFile } from "@/chat/contracts/projects";
// Where an upload belongs. No "recent" variant: you never upload *to* the library — a recent file
// enters the store via registerExisting(), not an upload task.
export type UploadTarget =
| { kind: "draft"; draftKey: string }
| { kind: "project"; projectId: number };
{ kind: "draft"; draftKey: string } | { kind: "project"; projectId: number };
function sameTarget(a: UploadTarget, b: UploadTarget): boolean {
if (a.kind === "draft" && b.kind === "draft")