feat(onboarding): first-run flow, vendor picker, and app-password setup #44

Merged
JMR-dev merged 4 commits from feat-onboarding-flow into main 2026-07-01 15:10:58 +00:00
JMR-dev commented 2026-07-01 05:14:08 +00:00 (Migrated from github.com)

Implements the onboarding epic (#26–#31) as one coherent feature.

What

  • #26 — First-run nav scaffold + welcome. AppViewModel gates the NavHost start destination on the stored account count (no accounts → onboarding, ≥1 → MAILBOX); the UI renders nothing until the count is known, so a cold start never flashes the wrong screen. Onboarding is a nested nav graph with a graph-scoped OnboardingViewModel that tracks the first account added this session. NoAccountState is removed in favour of a shared WelcomeContent used by both onboarding and the mailbox's runtime empty state.
  • #28 — Provider registry. MailProvider presets for Gmail/Yahoo/iCloud (IMAP+SMTP host/port/MailSecurity, app-password help URL, createAccount factory) mirroring Account.outlook, biased to STARTTLS where the vendor documents it (Gmail/iCloud SMTP 587), implicit TLS otherwise (all IMAP 993, Yahoo SMTP 465); never NONE. Host/port/security unit-tested for all three.
  • #27 — Vendor picker. AccountPickerScreen replaces the old two-button setup screen as the single entry point used by onboarding and the Settings/mailbox "Add account". Routes Outlook/Hotmail → existing MS OAuth (inline), Gmail/Yahoo/iCloud → app-password screen with the matching preset, Other → existing manual setup.
  • #29 — App-password guided screen. One reusable AppPasswordSetupScreen parameterized by provider key: explains what an app password is, warns to store it securely, links to the provider's app-password page (guarded against a missing browser), and collects only email + app password (servers come from the preset, shown read-only under "Server settings"). Verifies + persists via the existing addImapAccount. ViewModel unit tests cover valid input, blank input, connection failure, and unknown provider.
  • #30 — "Add another?" + first-account landing. After every onboarding add (OAuth, app-password, manual), an "Add another account?" prompt: Yes → back to the picker; No → open the first account added this session, filtered to its inbox (new optional account arg on the mailbox route; MailboxViewModel seeds the filter from it). Only inside onboarding — "Add account" from Settings/mailbox pops back to where the user was.
  • #31 — E2E + strings. Instrumented OnboardingFlowTest drives welcome → picker → app-password add → "add another?" → first account's inbox. Managed-device list and CI E2E matrix are already in lockstep (29–36). All new files carry the SPDX header; new copy is in strings.xml.

Testing

  • Fast CI gate green locally: assembleDebug + testDebugUnitTest (98 tests) + lintDebug + ktlintCheck + detekt, plus compileDebugAndroidTestKotlin.
  • Emulator E2E left to CI.

Notes

  • README reconciliation is intentionally deferred (owned by a separate unit), per the epic.
  • The onboarding E2E is backed by an in-memory FakeAccountRepository (consistent with the existing instrumented-test infra, which has no Hilt/GreenMail wiring); GreenMail-backed connection behaviour is covered by the repository unit tests.

🤖 Generated with Claude Code

Implements the onboarding epic (#26–#31) as one coherent feature. ## What - **#26 — First-run nav scaffold + welcome.** `AppViewModel` gates the NavHost start destination on the stored account count (no accounts → onboarding, ≥1 → `MAILBOX`); the UI renders nothing until the count is known, so a cold start never flashes the wrong screen. Onboarding is a nested nav graph with a graph-scoped `OnboardingViewModel` that tracks the first account added this session. `NoAccountState` is removed in favour of a shared `WelcomeContent` used by both onboarding and the mailbox's runtime empty state. - **#28 — Provider registry.** `MailProvider` presets for Gmail/Yahoo/iCloud (IMAP+SMTP host/port/`MailSecurity`, app-password help URL, `createAccount` factory) mirroring `Account.outlook`, biased to STARTTLS where the vendor documents it (Gmail/iCloud SMTP 587), implicit TLS otherwise (all IMAP 993, Yahoo SMTP 465); never `NONE`. Host/port/security unit-tested for all three. - **#27 — Vendor picker.** `AccountPickerScreen` replaces the old two-button setup screen as the **single** entry point used by onboarding and the Settings/mailbox "Add account". Routes Outlook/Hotmail → existing MS OAuth (inline), Gmail/Yahoo/iCloud → app-password screen with the matching preset, Other → existing manual setup. - **#29 — App-password guided screen.** One reusable `AppPasswordSetupScreen` parameterized by provider key: explains what an app password is, warns to store it securely, links to the provider's app-password page (guarded against a missing browser), and collects only email + app password (servers come from the preset, shown read-only under "Server settings"). Verifies + persists via the existing `addImapAccount`. ViewModel unit tests cover valid input, blank input, connection failure, and unknown provider. - **#30 — "Add another?" + first-account landing.** After every onboarding add (OAuth, app-password, manual), an "Add another account?" prompt: Yes → back to the picker; No → open the **first** account added this session, filtered to its inbox (new optional `account` arg on the mailbox route; `MailboxViewModel` seeds the filter from it). Only inside onboarding — "Add account" from Settings/mailbox pops back to where the user was. - **#31 — E2E + strings.** Instrumented `OnboardingFlowTest` drives welcome → picker → app-password add → "add another?" → first account's inbox. Managed-device list and CI E2E matrix are already in lockstep (`29–36`). All new files carry the SPDX header; new copy is in `strings.xml`. ## Testing - Fast CI gate green locally: `assembleDebug` + `testDebugUnitTest` (98 tests) + `lintDebug` + `ktlintCheck` + `detekt`, plus `compileDebugAndroidTestKotlin`. - Emulator E2E left to CI. ## Notes - README reconciliation is intentionally **deferred** (owned by a separate unit), per the epic. - The onboarding E2E is backed by an in-memory `FakeAccountRepository` (consistent with the existing instrumented-test infra, which has no Hilt/GreenMail wiring); GreenMail-backed connection behaviour is covered by the repository unit tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.