Commit Graph

7 Commits

Author SHA1 Message Date
cesnimda 2f173dc3e5 feat(ui): email dashboard UX refactor (PHASES 1/3/4) (#44)
CI / backend (push) Successful in 1m33s
CI / frontend (push) Successful in 33s
CI / format (push) Successful in 2m2s
CI / db-tests (push) Successful in 1m45s
Deploy Staging / deploy (push) Successful in 38s
Security / secrets (push) Successful in 6s
Security / dependencies (push) Successful in 1m17s
Security / sast (push) Successful in 56s
CI / backend (pull_request) Successful in 1m9s
CI / frontend (pull_request) Successful in 21s
CI / format (pull_request) Successful in 1m4s
CI / db-tests (pull_request) Successful in 1m27s
Security / secrets (pull_request) Successful in 6s
Security / dependencies (pull_request) Successful in 1m21s
Security / sast (pull_request) Successful in 1m8s
2026-07-04 21:16:21 +02:00
cesnimda 7710d49c77 feat: keyboard shortcuts for email navigation
'/' focuses the search bar from anywhere (Layout-level listener).
j/k move focus up/down the email list in FolderView and SearchResults;
e archives the focused email, # trashes it. All shortcuts are ignored
while an input/textarea/select has focus, so typing is never hijacked.

A small hint footer in the bottom-right reminds users of the shortcuts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 21:55:36 +02:00
cesnimda c11d747919 feat: bulk actions for email lists
Select multiple rows (checkbox per row) in FolderView, SearchResults,
and the Senders email panel. A toolbar appears with mark read/unread,
star, archive, and trash, applied to the whole selection via
CleanupService.ExecuteAsync (already scoped to UserId).

Shared via useSelection hook and BulkToolbar component to avoid
duplicating selection state across the three list views.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 21:53:43 +02:00
cesnimda 2f6d6abdd3 feat: quick actions on email rows (read/unread, star, trash)
- EmailRow shared component with hover action buttons: mark read/unread, star/unstar, trash
- Optimistic UI — local state patches immediately on click; row fades and becomes non-interactive during the API call
- Trashed rows disappear from the current folder view via onRemove callback
- Backend: EmailController single-email endpoints (POST /email/{id}/read|unread|star|unstar|trash|untrash)
- Star/Unstar added to CleanupActionType enum and CleanupService (maps to STARRED Gmail label via BatchModifyAsync)
- UserId scope enforced in ResolveTargetsAsync — a user can only act on their own emails
- action buttons use stopPropagation so clicking them does not open Gmail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 20:18:44 +02:00
cesnimda 4d15a3a8fb feat: click email row opens it in Gmail (noopener/noreferrer)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 20:14:06 +02:00
cesnimda 4b1d1b1b6e feat: infinite scroll for folder view
Replace page buttons with IntersectionObserver sentinel — scrolling near
the bottom automatically fetches and appends the next page of results.
Shows a loading indicator while fetching and a total count footer when
all emails are loaded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 20:05:17 +02:00
cesnimda 20d51b2c15 feat: folder view — clicking sidebar items shows filtered email list
- New FolderView page at /app/folder/:slug renders a paginated email table
- Sidebar links now route to their respective folder views
- Extended SearchRequestDto with IsInInbox, IsStarred, IsTrashed, GmailLabel, Category, MinSizeBytes
- SearchService applies the new filters; GmailLabel does a label-id lookup (SENT/DRAFT/SPAM)
- Frontend folderToRequest() maps every slug to the correct search payload
- Email rows show sender, subject+snippet, attachment icon, size, date; bold for unread
- Pagination controls for large folders

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 19:59:01 +02:00