Skip to content

QR-code 2FA setup and consolidated account settings#132

Merged
krazyjakee merged 2 commits into
masterfrom
claude/pedantic-snyder-805121
Jun 14, 2026
Merged

QR-code 2FA setup and consolidated account settings#132
krazyjakee merged 2 commits into
masterfrom
claude/pedantic-snyder-805121

Conversation

@krazyjakee

Copy link
Copy Markdown
Contributor

What changed

Two related account/security UX improvements.

1. QR-code 2FA enrollment

The 2FA setup previously showed only the TOTP secret as plain text, forcing users to type it into their authenticator app by hand. Now it renders the server's otpauth URI as a scannable QR code (using qr_flutter, already a dependency).

  • QR sits on a white quiet-zone background so it scans reliably regardless of the app theme.
  • The secret remains as copyable text (with a copy button) as a manual-entry fallback for servers that only return a bare secret.

2. Consolidated account settings

Account security (password, 2FA, delete account) was only reachable from a "Account settings" item buried in the avatar/status popup menu — separate from every other profile/account setting, which all live in Settings → Account.

  • Added a "Password & Security" tile to Settings → Account (under "Edit profile") that opens the same dialog.
  • Removed the "Account settings" item from the status popup, so the avatar button is now a pure status picker (online/idle/dnd/invisible + custom status).
  • Retitled the dialog from "Account settings" to "Password & Security" to match its new entry point.

New end-to-end path: Settings → Account → Password & Security → Enable 2FA → scan the QR code.

Why

  • Manual secret entry is error-prone; QR scanning is the expected 2FA enrollment flow.
  • One predictable home for account management instead of two divergent entry points.

Reviewer notes

  • No new dependencies — qr_flutter was already in pubspec.yaml/pubspec.lock.
  • flutter analyze --no-fatal-infos passes clean on all three changed files.
  • Not yet exercised in a running app (no device booted in this environment); changes are UI-only and analyzer-verified.

Files

  • lib/features/user/views/accord_account_settings.dart — QR code + copy button; dialog retitle
  • lib/features/settings/views/accord_settings_screen.dart — "Password & Security" tile
  • lib/features/user/components/self_status_button.dart — remove account item; status-picker only

🤖 Generated with Claude Code

krazyjakee and others added 2 commits June 14, 2026 00:54
Add a scannable QR code to the two-factor authentication enrollment
flow and move account security settings into the main Settings screen.

- Render the server's otpauth URI as a QR code (qr_flutter, already a
  dependency) in the 2FA setup, on a white quiet-zone background so it
  scans regardless of theme. The secret stays as copyable text with a
  copy button for manual entry as a fallback.
- Add a "Password & Security" tile to Settings → Account (password,
  two-factor authentication, delete account), consolidating account
  management where all other profile settings already live.
- Remove the "Account settings" item from the avatar/status popup so
  that button is now a pure status picker. Retitle the dialog to
  "Password & Security" to match its new entry point.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Extract bare TOTP secret from otpauth URI via extractTotpSecret() so
  the SelectableText and copy button show/copy the secret alone instead
  of the raw URI when the server omits the 'secret' field.
- Raise QR error-correction from L (7%) to M (15%) for better on-screen
  scan reliability.
- Add maxLength:6, textInputAction.done, and onSubmitted to the TOTP
  code field so the keyboard can submit the form directly.
- Add unit tests for extractTotpSecret() covering null, full URI, param
  order, case-insensitivity, and plain-secret pass-through.

https://claude.ai/code/session_012AcX8kWnAu6oh4tQRiYkg6

Copy link
Copy Markdown
Contributor Author

Code Review — PR #132

Reviewed accord_account_settings.dart, accord_settings_screen.dart, and self_status_button.dart. The overall approach is clean and the consolidation is well-motivated. Three issues fixed in commit bffccb8, ranked below by severity.


🟡 Medium — Copy button copies raw otpauth:// URI instead of the bare secret

File: lib/features/user/views/accord_account_settings.dart

_enable() parses the server response into two optional fields:

_secret = data['secret']?.toString();          // may be null
_otpauth = data['otpauth_uri']?.toString();    // may be null

When a server only returns otpauth_uri (no separate secret), the SelectableText and copy button both fell back to _otpauth, surfacing the full URI (otpauth://totp/user?secret=BASE32&issuer=…) as the "secret" to copy. A user pasting this into an authenticator that expects a bare Base32 key would fail.

Fix: Added extractTotpSecret(String? uri) — a package-visible helper that regex-extracts the ?secret= parameter from an otpauth URI and passes non-URI strings through unchanged. Display and copy now use _secret ?? extractTotpSecret(_otpauth) ?? ''. Six unit tests added in test/features/user/totp_uri_test.dart.


🔵 Low — QR error-correction level was L (7%)

File: lib/features/user/views/accord_account_settings.dart

QrImageView defaults to QrErrorCorrectLevel.L, the minimum reliability tier. On-screen scans are more prone to glare and partial occlusion than printed codes; QrErrorCorrectLevel.M (15%) is the standard choice for software-rendered QR codes.

Fix: Added errorCorrectionLevel: QrErrorCorrectLevel.M to QrImageView.


🔵 Low — TOTP code field accepted unlimited input and had no keyboard submit

File: lib/features/user/views/accord_account_settings.dart

The 6-digit code TextField had no maxLength, so users could accidentally type extra digits without visual feedback, leading to silent verification failure. The keyboard "Done" action also had no effect, requiring a tap on the button.

Fix: Added maxLength: 6, counterText: '' (hides the counter label), textInputAction: TextInputAction.done, and onSubmitted: (_) { if (!_busy) _verify(); }.


No issues found in accord_settings_screen.dart or self_status_button.dart — both changes are clean.

🤖 Generated with Claude Code


Generated by Claude Code

@krazyjakee krazyjakee merged commit 58dd399 into master Jun 14, 2026
2 checks passed
@krazyjakee krazyjakee deleted the claude/pedantic-snyder-805121 branch June 14, 2026 00:11
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