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