feat(settings): reorder accounts by drag in settings #240

Merged
JMR-dev merged 19 commits from feat-164-reorder-accounts into main 2026-07-04 01:48:45 +00:00
JMR-dev commented 2026-07-03 17:22:48 +00:00 (Migrated from github.com)

Summary

Lets the user set a persistent account order and reorder it by dragging in Settings (issue #164). Accounts gain a sortOrder column, and every surface that lists accounts — the Settings list, the drawer account switcher, and the compose account picker — reads the same ORDER BY sortOrder query, so a reorder in Settings is honored app-wide and survives a restart. In Settings a row can be long-pressed and dragged to a new position; new accounts are appended to the end.

Recovered WIP vs. finished

This branch continues an interrupted session whose work was recovered as a single wip: commit. I reviewed it end-to-end, verified the risky parts, fixed what was broken, and rebased it onto current main.

The recovered WIP already had (verified correct):

  • Data layer: AccountEntity.sortOrder (@ColumnInfo(defaultValue = "0")); AccountDao orders by it and adds insertAtEnd / reorder / nextSortOrder / setSortOrder (mutations in @Transactions); repository reorderAccounts + add-account paths switched to insertAtEnd; SettingsViewModel / SettingsScreen wiring; AccountReorderList drag UI; new string.
  • Migration: AccountDatabase v1→v2 (ACCOUNT_MIGRATION_1_2) adds the column and backfills existing accounts by their previous alphabetical (email) rank so the shown order does not shuffle on upgrade; registered in AccountDatabaseModule; exported 2.json; AccountMigrationTest. AccountDataMigrator (the pre-#111 cache→account-db move) creates the v2-shaped table and applies the same email-rank backfill, since ACCOUNT_MIGRATION_1_2 does not run for that path.
  • Tests: unit AccountReorderListTest (pure commitDrag maths); instrumented AccountDatabaseTest (append + reorder), AccountMigrationTest (v1→v2 backfill), AccountDataMigratorTest (pre-#111 backfill + DDL-matches-schema).

What I finished / corrected:

  • Verified the exported 2.json is exactly what Room generates: deleted it and force-regenerated via KSP — byte-identical, same identityHash. (Room groups scalar fields before @Embedded ones, so sortOrder lands after authType in the generated SQL even though it is declared last in the entity; the committed schema and the migrator DDL both match that.)
  • Fixed a ktlint function-signature violation on commitDrag that would have failed CI's Static-analysis gate.
  • The recovered WIP was based on a ~20-commit-stale main. Rebased it onto current main; the three overlapping files (SettingsScreen.kt, strings.xml, Fakes.kt) auto-merged and I verified each merge by hand. Confirmed main never touched AccountDatabase, so the migration and schema stay valid.
  • Ran the full fast gate green: assembleDebug, testDebugUnitTest, compileDebugAndroidTestKotlin, lintDebug, ktlintCheck, detekt.

Deferred / flagged

  • Emulator E2E not run locally (repo convention). The instrumented migration/DAO tests and the existing settings E2E only compile-checked here; CI runs the emulator matrix. The existing SettingsScreenTest seeds no accounts, so swapping the account ClickRows for AccountReorderList does not affect it.
  • No gesture-level UI test exercises the actual long-press-drag; the pure reorder maths (commitDrag) is unit-tested and the persisted reorder is instrumented-tested, but the Compose drag interaction itself is not. Reasonable follow-up if gesture coverage is wanted.

Migration note

This is a DB-migration change (AccountDatabase v1→v2). Auto-merge intentionally not enabled — please review the migration before merging.

Closes #164

🤖 Generated with Claude Code

## Summary Lets the user set a persistent account order and reorder it by dragging in Settings (issue #164). Accounts gain a `sortOrder` column, and every surface that lists accounts — the Settings list, the drawer account switcher, and the compose account picker — reads the same `ORDER BY sortOrder` query, so a reorder in Settings is honored app-wide and survives a restart. In Settings a row can be long-pressed and dragged to a new position; new accounts are appended to the end. ## Recovered WIP vs. finished This branch continues an interrupted session whose work was recovered as a single `wip:` commit. I reviewed it end-to-end, verified the risky parts, fixed what was broken, and rebased it onto current `main`. **The recovered WIP already had (verified correct):** - Data layer: `AccountEntity.sortOrder` (`@ColumnInfo(defaultValue = "0")`); `AccountDao` orders by it and adds `insertAtEnd` / `reorder` / `nextSortOrder` / `setSortOrder` (mutations in `@Transaction`s); repository `reorderAccounts` + add-account paths switched to `insertAtEnd`; `SettingsViewModel` / `SettingsScreen` wiring; `AccountReorderList` drag UI; new string. - Migration: `AccountDatabase` v1→v2 (`ACCOUNT_MIGRATION_1_2`) adds the column and backfills existing accounts by their previous alphabetical (email) rank so the shown order does not shuffle on upgrade; registered in `AccountDatabaseModule`; exported `2.json`; `AccountMigrationTest`. `AccountDataMigrator` (the pre-#111 cache→account-db move) creates the v2-shaped table and applies the same email-rank backfill, since `ACCOUNT_MIGRATION_1_2` does not run for that path. - Tests: unit `AccountReorderListTest` (pure `commitDrag` maths); instrumented `AccountDatabaseTest` (append + reorder), `AccountMigrationTest` (v1→v2 backfill), `AccountDataMigratorTest` (pre-#111 backfill + DDL-matches-schema). **What I finished / corrected:** - Verified the exported `2.json` is exactly what Room generates: deleted it and force-regenerated via KSP — byte-identical, same `identityHash`. (Room groups scalar fields before `@Embedded` ones, so `sortOrder` lands after `authType` in the generated SQL even though it is declared last in the entity; the committed schema and the migrator DDL both match that.) - Fixed a ktlint `function-signature` violation on `commitDrag` that would have failed CI's Static-analysis gate. - The recovered WIP was based on a ~20-commit-stale `main`. Rebased it onto current `main`; the three overlapping files (`SettingsScreen.kt`, `strings.xml`, `Fakes.kt`) auto-merged and I verified each merge by hand. Confirmed `main` never touched `AccountDatabase`, so the migration and schema stay valid. - Ran the full fast gate green: `assembleDebug`, `testDebugUnitTest`, `compileDebugAndroidTestKotlin`, `lintDebug`, `ktlintCheck`, `detekt`. ## Deferred / flagged - **Emulator E2E not run locally** (repo convention). The instrumented migration/DAO tests and the existing settings E2E only compile-checked here; CI runs the emulator matrix. The existing `SettingsScreenTest` seeds no accounts, so swapping the account `ClickRow`s for `AccountReorderList` does not affect it. - **No gesture-level UI test** exercises the actual long-press-drag; the pure reorder maths (`commitDrag`) is unit-tested and the persisted `reorder` is instrumented-tested, but the Compose drag interaction itself is not. Reasonable follow-up if gesture coverage is wanted. ## Migration note This is a **DB-migration** change (`AccountDatabase` v1→v2). Auto-merge intentionally not enabled — please review the migration before merging. Closes #164 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.