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