feat: unify thread list views via shared EmailThreadTile widget #431

Merged
guettlibot merged 5 commits from issue-424-unify-email-list-views into main 2026-06-05 16:11:30 +00:00
guettlibot commented 2026-06-04 20:33:51 +00:00 (Migrated from codeberg.org)

Closes #424

What changed

New widget: lib/ui/widgets/email_thread_tile.dart

A shared EmailThreadTile that handles:

  • Dismissible swipe gestures (archive left, delete right)
  • Selection-mode checkbox (when isSelecting is true, swipe is disabled)
  • Optional account-name subtitle line (showAccount / accountName) for combined-inbox use

This eliminates ~150 lines of duplicated thread-tile rendering code that existed separately in both EmailListScreen and CombinedInboxScreen.

CombinedInboxScreen — added multi-select + batch ops

  • Long-press a thread to enter selection mode
  • AppBar switches to "N selected" + close + select-all
  • Batch Archive and Delete via bottom action bar
  • Cross-account batch archive groups threads by accountId to resolve the correct archive folder per account
  • Compose FAB and drawer are hidden while selecting

EmailListScreen — refactored to use EmailThreadTile

  • Swipe handler extracted into _onSwipeDismissed() method (was an inline closure)
  • Duplicate date-formatting helpers removed (now live in email_thread_tile.dart)
  • All existing behaviour preserved

SearchScreen — no changes

Serves a different purpose (cross-entity discovery across folders, addresses, and emails). Its email section already reuses the shared EmailTile widget.

Verification

  • flutter analyze — no issues
  • flutter test test/unit/ test/widget/ — 492 tests pass
  • Golden files regenerated to match the refactored widget output
Closes #424 ## What changed ### New widget: `lib/ui/widgets/email_thread_tile.dart` A shared `EmailThreadTile` that handles: - `Dismissible` swipe gestures (archive left, delete right) - Selection-mode checkbox (when `isSelecting` is true, swipe is disabled) - Optional account-name subtitle line (`showAccount` / `accountName`) for combined-inbox use This eliminates ~150 lines of duplicated thread-tile rendering code that existed separately in both `EmailListScreen` and `CombinedInboxScreen`. ### `CombinedInboxScreen` — added multi-select + batch ops - Long-press a thread to enter selection mode - AppBar switches to "N selected" + close + select-all - Batch Archive and Delete via bottom action bar - Cross-account batch archive groups threads by `accountId` to resolve the correct archive folder per account - Compose FAB and drawer are hidden while selecting ### `EmailListScreen` — refactored to use `EmailThreadTile` - Swipe handler extracted into `_onSwipeDismissed()` method (was an inline closure) - Duplicate date-formatting helpers removed (now live in `email_thread_tile.dart`) - All existing behaviour preserved ### `SearchScreen` — no changes Serves a different purpose (cross-entity discovery across folders, addresses, and emails). Its email section already reuses the shared `EmailTile` widget. ## Verification - `flutter analyze` — no issues - `flutter test test/unit/ test/widget/` — 492 tests pass - Golden files regenerated to match the refactored widget output
Sign in to join this conversation.