diff options
-rw-r--r-- | commands/account/split.go | 13 | ||||
-rw-r--r-- | lib/messageview.go | 6 | ||||
-rw-r--r-- | lib/msgstore.go | 14 | ||||
-rw-r--r-- | widgets/account.go | 132 | ||||
-rw-r--r-- | widgets/msgviewer.go | 6 |
5 files changed, 69 insertions, 102 deletions
diff --git a/commands/account/split.go b/commands/account/split.go index daf1f0f0..6641641b 100644 --- a/commands/account/split.go +++ b/commands/account/split.go @@ -51,10 +51,8 @@ func (Split) Execute(aerc *widgets.Aerc, args []string) error { } if delta { n = acct.SplitSize() + n - // Maintain split direction when using deltas - if acct.SplitSize() > 0 { - args[0] = acct.SplitDirection() - } + acct.SetSplitSize(n) + return nil } } if n == acct.SplitSize() { @@ -66,8 +64,11 @@ func (Split) Execute(aerc *widgets.Aerc, args []string) error { // Don't allow split to go negative n = 1 } - if args[0] == "split" { + switch args[0] { + case "split": return acct.Split(n) + case "vsplit": + return acct.Vsplit(n) } - return acct.Vsplit(n) + return nil } diff --git a/lib/messageview.go b/lib/messageview.go index d7ff1908..d0754cc1 100644 --- a/lib/messageview.go +++ b/lib/messageview.go @@ -72,6 +72,12 @@ func NewMessageStoreView(messageInfo *models.MessageInfo, setSeen bool, store *MessageStore, pgp crypto.Provider, decryptKeys openpgp.PromptFunction, cb func(MessageView, error), ) { + if messageInfo == nil { + // Call nils to the callback, the split view will use this to + // display an empty view + cb(nil, nil) + return + } msv := &MessageStoreView{ messageInfo, store, nil, nil, messageInfo.BodyStructure, diff --git a/lib/msgstore.go b/lib/msgstore.go index c02d8f4d..1a56b2c8 100644 --- a/lib/msgstore.go +++ b/lib/msgstore.go @@ -69,6 +69,7 @@ type MessageStore struct { threadsMutex sync.Mutex iterFactory iterator.Factory + onSelect func(*models.MessageInfo) } const MagicUid = 0xFFFFFFFF @@ -79,7 +80,7 @@ func NewMessageStore(worker *types.Worker, thread bool, clientThreads bool, clientThreadsDelay time.Duration, reverseOrder bool, reverseThreadOrder bool, sortThreadSiblings bool, triggerNewEmail func(*models.MessageInfo), - triggerDirectoryChange func(), + triggerDirectoryChange func(), onSelect func(*models.MessageInfo), ) *MessageStore { if !dirInfo.Caps.Thread { clientThreads = true @@ -116,6 +117,7 @@ func NewMessageStore(worker *types.Worker, threadBuilderDelay: clientThreadsDelay, iterFactory: iterator.NewFactory(reverseOrder), + onSelect: onSelect, } } @@ -257,6 +259,9 @@ func (store *MessageStore) Update(msg types.WorkerMessage) { merge(existing, msg.Info) } else if msg.Info.Envelope != nil { store.Messages[msg.Info.Uid] = msg.Info + if store.selectedUid == msg.Info.Uid { + store.onSelect(msg.Info) + } } if msg.NeedsFlags { store.Lock() @@ -597,7 +602,7 @@ func (store *MessageStore) Selected() *models.MessageInfo { func (store *MessageStore) SelectedUid() uint32 { if store.selectedUid == MagicUid && len(store.Uids()) > 0 { iter := store.UidsIterator() - store.selectedUid = store.Uids()[iter.StartIndex()] + store.Select(store.Uids()[iter.StartIndex()]) } return store.selectedUid } @@ -612,6 +617,9 @@ func (store *MessageStore) Select(uid uint32) { if store.marker != nil { store.marker.UpdateVisualMark() } + if store.onSelect != nil { + store.onSelect(store.Selected()) + } } func (store *MessageStore) NextPrev(delta int) { @@ -639,7 +647,7 @@ func (store *MessageStore) NextPrev(delta int) { store.threadsMutex.Lock() store.threadCallback = func() { if uids := store.Uids(); len(uids) > newIdx { - store.selectedUid = uids[newIdx] + store.Select(uids[newIdx]) } } store.threadsMutex.Unlock() diff --git a/widgets/account.go b/widgets/account.go index 6f1b7cc3..19385014 100644 --- a/widgets/account.go +++ b/widgets/account.go @@ -39,7 +39,6 @@ type AccountView struct { split *MessageViewer splitSize int splitDebounce *time.Timer - splitUid uint32 splitDir string // Check-mail ticker @@ -158,9 +157,6 @@ 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) } @@ -295,7 +291,9 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) { if acct.dirlist.UiConfig(name).NewMessageBell { acct.host.Beep() } - }) + }, + acct.updateSplitView, + ) store.SetMarker(marker.New(store)) acct.dirlist.SetMsgStore(msg.Info.Name, store) } @@ -495,37 +493,33 @@ func (acct *AccountView) closeSplit() { {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(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.Store().SelectedUid() == acct.splitUid { +func (acct *AccountView) updateSplitView(msg *models.MessageInfo) { + if acct.splitSize == 0 { return } if acct.splitDebounce != nil { acct.splitDebounce.Stop() } fn := func() { - var err error - switch acct.SplitDirection() { - case "split": - err = acct.Split(acct.SplitSize()) - case "vsplit": - err = acct.Vsplit(acct.SplitSize()) - default: - return - } - if err != nil { - log.Errorf("could not update split: %v", err) - } - ui.Invalidate() + 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 + } + acct.split = NewMessageViewer(acct, view) + switch acct.splitDir { + case "split": + acct.grid.AddChild(acct.split).At(1, 1) + case "vsplit": + acct.grid.AddChild(acct.split).At(0, 2) + } + }) } acct.splitDebounce = time.AfterFunc(100*time.Millisecond, func() { ui.QueueFunc(fn) @@ -536,25 +530,24 @@ func (acct *AccountView) SplitSize() int { return acct.splitSize } -func (acct *AccountView) SplitDirection() string { - return acct.splitDir +func (acct *AccountView) SetSplitSize(n int) { + if n == 0 { + acct.closeSplit() + } + acct.splitSize = n } // 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) error { - if n == 0 { - acct.closeSplit() + acct.SetSplitSize(n) + if acct.splitDir == "split" || n == 0 { return nil } - 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_EXACT, Size: func() int { return acct.SplitSize() + 1 }}, {Strategy: ui.SIZE_WEIGHT, Size: ui.Const(1)}, }).Columns([]ui.GridSpec{ {Strategy: ui.SIZE_EXACT, Size: func() int { @@ -563,83 +556,36 @@ func (acct *AccountView) Split(n int) error { {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.dirlist, ui.BORDER_RIGHT, acct.uiConf)).Span(2, 1) acct.grid.AddChild(ui.NewBordered(acct.msglist, ui.BORDER_BOTTOM, acct.uiConf)).At(0, 1) - - if acct.msglist.Empty() { - acct.grid.AddChild(ui.NewFill(' ', tcell.StyleDefault)).At(1, 1) - ui.Invalidate() - return nil - } - - msg, err := acct.SelectedMessage() - if err != nil { - return fmt.Errorf("could not create split: %w", err) - } - acct.splitUid = msg.Uid - 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 - } - acct.split = NewMessageViewer(acct, view) - acct.grid.AddChild(acct.split).At(1, 1) - }) - ui.Invalidate() + acct.split = NewMessageViewer(acct, nil) + acct.grid.AddChild(acct.split).At(1, 1) + acct.updateSplitView(acct.msglist.Selected()) return nil } // 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) error { - if n == 0 { - acct.closeSplit() + acct.SetSplitSize(n) + if acct.splitDir == "vsplit" || n == 0 { return nil } - 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_EXACT, Size: 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.dirlist, ui.BORDER_RIGHT, acct.uiConf)).At(0, 0) acct.grid.AddChild(ui.NewBordered(acct.msglist, ui.BORDER_RIGHT, acct.uiConf)).At(0, 1) - - if acct.msglist.Empty() { - acct.grid.AddChild(ui.NewFill(' ', tcell.StyleDefault)).At(0, 2) - ui.Invalidate() - return nil - } - - msg, err := acct.SelectedMessage() - if err != nil { - return fmt.Errorf("could not create split: %w", err) - } - acct.splitUid = msg.Uid - - 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 - } - acct.split = NewMessageViewer(acct, view) - acct.grid.AddChild(acct.split).At(0, 2) - }) - ui.Invalidate() + acct.split = NewMessageViewer(acct, nil) + acct.grid.AddChild(acct.split).At(0, 2) + acct.updateSplitView(acct.msglist.Selected()) return nil } diff --git a/widgets/msgviewer.go b/widgets/msgviewer.go index 0c72fa79..29ad0a83 100644 --- a/widgets/msgviewer.go +++ b/widgets/msgviewer.go @@ -48,6 +48,12 @@ type PartSwitcher struct { func NewMessageViewer( acct *AccountView, msg lib.MessageView, ) *MessageViewer { + if msg == nil { + return &MessageViewer{ + acct: acct, + err: fmt.Errorf("(no message selected)"), + } + } hf := HeaderLayoutFilter{ layout: HeaderLayout(config.Viewer.HeaderLayout), keep: func(msg *models.MessageInfo, header string) bool { |