Skip to content

feat(ui): migrate seed input flow to Swift bridge and align watch build version#770

Closed
romchornyi wants to merge 5 commits into
masterfrom
fix/seed-entry-freeze
Closed

feat(ui): migrate seed input flow to Swift bridge and align watch build version#770
romchornyi wants to merge 5 commits into
masterfrom
fix/seed-entry-freeze

Conversation

@romchornyi
Copy link
Copy Markdown
Contributor

@romchornyi romchornyi commented May 21, 2026

Issue being fixed or feature implemented

This PR finalizes the Recover Wallet seed-entry migration path by moving seed phrase decision logic from Objective-C container code into Swift-side controller logic, while preserving the existing Objective-C public API and delegate contract.

What was done?

  • Introduced Swift-side seed input bridge/controller:
    • Added RecoverSeedPhraseInputController.swift
    • Added RecoverSeedPhraseInputView.swift
  • Kept SwiftUI view presentation-focused and moved recover/wipe decision flow to Swift controller side.
  • Preserved Objective-C-facing behavior and integration:
    • Updated DWRecoverContentView to be a thin adapter/container that hosts Swift input and forwards events.
    • Kept existing ObjC delegate callback paths intact.
    • Kept existing DWRecoverContentView public API usage pattern.
  • Added/updated bridging imports so Swift can access required ObjC types/constants.
  • Added targeted seed-input diagnostics gated behind compile-time flag SEED_INPUT_DIAGNOSTICS (instead of DEBUG), suitable for temporary diagnostic builds.

How Has This Been Tested?

Manual code-path verification by review against legacy behavior requirements:

  • submit on Return/Done
  • phrase cleanup pushback without unintended change callback
  • invalid-word handling path
  • recover vs wipe branching and delegate forwarding
  • append/replace phrase update flow

Breaking Changes

None.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

Summary by CodeRabbit

  • New Features

    • Redesigned seed-phrase recovery UI with a modern input view, external focus/selection controls, and improved submit handling.
    • New bridge controller for unified SwiftUI/Obj-C interaction and diagnostic logging support.
  • Bug Fixes

    • Improved view containment so appearance, sizing, and device traits propagate correctly during recovery.
    • More robust phrase validation and error reporting flows.
  • Chores

    • App version bumped to 8.5.7

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

Seed phrase recovery UI migrates from Objective-C UITextView to SwiftUI via a new Swift controller that bridges SwiftUI behavior to ObjC delegates. DWRecoverContentView now hosts and forwards to the controller; project files, bridging header, and build flags updated to include the new Swift sources and diagnostic flag.

Changes

Seed Phrase Recovery Refactoring

Layer / File(s) Summary
Swift controller delegate protocol and observable state
RecoverSeedPhraseInputController.swift
DWRecoverSeedPhraseInputControllerDelegate and RecoverSeedPhraseInputState are added; a bridged SwiftUI wrapper wires phrase binding and submit callbacks; diagnostic logging scaffold added.
SwiftUI seed phrase input presentation
RecoverSeedPhraseInputView.swift
RecoverSeedPhraseInputView with SeedPhraseTextView UIViewRepresentable configures UITextView (typing behaviors, autocorrect/spell-check disabled, insets), supports external focus/selection tokens, intercepts newline for submit, and includes previews and optional SEED_INPUT_DIAGNOSTICS logging.
Controller implementation and business logic
RecoverSeedPhraseInputController.swift
ObjC-exposed controller with delegate/model/title/phrase/viewController; continueAction() normalizes phrase, counts invalid words, routes wipe/recover outcomes, offers selection/replacement for incorrect words, and exposes text-control methods (activate, appendText, selectFirstOccurrence, replaceText).
Objective-C content view refactoring to Swift host
DWRecoverContentView.h, DWRecoverContentView.m
DWRecoverContentView now creates and delegates to RecoverSeedPhraseInputController, adds attachToParentViewController: for hosting containment, replaces UITextView-sizing with intrinsic-size approximation, forwards APIs to the controller, and forwards controller delegate callbacks to its own delegate.
Integration with view controller and model extensions
DWRecoverViewController.m, DWRecoverModel.h, DWRecoverModel.m
DWRecoverViewController.setupView calls contentView attachToParentViewController:self. DWRecoverModel adds read-only isRecoverAction to indicate recover-mode.
Build configuration, bridging headers, and diagnostic support
DashWallet.xcodeproj/project.pbxproj, dashwallet-Bridging-Header.h, UIViewController+DashWallet.swift
New Swift files added to project/targets and Views group; CURRENT_PROJECT_VERSION bumped to 8, MARKETING_VERSION to 8.5.7 in many configurations; SEED_INPUT_DIAGNOSTICS added to SWIFT_ACTIVE_COMPILATION_CONDITIONS; bridging header imports DashSync/DashSync.h and DWRecoverModel.h; presentSupportEmailController() early-returns with UIActivityViewController when diagnostics enabled.

