aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/aerc.conf.in6
-rw-r--r--config/config.go2
-rw-r--r--doc/aerc-config.5.scd5
-rw-r--r--lib/msgstore.go15
-rw-r--r--lib/ui/interfaces.go9
-rw-r--r--lib/ui/ui.go3
-rw-r--r--widgets/account.go4
-rw-r--r--widgets/aerc.go15
-rw-r--r--widgets/tabhost.go1
9 files changed, 56 insertions, 4 deletions
diff --git a/config/aerc.conf.in b/config/aerc.conf.in
index 55dfa130..4d0f9fd2 100644
--- a/config/aerc.conf.in
+++ b/config/aerc.conf.in
@@ -37,6 +37,12 @@ empty-dirlist=(no folders)
# Default: false
mouse-enabled=false
+#
+# Ring the bell when new messages are received
+#
+# Default: yes
+new-message-bell=true
+
[viewer]
#
# Specifies the pager to use when displaying emails. Note that some filters
diff --git a/config/config.go b/config/config.go
index 8ba705ca..bfcbecf6 100644
--- a/config/config.go
+++ b/config/config.go
@@ -32,6 +32,7 @@ type UIConfig struct {
EmptyMessage string `ini:"empty-message"`
EmptyDirlist string `ini:"empty-dirlist"`
MouseEnabled bool `ini:"mouse-enabled"`
+ NewMessageBell bool `ini:"new-message-bell"`
}
const (
@@ -344,6 +345,7 @@ func LoadConfigFromFile(root *string, sharedir string) (*AercConfig, error) {
EmptyMessage: "(no messages)",
EmptyDirlist: "(no folders)",
MouseEnabled: false,
+ NewMessageBell: true,
},
Viewer: ViewerConfig{
diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd
index 72823115..a57f760b 100644
--- a/doc/aerc-config.5.scd
+++ b/doc/aerc-config.5.scd
@@ -105,6 +105,11 @@ These options are configured in the *[ui]* section of aerc.conf.
Default: false
+*new-message-bell*
+ Ring the bell when a new message is received.
+
+ Default: true
+
## VIEWER
These options are configured in the *[viewer]* section of aerc.conf.
diff --git a/lib/msgstore.go b/lib/msgstore.go
index 48a105ed..b3461291 100644
--- a/lib/msgstore.go
+++ b/lib/msgstore.go
@@ -33,12 +33,14 @@ type MessageStore struct {
pendingHeaders map[uint32]interface{}
worker *types.Worker
- triggerNewEmail func(*models.MessageInfo)
+ triggerNewEmail func(*models.MessageInfo)
+ triggerDirectoryChange func()
}
func NewMessageStore(worker *types.Worker,
dirInfo *models.DirectoryInfo,
- triggerNewEmail func(*models.MessageInfo)) *MessageStore {
+ triggerNewEmail func(*models.MessageInfo),
+ triggerDirectoryChange func()) *MessageStore {
return &MessageStore{
Deleted: make(map[uint32]interface{}),
@@ -52,7 +54,8 @@ func NewMessageStore(worker *types.Worker,
pendingHeaders: make(map[uint32]interface{}),
worker: worker,
- triggerNewEmail: triggerNewEmail,
+ triggerNewEmail: triggerNewEmail,
+ triggerDirectoryChange: triggerDirectoryChange,
}
}
@@ -147,6 +150,7 @@ func merge(to *models.MessageInfo, from *models.MessageInfo) {
func (store *MessageStore) Update(msg types.WorkerMessage) {
update := false
+ directoryChange := false
switch msg := msg.(type) {
case *types.DirectoryInfo:
store.DirInfo = *msg.Info
@@ -159,6 +163,7 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
newMap[uid] = msg
} else {
newMap[uid] = nil
+ directoryChange = true
}
}
store.Messages = newMap
@@ -225,6 +230,10 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
if update {
store.update()
}
+
+ if directoryChange && store.triggerDirectoryChange != nil {
+ store.triggerDirectoryChange()
+ }
}
func (store *MessageStore) OnUpdate(fn func(store *MessageStore)) {
diff --git a/lib/ui/interfaces.go b/lib/ui/interfaces.go
index 9008ea72..2f634248 100644
--- a/lib/ui/interfaces.go
+++ b/lib/ui/interfaces.go
@@ -23,6 +23,10 @@ type Interactive interface {
Focus(focus bool)
}
+type Beeper interface {
+ OnBeep(func() error)
+}
+
type Simulator interface {
// Queues up the given input events for simulation
Simulate(events []tcell.Event)
@@ -33,6 +37,11 @@ type DrawableInteractive interface {
Interactive
}
+type DrawableInteractiveBeeper interface {
+ DrawableInteractive
+ Beeper
+}
+
// A drawable which contains other drawables
type Container interface {
Drawable
diff --git a/lib/ui/ui.go b/lib/ui/ui.go
index 13b640b4..4c3dd345 100644
--- a/lib/ui/ui.go
+++ b/lib/ui/ui.go
@@ -19,7 +19,7 @@ type UI struct {
}
func Initialize(conf *config.AercConfig,
- content DrawableInteractive) (*UI, error) {
+ content DrawableInteractiveBeeper) (*UI, error) {
screen, err := tcell.NewScreen()
if err != nil {
@@ -57,6 +57,7 @@ func Initialize(conf *config.AercConfig,
content.OnInvalidate(func(_ Drawable) {
atomic.StoreInt32(&state.invalid, 1)
})
+ content.OnBeep(screen.Beep)
content.Focus(true)
return &state, nil
diff --git a/widgets/account.go b/widgets/account.go
index 86ec00c8..de81ab85 100644
--- a/widgets/account.go
+++ b/widgets/account.go
@@ -205,6 +205,10 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
func(msg *models.MessageInfo) {
acct.conf.Triggers.ExecNewEmail(acct.acct,
acct.conf, msg)
+ }, func() {
+ if acct.conf.Ui.NewMessageBell {
+ acct.host.Beep()
+ }
})
acct.dirlist.SetMsgStore(msg.Info.Name, store)
store.OnUpdate(func(_ *lib.MessageStore) {
diff --git a/widgets/aerc.go b/widgets/aerc.go
index 90b56c82..23dac3e2 100644
--- a/widgets/aerc.go
+++ b/widgets/aerc.go
@@ -30,6 +30,7 @@ type Aerc struct {
statusline *StatusLine
pendingKeys []config.KeyStroke
tabs *libui.Tabs
+ beep func() error
}
func NewAerc(conf *config.AercConfig, logger *log.Logger,
@@ -84,6 +85,20 @@ func NewAerc(conf *config.AercConfig, logger *log.Logger,
return aerc
}
+func (aerc *Aerc) OnBeep(f func() error) {
+ aerc.beep = f
+}
+
+func (aerc *Aerc) Beep() {
+ if aerc.beep == nil {
+ aerc.logger.Printf("should beep, but no beeper")
+ return
+ }
+ if err := aerc.beep(); err != nil {
+ aerc.logger.Printf("tried to beep, but could not: %v", err)
+ }
+}
+
func (aerc *Aerc) Tick() bool {
more := false
for _, acct := range aerc.accounts {
diff --git a/widgets/tabhost.go b/widgets/tabhost.go
index 7c502cb2..2c33cf8d 100644
--- a/widgets/tabhost.go
+++ b/widgets/tabhost.go
@@ -8,4 +8,5 @@ type TabHost interface {
BeginExCommand()
SetStatus(status string) *StatusMessage
PushStatus(text string, expiry time.Duration) *StatusMessage
+ Beep()
}