messages.go

  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}