Repository navigation
Conversation
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
f3dd774 to
0a46981
Compare
|
History cleanup after a review question: commit 2 ("Upgrade to React Native 0.85.3") previously contained a spurious Audited the whole series for more of the same (blob-level revert detection across all commits + exact-line added-then-removed scan, lockfile excluded): this was the only instance. Final tree is bit-identical to the previously validated one, and all 5 commits re-passed the per-commit precommit gate (521/521 tests on commit 1's RN 0.79 base; 517/517 on 0.85). |
0a46981 to
30638ca
Compare
|
🔴→✅ Regression found in review and fixed: the PR was accidentally reverting develop PR #6044 ("Deprecate Botanix to keys-only mode on July 9, 2026") — the Fixed by restoring develop's versions of all 5 files into the upgrade commit — the upgrade legitimately changed zero lines in them, so they now drop out of the PR diff entirely. Verification:
The Botanix July 9 deprecation survives this PR. |
30638ca to
83b07b2
Compare
|
🐛 On-device Android testing found (and fixed) a blocking crash — new commit Symptom: release build on a physical device (OnePlus 5T) crashed the moment the password login scene mounted (tap "Sign in" from the welcome carousel). Root cause: RN 0.85's Android Fabric text measurement throws Fix: clamp animated font sizes to ≥1 (visually identical — the icon containers already collapse to zero width) in the GUI's Verified: rebuilt release APK on the same device — password login scene renders, inputs + eye icon work, zero fatal exceptions. Commit gated: localize/warnings clean, tsc clean, eslint 0 errors, 521/521 tests. Follow-up: edge-login-ui-rn needs the same clamp in its own repo ( |
12195dd to
5a23fed
Compare
|
♻️ Rebased onto current develop (was 67 commits behind and conflicting; now conflict-free). Same 6 commits, same content — mechanical notes:
Also: the edge-login-ui-rn fontSize fix now exists as a proper branch in that repo ( |
5a23fed to
a6c3123
Compare
|
🔁 Retargeted to React Native 0.86.0 / Expo SDK 57 — same 6-commit structure, now a single hop from 0.79.2 to current stable (no intermediate 0.85 in history). What changed in the retarget:
Verification: audits clean (0 develop-window stomps, 0 within-series reverts, coherent prebuilt-free lock); per-commit gates 6/6 at 557/557 (JS surface; post-sweep amendments were iOS-native only, covered by builds); Android release APK builds; iOS builds from source and boots to login on the simulator. On-device Android smoke pending device reconnect. edge-login-ui-rn's clamp branch ( |
a6c3123 to
19a162f
Compare
c4e6ae9 to
224c2e7
Compare
720de61 to
57ee1e1
Compare
Android ran reanimated 3 via the local `r3-hack` package on the old architecture while iOS ran reanimated 4 on Fabric. Reanimated 4 requires the new architecture, so route both platforms through reanimated 4 / worklets and enable the new architecture on Android: - babel.config.js: always use react-native-worklets/plugin; add api.cache(true) now that the config is static (no platform branch configuring the cache). - metro.config.js: drop the r3-hack Android resolver. - react-native.config.js: drop the reanimated sourceDir override and the worklets Android disable. - package.json: remove the r3-hack dependency; delete scripts/r3-hack. - android/gradle.properties: newArchEnabled=true. - useCarouselGesture: unify the withSpring config to the reanimated-4 algorithm on both platforms (Android previously used the reanimated-3 damping). Also dedupe yaob to ^0.4.0, fixing the nativeIo collision that crashed ZEC/Pirate wallet creation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the app from React Native 0.79 to 0.86.0 / Expo SDK 57, with both platforms on reanimated v4 and the new architecture. Expo SDK 57 is the release paired with RN 0.86, with React at 19.2. Bumps the RN-ecosystem dependencies together (reanimated 4.5, worklets 0.10, gesture-handler 2.32 per the SDK 57 pin set; TypeScript deliberately held at 5.8.3) and updates the jest preset, worklets resolver, and test snapshots. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Enable newArchEnabled, bump compile/target SDK 35->36, and rewrite settings.gradle for Expo SDK 56 autolinking. Unwrap MainApplication from the ReactNativeHostWrapper removed in SDK 56. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Expo autolinking + new-architecture Podfile (deployment target 16.4 - Expo SDK 57's floor; React Native 0.86 itself only needs 15.1), the ExpoReactNativeFactory AppDelegate, and RCTNewArchEnabled in Info.plist. Includes the build fixes needed under Xcode 26. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
React Native 0.86's Android Fabric text measurement throws IllegalArgumentException ("FontSize should be a positive value") for any Text whose font size is 0 - TextLayoutManager's letterSpacing.isNaN() check unconditionally invokes a getter that validates fontSize > 0. FilledTextInput animates its side-icon sizes to exactly 0 (clear icon on an empty input, left icon when focused), and those sizes feed AnimatedFontIcon's fontSize, so mounting any scene with a text input crashed the app - most visibly the password login scene via edge-login-ui-rn, which shares the same component pattern.
Clamp animated font sizes to a minimum of 1 (visually equivalent: the icon containers already collapse to zero width) in the GUI's AnimatedFontIcon and FilledTextInput, and apply the same one-line clamp to edge-login-ui-rn via patch-package until the fix lands upstream.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
React Native ships this protection default-off. Without it, a runaway ShadowTree commit loop aborts the app in native code with "assertion failed (attempts < 1024)", which reproduced on an Android 10 device while interacting with text inputs. The iOS side of this is a source patch, but Android loads the React Native core from a prebuilt library, so the default cannot be patched there. Override the flag at runtime instead. The override is once-per-process and load() already consumes it, so reset first and re-apply React Native's stable defaults alongside our one change.
The drawer's outside-tap overlay is an Animated.View whose dimming, touchability and stacking are all driven from a reanimated shared value. On Android below 12 under the new architecture those updates never apply, so the overlay never painted its scrim and never captured touches: taps fell through to the scene behind the open drawer and the drawer could not be closed by tapping outside. On those devices only, render a plain View driven by the drawer's discrete open state, sized explicitly because an absolutely positioned view sized only by insets measures 0x0 there. Every other platform keeps the original animated overlay, verified unchanged on an Android 16 emulator. React Navigation 7 makes this same change upstream, so this patch retires when we migrate.
On Android below 12 the blur library falls back to RenderScript, which cannot snapshot content rendered by the new architecture. Instead of the content behind it, it paints a flat gray wash, so modals, the tab bar, scene headers and footers, notification cards and the keyboard-avoiding buttons all rendered washed out or transparent. There is no way to make that blur render correctly, so skip it on those devices and have each host paint a solid background instead. The dark theme's modal color is translucent because it normally sits on top of the blur, so modals get a solid stand-in, and the QR modal gets a plain scrim in place of its blurred underlay. The login-ui patch carries the same fix for its own copies, plus a fix for a development-mode render error where animation worklets captured a Date they cannot serialize.
The auto-login effect runs on mount and disarms itself immediately, but on release builds this scene mounts before the core context reaches the store, so the attempt ran against the placeholder object, threw, and never retried. Bail out until the context is ready and let the effect re-run. Development builds win the race, which is why this only ever showed up in release builds.
View recycling only runs under the new architecture, so enabling it turned this on for the first time. Recycled views arrive still carrying visual properties from their previous use: a button that becomes enabled stays dimmed, and labels render at a stale font size. Both were reproduced on an Android 10 device, on the survey modal's Next button and the wallet name modal's title. Keep recycling off so views render the way they did before the architecture switch. Re-enabling it is a performance follow-up once the property-reset gaps are fixed upstream.
…ture Both new-architecture text layouts ignore `minimumFontScale`: iOS's RCTTextLayoutManager and Android's TextLayoutManager floor `adjustsFontSizeToFit` at an absolute `minimumFontSize`, 4pt when unset, so long labels shrank until illegible (seen on the wallet-name modal title and the amount modal header). React Native's Text never forwards that prop because the RCTText view config does not list it, so the react-native patch adds `minimumFontSize` there, and EdgeText (plus UnscaledText when a caller opts into shrinking with a scale) derives it from the style's font size: points on iOS, pixels on Android, whose shrink loop compares against a pixel text size. Snapshots gain the new prop.
Modals deliberately bleed past the bottom of the screen so the sheet never shows a seam above the navigation bar. That overhang sits behind the keyboard, which cut off the bottom of the modal's own content - the text input modal's submit button was only half visible. Drop the overhang while the keyboard is open, the same way SceneWrapper already drops its bottom inset. The drag slop stays, so swipe-to-dismiss is unchanged.
Two problems with how the amount and its currency code were laid out: The input carried a negative margin compensating for extra width that the old architecture added for short values. That extra width is gone, so the compensation pulled the currency code into the digits: '1USD' with one digit, correct spacing from two digits on. The input's width is also measured a render behind its contents, so a value that grows by more than one character at once - 123 becoming 1,234, which also gains a separator - was drawn wider than its box and the leading digits were clipped. Typing past it or deleting back to the same value looked fine, which is what made it look intermittent. Size the field with a matching Text instead, which measures in the same pass as the value it draws, and drop the obsolete margin.
The field echoes a keystroke before it has re-measured, so for one frame the text was wider than its box and slid left, taking the leading digits out of view before settling. A rejected keystroke made it worse: the value never changes, so the box never grows and the echo sat there until it was reverted. Reserve a character of width in the field so a keystroke always has somewhere to land. That reserved space reads as a slightly wider gap before the currency code, which is the trade: the alternative is letting the currency code sit over the reserved space, and then a keystroke briefly draws on top of it.
The Jenkins iOS agents' Xcode upgrade broke expo-modules-jsi 57.0.3 twice over. First, `abs(milliseconds)` in JavaScriptCodable+Date.swift became ambiguous (expo/expo#47957); upstream fixed it in 57.0.5 with `milliseconds.magnitude`, and the existing ~57.0.3 range already allows it, so the lockfile pin moves to 57.0.6 along with the matching pod. Second, the newer Swift rejects SWIFT_RETURNS_RETAINED on the two RuntimeScheduler constructors because the type is not imported as a shared reference. Upstream removed both annotations on their SDK 58 line; the patch mirrors that change exactly and is droppable once a 57.x release picks it up (57.0.6 is currently the newest).
The Jenkins agent's newer Swift rejects EventEmitter's
`nonisolated(unsafe) weak let` captures being sent into the JavaScript
actor ("sending 'emitter' risks causing data races"). Upstream's SDK 58
line already fixed this by boxing the weak reference in the
NonisolatedUnsafeWeakVar wrapper that 57.0.6 ships but does not yet use
here; this patch mirrors that change exactly. No 57.x release carries it
(57.0.14 is byte-identical in this file), so the patch is droppable when
one does.
`deprecated-react-native-prop-types` exists to shim libraries that import PropTypes from react-native; RN 0.86 removed those exports entirely and nothing in the app imports it. `@types/react-native` is stale at 0.71 and obsolete since react-native ships its own types. `react-native-email-link` looks equally unused — it appears in no source file — but it stays: edge-login-ui-rn imports it in PasswordRecoveryActions while declaring it only as a devDependency, so the app has to supply it. Removing it breaks the bundle at password recovery. Fourteen other packages reach us the same way; `react-native-linear-gradient`, `rn-id-blurview`, `react-native-vector-icons` and `react-native-permissions` are the ones that matter for any future dependency cleanup.
react-native-linear-gradient has no codegen spec, so every gradient in the app - cards, buttons, the header, the tab bar, the scene background - was drawn through Fabric's legacy view-manager interop. expo-linear-gradient is a real Fabric component and Expo is already a dependency, so this swap removes a native dependency rather than adding one: edge-login-ui-rn's six gradient scenes migrate through the regenerated patch, which lets react-native-linear-gradient leave package.json entirely (verified on device that removing it beforehand left PinLoginScene throwing "View config not found for component BVLinearGradient"), and the BVLinearGradient pod gives way to ExpoLinearGradient. The props are the same (`colors`, `start`, `end`, `locations`); nothing uses `useAngle`, the one prop Expo lacks. What differs is the typing: Expo wants the color and location arrays to be tuples of two or more, since a gradient with fewer stops has nothing to interpolate. The theme's gradient fields become `GradientColors` to match, and the six scenes that darken the first stop of the asset background build a new tuple instead of mutating a copy. react-native-gifted-charts also reaches for a gradient, but it tries react-native-linear-gradient and falls back to expo-linear-gradient, with both declared optional; the bundle builds and resolves to the Expo one. expo-linear-gradient is mocked in jestSetup because importing it pulls in expo-modules-core, which expects native globals the react-native jest preset doesn't provide. Snapshots move from BVLinearGradient to that mock. Touching these files takes them off the ESLint warnings list, so their pre-existing lint errors are fixed here too.
edge-login-ui-rn asked for react-native-airship ^0.2.9 and patina ^0.1.6 while this app asks for ^0.3.0 and ^0.2.0, so npm installed both — nested copies under edge-login-ui-rn alongside ours. Both packages are UI-layer singletons: airship owns the portal host every modal mounts into, and patina caches themed styles. Two module instances of either is the same class of problem as the duplicate yaob that once cross-wired native IO. edge-login-ui-rn now asks for the same versions, but npm resolves the dependency tree from its published manifest, so that alone won't collapse the duplicates until a release goes out. The overrides make it true today and stay correct afterwards. Both are pure JavaScript, so no native rebuild is involved. Verified the auto-logoff modal still mounts and dismisses through the portal host.
react-native-keyboard-aware-scroll-view has had no release since 2022. It
is pure JavaScript, so it never appeared in a codegen audit, but it drives
its scrolling with findNodeHandle, UIManager.measureInWindow and
UIManager.viewIsDescendantOf - the legacy measurement APIs the new
architecture only serves through a compatibility shim. We already depend on
react-native-keyboard-controller, which ships an equivalent component.
`extraScrollHeight` becomes `bottomOffset`, and the `enableOnAndroid` /
`enableAutomaticScroll` opt-ins go away because the replacement always does
both. Everything else is plain ScrollView props. SendScene2 keeps a ref to
scroll to the end, which is now a plain `ref` rather than `innerRef`, and
takes React Native's `scrollToEnd({ animated })` signature instead of the
old library's positional one.
SurveyModal is the one behavior change: it passed an extraScrollHeight of
-16rem on iOS against +9rem on Android, a hack around the old library
measuring the two platforms differently. bottomOffset means the same thing
on both, so both now pass the 2.75rem every other scene uses.
edge-login-ui-rn makes the same migration in its three keyboard scenes, so
its patch is regenerated here - and renamed to 3.37.2, the version npm
actually resolves, silencing the version-mismatch warning every install
printed. Verified on Android: the address form scrolls a field near the
bottom clear of the keyboard on focus and accepts input. Touching these
files takes them off the ESLint warnings list, so their pre-existing lint
errors are fixed too.
LoginScene has published `global.ReactNativeBlurView` since 2020, when edge-login-ui-rn could not add a native dependency without a breaking release and instead feature-detected a blur component the host snuck to it at runtime (falling back to a dim underlay without one). The reading side was deleted from login-ui in September 2023 (v2.15.0), when its modals started importing rn-id-blurview directly. Nothing in this app, in the installed login-ui lib, or anywhere else in node_modules reads the global today, so the assignment has been write-only for almost three years. The rn-id-blurview import here existed only to feed it.
Under the new architecture the old blur path (rn-id-blurview, Dimezis 2) snapshots the window with a software canvas that renders empty on every Android version - the API < 31 grey wash and a silently transparent sheet on 12+ are the same disease with different symptoms. Modal sheets were see-through over busy scenes, and the chrome tint had been impersonating blur all along. Dimezis 3 fixed the snapshot in hardware but changed the contract: content must be wrapped in an explicit blur target, and whole-window sampling is gone. expo-blur ships that backend as a Fabric-native component, so this adds expo-blur (and its pod) rather than another native dependency. Two targets cover the two kinds of blur surface, shaped by one hard constraint: a blur view must never sit inside its own target, or the renderer recurses computing transforms and overflows the stack (a native libhwui crash). - Modals: the app tree gains one BlurTarget wrapping Main, inside the Airship layer, so ModalBlurBackground (EdgeModal) and the QR modal underlay sample the app content from outside it. login-ui mounts the equivalent target in LoginUiProvider for its own modals, delivered through the regenerated patch. - Chrome: the header, scene footer, tab bar, and notification cards overlay the scene and live inside the app-level target, so each SceneWrapper wraps its content (background dots plus children, excluding the absolutely-positioned footer overlay) in its own target and publishes the ref through a registry while focused. ChromeBlurBackground samples whichever scene is focused, retargeting as navigation changes, and falls back to the long-standing tint when no scene publishes one (login, scenes outside SceneWrapper). The scene footer needs no special casing: with tabs it portals into MenuTabs and without them it is absolutely positioned, so it never sits inside what it samples. Modal backgrounds return to translucent-over-blur on 12+, keeping the solid color below API 31 where no blur implementation can render. iOS keeps its existing whole-window blur, unchanged. Verified on device: the sort modal frosts the wallet list, the security-alerts modal is opaque and legible, the tab bar softly blurs list content scrolling beneath it, and no recursion crash across cold start, tab switches, and stack navigation.
Edge-to-edge draws the window under the status bar, and the Airship layer's safe-area measurement is iOS-only (it measures through React Native's SafeAreaView, a no-op on Android), so dropdown notifications - received transactions, error alerts - slid in underneath the status bar and camera cutout instead of below them. Add the top inset to the dropdown's own padding on Android. iOS already receives it from the Airship layer, so it is excluded there to avoid a doubled gap. login-ui's error dropdown gets the same fix through the regenerated patch.
Two fixes in 6.0.0 target exactly this app's setup: new-architecture detection on React Native 0.77+ and an Android soft exception when the event emitter is touched before initialization (plus Android listener-leak fixes). The breaking changes do not reach us - Flipper support removal (React Native itself dropped Flipper), Flow-to-TypeScript codegen internals, and renames of old-bridge lifecycle APIs the app never calls. Our entire usage is the standard performance mark/measure API in perf.ts.
Both upgrades take the module from bridge interop to codegen under the new architecture. Sound 0.13.0 changes nothing in the API we touch (setCategory, load, play). Haptic-feedback 3.0.0 keeps the default-export trigger() call both this app and edge-login-ui-rn use; its breaking changes are additions (hooks, patterns) and the TurboModule conversion, which is why jest now needs a mock - the import itself demands a native binding. login-ui pins ^1.14.0 until its next release, so an npm override keeps the tree at one copy, the same arrangement airship and patina already use; the login-ui branch bumps its own range in lockstep.
The disable animation's shared value always started at 0 (enabled), and a mount effect then animated it toward the actual disabled prop. An input mounted with disabled=true therefore flashed its enabled look for ~300ms every time its scene appeared - most visibly the spending-limit amount field, whose scene mounts it disabled whenever the limit is switched off. Seed the shared value with the mounted state so the first frame is already correct; later prop changes still animate as before. Fix the same pattern in edge-login-ui-rn's copies of these inputs via the login-ui patch, mirroring an identical commit in that repo.
Regenerate patches/edge-login-ui-rn+3.37.2.patch from the edge-login-ui-rn branch (PR #301) so the app picks up the fixes mirrored there: EdgeText truncating instead of shrinking on Android, EdgeModal dropping its bottom overhang while the keyboard is open (seeded from Keyboard.isVisible), and the animated font-size clamps in both text inputs. This lands as one commit rather than fixups to the matching feature commits because the 3.37.2 patch file postdates them - it was created by the keyboard-controller commit and evolves forward from there. The patch disappears entirely once login-ui releases and the dependency bumps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@react-navigation/drawer's Overlay spreads StyleSheet.absoluteFillObject, which React Native 0.86 removed; spreading the now-undefined value yields an empty style, so the side menu's dimming overlay had no geometry on both platforms - the scene stayed undimmed and tapping outside the menu no longer closed it. Spread absoluteFill instead, in both drawer implementations, via the existing drawer patch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regenerate patches/edge-login-ui-rn+3.37.2.patch from the edge-login-ui-rn branch (PR #301): the absolute-fill literal that restores the modal blur sheet and the EdgeButton, EdgeCard and ChallengeModal backgrounds on React Native 0.86, the expo-blur backend on iOS, and the removal of the dead common/BlurBackground module. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Android 12+ already blurs through expo-blur. Use it for every iOS blur surface as well - modals, header, tab bar, scene footer, notification cards and the QR underlay - and drop rn-id-blurview: an old-architecture RCTViewManager with no codegen spec, so it only reaches the new architecture through the legacy interop layer, and the same class of library that could not render at all on Android. Removes the pod and the module declaration; snapshots follow the component rename. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
57ee1e1 to
bb41a87
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bb41a87. Configure here.
| @@ -1772,6 +1783,7 @@ PODS: | |||
| - ReactCodegen | |||
| - ReactCommon/turbomodule/bridging | |||
| - ReactCommon/turbomodule/core | |||
| - ReactNativeDependencies | |||
There was a problem hiding this comment.
WebView patches no longer apply
High Severity
react-native-webview moved to 13.16.1, but patches/react-native-webview+13.15.0.patch still targets the old version, so patch-package skips it. That drops the origin-whitelist end anchor (prefix origins can pass), the Android download-permission check, and the onLoadProgress navigation-state update used in wallet webviews.
Reviewed by Cursor Bugbot for commit bb41a87. Configure here.
| /** A blur background WITHOUT rounded corners. For the scene header/footer, | ||
| * which also live inside the blur target - see BlurBackground. */ |
There was a problem hiding this comment.
Suggestion: this doc comment documents nothing. It describes a "blur background WITHOUT rounded corners" export that no longer exists, and ChromeBlurBackground has its own comment right below. A reader will go looking for the missing export; delete these two lines.
| ? '#2b2b2b' | ||
| : '#f2f2f2' |
There was a problem hiding this comment.
Suggestion: the Android <12 fallback colors are literals here ('#2b2b2b' / '#f2f2f2') and again in BlurBackground.tsx:26 ('#161616' / '#f6f6f6'), so a theme color change skips these surfaces on the devices that take the fallback. Two theme keys (modal and chrome fallback) would keep them in the theme files. edge-login-ui-rn#301 hardcodes the same modal pair, so the key names could match across both repos.
| .delay(delay) | ||
| // reanimated declares the preset statics as returning the base builder, but | ||
| // at runtime they return the preset instance with the full complex surface: | ||
| let builder = (animBuilder.delay(delay) as ComplexAnimationBuilder<any>) |
There was a problem hiding this comment.
Suggestion: ComplexAnimationBuilder<any> can be plain ComplexAnimationBuilder. In reanimated 4.5.3 the type parameter defaults to StyleProps (ComplexAnimationBuilder<TValues = StyleProps>), which is what getAnimBuilder already returns, and the withInitialValues({ transform: [...] }) calls below fit Partial<StyleProps>. With any, a wrong shape passed to withInitialValues type-checks.
|
|
||
| /** A blur background WITH rounded corners, used for most components */ | ||
| export const BlurBackground = () => { | ||
| // Android below 12 (API 31) has no working blur under the new architecture: |
There was a problem hiding this comment.
Noting for reference: 5% of our Android users in the past 30d fall under this category. Acceptable tradeoff.
(Not a change request)


iOS blur root cause (found with a physical iPhone X, iOS 16.7): React Native 0.86
removed
StyleSheet.absoluteFillObject; spreading the now-undefined value yields anempty style, so any absolutely positioned layer that spread it collapsed to nothing.
edge-login-ui-rn spread it in six places (its modal blur sheet - the "grey modal" with
the scene sharp behind it - plus EdgeButton, EdgeCard and ChallengeModal backgrounds),
fixed in PR #301 and carried here through the patch. The same collapse hit
@react-navigation/drawer's overlay (side menu no longer dimmed or closed on outsidetap) - fixed via the drawer patch. Two blur libraries failed identically before the
fix, which is how the library was ruled out; iOS now unifies on expo-blur and
rn-id-blurviewis dropped. Verified: login-ui and GUI modals blur on simulator anddevice; side-menu overlay dims and closes.
Note
High Risk
Full-stack platform upgrade (new architecture, native toolchains, Firebase, and rendering) touches every screen; regressions in blur, navigation overlays, scrolling, and native crashes are plausible despite targeted flag and library mitigations.
Overview
Upgrades the app to React Native 0.86 and Expo SDK 57 with the new architecture enabled on Android and iOS, including Gradle 9 / compileSdk 36, Expo’s unified autolinking, Hermes V1 with React-Core built from source on iOS (min deployment 16.4), and bumped native deps (Firebase 12, Reanimated 4.5, etc.).
Android startup drops
ReactNativeHostWrapperand, after new-archload(), resets React Native feature flags to enable ShadowTree commit-exhaustion protection and keep view recycling disabled so recycled views don’t leave stale dimmed buttons or font sizes. Release lint is turned off to avoid OOM; Gradle JVM heap is increased.UI stack migrations replace legacy blur/gradient/keyboard libraries with expo-blur, expo-linear-gradient, and react-native-keyboard-controller; rn-id-blurview and react-native-linear-gradient are removed from pods. Babel now always uses
react-native-worklets/plugin(no Android-specific Reanimated path).The CHANGELOG records follow-on fixes for new-arch behavior: side-menu overlay tap-to-close, modal/header blur (solid fallbacks on older Android), keyboard/modal/amount-field/accessibility issues,
minimumFontScalevia a small RN patch, deduped airship/patina installs, and measured Android scroll performance gains in release benchmarks.Reviewed by Cursor Bugbot for commit bb41a87. Bugbot is set up for automated code reviews on this repo. Configure here.