Sequence Diagram(s)

sequenceDiagram
  participant ViewController as DWRecoverViewController
  participant ContentView as DWRecoverContentView
  participant Controller as RecoverSeedPhraseInputController
  participant State as RecoverSeedPhraseInputState
  participant SwiftUI as RecoverSeedPhraseInputView
  participant Delegate as Recovery Delegate

  ViewController->>ContentView: attachToParentViewController(self)
  ContentView->>Controller: init(delegate: self)
  Controller->>State: initialize state
  ContentView->>Controller: addChild(viewController)
  Controller->>SwiftUI: UIHostingController presents view

  Note over SwiftUI,Controller: User enters seed phrase
  SwiftUI->>State: phrase binding updated
  State->>Controller: onPhraseChange callback
  Controller->>ContentView: phraseDidChange(phrase:)
  ContentView->>Delegate: phraseDidChange(phrase:)

  Note over SwiftUI,Controller: User submits phrase
  SwiftUI->>Controller: onSubmit callback
  Controller->>Controller: continueAction()
  
  alt Invalid word count
    Controller->>ContentView: showIncorrectWord(word:)
    ContentView->>Delegate: showIncorrectWord(word:)
  else Bad recovery phrase
    Controller->>ContentView: badRecoveryPhrase()
    ContentView->>Delegate: badRecoveryPhrase()
  else Wipe not allowed
    Controller->>ContentView: wipeNotAllowed()
    ContentView->>Delegate: wipeNotAllowed()
  else Recover success
    Controller->>ContentView: didRecoverWalletWith(info:)
    ContentView->>Delegate: didRecoverWalletWith(info:)
  end

  Delegate->>ViewController: handle outcome
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A seed phrase blooms in SwiftUI's light,
From UITextView's old-fashioned sight,
Bridges of ObjC and Swift unite,
Callbacks and hosts make the flow just right,
Wallets recover beneath a rabbit's delight 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.74% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main changes: migrating seed input flow to a Swift bridge and updating build versions, which align with the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/seed-entry-freeze

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@romchornyi romchornyi changed the title feat(recover): migrate seed input flow to Swift bridge and align watch build version feat(ui): migrate seed input flow to Swift bridge and align watch build version May 21, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@DashWallet/Sources/UI/Setup/RecoverWallet/Views/DWRecoverContentView.m`:
- Around line 55-59: The child view controller's view (hostView created from
inputController.viewController.view) is being added to self before the view
controller containment calls; move the call that adds hostView as a subview and
sets its translatesAutoresizingMaskIntoConstraints/backgroundColor and
constraints so it happens after you call addChildViewController: on
inputController.viewController but before you call
didMoveToParentViewController:; ensure addChildViewController: is called on the
parent (self) with inputController.viewController, then addSubview:hostView and
activate constraints, then call didMoveToParentViewController: to complete
containment.

In
`@DashWallet/Sources/UI/Setup/RecoverWallet/Views/RecoverSeedPhraseInputController.swift`:
- Around line 137-140: Replace the hard-coded raw-value constant by comparing
the model action directly to the Objective-C enum case: remove private let
recoverActionRawValue and change checks like model.action.rawValue ==
recoverActionRawValue in RecoverSeedPhraseInputController to compare
model.action (or its value) against DWRecoverAction_Recover; alternatively add a
boolean on DWRecoverModel (e.g., isRecoverAction) and use that in the routing
logic to avoid relying on enum ordering.

In `@WatchApp` Extension/Info.plist:
- Line 24: The Info.plist currently hardcodes CFBundleVersion as "12"; change
that string to use the Xcode build variable (e.g., replace the literal with
$(CURRENT_PROJECT_VERSION) or $(MARKETING_VERSION) as appropriate for your
versioning policy) so the WatchApp Extension inherits the iOS app's project
version automatically; ensure the WatchApp Extension target's
CURRENT_PROJECT_VERSION (or MARKETING_VERSION) build setting is configured to
match the main iOS app so the plist value stays in sync and you no longer need
to edit CFBundleVersion by hand.

In `@WatchApp/Info.plist`:
- Line 24: The CFBundleVersion in WatchApp/Info.plist was hardcoded to "12";
revert it to use the build variable by replacing the literal with
$(CURRENT_PROJECT_VERSION) so the WatchApp target inherits the project's build
number automatically; ensure the WatchApp target's CURRENT_PROJECT_VERSION is
set in Xcode project settings and keep CFBundleShortVersionString using
$(MARKETING_VERSION) if applicable to maintain parity with the iOS app.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 44cd4f2f-994b-4505-b404-4f6f7217c2b9

📥 Commits

Reviewing files that changed from the base of the PR and between 6aaecc1 and 10ea515.

📒 Files selected for processing (9)
  • DashWallet.xcodeproj/project.pbxproj
  • DashWallet/Sources/UI/Setup/RecoverWallet/DWRecoverViewController.m
  • DashWallet/Sources/UI/Setup/RecoverWallet/Views/DWRecoverContentView.h
  • DashWallet/Sources/UI/Setup/RecoverWallet/Views/DWRecoverContentView.m
  • DashWallet/Sources/UI/Setup/RecoverWallet/Views/RecoverSeedPhraseInputController.swift
  • DashWallet/Sources/UI/Setup/RecoverWallet/Views/RecoverSeedPhraseInputView.swift
  • DashWallet/dashwallet-Bridging-Header.h
  • WatchApp Extension/Info.plist
  • WatchApp/Info.plist

Comment thread DashWallet/Sources/UI/Setup/RecoverWallet/Views/DWRecoverContentView.m Outdated
Comment thread WatchApp Extension/Info.plist Outdated
Comment thread WatchApp/Info.plist Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@DashWallet.xcodeproj/project.pbxproj`:
- Line 10839: The SWIFT_ACTIVE_COMPILATION_CONDITIONS entry currently enables
SEED_INPUT_DIAGNOSTICS in non-debug builds; remove SEED_INPUT_DIAGNOSTICS from
any build configurations that do not include DEBUG so diagnostic code isn't
shipped. Locate the SWIFT_ACTIVE_COMPILATION_CONDITIONS assignments (e.g., the
line containing "PIGGYCARDS_ENABLED SEED_INPUT_DIAGNOSTICS") and ensure
SEED_INPUT_DIAGNOSTICS is only present in debug configurations (where DEBUG is
defined), leaving release/distribution configurations without that flag; also
update the other identical occurrence noted in the diff so both spots are fixed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: efcb6ee3-de5a-4c82-80fa-411c324a2de9

