From 2512c0403fa42b19c3e87fed44240da045ec902f Mon Sep 17 00:00:00 2001 From: Koni Marti Date: Fri, 18 Mar 2022 22:35:33 +0100 Subject: statusline: implement per-account status Implement a statusline state for each account. Keep the ex line and the push notifications global. Add account name prefix to push notifications. Prefix status line with account name when multiple accounts are available. Use account-specific status line for each tab where an account is defined. Handle threading, filter/search, viewer passthrough and connection status. Signed-off-by: Koni Marti Acked-by: Robin Jarry --- widgets/account.go | 41 ++++++++++++++++++++++++++++++----------- widgets/aerc.go | 14 +++++++++----- widgets/status.go | 16 +--------------- 3 files changed, 40 insertions(+), 31 deletions(-) (limited to 'widgets') diff --git a/widgets/account.go b/widgets/account.go index 87a8cef..647a3ae 100644 --- a/widgets/account.go +++ b/widgets/account.go @@ -4,12 +4,14 @@ import ( "errors" "fmt" "log" + "time" "github.com/gdamore/tcell/v2" "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/sort" + "git.sr.ht/~rjarry/aerc/lib/statusline" "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker" @@ -29,6 +31,7 @@ type AccountView struct { logger *log.Logger msglist *MessageList worker *types.Worker + state *statusline.State } func (acct *AccountView) UiConfig() config.UIConfig { @@ -55,6 +58,7 @@ func NewAccountView(aerc *Aerc, conf *config.AercConfig, acct *config.AccountCon conf: conf, host: host, logger: logger, + state: statusline.NewState(acct.Name, len(conf.Accounts) > 1, " | "), } view.grid = ui.NewGrid().Rows([]ui.GridSpec{ @@ -86,7 +90,7 @@ func NewAccountView(aerc *Aerc, conf *config.AercConfig, acct *config.AccountCon worker.PostAction(&types.Configure{Config: acct}, nil) worker.PostAction(&types.Connect{}, nil) - host.SetStatus("Connecting...") + view.SetStatus(statusline.ConnectionActivity("Connecting...")) return view, nil } @@ -105,8 +109,22 @@ func (acct *AccountView) Tick() bool { } } -func (acct *AccountView) SetStatus(msg string) { - acct.host.SetStatus(msg) +func (acct *AccountView) SetStatus(setters ...statusline.SetStateFunc) { + for _, fn := range setters { + fn(acct.state) + } +} + +func (acct *AccountView) UpdateStatus() { + acct.host.SetStatus(acct.state.String()) +} + +func (acct *AccountView) PushStatus(status string, expiry time.Duration) { + acct.aerc.PushStatus(fmt.Sprintf("%s: %v", acct.acct.Name, status), expiry) +} + +func (acct *AccountView) PushError(err error) { + acct.aerc.PushError(fmt.Sprintf("%s: %v", acct.acct.Name, err)) } func (acct *AccountView) AccountConfig() *config.AccountConfig { @@ -140,6 +158,7 @@ func (acct *AccountView) Invalidate() { } func (acct *AccountView) Draw(ctx *ui.Context) { + acct.UpdateStatus() acct.grid.Draw(ctx) } @@ -203,7 +222,7 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) { case *types.Done: switch msg.InResponseTo().(type) { case *types.Connect, *types.Reconnect: - acct.host.SetStatus("Listing mailboxes...") + acct.SetStatus(statusline.ConnectionActivity("Listing mailboxes...")) acct.logger.Println("Listing mailboxes...") acct.dirlist.UpdateList(func(dirs []string) { var dir string @@ -221,13 +240,13 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) { } acct.msglist.SetInitDone() acct.logger.Println("Connected.") - acct.host.SetStatus("Connected.") + acct.SetStatus(statusline.Connected(true)) }) case *types.Disconnect: acct.dirlist.UpdateList(nil) acct.msglist.SetStore(nil) acct.logger.Println("Disconnected.") - acct.host.SetStatus("Disconnected.") + acct.SetStatus(statusline.Connected(false)) case *types.OpenDirectory: if store, ok := acct.dirlist.SelectedMsgStore(); ok { // If we've opened this dir before, we can re-render it from @@ -289,14 +308,14 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) { case *types.LabelList: acct.labels = msg.Labels case *types.ConnError: - acct.logger.Printf("connection error: %v", msg.Error) - acct.host.SetStatus("Disconnected.") - acct.aerc.PushError(fmt.Sprintf("%v", msg.Error)) + acct.logger.Printf("connection error: [%s] %v", acct.acct.Name, msg.Error) + acct.SetStatus(statusline.Connected(false)) + acct.PushError(msg.Error) acct.msglist.SetStore(nil) acct.worker.PostAction(&types.Reconnect{}, nil) case *types.Error: acct.logger.Printf("%v", msg.Error) - acct.aerc.PushError(fmt.Sprintf("%v", msg.Error)) + acct.PushError(msg.Error) } } @@ -306,7 +325,7 @@ func (acct *AccountView) getSortCriteria() []*types.SortCriterion { } criteria, err := sort.GetSortCriteria(acct.UiConfig().Sort) if err != nil { - acct.aerc.PushError(" ui.sort: " + err.Error()) + acct.PushError(fmt.Errorf("ui sort: %v", err)) return nil } return criteria diff --git a/widgets/aerc.go b/widgets/aerc.go index 3a8f47f..a8b23fe 100644 --- a/widgets/aerc.go +++ b/widgets/aerc.go @@ -337,6 +337,7 @@ func (aerc *Aerc) NumTabs() int { func (aerc *Aerc) NewTab(clickable ui.Drawable, name string) *ui.Tab { tab := aerc.tabs.Add(clickable, name) aerc.tabs.Select(len(aerc.tabs.Tabs) - 1) + aerc.UpdateStatus() return tab } @@ -400,17 +401,20 @@ func (aerc *Aerc) SelectPreviousTab() bool { return aerc.tabs.SelectPrevious() } -// TODO: Use per-account status lines, but a global ex line func (aerc *Aerc) SetStatus(status string) *StatusMessage { return aerc.statusline.Set(status) } -func (aerc *Aerc) SetExtraStatus(status string) { - aerc.statusline.SetExtra(status) +func (aerc *Aerc) UpdateStatus() { + if acct := aerc.SelectedAccount(); acct != nil { + acct.UpdateStatus() + } else { + aerc.ClearStatus() + } } -func (aerc *Aerc) ClearExtraStatus() { - aerc.statusline.ClearExtra() +func (aerc *Aerc) ClearStatus() { + aerc.statusline.Set("") } func (aerc *Aerc) SetError(status string) *StatusMessage { diff --git a/widgets/status.go b/widgets/status.go index 960f244..c70d215 100644 --- a/widgets/status.go +++ b/widgets/status.go @@ -14,7 +14,6 @@ type StatusLine struct { ui.Invalidatable stack []*StatusMessage fallback StatusMessage - extra string aerc *Aerc uiConfig config.UIConfig } @@ -30,7 +29,6 @@ func NewStatusLine(uiConfig config.UIConfig) *StatusLine { style: uiConfig.GetStyle(config.STYLE_STATUSLINE_DEFAULT), message: "Idle", }, - extra: "", uiConfig: uiConfig, } } @@ -51,11 +49,7 @@ func (status *StatusLine) Draw(ctx *ui.Context) { pendingKeys += string(pendingKey.Rune) } } - text := line.message - if status.extra != "" { - text += " " + status.extra - } - message := runewidth.FillRight(text, ctx.Width()-len(pendingKeys)-5) + message := runewidth.FillRight(line.message, ctx.Width()-len(pendingKeys)-5) ctx.Printf(0, 0, line.style, "%s%s", message, pendingKeys) } @@ -109,14 +103,6 @@ func (status *StatusLine) PushSuccess(text string) *StatusMessage { return msg } -func (status *StatusLine) SetExtra(text string) { - status.extra = text -} - -func (status *StatusLine) ClearExtra() { - status.extra = "" -} - func (status *StatusLine) Expire() { status.stack = nil } -- cgit v1.2.3