Skip to content

Centralize onboarding completion#806

Merged
praveenperera merged 3 commits into
masterfrom
onboarding-reentry
Jun 25, 2026
Merged

Centralize onboarding completion#806
praveenperera merged 3 commits into
masterfrom
onboarding-reentry

Conversation

@praveenperera

Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 87c6f84c-7216-4d3b-97f0-787b04959a99

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch onboarding-reentry

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7021a126b6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rust/src/database/global_flag.rs Outdated
@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown

Greptile Summary

This PR centralizes the onboarding completion decision into Rust, replacing the per-platform isTermsAccepted flag + scattered UI-state logic with a single CompletedOnboarding flag in the database, exposed as FfiApp::needs_onboarding().

  • New completion path: OnboardingManager.complete_onboarding now calls mark_onboarding_complete() (writes CompletedOnboarding=true, fires DatabaseUpdated) instead of dispatching AppAction::AcceptTerms. Both iOS and Android react to DatabaseUpdated by re-reading needs_onboarding and transitioning startupMode accordingly.
  • Migration backfill: Database::new() calls backfill_onboarding_complete_from_legacy_state to promote existing users' AcceptedTerms flag to CompletedOnboarding, guarded by wallet presence and absence of in-flight onboarding progress.
  • TermsContext simplification: Removes StartupRestoreRecovery (a non-terminal terms context that redirected to Welcome); all terms acceptance now triggers the full completion flow, and the startup cloud-check path for users with prior accepted terms but no wallets is intentionally dropped.

Confidence Score: 5/5

Safe to merge — the centralization is well-structured and the migration backfill correctly handles existing users.

The Rust-side mark_onboarding_complete / needs_onboarding contract is clean and idempotent. The backfill logic is guarded by wallet presence and absence of in-flight progress, and the set_inner(notify: false) call at initialization avoids spurious reconcile loops. Both iOS and Android react to DatabaseUpdated to re-read the flag, making the host-side transition deterministic. The removal of StartupRestoreRecovery and allow_auto_advance simplifies state that was previously hard to reason about, and test coverage for the new backfill path is adequate.

No files require special attention. The set_inner FFI-exposure concern in global_flag.rs was already filed in a prior review thread.

Important Files Changed