📥 Commits

Reviewing files that changed from the base of the PR and between d2d32bd and c7122fe.

📒 Files selected for processing (1)
  • DashWallet.xcodeproj/project.pbxproj

PRODUCT_BUNDLE_IDENTIFIER = org.dashfoundation.dash;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = PIGGYCARDS_ENABLED;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "PIGGYCARDS_ENABLED SEED_INPUT_DIAGNOSTICS";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not enable SEED_INPUT_DIAGNOSTICS in non-debug build configurations.

These configs omit DEBUG but still compile diagnostics code. For seed-entry flows, that can unintentionally ship diagnostic behavior into distribution builds.

Suggested fix
- SWIFT_ACTIVE_COMPILATION_CONDITIONS = "PIGGYCARDS_ENABLED SEED_INPUT_DIAGNOSTICS";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "PIGGYCARDS_ENABLED";

Also applies to: 11823-11823

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet.xcodeproj/project.pbxproj` at line 10839, The
SWIFT_ACTIVE_COMPILATION_CONDITIONS entry currently enables
SEED_INPUT_DIAGNOSTICS in non-debug builds; remove SEED_INPUT_DIAGNOSTICS from
any build configurations that do not include DEBUG so diagnostic code isn't
shipped. Locate the SWIFT_ACTIVE_COMPILATION_CONDITIONS assignments (e.g., the
line containing "PIGGYCARDS_ENABLED SEED_INPUT_DIAGNOSTICS") and ensure
SEED_INPUT_DIAGNOSTICS is only present in debug configurations (where DEBUG is
defined), leaving release/distribution configurations without that flag; also
update the other identical occurrence noted in the diff so both spots are fixed.

@romchornyi romchornyi closed this May 25, 2026
@romchornyi romchornyi deleted the fix/seed-entry-freeze branch May 25, 2026 15:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants