1package tui
2
3import (
4 calendar "github.com/floatpane/go-icalendar"
5 "github.com/floatpane/matcha/backend"
6 "github.com/floatpane/matcha/config"
7 "github.com/floatpane/matcha/daemonrpc"
8 "github.com/floatpane/matcha/fetcher"
9)
10
11type MailboxKind string
12
13const (
14 MailboxInbox MailboxKind = "inbox"
15 MailboxSent MailboxKind = "sent"
16 MailboxTrash MailboxKind = "trash"
17 MailboxArchive MailboxKind = "archive"
18)
19
20type ViewEmailMsg struct {
21 Index int
22 UID uint32
23 AccountID string
24 Mailbox MailboxKind
25 Email *fetcher.Email
26}
27
28type SendEmailMsg struct {
29 To string
30 Cc string // Cc recipient(s)
31 Bcc string // Bcc recipient(s)
32 Subject string
33 Body string
34 AttachmentPaths []string
35 InReplyTo string
36 References []string
37 AccountID string // ID of the account to send from
38 FromOverride string // Custom From address (used when account is catch-all)
39 QuotedText string // Hidden quoted text appended when sending
40 Signature string // Signature to append to email body
41 SignSMIME bool // Whether to sign the email using S/MIME
42 EncryptSMIME bool // Whether to encrypt the email using S/MIME
43 SignPGP bool // Whether to sign the email using PGP
44}
45
46type EmailQueuedMsg struct {
47 JobID string
48 DelaySeconds int
49}
50
51type EmailDelayExpiredMsg struct {
52 JobID string
53}
54
55type UndoSendMsg struct {
56 JobID string
57}
58
59type Credentials struct {
60 Provider string
61 Name string
62 Host string // Host (this was the previous "Email Address" field in the UI)
63 FetchEmail string // Single email address to fetch messages for. If empty, code should default this to Host when creating the account.
64 SendAsEmail string // Optional From header email. If empty, sending falls back to FetchEmail, then Host.
65 CatchAll bool // Show all inbox messages regardless of To address.
66 Password string
67 IMAPServer string
68 IMAPPort int
69 SMTPServer string
70 SMTPPort int
71 Insecure bool
72 AuthMethod string // "password" or "oauth2"
73 Protocol string // "imap" (default), "jmap", or "pop3"
74 JMAPEndpoint string // JMAP session URL
75 POP3Server string // POP3 server hostname
76 POP3Port int // POP3 server port
77 MaildirPath string // Local Maildir root
78}
79
80// StartOAuth2Msg is sent when the user requests OAuth2 authorization for a Gmail account.
81type StartOAuth2Msg struct {
82 Email string
83}
84
85// OAuth2CompleteMsg is sent when OAuth2 authorization completes.
86type OAuth2CompleteMsg struct {
87 Email string
88 Err error
89}
90
91type ChooseServiceMsg struct {
92 Service string
93}
94
95type EmailResultMsg struct {
96 Err error
97}
98
99type ClearStatusMsg struct{}
100
101type EmailsFetchedMsg struct {
102 Emails []fetcher.Email
103 AccountID string
104 Mailbox MailboxKind
105}
106
107type UpdatePreviewMsg struct {
108 UID uint32
109 AccountID string
110}
111
112type PreviewBodyFetchedMsg struct {
113 UID uint32
114 AccountID string
115 Body string
116 BodyMIMEType string
117 Attachments []fetcher.Attachment
118 Err error
119}
120
121type FetchErr error
122
123type SearchRequestedMsg struct {
124 Query backend.SearchQuery
125 Mailbox MailboxKind
126 FolderName string
127 AccountID string
128}
129
130type SearchResultsMsg struct {
131 Query backend.SearchQuery
132 Emails []fetcher.Email
133 Err error
134}
135
136type ApplySearchResultsMsg struct {
137 Query backend.SearchQuery
138 Emails []fetcher.Email
139}
140
141type GoToInboxMsg struct{}
142
143type GoToSentInboxMsg struct{}
144
145type GoToSendMsg struct {
146 To string
147 Subject string
148 Body string
149}
150
151type GoToSettingsMsg struct{}
152
153type GoToTrashArchiveMsg struct{}
154
155type GoToSignatureEditorMsg struct {
156 AccountID string
157}
158
159type FetchMoreEmailsMsg struct {
160 Offset uint32
161 AccountID string
162 Mailbox MailboxKind
163 Limit uint32
164}
165
166type FetchingMoreEmailsMsg struct{}
167
168type EmailsAppendedMsg struct {
169 Emails []fetcher.Email
170 AccountID string
171 Mailbox MailboxKind
172}
173
174type ReplyToEmailMsg struct {
175 Email fetcher.Email
176}
177
178type ForwardEmailMsg struct {
179 Email fetcher.Email
180}
181
182type SetComposerCursorToStartMsg struct{}
183
184type GoToFilePickerMsg struct{}
185
186type FileSelectedMsg struct {
187 Paths []string
188}
189
190type CancelFilePickerMsg struct{}
191
192type DeleteEmailMsg struct {
193 UID uint32
194 AccountID string
195 Mailbox MailboxKind
196}
197
198type ArchiveEmailMsg struct {
199 UID uint32
200 AccountID string
201 Mailbox MailboxKind
202}
203
204type EmailActionDoneMsg struct {
205 UID uint32
206 AccountID string
207 Mailbox MailboxKind
208 Err error
209}
210
211// Batch operation messages
212type BatchDeleteEmailsMsg struct {
213 UIDs []uint32
214 AccountID string
215 Mailbox MailboxKind
216}
217
218type BatchArchiveEmailsMsg struct {
219 UIDs []uint32
220 AccountID string
221 Mailbox MailboxKind
222}
223
224type BatchMoveEmailsMsg struct {
225 UIDs []uint32
226 AccountID string
227 SourceFolder string
228 DestFolder string
229}
230
231type BatchEmailActionDoneMsg struct {
232 Count int
233 SuccessCount int
234 FailureCount int
235 Action string // "delete", "archive", or "move"
236 Mailbox MailboxKind
237 Err error
238}
239
240type GoToChoiceMenuMsg struct{}
241
242type DownloadAttachmentMsg struct {
243 Index int
244 Filename string
245 PartID string
246 Data []byte
247 AccountID string
248 Encoding string
249 Mailbox MailboxKind
250}
251
252type AttachmentDownloadedMsg struct {
253 Path string
254 Err error
255}
256
257type RestoreViewMsg struct{}
258
259type BackToInboxMsg struct{}
260
261type BackToMailboxMsg struct {
262 Mailbox MailboxKind
263}
264
265// --- Draft Messages ---
266
267// DiscardDraftMsg signals that a draft should be cached.
268type DiscardDraftMsg struct {
269 ComposerState *Composer
270}
271
272type EmailBodyFetchedMsg struct {
273 UID uint32
274 Body string
275 BodyMIMEType string
276 Attachments []fetcher.Attachment
277 Err error
278 AccountID string
279 Mailbox MailboxKind
280}
281
282// --- Multi-Account Messages ---
283
284// GoToAddAccountMsg signals navigation to the add account screen.
285type GoToAddAccountMsg struct{}
286
287// GoToAddMailingListMsg signals navigation to the add mailing list screen.
288type GoToAddMailingListMsg struct{}
289
290// GoToEditAccountMsg signals navigation to edit an existing account.
291type GoToEditAccountMsg struct {
292 AccountID string
293 Provider string
294 Name string
295 Email string
296 FetchEmail string
297 SendAsEmail string
298 CatchAll bool
299 IMAPServer string
300 IMAPPort int
301 SMTPServer string
302 SMTPPort int
303 Insecure bool
304 Protocol string
305 JMAPEndpoint string
306 POP3Server string
307 POP3Port int
308 MaildirPath string
309}
310
311// GoToEditMailingListMsg signals navigation to edit an existing mailing list.
312type GoToEditMailingListMsg struct {
313 Index int
314 Name string
315 Addresses string
316}
317
318// SaveMailingListMsg signals that a new or edited mailing list should be saved.
319type SaveMailingListMsg struct {
320 Name string
321 Addresses string
322 EditIndex int // -1 means new, >= 0 means editing existing
323}
324
325// AddAccountMsg signals that a new account should be added.
326type AddAccountMsg struct {
327 Credentials Credentials
328}
329
330// AccountAddedMsg signals that an account was successfully added.
331type AccountAddedMsg struct {
332 AccountID string
333 Err error
334}
335
336// DeleteAccountMsg signals that an account should be deleted.
337type DeleteAccountMsg struct {
338 AccountID string
339}
340
341// AccountDeletedMsg signals that an account was successfully deleted.
342type AccountDeletedMsg struct {
343 AccountID string
344 Err error
345}
346
347// SwitchAccountMsg signals switching to view a specific account's inbox.
348type SwitchAccountMsg struct {
349 AccountID string // Empty string means "ALL" accounts
350}
351
352// AllEmailsFetchedMsg signals that emails from all accounts have been fetched.
353type AllEmailsFetchedMsg struct {
354 EmailsByAccount map[string][]fetcher.Email
355 Mailbox MailboxKind
356}
357
358// SwitchFromAccountMsg signals changing the "From" account in composer.
359type SwitchFromAccountMsg struct {
360 AccountID string
361}
362
363// GoToAccountListMsg signals navigation to the account list in settings.
364type GoToAccountListMsg struct{}
365
366// --- Draft Messages (persisted) ---
367
368// SaveDraftMsg signals that the current draft should be saved to disk.
369type SaveDraftMsg struct {
370 Draft config.Draft
371}
372
373// DraftSavedMsg signals that a draft was saved successfully.
374type DraftSavedMsg struct {
375 DraftID string
376 Err error
377}
378
379// LoadDraftsMsg signals a request to load all saved drafts.
380type LoadDraftsMsg struct{}
381
382// DraftsLoadedMsg signals that drafts were loaded from disk.
383type DraftsLoadedMsg struct {
384 Drafts []config.Draft
385}
386
387// OpenDraftMsg signals that a specific draft should be opened in the composer.
388type OpenDraftMsg struct {
389 Draft config.Draft
390}
391
392// DeleteDraftMsg signals that a draft should be deleted.
393type DeleteSavedDraftMsg struct {
394 DraftID string
395}
396
397// DraftDeletedMsg signals that a draft was deleted.
398type DraftDeletedMsg struct {
399 DraftID string
400 Err error
401}
402
403// GoToDraftsMsg signals navigation to the drafts list.
404type GoToDraftsMsg struct{}
405
406// --- Cache Messages ---
407
408// CachedEmailsLoadedMsg signals that cached emails were loaded from disk.
409type CachedEmailsLoadedMsg struct {
410 Cache *config.EmailCache
411}
412
413// RefreshingEmailsMsg signals that a background refresh is in progress.
414type RefreshingEmailsMsg struct {
415 Mailbox MailboxKind
416}
417
418// EmailsRefreshedMsg signals that fresh emails have been fetched in the background.
419type EmailsRefreshedMsg struct {
420 EmailsByAccount map[string][]fetcher.Email
421 Mailbox MailboxKind
422}
423
424// RequestRefreshMsg signals a request to refresh emails from the server.
425type RequestRefreshMsg struct {
426 Mailbox MailboxKind
427 Counts map[string]int
428 FolderName string
429}
430
431// --- Folder Messages ---
432
433// FoldersFetchedMsg signals that IMAP folders have been fetched for all accounts.
434//
435// Errors holds per-account fetch failures (e.g. broken IMAP login, network
436// unreachable). Accounts that succeeded appear in FoldersByAccount; accounts
437// that failed appear in Errors. The two are disjoint by construction. This
438// lets the TUI surface a non-fatal warning instead of silently dropping the
439// affected account's folder list.
440type FoldersFetchedMsg struct {
441 FoldersByAccount map[string][]fetcher.Folder // accountID -> folders
442 MergedFolders []fetcher.Folder // unique folders across all accounts
443 Errors map[string]error // accountID -> fetch error, if any
444}
445
446// SwitchFolderMsg signals switching to a different IMAP folder.
447type SwitchFolderMsg struct {
448 FolderName string
449 PreviousFolder string
450 AccountID string
451}
452
453// FolderEmailsFetchedMsg signals that emails from a folder have been fetched.
454type FolderEmailsFetchedMsg struct {
455 Emails []fetcher.Email
456 AccountID string
457 FolderName string
458}
459
460// FolderEmailsAppendedMsg signals that more emails from a folder have been fetched (pagination).
461type FolderEmailsAppendedMsg struct {
462 Emails []fetcher.Email
463 AccountID string
464 FolderName string
465}
466
467// MoveEmailMsg signals a request to show the move-to-folder picker.
468type MoveEmailMsg struct {
469 UID uint32
470 AccountID string
471 SourceFolder string
472}
473
474// MoveEmailToFolderMsg signals that an email should be moved to a folder.
475type MoveEmailToFolderMsg struct {
476 UID uint32
477 AccountID string
478 SourceFolder string
479 DestFolder string
480}
481
482// EmailMovedMsg signals that an email was moved to a folder.
483type EmailMovedMsg struct {
484 UID uint32
485 AccountID string
486 SourceFolder string
487 DestFolder string
488 Err error
489}
490
491// MarkEmailAsReadMsg signals that an email should be marked as read on the server.
492type MarkEmailAsReadMsg struct {
493 UID uint32
494 AccountID string
495 FolderName string
496}
497
498// EmailMarkedReadMsg signals that an email was marked as read.
499type EmailMarkedReadMsg struct {
500 UID uint32
501 AccountID string
502 Err error
503}
504
505// EmailMarkedUnreadMsg signals that an email was marked as unread.
506type EmailMarkedUnreadMsg struct {
507 UID uint32
508 AccountID string
509 Err error
510}
511
512// FetchFolderMoreEmailsMsg signals a request to fetch more emails from a folder (pagination).
513type FetchFolderMoreEmailsMsg struct {
514 Offset uint32
515 AccountID string
516 FolderName string
517 Limit uint32
518}
519
520// --- External Editor Messages ---
521
522// OpenEditorMsg signals that the composer body should be opened in $EDITOR.
523type OpenEditorMsg struct{}
524
525// EditorFinishedMsg signals that the external editor has closed.
526type EditorFinishedMsg struct {
527 Body string
528 Err error
529}
530
531// --- IDLE Messages ---
532
533// IdleNewMailMsg signals that IMAP IDLE detected new mail for an account/folder.
534type IdleNewMailMsg struct {
535 AccountID string
536 FolderName string
537}
538
539// --- Daemon Messages ---
540
541// DaemonEventMsg wraps an event pushed from the daemon process.
542type DaemonEventMsg struct {
543 Event *daemonrpc.Event
544}
545
546// --- Plugin Messages ---
547
548// PluginNotifyMsg signals that a plugin wants to show a notification.
549type PluginNotifyMsg struct {
550 Message string
551 Duration float64 // Duration in seconds (default 2)
552}
553
554// PluginKeyBinding describes a plugin-registered keyboard shortcut for display in the help bar.
555type PluginKeyBinding struct {
556 Key string
557 Description string
558}
559
560// PluginPromptSubmitMsg signals that the user submitted a plugin prompt input.
561type PluginPromptSubmitMsg struct {
562 Value string
563}
564
565// PluginPromptCancelMsg signals that the user cancelled a plugin prompt input.
566type PluginPromptCancelMsg struct{}
567
568// GoToMarketplaceMsg signals navigation to the plugin marketplace.
569type GoToMarketplaceMsg struct{}
570
571// PasswordVerifiedMsg signals that the encryption password was verified (or failed).
572type PasswordVerifiedMsg struct {
573 Key []byte // The derived encryption key (nil on failure)
574 Err error // Non-nil if verification failed
575}
576
577// SecureModeEnabledMsg signals that encryption was enabled from settings.
578type SecureModeEnabledMsg struct {
579 Err error
580}
581
582// SecureModeDisabledMsg signals that encryption was disabled from settings.
583type SecureModeDisabledMsg struct {
584 Err error
585}
586
587// SendRSVPMsg signals that user wants to send RSVP to calendar invite
588type SendRSVPMsg struct {
589 OriginalICS []byte
590 Event *calendar.Event
591 Response string // "ACCEPTED", "DECLINED", "TENTATIVE"
592 AccountID string
593 InReplyTo string
594 References []string
595}
596
597// RSVPResultMsg signals that RSVP was sent (or failed)
598type LanguageChangedMsg struct{}
599
600// ConfigSavedMsg signals the config was written to disk and downstream
601// consumers (notably the daemon) should reload it.
602type ConfigSavedMsg struct{}
603
604type RSVPResultMsg struct {
605 Err error
606 Response string // "ACCEPTED", "DECLINED", "TENTATIVE"
607 Organizer string // organizer email for Google Calendar note
608}