diff --git a/.cursor/rules/project-overview.mdc b/.cursor/rules/project-overview.mdc
index ee74b27..faffe37 100644
--- a/.cursor/rules/project-overview.mdc
+++ b/.cursor/rules/project-overview.mdc
@@ -11,7 +11,7 @@ Offline-first **Expo SDK 56** (React Native **0.85**, React **19.2.3**) companio
- Entry: `App.tsx` → `initializeDatabase()` → `syncAllData()` → `AppNavigator`
- App config: `app.config.ts` (EAS project ID, plugins, package id)
-- Screens: `src/app/tabs/` (`ProjectList`, `ViewProject`, `ViewChapter`)
+- Screens: `src/app/tabs/` (`ProjectList`, `ViewProject`, `drafting/DraftingPage` + `RecordTab`)
- API: `src/services/api.ts` (`FluentAPI`)
- Sync: `src/services/sync.ts`
- DB writes: `src/db/repository.ts` | reads: `src/db/queries.ts`
diff --git a/app.config.ts b/app.config.ts
index 2f3eb57..f09b711 100644
--- a/app.config.ts
+++ b/app.config.ts
@@ -74,6 +74,14 @@ const config: ExpoConfig = {
],
'./plugins/withRNScreensFragmentFactory',
'expo-secure-store',
+ 'expo-asset',
+ [
+ 'expo-audio',
+ {
+ microphonePermission:
+ 'Fluent needs access to your microphone so translators can record verse drafts.',
+ },
+ ],
],
};
diff --git a/docs/AGENT_ONBOARDING.md b/docs/AGENT_ONBOARDING.md
index f64d9b0..c2b60f2 100644
--- a/docs/AGENT_ONBOARDING.md
+++ b/docs/AGENT_ONBOARDING.md
@@ -32,7 +32,7 @@ Quick map for Cursor agents, other coding tools, and new contributors. Verified
| Path | Purpose |
|------|---------|
| [`App.tsx`](../App.tsx) | Root: DB init + initial `syncAllData`, then navigator |
-| [`src/app/tabs/`](../src/app/tabs/) | Screens: `ProjectList`, `ViewProject`, `ViewChapter` |
+| [`src/app/tabs/`](../src/app/tabs/) | Screens: `ProjectList`, `ViewProject`, `drafting/DraftingPage` (parent shell stub for #47) with `RecordTab` (#49) |
| [`src/navigation/`](../src/navigation/) | Stack navigator |
| [`src/services/api.ts`](../src/services/api.ts) | HTTP client (`FluentAPI`) — see [api-client-standard.md](guides/api-client-standard.md) |
| [`src/services/sync.ts`](../src/services/sync.ts) | Sync orchestration, retries, KV counts |
@@ -209,7 +209,9 @@ When adding features: mock `op-sqlite`, navigation, and sync in screen tests fol
- [x] Dependabot reviewers: `eten-tech-foundation/fluent-admin`
- [x] Mock or gate `fluent-api.test.ts` for offline CI
- [ ] Align `format:check` glob with `format` or document intentionally narrow check
-- [ ] Wire `recordings` table to actual audio capture/upload
+- [x] Wire `recordings` table to actual audio capture (issue #49 — upload still pending)
+- [ ] Upload/sync draft recordings to the Fluent server (`sync_status='pending'` rows)
+- [ ] Replace parent drafting shell stub with full #47 implementation (chapter audio player, tab persistence)
## Related docs
diff --git a/modules/aac-remux/android/build.gradle b/modules/aac-remux/android/build.gradle
new file mode 100644
index 0000000..cffab04
--- /dev/null
+++ b/modules/aac-remux/android/build.gradle
@@ -0,0 +1,18 @@
+plugins {
+ id 'com.android.library'
+ id 'expo-module-gradle-plugin'
+}
+
+group = 'expo.modules.aacremux'
+version = '0.1.0'
+
+android {
+ namespace "expo.modules.aacremux"
+ defaultConfig {
+ versionCode 1
+ versionName "0.1.0"
+ }
+ lintOptions {
+ abortOnError false
+ }
+}
diff --git a/modules/aac-remux/android/src/main/AndroidManifest.xml b/modules/aac-remux/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a2f47b6
--- /dev/null
+++ b/modules/aac-remux/android/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/modules/aac-remux/android/src/main/java/expo/modules/aacremux/AacRemuxModule.kt b/modules/aac-remux/android/src/main/java/expo/modules/aacremux/AacRemuxModule.kt
new file mode 100644
index 0000000..a49c0ef
--- /dev/null
+++ b/modules/aac-remux/android/src/main/java/expo/modules/aacremux/AacRemuxModule.kt
@@ -0,0 +1,116 @@
+package expo.modules.aacremux
+
+import android.media.MediaCodec
+import android.media.MediaExtractor
+import android.media.MediaFormat
+import android.media.MediaMuxer
+import android.net.Uri
+import expo.modules.kotlin.exception.CodedException
+import expo.modules.kotlin.modules.Module
+import expo.modules.kotlin.modules.ModuleDefinition
+import java.nio.ByteBuffer
+
+/**
+ * Repackages a raw ADTS AAC (`.aac`) recording into an MP4/M4A container without
+ * re-encoding. ADTS is what we capture (self-framing, so it survives a process
+ * kill and concatenates by byte-append), but ExoPlayer cannot reliably seek a
+ * raw ADTS stream. Copying the AAC elementary stream into an MP4 container adds
+ * the sample table that makes review playback seekable — a lossless remux, not
+ * a transcode.
+ */
+class AacRemuxModule : Module() {
+ override fun definition() = ModuleDefinition {
+ Name("AacRemux")
+
+ AsyncFunction("remuxToMp4") { sourceUri: String, destUri: String ->
+ remux(toFilePath(sourceUri), toFilePath(destUri))
+ destUri
+ }
+ }
+
+ private fun toFilePath(uri: String): String =
+ if (uri.startsWith("file://")) {
+ Uri.parse(uri).path ?: uri.removePrefix("file://")
+ } else {
+ uri
+ }
+
+ private fun remux(srcPath: String, dstPath: String) {
+ val extractor = MediaExtractor()
+ var muxer: MediaMuxer? = null
+ var muxerStarted = false
+ try {
+ extractor.setDataSource(srcPath)
+
+ var audioTrackIndex = -1
+ var trackFormat: MediaFormat? = null
+ for (i in 0 until extractor.trackCount) {
+ val candidate = extractor.getTrackFormat(i)
+ val mime = candidate.getString(MediaFormat.KEY_MIME)
+ if (mime != null && mime.startsWith("audio/")) {
+ audioTrackIndex = i
+ trackFormat = candidate
+ break
+ }
+ }
+
+ val format = trackFormat
+ ?: throw CodedException("No audio track found in $srcPath")
+ extractor.selectTrack(audioTrackIndex)
+
+ // ADTS carries no container timestamps, so synthesize monotonically
+ // increasing presentation times from the fixed AAC frame length
+ // (1024 samples per frame). MP4 requires increasing timestamps.
+ val sampleRate = if (format.containsKey(MediaFormat.KEY_SAMPLE_RATE)) {
+ format.getInteger(MediaFormat.KEY_SAMPLE_RATE)
+ } else {
+ 44100
+ }
+ val frameDurationUs = 1_000_000L * 1024L / sampleRate
+
+ muxer = MediaMuxer(dstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
+ val outputTrackIndex = muxer.addTrack(format)
+ muxer.start()
+ muxerStarted = true
+
+ val maxInputSize = if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
+ format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE).coerceAtLeast(64 * 1024)
+ } else {
+ 256 * 1024
+ }
+ val buffer = ByteBuffer.allocate(maxInputSize)
+ val bufferInfo = MediaCodec.BufferInfo()
+ var presentationTimeUs = 0L
+
+ while (true) {
+ val sampleSize = extractor.readSampleData(buffer, 0)
+ if (sampleSize < 0) {
+ break
+ }
+ bufferInfo.offset = 0
+ bufferInfo.size = sampleSize
+ bufferInfo.presentationTimeUs = presentationTimeUs
+ bufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME
+ muxer.writeSampleData(outputTrackIndex, buffer, bufferInfo)
+ presentationTimeUs += frameDurationUs
+ extractor.advance()
+ }
+ } catch (e: CodedException) {
+ throw e
+ } catch (e: Exception) {
+ throw CodedException("Failed to remux AAC to MP4: ${e.message}")
+ } finally {
+ if (muxerStarted) {
+ try {
+ muxer?.stop()
+ } catch (_: Exception) {
+ }
+ }
+ try {
+ muxer?.release()
+ } catch (_: Exception) {
+ }
+ extractor.release()
+ }
+ }
+}
diff --git a/modules/aac-remux/expo-module.config.json b/modules/aac-remux/expo-module.config.json
new file mode 100644
index 0000000..dded5a4
--- /dev/null
+++ b/modules/aac-remux/expo-module.config.json
@@ -0,0 +1,6 @@
+{
+ "platforms": ["android"],
+ "android": {
+ "modules": ["expo.modules.aacremux.AacRemuxModule"]
+ }
+}
diff --git a/package-lock.json b/package-lock.json
index 538ee08..3d83de8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,8 +17,12 @@
"@tanstack/react-query": "^5.96.1",
"babel-preset-expo": "~56.0.0",
"expo": "~56.0.15",
+ "expo-asset": "~56.0.19",
+ "expo-audio": "~56.0.12",
"expo-build-properties": "~56.0.22",
+ "expo-crypto": "~56.0.4",
"expo-dev-client": "~56.0.22",
+ "expo-file-system": "~56.0.8",
"expo-secure-store": "~56.0.4",
"expo-updates": "~56.0.21",
"lucide-react-native": "^0.544.0",
@@ -2362,9 +2366,9 @@
}
},
"node_modules/@expo/env": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.4.1.tgz",
- "integrity": "sha512-3c9Mg9x0HmGPEsVrGAGyEDJsNUOZ55cZvZ47/HLmXh7MHV9Zv7My73wThklKrObaBBoMfE4YqpKjYKDRzojpjQ==",
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.3.1.tgz",
+ "integrity": "sha512-JvBdZa5OkTd+dGEtt3fLW9OF6RlIp9SNu9VyMSiWPV5szMDTSAYbX8Uj3cRvZcU1zzaRbqnTSsHk2AE8WXHfxQ==",
"license": "MIT",
"dependencies": {
"chalk": "^4.0.0",
@@ -2511,6 +2515,81 @@
"metro-transform-worker": "0.84.4"
}
},
+ "node_modules/@expo/metro-config": {
+ "version": "56.0.16",
+ "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-56.0.16.tgz",
+ "integrity": "sha512-mxPZ23exC6kkEpPYQOteamaiWYER3uDk2IqKys7EJwtIKc3F1207Xtsdko/DNNG04DLwpN/WM2UlNl+Ak8uPRg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.20.0",
+ "@babel/core": "^7.20.0",
+ "@babel/generator": "^7.20.5",
+ "@expo/config": "~56.0.11",
+ "@expo/env": "~2.3.1",
+ "@expo/json-file": "~10.2.0",
+ "@expo/metro": "~56.0.0",
+ "@expo/require-utils": "^56.1.4",
+ "@expo/spawn-async": "^1.8.0",
+ "@jridgewell/gen-mapping": "^0.3.13",
+ "@jridgewell/remapping": "^2.3.5",
+ "@jridgewell/sourcemap-codec": "^1.5.5",
+ "browserslist": "^4.25.0",
+ "chalk": "^4.1.0",
+ "debug": "^4.3.2",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "hermes-parser": "^0.33.3",
+ "jsc-safe-url": "^0.2.4",
+ "lightningcss": "^1.30.1",
+ "picomatch": "^4.0.4",
+ "postcss": "^8.5.14",
+ "resolve-from": "^5.0.0"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ },
+ "peerDependenciesMeta": {
+ "expo": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@expo/metro-config/node_modules/hermes-estree": {
+ "version": "0.33.3",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.33.3.tgz",
+ "integrity": "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg==",
+ "license": "MIT"
+ },
+ "node_modules/@expo/metro-config/node_modules/hermes-parser": {
+ "version": "0.33.3",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.33.3.tgz",
+ "integrity": "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.33.3"
+ }
+ },
+ "node_modules/@expo/metro-config/node_modules/picomatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/@expo/metro-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/@expo/metro-file-map": {
"version": "56.0.3",
"resolved": "https://registry.npmjs.org/@expo/metro-file-map/-/metro-file-map-56.0.3.tgz",
@@ -2975,9 +3054,9 @@
}
},
"node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
- "version": "3.14.2",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
- "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz",
+ "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==",
"devOptional": true,
"license": "MIT",
"dependencies": {
@@ -3130,9 +3209,9 @@
}
},
"node_modules/@jest/diff-sequences": {
- "version": "30.3.0",
- "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.3.0.tgz",
- "integrity": "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==",
+ "version": "30.4.0",
+ "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.4.0.tgz",
+ "integrity": "sha512-zOpzlfUs45l6u7jm39qr87JCHUDsaeCtvL+kQe/Vn9jSnRB4/5IPXISm0h9I1vZW/o00Kn4UTJ2MOlhnUGwv3g==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3717,9 +3796,9 @@
}
},
"node_modules/@react-native-community/cli/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"devOptional": true,
"license": "ISC",
"bin": {
@@ -4047,11 +4126,10 @@
"react": "^19.2.3"
}
},
- "node_modules/@react-native/jest-preset/node_modules/@react-native/js-polyfills": {
+ "node_modules/@react-native/js-polyfills": {
"version": "0.85.3",
"resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.85.3.tgz",
"integrity": "sha512-U2+aMshIXf1uFn77tpBb/xhHWB9vkVrMpt7kkucAugF8hJKYTDGB587X7WwelHduK2KBfhl4giSv0rzZGoef9A==",
- "devOptional": true,
"license": "MIT",
"engines": {
"node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
@@ -4599,9 +4677,9 @@
}
},
"node_modules/@testing-library/react-native/node_modules/@jest/schemas": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz",
- "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==",
+ "version": "30.4.1",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz",
+ "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4632,27 +4710,21 @@
}
},
"node_modules/@testing-library/react-native/node_modules/pretty-format": {
- "version": "30.3.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz",
- "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==",
+ "version": "30.4.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz",
+ "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/schemas": "30.0.5",
+ "@jest/schemas": "30.4.1",
"ansi-styles": "^5.2.0",
- "react-is": "^18.3.1"
+ "react-is-18": "npm:react-is@^18.3.1",
+ "react-is-19": "npm:react-is@^19.2.5"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@testing-library/react-native/node_modules/react-is": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@tootallnate/once": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz",
@@ -5020,9 +5092,9 @@
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -5100,9 +5172,9 @@
"license": "MIT"
},
"node_modules/@xmldom/xmldom": {
- "version": "0.8.12",
- "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.12.tgz",
- "integrity": "sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg==",
+ "version": "0.8.13",
+ "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz",
+ "integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
@@ -5755,9 +5827,9 @@
}
},
"node_modules/babel-preset-expo": {
- "version": "56.0.15",
- "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-56.0.15.tgz",
- "integrity": "sha512-0MqbQoM6nBUbKvgu2xJ4VixZnUTGTq3HB2WwvOikdO4CiPxbQ+wGA25fOoHHSni5iEFW39wy6y1ookTWlq3wVw==",
+ "version": "56.0.16",
+ "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-56.0.16.tgz",
+ "integrity": "sha512-HkTZP+nWVGTibw+JCiy2yCXPPXhFUbqG6xdZRSnnAv+tZUdsCdvGnfEl14shS1mZWIY0VSf/rWpkzIEsZKyqhQ==",
"license": "MIT",
"dependencies": {
"@babel/generator": "^7.20.5",
@@ -5806,7 +5878,7 @@
"peerDependencies": {
"@babel/runtime": "^7.20.0",
"expo": "*",
- "expo-widgets": "^56.0.18",
+ "expo-widgets": "^56.0.20",
"react-refresh": ">=0.14.0 <1.0.0"
},
"peerDependenciesMeta": {
@@ -5866,7 +5938,6 @@
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.2.tgz",
"integrity": "sha512-aTvMFUWkBmjzKtEQMDGGDNF8bkfpD5N1b/FCwt7A3wrU4t1o/e/85Wzkluh6JlODCjqVESYCkQCdTXqZ9G7VFg==",
"license": "Apache-2.0",
- "optional": true,
"dependencies": {
"bare-events": "^2.5.4",
"bare-path": "^3.0.0",
@@ -5891,7 +5962,6 @@
"resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.9.1.tgz",
"integrity": "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ==",
"license": "Apache-2.0",
- "optional": true,
"engines": {
"bare": ">=1.14.0"
}
@@ -5901,7 +5971,6 @@
"resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.1.tgz",
"integrity": "sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ==",
"license": "Apache-2.0",
- "optional": true,
"dependencies": {
"bare-os": "^3.0.1"
}
@@ -5911,7 +5980,6 @@
"resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.1.tgz",
"integrity": "sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow==",
"license": "Apache-2.0",
- "optional": true,
"dependencies": {
"streamx": "^2.25.0",
"teex": "^1.0.1"
@@ -5938,7 +6006,6 @@
"resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.5.tgz",
"integrity": "sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ==",
"license": "Apache-2.0",
- "optional": true,
"dependencies": {
"bare-path": "^3.0.0"
}
@@ -6784,43 +6851,6 @@
"node": ">=12"
}
},
- "node_modules/data-urls/node_modules/tr46": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
- "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "punycode": "^2.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/data-urls/node_modules/webidl-conversions": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
- "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/data-urls/node_modules/whatwg-url": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
- "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tr46": "^3.0.0",
- "webidl-conversions": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/data-view-buffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
@@ -7154,16 +7184,6 @@
"node": ">=12"
}
},
- "node_modules/domexception/node_modules/webidl-conversions": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
- "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
@@ -7746,14 +7766,14 @@
"license": "MIT"
},
"node_modules/eslint-plugin-react/node_modules/resolve": {
- "version": "2.0.0-next.6",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz",
- "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==",
+ "version": "2.0.0-next.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
+ "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
- "is-core-module": "^2.16.1",
+ "is-core-module": "^2.16.2",
"node-exports-info": "^1.6.0",
"object-keys": "^1.1.1",
"path-parse": "^1.0.7",
@@ -8092,6 +8112,33 @@
}
}
},
+ "node_modules/expo-asset": {
+ "version": "56.0.19",
+ "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-56.0.19.tgz",
+ "integrity": "sha512-huGY0bVfYUivNOir+iUEjjW9IbNHzLFNo8d6FGh22u1OsXcFR7Za3vpu5V1gMp0dc31wiqmsXkTazjm+Rro3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/image-utils": "^0.10.2",
+ "expo-constants": "~56.0.20"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-audio": {
+ "version": "56.0.12",
+ "resolved": "https://registry.npmjs.org/expo-audio/-/expo-audio-56.0.12.tgz",
+ "integrity": "sha512-ne2UIO/HsQoBL9e+tGs5N9Sf3NyW5sJMm4sDkexbSJRc2IchLDG+9Msu/+l5N4RlZ8SiF42wRyWsh/Usg+SwOw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "expo-asset": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/expo-build-properties": {
"version": "56.0.22",
"resolved": "https://registry.npmjs.org/expo-build-properties/-/expo-build-properties-56.0.22.tgz",
@@ -8116,9 +8163,9 @@
}
},
"node_modules/expo-build-properties/node_modules/semver": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
- "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -8127,6 +8174,28 @@
"node": ">=10"
}
},
+ "node_modules/expo-constants": {
+ "version": "56.0.20",
+ "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-56.0.20.tgz",
+ "integrity": "sha512-4HgoVvUiMvcqujr/CUj7L1tumLWj8WX0PLM77OriDPoaJrMEwUHd841m4o4IoUyMPVT8XTiTiPFwJtGali8+9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/env": "~2.3.1"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-crypto": {
+ "version": "56.0.4",
+ "resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-56.0.4.tgz",
+ "integrity": "sha512-fRNEhoXRXgAWBpe3/hq5X+KXTit3OZqdiAGts1YvNEUHQb+H5591mpPac0Yw+sZg9pXcrjRnzo5AxvZaENpc7g==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
"node_modules/expo-dev-client": {
"version": "56.0.22",
"resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-56.0.22.tgz",
@@ -8186,6 +8255,16 @@
"integrity": "sha512-r8h0ZIExacCrSRgY+ARfhMvFqosLHLJt1L7jyhvabfr1DN/ZDKDsYbovss2tzkpEUZGxZ3BPcB5epCwUsBBdOA==",
"license": "MIT"
},
+ "node_modules/expo-file-system": {
+ "version": "56.0.8",
+ "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-56.0.8.tgz",
+ "integrity": "sha512-NrH41/8snGIBSbYicwVLB4txPdgCATd7ZYhMAGS3YJZ9GbnduhlAoV4/YCbGayjrbpE9bJb/6wegPL/zmvRMnQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/expo-json-utils": {
"version": "56.0.0",
"resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-56.0.0.tgz",
@@ -8479,20 +8558,6 @@
"react-native": "*"
}
},
- "node_modules/expo/node_modules/@expo/env": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.3.1.tgz",
- "integrity": "sha512-JvBdZa5OkTd+dGEtt3fLW9OF6RlIp9SNu9VyMSiWPV5szMDTSAYbX8Uj3cRvZcU1zzaRbqnTSsHk2AE8WXHfxQ==",
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.0.0",
- "debug": "^4.3.4",
- "getenv": "^2.0.0"
- },
- "engines": {
- "node": ">=20.12.0"
- }
- },
"node_modules/expo/node_modules/@expo/log-box": {
"version": "56.0.14",
"resolved": "https://registry.npmjs.org/@expo/log-box/-/log-box-56.0.14.tgz",
@@ -8510,45 +8575,6 @@
"react-native": "*"
}
},
- "node_modules/expo/node_modules/@expo/metro-config": {
- "version": "56.0.16",
- "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-56.0.16.tgz",
- "integrity": "sha512-mxPZ23exC6kkEpPYQOteamaiWYER3uDk2IqKys7EJwtIKc3F1207Xtsdko/DNNG04DLwpN/WM2UlNl+Ak8uPRg==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.20.0",
- "@babel/core": "^7.20.0",
- "@babel/generator": "^7.20.5",
- "@expo/config": "~56.0.11",
- "@expo/env": "~2.3.1",
- "@expo/json-file": "~10.2.0",
- "@expo/metro": "~56.0.0",
- "@expo/require-utils": "^56.1.4",
- "@expo/spawn-async": "^1.8.0",
- "@jridgewell/gen-mapping": "^0.3.13",
- "@jridgewell/remapping": "^2.3.5",
- "@jridgewell/sourcemap-codec": "^1.5.5",
- "browserslist": "^4.25.0",
- "chalk": "^4.1.0",
- "debug": "^4.3.2",
- "getenv": "^2.0.0",
- "glob": "^13.0.0",
- "hermes-parser": "^0.33.3",
- "jsc-safe-url": "^0.2.4",
- "lightningcss": "^1.30.1",
- "picomatch": "^4.0.4",
- "postcss": "^8.5.14",
- "resolve-from": "^5.0.0"
- },
- "peerDependencies": {
- "expo": "*"
- },
- "peerDependenciesMeta": {
- "expo": {
- "optional": true
- }
- }
- },
"node_modules/expo/node_modules/@expo/ws-tunnel": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-2.0.0.tgz",
@@ -8682,44 +8708,6 @@
"node": ">=0.8.0"
}
},
- "node_modules/expo/node_modules/expo-asset": {
- "version": "56.0.19",
- "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-56.0.19.tgz",
- "integrity": "sha512-huGY0bVfYUivNOir+iUEjjW9IbNHzLFNo8d6FGh22u1OsXcFR7Za3vpu5V1gMp0dc31wiqmsXkTazjm+Rro3vA==",
- "license": "MIT",
- "dependencies": {
- "@expo/image-utils": "^0.10.2",
- "expo-constants": "~56.0.20"
- },
- "peerDependencies": {
- "expo": "*",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo/node_modules/expo-constants": {
- "version": "56.0.20",
- "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-56.0.20.tgz",
- "integrity": "sha512-4HgoVvUiMvcqujr/CUj7L1tumLWj8WX0PLM77OriDPoaJrMEwUHd841m4o4IoUyMPVT8XTiTiPFwJtGali8+9Q==",
- "license": "MIT",
- "dependencies": {
- "@expo/env": "~2.3.1"
- },
- "peerDependencies": {
- "expo": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo/node_modules/expo-file-system": {
- "version": "56.0.8",
- "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-56.0.8.tgz",
- "integrity": "sha512-NrH41/8snGIBSbYicwVLB4txPdgCATd7ZYhMAGS3YJZ9GbnduhlAoV4/YCbGayjrbpE9bJb/6wegPL/zmvRMnQ==",
- "license": "MIT",
- "peerDependencies": {
- "expo": "*",
- "react-native": "*"
- }
- },
"node_modules/expo/node_modules/expo-font": {
"version": "56.0.7",
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-56.0.7.tgz",
@@ -8753,21 +8741,6 @@
"node": ">=4"
}
},
- "node_modules/expo/node_modules/hermes-estree": {
- "version": "0.33.3",
- "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.33.3.tgz",
- "integrity": "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg==",
- "license": "MIT"
- },
- "node_modules/expo/node_modules/hermes-parser": {
- "version": "0.33.3",
- "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.33.3.tgz",
- "integrity": "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA==",
- "license": "MIT",
- "dependencies": {
- "hermes-estree": "0.33.3"
- }
- },
"node_modules/expo/node_modules/log-symbols": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
@@ -8937,15 +8910,6 @@
}
}
},
- "node_modules/expo/node_modules/zod": {
- "version": "3.25.76",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
- "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- },
"node_modules/exponential-backoff": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz",
@@ -9228,17 +9192,17 @@
}
},
"node_modules/form-data": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
- "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.2",
- "mime-types": "^2.1.12"
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
},
"engines": {
"node": ">= 6"
@@ -9610,9 +9574,9 @@
}
},
"node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -10030,12 +9994,12 @@
}
},
"node_modules/is-core-module": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
- "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
"license": "MIT",
"dependencies": {
- "hasown": "^2.0.2"
+ "hasown": "^2.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -10472,9 +10436,9 @@
}
},
"node_modules/istanbul-lib-instrument/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -10733,25 +10697,25 @@
}
},
"node_modules/jest-diff": {
- "version": "30.3.0",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz",
- "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==",
+ "version": "30.4.1",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.4.1.tgz",
+ "integrity": "sha512-CRpFK0RtLriVDGcPPAnR6HMVI8bSR2jnUIgralhauzYQZIb4RH9AtEInTuQr65LmmGggGcRT6HIASxwqsVsmlA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/diff-sequences": "30.3.0",
+ "@jest/diff-sequences": "30.4.0",
"@jest/get-type": "30.1.0",
"chalk": "^4.1.2",
- "pretty-format": "30.3.0"
+ "pretty-format": "30.4.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-diff/node_modules/@jest/schemas": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz",
- "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==",
+ "version": "30.4.1",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz",
+ "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10782,27 +10746,21 @@
}
},
"node_modules/jest-diff/node_modules/pretty-format": {
- "version": "30.3.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz",
- "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==",
+ "version": "30.4.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz",
+ "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/schemas": "30.0.5",
+ "@jest/schemas": "30.4.1",
"ansi-styles": "^5.2.0",
- "react-is": "^18.3.1"
+ "react-is-18": "npm:react-is@^18.3.1",
+ "react-is-19": "npm:react-is@^19.2.5"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/jest-diff/node_modules/react-is": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/jest-docblock": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
@@ -10967,25 +10925,25 @@
}
},
"node_modules/jest-matcher-utils": {
- "version": "30.3.0",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz",
- "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==",
+ "version": "30.4.1",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.4.1.tgz",
+ "integrity": "sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jest/get-type": "30.1.0",
"chalk": "^4.1.2",
- "jest-diff": "30.3.0",
- "pretty-format": "30.3.0"
+ "jest-diff": "30.4.1",
+ "pretty-format": "30.4.1"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
"node_modules/jest-matcher-utils/node_modules/@jest/schemas": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz",
- "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==",
+ "version": "30.4.1",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz",
+ "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11016,27 +10974,21 @@
}
},
"node_modules/jest-matcher-utils/node_modules/pretty-format": {
- "version": "30.3.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz",
- "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==",
+ "version": "30.4.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz",
+ "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/schemas": "30.0.5",
+ "@jest/schemas": "30.4.1",
"ansi-styles": "^5.2.0",
- "react-is": "^18.3.1"
+ "react-is-18": "npm:react-is@^18.3.1",
+ "react-is-19": "npm:react-is@^19.2.5"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/jest-matcher-utils/node_modules/react-is": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/jest-message-util": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
@@ -11268,9 +11220,9 @@
}
},
"node_modules/jest-snapshot/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -11533,9 +11485,19 @@
"license": "MIT"
},
"node_modules/js-yaml": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
- "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
+ "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodeca"
+ }
+ ],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
@@ -11623,43 +11585,6 @@
"node": ">= 6"
}
},
- "node_modules/jsdom/node_modules/tr46": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
- "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "punycode": "^2.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/jsdom/node_modules/webidl-conversions": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
- "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/jsdom/node_modules/whatwg-url": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
- "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tr46": "^3.0.0",
- "webidl-conversions": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/jsdom/node_modules/ws": {
"version": "8.21.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
@@ -11789,13 +11714,13 @@
}
},
"node_modules/launch-editor": {
- "version": "2.13.2",
- "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.2.tgz",
- "integrity": "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==",
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.14.1.tgz",
+ "integrity": "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==",
"license": "MIT",
"dependencies": {
"picocolors": "^1.1.1",
- "shell-quote": "^1.8.3"
+ "shell-quote": "^1.8.4"
}
},
"node_modules/leven": {
@@ -11982,6 +11907,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -12002,6 +11930,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "musl"
+ ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -12022,6 +11953,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -12042,6 +11976,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "musl"
+ ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -12360,9 +12297,9 @@
}
},
"node_modules/make-dir/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -13017,9 +12954,9 @@
}
},
"node_modules/node-abi/node_modules/semver": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
- "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -13592,9 +13529,9 @@
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
- "version": "11.3.5",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz",
- "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==",
+ "version": "11.5.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz",
+ "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==",
"license": "BlueOak-1.0.0",
"engines": {
"node": "20 || >=22"
@@ -13802,9 +13739,9 @@
"license": "ISC"
},
"node_modules/prebuild-install/node_modules/tar-fs": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
- "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
+ "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==",
"license": "MIT",
"dependencies": {
"chownr": "^1.1.1",
@@ -14136,9 +14073,9 @@
}
},
"node_modules/react-devtools-core/node_modules/ws": {
- "version": "7.5.10",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
- "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "version": "7.5.11",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz",
+ "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==",
"license": "MIT",
"engines": {
"node": ">=8.3.0"
@@ -14169,9 +14106,25 @@
}
},
"node_modules/react-is": {
- "version": "19.2.5",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.5.tgz",
- "integrity": "sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ==",
+ "version": "19.2.7",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz",
+ "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==",
+ "license": "MIT"
+ },
+ "node_modules/react-is-18": {
+ "name": "react-is",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/react-is-19": {
+ "name": "react-is",
+ "version": "19.2.7",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz",
+ "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==",
+ "dev": true,
"license": "MIT"
},
"node_modules/react-native": {
@@ -14372,9 +14325,9 @@
}
},
"node_modules/react-native-bootsplash/node_modules/fast-xml-parser": {
- "version": "4.5.6",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.6.tgz",
- "integrity": "sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A==",
+ "version": "4.5.7",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.7.tgz",
+ "integrity": "sha512-a6Qh1RMCNbSrU1+sAyAAZH3rTe+OaWJbNZIq0S+ifZciUUOQtlVxBJwoTUE2bYhysmG/RYyI5WJFIKdBahJdrQ==",
"funding": [
{
"type": "github",
@@ -14390,9 +14343,9 @@
}
},
"node_modules/react-native-bootsplash/node_modules/fs-extra": {
- "version": "11.3.5",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz",
- "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==",
+ "version": "11.3.6",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.6.tgz",
+ "integrity": "sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
@@ -14416,9 +14369,9 @@
}
},
"node_modules/react-native-bootsplash/node_modules/prettier": {
- "version": "3.8.3",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
- "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
+ "version": "3.9.4",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.4.tgz",
+ "integrity": "sha512-yWG/o/4oJfo036EKAfK6ACAoDOfHeRHx4tuxkfBZiauURiaSmYwlpOr5LQqKtIkRD2z1PLteme2WoxEnj4tHTg==",
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
@@ -14440,9 +14393,9 @@
}
},
"node_modules/react-native-bootsplash/node_modules/semver": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
- "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -14584,15 +14537,6 @@
}
}
},
- "node_modules/react-native/node_modules/@react-native/js-polyfills": {
- "version": "0.85.3",
- "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.85.3.tgz",
- "integrity": "sha512-U2+aMshIXf1uFn77tpBb/xhHWB9vkVrMpt7kkucAugF8hJKYTDGB587X7WwelHduK2KBfhl4giSv0rzZGoef9A==",
- "license": "MIT",
- "engines": {
- "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
- }
- },
"node_modules/react-native/node_modules/commander": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
@@ -14603,9 +14547,9 @@
}
},
"node_modules/react-native/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -14615,9 +14559,9 @@
}
},
"node_modules/react-native/node_modules/ws": {
- "version": "7.5.10",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
- "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "version": "7.5.11",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz",
+ "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==",
"license": "MIT",
"engines": {
"node": ">=8.3.0"
@@ -15242,9 +15186,9 @@
}
},
"node_modules/sharp/node_modules/semver": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
- "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -16047,9 +15991,9 @@
"license": "MIT"
},
"node_modules/tar-fs": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.2.tgz",
- "integrity": "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.3.tgz",
+ "integrity": "sha512-/hU4AXnIdZu+Gvl1pk0oI5f5HxWsCJRtY2aFaJdk9VvyL48DWU6iU5WAIPG+wIi1YvWA6eTJvIviP/tMAZZNwQ==",
"license": "MIT",
"dependencies": {
"pump": "^3.0.0",
@@ -16061,12 +16005,13 @@
}
},
"node_modules/tar-stream": {
- "version": "3.1.7",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
- "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.0.tgz",
+ "integrity": "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==",
"license": "MIT",
"dependencies": {
"b4a": "^1.6.4",
+ "bare-fs": "^4.5.5",
"fast-fifo": "^1.2.0",
"streamx": "^2.15.0"
}
@@ -16076,7 +16021,6 @@
"resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
"integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==",
"license": "MIT",
- "optional": true,
"dependencies": {
"streamx": "^2.12.5"
}
@@ -16195,9 +16139,9 @@
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"license": "MIT",
"engines": {
"node": ">=12"
@@ -16265,6 +16209,19 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/tr46": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
+ "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/ts-api-utils": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
@@ -16735,6 +16692,16 @@
"defaults": "^1.0.3"
}
},
+ "node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/whatwg-encoding": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
@@ -16778,6 +16745,20 @@
"node": ">=12"
}
},
+ "node_modules/whatwg-url": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
+ "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "^3.0.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/whatwg-url-minimum": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/whatwg-url-minimum/-/whatwg-url-minimum-0.1.2.tgz",
@@ -17081,9 +17062,9 @@
}
},
"node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "version": "17.7.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
+ "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
"license": "MIT",
"dependencies": {
"cliui": "^8.0.1",
@@ -17120,10 +17101,9 @@
}
},
"node_modules/zod": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
- "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
- "dev": true,
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
diff --git a/package.json b/package.json
index 96dbac5..51e576e 100644
--- a/package.json
+++ b/package.json
@@ -26,8 +26,12 @@
"@tanstack/react-query": "^5.96.1",
"babel-preset-expo": "~56.0.0",
"expo": "~56.0.15",
+ "expo-asset": "~56.0.19",
+ "expo-audio": "~56.0.12",
"expo-build-properties": "~56.0.22",
+ "expo-crypto": "~56.0.4",
"expo-dev-client": "~56.0.22",
+ "expo-file-system": "~56.0.8",
"expo-secure-store": "~56.0.4",
"expo-updates": "~56.0.21",
"lucide-react-native": "^0.544.0",
@@ -75,4 +79,4 @@
"glob": "^13.0.6",
"rimraf": "^4.0.0"
}
-}
+}
\ No newline at end of file
diff --git a/src/app/context/DraftingContext.test.tsx b/src/app/context/DraftingContext.test.tsx
new file mode 100644
index 0000000..cff914e
--- /dev/null
+++ b/src/app/context/DraftingContext.test.tsx
@@ -0,0 +1,69 @@
+import React from 'react';
+import { Text } from 'react-native';
+import { act, render, screen } from '@testing-library/react-native';
+import { DraftingProvider, useDraftingContext } from './DraftingContext';
+import type { ChapterAssignmentData, VerseData } from '../../types/db/types';
+
+const VERSES: VerseData[] = [
+ { bibleId: 1, bookId: 41, chapterNumber: 14, verseNumber: 1, text: 'v1' },
+ { bibleId: 1, bookId: 41, chapterNumber: 14, verseNumber: 5, text: 'v5' },
+ { bibleId: 1, bookId: 41, chapterNumber: 14, verseNumber: 9, text: 'v9' },
+];
+
+const CHAPTER: ChapterAssignmentData = {
+ id: 88,
+ projectUnitId: 7,
+ bibleId: 1,
+ bookId: 41,
+ chapterNumber: 14,
+ status: 'in_progress',
+};
+
+let selectedFromContext = -1;
+
+function Probe() {
+ const { selectedVerse } = useDraftingContext();
+ selectedFromContext = selectedVerse;
+ return {`verse:${selectedVerse}`};
+}
+
+function renderProvider(initialVerse: number) {
+ return render(
+
+
+ ,
+ );
+}
+
+describe('DraftingProvider', () => {
+ it('exposes the initial verse as the selected verse', () => {
+ renderProvider(5);
+ expect(screen.getByText('verse:5')).toBeTruthy();
+ });
+
+ it('re-points the selected verse when initialVerse changes', () => {
+ const { rerender } = renderProvider(1);
+ expect(screen.getByText('verse:1')).toBeTruthy();
+
+ act(() => {
+ rerender(
+
+
+ ,
+ );
+ });
+
+ expect(screen.getByText('verse:9')).toBeTruthy();
+ expect(selectedFromContext).toBe(9);
+ });
+});
diff --git a/src/app/context/DraftingContext.tsx b/src/app/context/DraftingContext.tsx
index 62d2a3b..d0b1964 100644
--- a/src/app/context/DraftingContext.tsx
+++ b/src/app/context/DraftingContext.tsx
@@ -1,4 +1,4 @@
-import { VerseData } from '../../types/db/types';
+import { ChapterAssignmentData, VerseData } from '../../types/db/types';
import React, { createContext, useContext, useMemo, useState } from 'react';
interface DraftingContextValue {
@@ -6,6 +6,9 @@ interface DraftingContextValue {
setSelectedVerse: (verseNumber: number) => void;
verses: VerseData[];
+ chapterAssignment: ChapterAssignmentData;
+ /** Book name for verse references (falls back to route chapter name). */
+ bookDisplayName: string;
/**
* The verse whose source audio is currently playing, tracked
* independently of `selectedVerse`. Not wired to real audio yet —
@@ -24,29 +27,47 @@ interface DraftingProviderProps {
children: React.ReactNode;
verses: VerseData[];
initialVerse: number;
+ chapterAssignment: ChapterAssignmentData;
+ bookDisplayName: string;
}
export function DraftingProvider({
children,
verses,
initialVerse,
+ chapterAssignment,
+ bookDisplayName,
}: DraftingProviderProps) {
const [selectedVerse, setSelectedVerse] = useState(initialVerse);
const [currentlyPlayingVerse, setCurrentlyPlayingVerse] = useState<
number | null
>(null);
+ // Re-point the selection when the screen hands us a new target verse (e.g. a
+ // recovery navigation, or a chapter reload with a new default). Without this
+ // the selection would stay frozen at the first mount's value if the provider
+ // is kept mounted across an initialVerse change.
+ const [prevInitialVerse, setPrevInitialVerse] = useState(initialVerse);
+ if (initialVerse !== prevInitialVerse) {
+ setPrevInitialVerse(initialVerse);
+ setSelectedVerse(initialVerse);
+ }
+
const value = useMemo(
() => ({
selectedVerse,
setSelectedVerse,
verses,
+ chapterAssignment,
+ bookDisplayName,
currentlyPlayingVerse,
setCurrentlyPlayingVerse,
}),
[
selectedVerse,
verses,
+ chapterAssignment,
+ bookDisplayName,
currentlyPlayingVerse,
setSelectedVerse,
setCurrentlyPlayingVerse,
diff --git a/src/app/screens/DraftingScreen.tsx b/src/app/screens/DraftingScreen.tsx
index 764b7f0..0e33979 100644
--- a/src/app/screens/DraftingScreen.tsx
+++ b/src/app/screens/DraftingScreen.tsx
@@ -6,7 +6,7 @@ import { RecordTab } from '../tabs/RecordTab';
import { useSyncStatus } from '../../hooks/useSyncStatus';
import { onSyncComplete } from '../../services/syncEvents';
import { StackNavigationProp } from '@react-navigation/stack';
-import React, { useCallback, useEffect, useState } from 'react';
+import React, { useCallback, useEffect, useRef, useState } from 'react';
import { RootStackParamList } from '../../types/navigation/types';
import { DraftingHeader } from '../../components/layout/DraftingHeader';
import { ChapterAssignmentData, VerseData } from '../../types/db/types';
@@ -23,8 +23,9 @@ import {
} from '../context/DraftingContext';
import {
DraftingTab,
- DraftingTabBar,
-} from '../../components/layout/DraftingTabBar';
+ type TabSwitchGuardRef,
+} from '../../types/drafting/types';
+import { DraftingTabBar } from '../../components/layout/DraftingTabBar';
import {
getBibleTexts,
getChapterAssignmentById,
@@ -38,10 +39,10 @@ type Route = RouteProp;
export default function DraftingScreen() {
const navigation = useNavigation