refactor(ui): unify email-list code across folder, combined inbox, search #557

Open
guettlibot wants to merge 2 commits from issue-533-shared-email-list into main
guettlibot commented 2026-06-10 13:00:06 +00:00 (Migrated from codeberg.org)

Summary

Closes #533.

Pulls selection, swipe, pagination and batch actions out of three near-duplicate screens into a single shared widget so folder view, combined inbox, in-folder search results and by-address lists share one tile renderer, one selection controller and one batch-action bottom bar.

What changed

  • New EmailThreadList widget + EmailThreadListController (lib/ui/widgets/email_thread_list.dart) own the list rendering, selection set, optional swipe-to-archive/delete and optional pagination. Hosts listen to the controller to swap between their normal AppBar/drawer/FAB and the shared selection AppBar / BottomAppBar (buildSelectionAppBar, buildSelectionBottomBar).
  • Shared batch helpers (lib/ui/screens/email_action_helpers.dart) — batchArchive, batchDelete, batchMarkSpam, batchMove, batchSnooze and swipeDismissThread now live here and group threads by account so a multi-account selection still produces correctly scoped repository calls and undo actions.
  • Combined inbox gains the full action set (was archive + delete only).
  • Duplicate EmailThreadTile widget is removed. ThreadTile is the single tile used everywhere. Search results now render with the same unread/flag icons as the inbox list (golden files regenerated).
  • AddressEmailsScreen adopts the shared list, gaining selection + batch actions for free.

ThreadDetailScreen is intentionally out of scope — its message list is single-thread and differs in shape.

Net diff

 lib/ui/screens/address_emails_screen.dart         |  78 +--
 lib/ui/screens/combined_inbox_screen.dart         | 282 ++--
 lib/ui/screens/email_action_helpers.dart          | 295 +++
 lib/ui/screens/email_list_screen.dart             | 595 ++------
 lib/ui/widgets/email_thread_list.dart             | new
 lib/ui/widgets/email_thread_tile.dart             | deleted
 test/widget/email_thread_list_controller_test.dart| new

Test plan

  • `dart analyze lib/` — no issues
  • `flutter test test/widget/` — 183/183 pass (including 25 EmailListScreen tests covering selection, archive-with-missing-folder dialogs, search delete-and-pop, and stale-search guards)
  • `flutter test test/unit/` — 378/378 pass
  • New `EmailThreadListController` unit tests cover toggle/clear/selectAll/updateThreads and multi-account selection ordering
  • Golden files regenerated for the unified search-result rendering
## Summary Closes #533. Pulls selection, swipe, pagination and batch actions out of three near-duplicate screens into a single shared widget so folder view, combined inbox, in-folder search results and by-address lists share one tile renderer, one selection controller and one batch-action bottom bar. ### What changed - **New `EmailThreadList` widget + `EmailThreadListController`** (`lib/ui/widgets/email_thread_list.dart`) own the list rendering, selection set, optional swipe-to-archive/delete and optional pagination. Hosts listen to the controller to swap between their normal AppBar/drawer/FAB and the shared selection AppBar / BottomAppBar (`buildSelectionAppBar`, `buildSelectionBottomBar`). - **Shared batch helpers** (`lib/ui/screens/email_action_helpers.dart`) — `batchArchive`, `batchDelete`, `batchMarkSpam`, `batchMove`, `batchSnooze` and `swipeDismissThread` now live here and group threads by account so a multi-account selection still produces correctly scoped repository calls and undo actions. - **Combined inbox** gains the full action set (was archive + delete only). - **Duplicate `EmailThreadTile`** widget is removed. `ThreadTile` is the single tile used everywhere. Search results now render with the same unread/flag icons as the inbox list (golden files regenerated). - **`AddressEmailsScreen`** adopts the shared list, gaining selection + batch actions for free. `ThreadDetailScreen` is intentionally out of scope — its message list is single-thread and differs in shape. ### Net diff ``` lib/ui/screens/address_emails_screen.dart | 78 +-- lib/ui/screens/combined_inbox_screen.dart | 282 ++-- lib/ui/screens/email_action_helpers.dart | 295 +++ lib/ui/screens/email_list_screen.dart | 595 ++------ lib/ui/widgets/email_thread_list.dart | new lib/ui/widgets/email_thread_tile.dart | deleted test/widget/email_thread_list_controller_test.dart| new ``` ## Test plan - [x] \`dart analyze lib/\` — no issues - [x] \`flutter test test/widget/\` — 183/183 pass (including 25 EmailListScreen tests covering selection, archive-with-missing-folder dialogs, search delete-and-pop, and stale-search guards) - [x] \`flutter test test/unit/\` — 378/378 pass - [x] New \`EmailThreadListController\` unit tests cover toggle/clear/selectAll/updateThreads and multi-account selection ordering - [x] Golden files regenerated for the unified search-result rendering
You are not authorized to merge this pull request.
This pull request can be merged automatically.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin issue-533-shared-email-list:issue-533-shared-email-list
git checkout issue-533-shared-email-list
Sign in to join this conversation.