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.
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.
## 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)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Lets the user set a persistent account order and reorder it by dragging in Settings (issue #164). Accounts gain a
sortOrdercolumn, and every surface that lists accounts — the Settings list, the drawer account switcher, and the compose account picker — reads the sameORDER BY sortOrderquery, 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 currentmain.The recovered WIP already had (verified correct):
AccountEntity.sortOrder(@ColumnInfo(defaultValue = "0"));AccountDaoorders by it and addsinsertAtEnd/reorder/nextSortOrder/setSortOrder(mutations in@Transactions); repositoryreorderAccounts+ add-account paths switched toinsertAtEnd;SettingsViewModel/SettingsScreenwiring;AccountReorderListdrag UI; new string.AccountDatabasev1→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 inAccountDatabaseModule; exported2.json;AccountMigrationTest.AccountDataMigrator(the pre-#111 cache→account-db move) creates the v2-shaped table and applies the same email-rank backfill, sinceACCOUNT_MIGRATION_1_2does not run for that path.AccountReorderListTest(purecommitDragmaths); instrumentedAccountDatabaseTest(append + reorder),AccountMigrationTest(v1→v2 backfill),AccountDataMigratorTest(pre-#111 backfill + DDL-matches-schema).What I finished / corrected:
2.jsonis exactly what Room generates: deleted it and force-regenerated via KSP — byte-identical, sameidentityHash. (Room groups scalar fields before@Embeddedones, sosortOrderlands afterauthTypein the generated SQL even though it is declared last in the entity; the committed schema and the migrator DDL both match that.)function-signatureviolation oncommitDragthat would have failed CI's Static-analysis gate.main. Rebased it onto currentmain; the three overlapping files (SettingsScreen.kt,strings.xml,Fakes.kt) auto-merged and I verified each merge by hand. Confirmedmainnever touchedAccountDatabase, so the migration and schema stay valid.assembleDebug,testDebugUnitTest,compileDebugAndroidTestKotlin,lintDebug,ktlintCheck,detekt.Deferred / flagged
SettingsScreenTestseeds no accounts, so swapping the accountClickRows forAccountReorderListdoes not affect it.commitDrag) is unit-tested and the persistedreorderis 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 (
AccountDatabasev1→v2). Auto-merge intentionally not enabled — please review the migration before merging.Closes #164
🤖 Generated with Claude Code