28 Commits

Author SHA1 Message Date
c4374b42ea default to Inbox perspective, show GTD item detail, reduce toolbar
- default to Inbox perspective (not INBOX mailbox) after first sync
- selectItemForDetail bridges GTD item selection to detail pane by
  creating a synthetic ThreadSummary for email items
- reduce GTD toolbar from 5 to 3 buttons (defer, complete, discard),
  someday/project remain accessible via keyboard shortcuts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:56:19 +01:00
3c21a4c461 fix empty detail view on thread select, reduce toolbar overflow
- add .id(selectedThread?.id) to ThreadDetailView to force SwiftUI
  NavigationSplitView detail re-evaluation on selection change
- selectMailbox clears selectedThread/messages to avoid stale state
- remove defer/project buttons from folder toolbar (4 buttons instead of 7),
  keyboard shortcuts still work

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:50:19 +01:00
367359abe6 filter thread list by selected mailbox, fix sidebar selection
- threadSummariesFromDB accepts optional mailboxId filter, uses EXISTS subquery
  to show only threads containing messages in the selected mailbox
- add selectMailbox() and selectPerspective() to MailViewModel for clean
  state transitions between folder view and GTD perspective view
- sidebar highlights selected mailbox/perspective, clears state on switch
- default to INBOX mailbox after first sync

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:44:41 +01:00
6bd1163c6c mark messages as read when selecting a thread
Updates local flags and enqueues \\Seen flag action for IMAP sync.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:36:57 +01:00
0433ed1f7e fix double sync race: remove duplicate syncNow calls, add sync guard
- connectAccount() and loadExistingAccount() no longer call syncNow() —
  the .task modifier on mailView handles initial sync + periodic sync
- add isSyncing guard to prevent concurrent syncNow() calls that race
  on the IMAP connection and cause "Previous command interrupted"
- reload mailboxes after each sync (needed on first sync when DB is empty)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:22:39 +01:00
01605a01ec fix FK constraint: skip duplicate messages before thread reconstruction
- insertMessages checks (mailboxId, uid) existence before INSERT, returns
  only actually inserted records
- syncMailbox only runs ThreadReconstructor on newly inserted messages,
  preventing FK violations from stale UUIDs referencing ignored records
- improve error logging to show full error description

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:02:55 +01:00
ff91e397e8 fix sync: INSERT OR IGNORE for duplicate messages, fix leaked IMAP continuations
- insertMessages uses INSERT OR IGNORE on (mailboxId, uid) conflict instead of
  crashing on UNIQUE constraint when messages are re-fetched after restart
- IMAPResponseHandler.sendCommand resumes any leaked previous continuation before
  registering a new one, preventing DuplicateCommandTag errors
