Skip to content

refactor(suite-native): separate app composition from initialization - #32199

Merged
peter-sanderson merged 5 commits into
developfrom
refactor-native-app-initialization
Sep 8, 2026
Merged

refactor(suite-native): separate app composition from initialization#32199
peter-sanderson merged 5 commits into
developfrom
refactor-native-app-initialization

Conversation

@peter-sanderson

@peter-sanderson peter-sanderson commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Description

Align native startup with web and desktop by creating the Redux store and services synchronously, then injecting services into Redux extra. A separate init service starts persistence, waits for hydration, and runs application initialization while preserving native storage and migrations. This follows #32195.

🌐 Preview deployments

🌐 Suite Web preview: https://dev.suite.sldev.cz/suite-web/refactor-native-app-initialization/web/

🔍 Currents Test Results

🔍 Suite desktop test results: View in Currents

🔍 Suite web test results: View in Currents

🔍 Suite native android test results: View in Currents

🔒 Quarantined E2E Tests

Trezor Suite (web) — 3 test(s)
Test Type
Staking - Cardano > Stake Cardano 🤖 auto
Trading - Swap > Swap SOL USDT token to ETH 🤖 auto
Trading - Swap coin to token > Swap Solana to USDC 🤖 auto

Updated: 2026-09-08T18:25:17.235Z • 3 test(s) total

Trezor Suite (desktop) — 3 test(s)
Test Type
Suite Sync - Update and Remove Labels > Update and remove labels syncs correctly to relay 🤖 auto
Quarantine test: "Suite Sync - Quota Manager top-up,Exceeded wallet limit is topped up from the device pool" 🙋 manual
Trading - Swap > Swap SOL USDT token to ETH 🤖 auto

Updated: 2026-09-08T18:23:45.650Z • 3 test(s) total

🤖 LLM Test Recommendations

Summary: The changes span Redux store creation and extra-dependency configuration for both web and native Suite. Most candidate tests only transitively import these global files, so a minimal representative set is recommended: validate app boot and persistence (initial-run, db-migration) and exercise state-dependent flows that rely on correct store setup (analytics, multi-session, remembered-wallet hydration). The bulk of the diff is native-only and is not covered by the web/electron E2E suite; those native files should be validated separately via the modified native E2E tests.

Changed files (22)
  • packages/suite/src/reducers/createReduxStore.ts
  • suite-common/redux-utils/src/createReduxExtra.test.ts
  • suite-common/redux-utils/src/createReduxExtra.ts
  • suite-common/redux-utils/src/index.ts
  • suite-native/app/e2e/tests/tradingExchangeFlow.test.ts
  • suite-native/app/e2e/tests/tradingSellFlow.test.ts
  • suite-native/app/index.js
  • suite-native/app/package.json
  • suite-native/app/src/App.tsx
  • suite-native/app/src/createNativeInit.tsx
  • suite-native/app/src/createSuiteNativeCompositionRoot.ts
  • suite-native/app/src/initSentry.ts
  • suite-native/app/tsconfig.json
  • suite-native/state/mocks/mockInitialAppState.ts
  • suite-native/state/src/NativeServices.ts
  • suite-native/state/src/StoreProvider.tsx
  • suite-native/state/src/createHydrateReduxStore.ts
  • suite-native/state/src/createNativeExtraDependencies.ts
  • suite-native/state/src/createNativeServicesCompositionRoot.ts
  • suite-native/state/src/createReduxStore.ts
  • suite-native/state/src/createStorePersistor.ts
  • suite-native/state/src/index.ts

Recommended tests (5)

🔴 High priority (2)
  • suite/e2e/tests/suite/initial-run.test.ts — This test validates the app boots correctly on first run and that onboarding/analytics state persists across reloads, which directly exercises the web Redux store creation and hydration path changed in createReduxStore.ts and createReduxExtra.ts.
  • suite/e2e/tests/suite/db-migration.test.ts — This test upgrades an older Suite version's persisted state and verifies settings survive migration, directly stressing store hydration, persistence, and state shape from the changed store/extra-dependency code.
🟡 Medium priority (3)
  • suite/e2e/tests/analytics/events.test.ts — Analytics event dispatching and interception depend on the store's middleware and extra thunk dependencies configured by createReduxExtra.ts; this test verifies the analytics pipeline still emits correct events after the shared utility changes.
  • suite/e2e/tests/suite/multiple-sessions.test.ts — This test exercises Bridge session state across page reloads and multiple tabs, which relies on the store being re-created correctly on each load.
  • suite/e2e/tests/trading/remembered-wallet-loading.test.ts — This test seeds persisted wallet state into IndexedDB and reloads Suite, validating that the store hydrates remembered wallets correctly after the store creation changes.

⚠️ Changes with no test coverage (19)

  • suite-common/redux-utils/src/createReduxExtra.test.ts
  • suite-native/app/e2e/tests/tradingExchangeFlow.test.ts
  • suite-native/app/e2e/tests/tradingSellFlow.test.ts
  • suite-native/app/index.js
  • suite-native/app/package.json
  • suite-native/app/src/App.tsx
  • suite-native/app/src/createNativeInit.tsx
  • suite-native/app/src/createSuiteNativeCompositionRoot.ts
  • suite-native/app/src/initSentry.ts
  • suite-native/app/tsconfig.json
  • suite-native/state/mocks/mockInitialAppState.ts
  • suite-native/state/src/NativeServices.ts
  • suite-native/state/src/StoreProvider.tsx
  • suite-native/state/src/createHydrateReduxStore.ts
  • suite-native/state/src/createNativeExtraDependencies.ts
  • suite-native/state/src/createNativeServicesCompositionRoot.ts
  • suite-native/state/src/createReduxStore.ts
  • suite-native/state/src/createStorePersistor.ts
  • suite-native/state/src/index.ts

Updated: 2026-09-08T18:22:23.637Z

@peter-sanderson peter-sanderson added the no-project This label is used to specify that PR doesn't need to be added to a project label Sep 7, 2026
@peter-sanderson
peter-sanderson changed the base branch from develop to refactor-suite-app-initialization September 7, 2026 22:49
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

⚡️ Performance report (alpha)

Note

Alpha release: The limits are still being calibrated, and each measurement is
usually a single run on a shared CI runner, so expect noise between runs. Treat a
number as a hint to look closer, not as a verdict.

desktop / group 6

🟢 Within limits.

Each metric reads measured/limit (% of limit).

Scenario TBT Long tasks Longest task React commits Interaction
account-switch [T3W1] 227/700 ms
(32 %)
2/5
(40 %)
266/700 ms
(38 %)
32/80
(40 %)
626 ms
multi-account-discovery [T3W1] 1012/7000 ms
(14 %)
41/100
(41 %)
234/800 ms
(29 %)
240/400
(60 %)
6839 ms
wallet-discovery [T3W1] 514/2000 ms
(26 %)
20/45
(44 %)
174/400 ms
(44 %)
196/410
(48 %)
5687 ms

useReportAppInitToAnalytics();

useEffect(() => {
if (!isApplicationInitDispatchedRef.current) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing isApplicationInitDispatchedRef does not remove the duplicate-initialization guard: it moves that responsibility from React into createNativeInit. The service caches its initialization promise with initialization ??= ..., so repeated calls to the same init() instance return the same promise and dispatch applicationInitThunk only once. Because the composition root is created outside React, component rerenders or remounts do not reset that guard; the old ref only protected a single mounted component instance.

There is a separate lifecycle change to review: initialization previously started from a React effect after the component mounted, whereas it now starts after Redux hydration and may run before the React providers mount. Initialization code that relies on mounted UI infrastructure therefore needs checking. That timing concern—and hydration/error handling—is independent of removing the ref; adding the ref back would not address it.

@trezor-bot

trezor-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ Previously successful run of [Test] suite-native Android E2E workflow has been found.
⏭️ Skipping tests for this run.
💡 If you are unsure about your latest changes, please rerun the workflow manually. (Use the Re-run all jobs option)

@peter-sanderson
peter-sanderson marked this pull request as ready for review September 8, 2026 10:39
@peter-sanderson
peter-sanderson force-pushed the refactor-native-app-initialization branch 6 times, most recently from cfc6ee0 to 1ba49cb Compare September 8, 2026 13:29
Base automatically changed from refactor-suite-app-initialization to develop September 8, 2026 13:33
@peter-sanderson
peter-sanderson force-pushed the refactor-native-app-initialization branch from 1ba49cb to 8abd17b Compare September 8, 2026 13:33
return () => {
// Repeated startup calls must not start duplicate Connect sessions or periodic workers.
if (App === null) {
markStartupJsBundleEvaluated();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this before call of the compositionRoot into an index.js

@matejkriz

Copy link
Copy Markdown
Member

@matejkriz
matejkriz force-pushed the refactor-native-app-initialization branch from e2ca868 to a2f1dde Compare September 8, 2026 15:25

@matejkriz matejkriz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on both iOS and Android on local and ad-hoc builds and I haven't observed any issues.

@peter-sanderson
peter-sanderson force-pushed the refactor-native-app-initialization branch from 771ff4d to 65a9d0b Compare September 8, 2026 18:18
@peter-sanderson
peter-sanderson merged commit 8fd366b into develop Sep 8, 2026
35 checks passed
@peter-sanderson
peter-sanderson deleted the refactor-native-app-initialization branch September 8, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-project This label is used to specify that PR doesn't need to be added to a project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants