Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ type MailingList struct {

// Config stores the user's email configuration with multiple accounts.
type Config struct {
Accounts []Account `json:"accounts"`
DisableImages bool `json:"disable_images,omitempty"`
HideTips bool `json:"hide_tips,omitempty"`
Theme string `json:"theme,omitempty"`
MailingLists []MailingList `json:"mailing_lists,omitempty"`
Accounts []Account `json:"accounts"`
DisableImages bool `json:"disable_images,omitempty"`
HideTips bool `json:"hide_tips,omitempty"`
DisableNotifications bool `json:"disable_notifications,omitempty"`
Theme string `json:"theme,omitempty"`
MailingLists []MailingList `json:"mailing_lists,omitempty"`
}

// GetIMAPServer returns the IMAP server address for the account.
Expand Down Expand Up @@ -192,11 +193,12 @@ func LoadConfig() (*Config, error) {
AuthMethod string `json:"auth_method,omitempty"`
}
type diskConfig struct {
Accounts []rawAccount `json:"accounts"`
DisableImages bool `json:"disable_images,omitempty"`
HideTips bool `json:"hide_tips,omitempty"`
Theme string `json:"theme,omitempty"`
MailingLists []MailingList `json:"mailing_lists,omitempty"`
Accounts []rawAccount `json:"accounts"`
DisableImages bool `json:"disable_images,omitempty"`
HideTips bool `json:"hide_tips,omitempty"`
DisableNotifications bool `json:"disable_notifications,omitempty"`
Theme string `json:"theme,omitempty"`
MailingLists []MailingList `json:"mailing_lists,omitempty"`
}

var raw diskConfig
Expand Down Expand Up @@ -226,6 +228,7 @@ func LoadConfig() (*Config, error) {

config.DisableImages = raw.DisableImages
config.HideTips = raw.HideTips
config.DisableNotifications = raw.DisableNotifications
config.Theme = raw.Theme
config.MailingLists = raw.MailingLists
for _, rawAcc := range raw.Accounts {
Expand Down
12 changes: 12 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/floatpane/matcha/clib"
"github.com/floatpane/matcha/config"
"github.com/floatpane/matcha/fetcher"
"github.com/floatpane/matcha/notify"
"github.com/floatpane/matcha/plugin"
"github.com/floatpane/matcha/sender"
"github.com/floatpane/matcha/theme"
Expand Down Expand Up @@ -485,6 +486,17 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, fetchFolderEmailsCmd(m.config, m.folderInbox.GetCurrentFolder())

case tui.IdleNewMailMsg:
// Send desktop notification for new mail (if enabled)
if m.config == nil || !m.config.DisableNotifications {
accountName := msg.AccountID
if m.config != nil {
if acc := m.config.GetAccountByID(msg.AccountID); acc != nil {
accountName = acc.Email
}
}
go notify.Send("Matcha", fmt.Sprintf("New mail in %s (%s)", msg.FolderName, accountName))
}

// IDLE detected new mail — refetch the folder if we're viewing it
if m.folderInbox != nil && m.folderInbox.GetCurrentFolder() == msg.FolderName {
return m, tea.Batch(
Expand Down
21 changes: 21 additions & 0 deletions notify/notify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package notify

import (
"fmt"
"os/exec"
"runtime"
)

// Send delivers a desktop notification with the given title and body.
// On macOS it uses osascript; on Linux it uses notify-send.
func Send(title, body string) error {
switch runtime.GOOS {
case "darwin":
script := fmt.Sprintf(`display notification %q with title %q sound name "default"`, body, title)
return exec.Command("osascript", "-e", script).Run()
case "linux":
return exec.Command("notify-send", title, body).Run()
default:
return nil
}
}
29 changes: 24 additions & 5 deletions tui/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ func (m *Settings) updateMain(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
m.cursor--
}
case "down", "j":
// Options: 0: Email Accounts, 1: Theme, 2: Image Display, 3: Edit Signature, 4: Contextual Tips, 5: Mailing Lists
if m.cursor < 5 {
// Options: 0: Email Accounts, 1: Theme, 2: Image Display, 3: Edit Signature, 4: Contextual Tips, 5: Desktop Notifications, 6: Mailing Lists
if m.cursor < 6 {
m.cursor++
}
case "enter":
Expand Down Expand Up @@ -160,7 +160,11 @@ func (m *Settings) updateMain(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
m.cfg.HideTips = !m.cfg.HideTips
_ = config.SaveConfig(m.cfg)
return m, nil
case 5: // Mailing Lists
case 5: // Desktop Notifications
m.cfg.DisableNotifications = !m.cfg.DisableNotifications
_ = config.SaveConfig(m.cfg)
return m, nil
case 6: // Mailing Lists
m.state = SettingsMailingLists
m.cursor = 0
return m, nil
Expand Down Expand Up @@ -443,9 +447,22 @@ func (m *Settings) viewMain() string {
}
b.WriteString("\n")

// Option 5: Mailing Lists
mailingListsText := "Mailing Lists"
// Option 5: Desktop Notifications
notifStatus := "ON"
if m.cfg.DisableNotifications {
notifStatus = "OFF"
}
notifText := fmt.Sprintf("Desktop Notifications: %s", notifStatus)
if m.cursor == 5 {
b.WriteString(selectedAccountItemStyle.Render("> " + notifText))
} else {
b.WriteString(accountItemStyle.Render(" " + notifText))
}
b.WriteString("\n")

// Option 6: Mailing Lists
mailingListsText := "Mailing Lists"
if m.cursor == 6 {
b.WriteString(selectedAccountItemStyle.Render("> " + mailingListsText))
} else {
b.WriteString(accountItemStyle.Render(" " + mailingListsText))
Expand All @@ -466,6 +483,8 @@ func (m *Settings) viewMain() string {
case 4:
tip = "Toggle displaying helpful contextual tips like this one."
case 5:
tip = "Toggle desktop notifications when new mail arrives."
case 6:
tip = "Manage groups of email addresses to quickly send to multiple people."
}
if tip != "" {
Expand Down