feat(onboarding): mnemonic-entry refactor + ASB UX hardening#507
Draft
yasin-ce wants to merge 4 commits into
Draft
feat(onboarding): mnemonic-entry refactor + ASB UX hardening#507yasin-ce wants to merge 4 commits into
yasin-ce wants to merge 4 commits into
Conversation
Replaces the small `PWRoundIcon` chip with a 4×xxl direct-SVG render of shield-check, matching the hero-illustration scale used by every other onboarding info screen (WatchInfoScreen, ImportInfoScreen, the backup family). Tints via `theme.colors.textMain` since shield-check.svg uses `currentColor`, so it adapts to light/dark mode automatically. Adds a `vi.mock` for the SVG in the integration setup — jsdom chokes on the long data URL `svgr` emits otherwise.
`BackupVerificationScreen` shows the quiz tiles whose `options` contain the real mnemonic words (mixed with decoys). Even though the user hasn't picked the correct order yet, an attacker who captures the screen learns the candidate set. Aligns with the screen-capture prevention already applied to `BackupReminderMnemonicScreen` and `ViewPassphraseContent`.
Pulls the mnemonic-input mechanic out of ImportAccountScreen (where it
was an ~180-line slab of paste-distribution, clipboard fallback, and
suggestion derivation) into a reusable hook + util + component, then
adopts them across both import flows:
- `useMnemonicWordEntry` — focus management, multi-separator paste
distribution, iOS-autocomplete-safe clipboard fallback,
wordlist-driven suggestions. Wordlist- and copy-agnostic; callers
pass `onTooManyWords` / `onInsufficientSlots` so screen-specific
i18n stays out.
- `splitMnemonic` — accepts any mix of whitespace + commas.
- `MnemonicSuggestionBar` — sticky horizontal pill bar that renders
nothing when there are no suggestions, replaces the old
per-row `WordSuggestionDropdown` (deleted).
Same diff also lands four orthogonal hardenings that touch the same
screens, so they're bundled here rather than fragmented:
- Screen-capture prevention on AsbImportKeyScreen and
ImportAccountScreen via `usePreventScreenCapture`.
- Success-path uses `navigation.replace` so the typed mnemonic in the
input hook's state is dropped for GC when the screen unmounts;
back-nav from later steps no longer lands on a prefilled screen.
- AsbImportKey redirects to the file-pick step when `envelope` is
null (defensive; covers the rare flow where the store gets wiped
while the screen is mounted).
- Replaces the `HEADER_HEIGHT = 50` magic constant with
`useHeaderHeight()` from `@react-navigation/elements` for the
`KeyboardAvoidingView.keyboardVerticalOffset` on both screens.
Includes vitest mocks for `@react-navigation/elements.useHeaderHeight`
(throws under the headless test navigator) and unit/component/integration
test coverage for the new primitives.
After a successful import, SelectAccounts cleanup runs `reset()` on the flow store to zero decrypted private keys. If the user then navigates back into the backup screen (Android system back from Result, etc.), the local "Pasted backup" card kept rendering because `loadedFile` is React state separate from the store. Tapping Next jumped to a Key screen with no envelope, which bounced back here — a silent loop. Sync `loadedFile` to `envelope`: when the store is wiped externally, clear the local indicator so Continue properly disables and the user has to re-pick / re-paste. Adds a regression integration test that drives the wipe through the same `useAsbImportFlowStore.reset()` SelectAccounts cleanup performs (no need to simulate the full stack-nav cascade through Result).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #500. Four logically grouped commits cleaning up the ASB import flow:
style(onboarding):hero-scale shield illustration onAsbImportInfoScreen, replacing the smallPWRoundIconchip with a direct-SVG render at the same scale asWatchInfoScreen/ImportInfoScreen.feat(security):usePreventScreenCaptureonBackupVerificationScreen(quiz tiles include the real mnemonic words mixed with decoys).feat(onboarding):extractuseMnemonicWordEntry+MnemonicSuggestionBar+splitMnemonicfrom the 180-line slab insideImportAccountScreen, adopted across bothImportAccountScreenandAsbImportKeyScreen. Same diff lands four hardenings on the two screens: screen-capture prevention,navigation.replaceon success paths (typed mnemonic drops for GC on unmount), envelope-missing redirect onAsbImportKeyScreen, anduseHeaderHeight()replacing theHEADER_HEIGHT = 50magic.fix(onboarding):syncAsbImportBackupScreen's localloadedFileto the store'senvelope— when the wizard wipes the store post-import, the "Pasted backup" card now disappears so the user can't loop through Key→Backup with a stale state.Test plan
pnpm pre-push --no-fail-on-error— all checks green (lint, typecheck, formatter, copyright headers, i18n, secrets)onboarding-import-asb.test.tsx— 8/8 (1 new regression test for the back-nav scenario)onboarding-import-algo25.test.tsx— 4/4onboarding-import-hd.test.tsx— 7/7backup.test.tsx— 5/5useMnemonicWordEntry.spec.ts— 12 scenarios covering paste distribution (multiple separators), clipboard fallback (incl. iOS autocomplete regression), focus advancement at boundaries, error-callback wiringMnemonicSuggestionBar.spec.tsx— render, empty-state hide, tap callbacksplitMnemonic.spec.ts— 5 separator-mix variants