Filename Overview
rust/src/database/global_flag.rs Adds mark_onboarding_complete, is_onboarding_complete, and the backfill helper; introduces set_inner(notify: bool) split. The #[uniffi::export] impl block still exposes set_inner to FFI bindings (flagged in a prior review thread).
rust/src/database.rs Adds backfill_onboarding_complete_from_legacy_state call at the end of Database::new(); correct and idempotent — early-returns once CompletedOnboarding is already set.
rust/src/manager/onboarding_manager.rs Replaces App::handle_action(AcceptTerms) with mark_onboarding_complete() in complete_onboarding; correctly handles failure via CompletionFailed event. Removes maybe_advance_accepted_terms in favour of the backfill approach.
rust/src/manager/onboarding_manager/flow_state.rs Removes StartupRestoreRecovery context and allow_auto_advance field; accept_terms() now always returns CompleteOnboarding. TermsContext::completion_target() changed to infallible. Logic is clean after removing the non-terminal case.
ios/Cove/AppManager.swift Replaces isTermsAccepted with needsOnboarding; initialized to true (conservative default) and set from rust.needsOnboarding() in init and on DatabaseUpdated. Removes agreeToTerms().
android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt Removes complex persisted-onboarding-progress read/retry logic; LaunchedEffect now only tracks app.needsOnboarding for startupMode. Large simplification with no regressions on the expected paths.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant UI as OnboardingContainer (iOS/Android)
    participant OM as RustOnboardingManager
    participant FS as FlowState
    participant DB as GlobalFlagTable
    participant AM as AppManager

    UI->>OM: dispatch(AcceptTerms)
    OM->>FS: apply_user_action(AcceptTerms)
    FS-->>OM: TransitionCommand::CompleteOnboarding(target)
    OM->>OM: complete_onboarding(target)
    OM->>OM: select_latest_or_new_wallet() / select_wallet()
    OM->>DB: mark_onboarding_complete()
    DB->>DB: "set_inner(CompletedOnboarding=true, notify=true)"
    DB-->>AM: DatabaseUpdated reconcile event
    AM->>AM: "needsOnboarding = rust.needsOnboarding() → false"
    AM-->>UI: startupMode transitions to READY
    OM->>OM: sync_onboarding_progress(None)
    OM->>UI: "Message::Complete → callback sets startupMode=READY (idempotent)"

    Note over DB,AM: On first Database::new() (startup / reset)
    DB->>DB: backfill_onboarding_complete_from_legacy_state()
    DB->>DB: read AcceptedTerms (legacy key)
    DB->>DB: "if terms+wallets+no progress → set CompletedOnboarding=true (notify=false)"
    AM->>AM: "needsOnboarding = rust.needsOnboarding() (reads backfilled value)"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant UI as OnboardingContainer (iOS/Android)
    participant OM as RustOnboardingManager
    participant FS as FlowState
    participant DB as GlobalFlagTable
    participant AM as AppManager

    UI->>OM: dispatch(AcceptTerms)
    OM->>FS: apply_user_action(AcceptTerms)
    FS-->>OM: TransitionCommand::CompleteOnboarding(target)
    OM->>OM: complete_onboarding(target)
    OM->>OM: select_latest_or_new_wallet() / select_wallet()
    OM->>DB: mark_onboarding_complete()
    DB->>DB: "set_inner(CompletedOnboarding=true, notify=true)"
    DB-->>AM: DatabaseUpdated reconcile event
    AM->>AM: "needsOnboarding = rust.needsOnboarding() → false"
    AM-->>UI: startupMode transitions to READY
    OM->>OM: sync_onboarding_progress(None)
    OM->>UI: "Message::Complete → callback sets startupMode=READY (idempotent)"

    Note over DB,AM: On first Database::new() (startup / reset)
    DB->>DB: backfill_onboarding_complete_from_legacy_state()
    DB->>DB: read AcceptedTerms (legacy key)
    DB->>DB: "if terms+wallets+no progress → set CompletedOnboarding=true (notify=false)"
    AM->>AM: "needsOnboarding = rust.needsOnboarding() (reads backfilled value)"
Loading

Reviews (2): Last reviewed commit: "Skip onboarding backfill with progress" | Re-trigger Greptile

Comment thread rust/src/database/global_flag.rs
Persist completed onboarding in redb from Rust and expose one needs-onboarding decision to the mobile shells. Remove the separate accepted-terms startup path so iOS and Android no longer duplicate eligibility checks.
Remove the generated UniFFI bindings and API surface for set_inner (Kotlin/Swift): deleted external/uniffi calls, interface/class methods, and associated checksum checks. Regenerated bindings reflect that set_inner is now internal/private. Rust GlobalFlagTable was cleaned up by moving/merging get_bool_config, set_bool_config, and toggle_bool_config (removed duplicate block) and keeping set_inner as an internal method. No behavioral changes intended — this is a binding/regeneration cleanup after making set_inner non-public.
@praveenperera praveenperera enabled auto-merge (squash) June 25, 2026 20:15
@praveenperera praveenperera disabled auto-merge June 25, 2026 20:15
@praveenperera praveenperera merged commit 15c1072 into master Jun 25, 2026
9 checks passed
@praveenperera praveenperera deleted the onboarding-reentry branch June 25, 2026 20:15
praveenperera added a commit that referenced this pull request Jun 25, 2026
* Centralize onboarding completion

Persist completed onboarding in redb from Rust and expose one needs-onboarding decision to the mobile shells. Remove the separate accepted-terms startup path so iOS and Android no longer duplicate eligibility checks.

* Remove set_inner binding and regenerate UniFFI code

Remove the generated UniFFI bindings and API surface for set_inner (Kotlin/Swift): deleted external/uniffi calls, interface/class methods, and associated checksum checks. Regenerated bindings reflect that set_inner is now internal/private. Rust GlobalFlagTable was cleaned up by moving/merging get_bool_config, set_bool_config, and toggle_bool_config (removed duplicate block) and keeping set_inner as an internal method. No behavioral changes intended — this is a binding/regeneration cleanup after making set_inner non-public.

* Skip onboarding backfill with progress
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.

1 participant