aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorTim Culverhouse <tim@timculverhouse.com>2022-10-17 15:16:11 -0500
committerRobin Jarry <robin@jarry.cc>2022-10-18 22:25:35 +0200
commitbad694e466705db83da2e864a3988255eb97055a (patch)
tree2898491fa51a998c5f034399ed17a8991abddc1b /widgets
parent7016c6f86ae09b3e49eab665aa013628db4ee102 (diff)
downloadaerc-bad694e466705db83da2e864a3988255eb97055a.tar.gz
ui: add :split and :vsplit view options
Add :split and :vsplit commands, which split the message list view to include a message viewer. Each command takes an int, or a delta value ("+1", "-1"). The int value is the resulting size of the message list, and a new message viewer will be displayed below / to the right of the message list. This viewer *does not* set seen flags. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'widgets')
-rw-r--r--widgets/account.go153
1 files changed, 153 insertions, 0 deletions
diff --git a/widgets/account.go b/widgets/account.go
index cafc29de..b6000f7c 100644
--- a/widgets/account.go
+++ b/widgets/account.go
@@ -37,6 +37,12 @@ type AccountView struct {
newConn bool // True if this is a first run after a new connection/reconnection
uiConf *config.UIConfig
+ split *MessageViewer
+ splitSize int
+ splitDebounce *time.Timer
+ splitMsg *models.MessageInfo
+ splitDir string
+
// Check-mail ticker
ticker *time.Ticker
checkingMail bool
@@ -151,6 +157,9 @@ func (acct *AccountView) Draw(ctx *ui.Context) {
if acct.state.SetWidth(ctx.Width()) {
acct.UpdateStatus()
}
+ if acct.SplitSize() > 0 {
+ acct.UpdateSplitView()
+ }
acct.grid.Draw(ctx)
}
@@ -466,3 +475,147 @@ func (acct *AccountView) CheckMailTimer(d time.Duration) {
}
}()
}
+
+func (acct *AccountView) clearSplit() {
+ if acct.split != nil {
+ acct.split.Close()
+ }
+ acct.splitSize = 0
+ acct.splitDir = ""
+ acct.split = nil
+ acct.grid = ui.NewGrid().Rows([]ui.GridSpec{
+ {Strategy: ui.SIZE_WEIGHT, Size: ui.Const(1)},
+ }).Columns([]ui.GridSpec{
+ {Strategy: ui.SIZE_EXACT, Size: func() int {
+ return acct.UiConfig().SidebarWidth
+ }},
+ {Strategy: ui.SIZE_WEIGHT, Size: ui.Const(1)},
+ })
+
+ if acct.uiConf.SidebarWidth > 0 {
+ acct.grid.AddChild(ui.NewBordered(acct.dirlist, ui.BORDER_RIGHT, acct.uiConf))
+ }
+ acct.grid.AddChild(acct.msglist).At(0, 1)
+ ui.Invalidate()
+}
+
+func (acct *AccountView) UpdateSplitView() {
+ if acct.Store() == nil {
+ return
+ }
+ if acct.splitMsg == acct.msglist.Selected() {
+ return
+ }
+ if acct.splitDebounce != nil {
+ acct.splitDebounce.Stop()
+ }
+ fn := func() {
+ if acct.split != nil {
+ acct.split.Close()
+ }
+ msg, err := acct.SelectedMessage()
+ if err != nil {
+ return
+ }
+ lib.NewMessageStoreView(msg, false, acct.Store(), acct.aerc.Crypto, acct.aerc.DecryptKeys,
+ func(view lib.MessageView, err error) {
+ if err != nil {
+ acct.aerc.PushError(err.Error())
+ return
+ }
+ orig := acct.split
+ acct.split = NewMessageViewer(acct, acct.conf, view)
+ acct.grid.ReplaceChild(orig, acct.split)
+ })
+ acct.splitMsg = msg
+ ui.Invalidate()
+ }
+ acct.splitDebounce = time.AfterFunc(100*time.Millisecond, func() {
+ ui.QueueFunc(fn)
+ })
+}
+
+func (acct *AccountView) SplitSize() int {
+ return acct.splitSize
+}
+
+func (acct *AccountView) SplitDirection() string {
+ return acct.splitDir
+}
+
+// Split splits the message list view horizontally. The message list will be n
+// rows high. If n is 0, any existing split is removed
+func (acct *AccountView) Split(n int) {
+ if n == 0 {
+ acct.clearSplit()
+ return
+ }
+ acct.splitSize = n
+ acct.splitDir = "split"
+ if acct.split != nil {
+ acct.split.Close()
+ }
+ acct.grid = ui.NewGrid().Rows([]ui.GridSpec{
+ // Add 1 so that the splitSize is the number of visible messages
+ {Strategy: ui.SIZE_EXACT, Size: ui.Const(acct.splitSize + 1)},
+ {Strategy: ui.SIZE_WEIGHT, Size: ui.Const(1)},
+ }).Columns([]ui.GridSpec{
+ {Strategy: ui.SIZE_EXACT, Size: func() int {
+ return acct.UiConfig().SidebarWidth
+ }},
+ {Strategy: ui.SIZE_WEIGHT, Size: ui.Const(1)},
+ })
+
+ if acct.uiConf.SidebarWidth > 0 {
+ acct.grid.AddChild(ui.NewBordered(acct.dirlist, ui.BORDER_RIGHT, acct.uiConf)).Span(2, 1)
+ }
+ acct.grid.AddChild(ui.NewBordered(acct.msglist, ui.BORDER_BOTTOM, acct.uiConf)).At(0, 1)
+ lib.NewMessageStoreView(acct.msglist.Selected(), false, acct.Store(), acct.aerc.Crypto, acct.aerc.DecryptKeys,
+ func(view lib.MessageView, err error) {
+ if err != nil {
+ acct.aerc.PushError(err.Error())
+ return
+ }
+ acct.split = NewMessageViewer(acct, acct.conf, view)
+ acct.grid.AddChild(acct.split).At(1, 1)
+ })
+ ui.Invalidate()
+}
+
+// Vsplit splits the message list view vertically. The message list will be n
+// rows wide. If n is 0, any existing split is removed
+func (acct *AccountView) Vsplit(n int) {
+ if n == 0 {
+ acct.clearSplit()
+ return
+ }
+ acct.splitSize = n
+ acct.splitDir = "vsplit"
+ if acct.split != nil {
+ acct.split.Close()
+ }
+ acct.grid = ui.NewGrid().Rows([]ui.GridSpec{
+ {Strategy: ui.SIZE_WEIGHT, Size: ui.Const(1)},
+ }).Columns([]ui.GridSpec{
+ {Strategy: ui.SIZE_EXACT, Size: func() int {
+ return acct.UiConfig().SidebarWidth
+ }},
+ {Strategy: ui.SIZE_EXACT, Size: ui.Const(acct.splitSize)},
+ {Strategy: ui.SIZE_WEIGHT, Size: ui.Const(1)},
+ })
+
+ if acct.uiConf.SidebarWidth > 0 {
+ acct.grid.AddChild(ui.NewBordered(acct.dirlist, ui.BORDER_RIGHT, acct.uiConf)).At(0, 0)
+ }
+ acct.grid.AddChild(ui.NewBordered(acct.msglist, ui.BORDER_RIGHT, acct.uiConf)).At(0, 1)
+ lib.NewMessageStoreView(acct.msglist.Selected(), false, acct.Store(), acct.aerc.Crypto, acct.aerc.DecryptKeys,
+ func(view lib.MessageView, err error) {
+ if err != nil {
+ acct.aerc.PushError(err.Error())
+ return
+ }
+ acct.split = NewMessageViewer(acct, acct.conf, view)
+ acct.grid.AddChild(acct.split).At(0, 2)
+ })
+ ui.Invalidate()
+}