- add channelInactive handler to resume pending continuations on connection drop
- add error type to sync failure log for better diagnostics

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 11:58:29 +01:00
d5eaf35665 add attachmentCount to ThreadSummary, paperclip badges in thread and item lists
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 11:38:29 +01:00
016c163b75 add attachment chips to message view with download, Quick Look preview
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 11:36:05 +01:00
5c547f6faa add compose attachment UI: file picker, drag-drop, paste, chip strip, send path
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 11:33:25 +01:00
31ab18cb2a fix remaining code review issues, add HTML email rendering, charset-aware MIME decoding
- add charset-aware string decoding in MIMEParser (supports UTF-8, Latin-1, Windows-1252, etc.)
- fix prefetchBodies: remove broken ISO8601 date filter that prevented body fetching
- fix ensureBodyLoaded to use fetchFullMessage + MIMEParser instead of broken fetchBody
- add N+1 query fix: inboxMessagesExcludingDeferred uses SQL LEFT JOIN instead of per-message deferral check
- add inboxMessageCountExcludingDeferred for efficient perspective counts
- add unreadMessageCount, totalMessageCount queries to MailStore
- wire mailbox unread/total counts in loadMailboxes (were hardcoded to 0)
- add flag sync: reconcileFlags fetches flags for existing UIDs, updates local read/flagged state
- move account config from UserDefaults to Application Support file, auto-migrate existing config
- render HTML emails by default (toggle to plain text), render plain text as HTML for proper Unicode/emoji
- replace print() with os_log Logger in SyncCoordinator

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 10:05:19 +01:00
10b7cb2fd2 fix code review issues: deferral date format, storeFlags SELECT, event loop leaks, GTD selection tracking
- fix deferral resurfacing using VTODOParser.formatDateOnly instead of ISO8601 (date format mismatch)
- add SELECT mailbox before UID STORE in storeFlags (IMAP protocol requirement)
- pass credentials to SyncCoordinator so IDLE monitoring activates
- add selectedItem tracking to MailViewModel, wire List selection in GTD views
- fix startPeriodicSync to sleep-first, preventing duplicate sync on launch
- add deinit cleanup for EventLoopGroup in IMAPConnection, SMTPConnection
- use separate IMAP client for attachment downloads, avoid shared connection interference
- remove [weak self] from IMAPIdleClient actor Task to prevent orphaned connections
- fix isGTDPerspective to check selectedMailbox instead of items.isEmpty
- fix fetchBody to use complete RFC822 fetch instead of BODY[TEXT]
- reuse single IMAP connection per ActionQueue.flush() batch
- add requiresIMAP to ActionPayload for connection batching
- load task categories from label store instead of hardcoded empty array
- suppress NIOSSLHandler Sendable warnings via Package.swift unsafeFlags
- fix unused variable warnings across codebase

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 23:13:46 +01:00
55ec465677 bump periodic sync to 15min (IDLE is fast path), add MIMEParser to app targets
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 13:44:41 +01:00
f28b44d445 move v0.1 artifacts to DELETE/, fix xcode build, bump calver to 2026.03.14
- move backend/, clients/, scripts/ to DELETE/ (v0.1 era, replaced by on-device arch)
- delete feature/v0.1-backend-and-macos branch
- add TaskStore dependency to project.yml
- fix ComposeViewModel deinit concurrency, make toMessageSummary public
- regenerate Xcode project, verify macOS build succeeds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 10:40:41 +01:00
8f63b1c7c1 fix task store wiring: correct directory path, pass to sync coordinator, remove unused stub
- TaskStore directory changed from `tasks-<id>` to `<accountId>/tasks/` per spec
- TaskStore now created before SyncCoordinator and passed as `taskStore:` arg so deferral resurfacing works
- Use `mailStore.databaseWriter` instead of raw `dbPool` for consistency
- Remove unused `deferSelectedItem` stub (all callers use `deferItem(_:until:)` directly)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 10:31:00 +01:00
bec9b7eb40 add app UI for GTD triage: perspectives, task creation, defer/label pickers, linked tasks
- replace mailbox-only sidebar with 6 GTD perspectives (inbox, today, upcoming, projects, someday, archive)
- add TaskEditViewModel/TaskEditView for creating tasks with optional due date, linked message
- add DeferPicker (tomorrow, next week, pick date, someday) and LabelPicker (searchable, type-to-create)
- add GTD triage actions in MailViewModel: defer, file, discard, complete for unified ItemSummary
- add GTD keyboard shortcuts in ThreadListView: d (defer), ⇧D (someday), p (project), ⌘⏎ (complete), ⌫ (discard)
- show linked tasks inline in ThreadDetailView with status badges, merged timeline

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 10:31:00 +01:00
f3da0784b9 wire end-to-end: smtp provider for ActionQueue, actionQueue for SyncCoordinator, body fetch for reply/forward
- MailViewModel.setup() now creates SMTPClient provider when SMTP config is present,
  passes it to ActionQueue so send actions work
- ActionQueue is passed to SyncCoordinator so pending actions flush before sync
- Add ensureBodyLoaded() to fetch message body via IMAP before opening compose
- ThreadDetailView uses callback instead of binding for compose requests,
  allowing ContentView to fetch body before presenting sheet
- Add SMTPClient dependency to both app targets in project.yml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 06:00:42 +01:00
0bfcf2d610 add triage UI: archive, delete, flag, read/unread, move actions with auto-advance, compose triggers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 05:55:19 +01:00
5c0c5a5bda add compose flow: ComposeViewModel with draft auto-save, ComposeView with form UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 05:50:42 +01:00
7d847693d7 extend AutoDiscovery for SMTP, add SMTP fields to account setup UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 05:32:17 +01:00
d5661459e4 bump calver to 2026.03.13, v0.2 complete: native swift email client with imap sync, grdb, swiftui
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:39:29 +01:00
deb4c1d15c add offline banner, sync status indicators
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:34:12 +01:00
00b5632f3f add imap auto-discovery: mozilla ispdb, dns srv fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:33:37 +01:00
1b8f3b6665 add keychain credential storage, persist account config
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:25:49 +01:00
74179cb534 add html email rendering with wkwebview, script/tracker blocking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:23:15 +01:00
e3159d61e8 add three-column swiftui layout: sidebar, thread list, detail, account setup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:23:04 +01:00
6f0ba20d86 add mail, account setup viewmodels with grdb observation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:23:00 +01:00
1b915fc9ab scaffold multi-platform xcode project with xcodegen
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:17:11 +01:00