threading: refactor reselect logic

This patch refactors reselection of a message during certain operations
(searching, filtering, clearing, deleting, moving, new message arrival).
The addition of server-side filtering for threaded views broke the
existing reselection logic.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Tim Culverhouse 2022-07-05 14:48:41 -05:00 committed by Robin Jarry
parent c2f4404fca
commit a953e4dbe9
4 changed files with 27 additions and 28 deletions

View File

@ -52,9 +52,8 @@ func (Clear) Execute(aerc *widgets.Aerc, args []string) error {
if clearSelected { if clearSelected {
defer store.Select(0) defer store.Select(0)
} else { } else {
defer store.Reselect(store.Selected()) store.SetReselect(store.Selected())
} }
store.ApplyClear() store.ApplyClear()
acct.SetStatus(statusline.SearchFilterClear()) acct.SetStatus(statusline.SearchFilterClear())

View File

@ -34,7 +34,7 @@ func (ToggleThreads) Execute(aerc *widgets.Aerc, args []string) error {
if err != nil { if err != nil {
return err return err
} }
defer store.Reselect(store.Selected()) store.SetReselect(store.Selected())
store.SetThreadedView(!store.ThreadedView()) store.SetThreadedView(!store.ThreadedView())
acct.SetStatus(statusline.Threading(store.ThreadedView())) acct.SetStatus(statusline.Threading(store.ThreadedView()))
acct.Messages().Invalidate() acct.Messages().Invalidate()

View File

@ -21,6 +21,7 @@ type MessageStore struct {
Threads []*types.Thread Threads []*types.Thread
selected int selected int
reselect *models.MessageInfo
bodyCallbacks map[uint32][]func(*types.FullMessage) bodyCallbacks map[uint32][]func(*types.FullMessage)
headerCallbacks map[uint32][]func(*types.MessageInfo) headerCallbacks map[uint32][]func(*types.MessageInfo)
@ -196,6 +197,9 @@ func merge(to *models.MessageInfo, from *models.MessageInfo) {
func (store *MessageStore) Update(msg types.WorkerMessage) { func (store *MessageStore) Update(msg types.WorkerMessage) {
update := false update := false
directoryChange := false directoryChange := false
if store.reselect == nil {
store.SetReselect(store.Selected())
}
switch msg := msg.(type) { switch msg := msg.(type) {
case *types.DirectoryInfo: case *types.DirectoryInfo:
store.DirInfo = *msg.Info store.DirInfo = *msg.Info
@ -363,6 +367,7 @@ func (store *MessageStore) SetThreadedView(thread bool) {
if store.threadedView { if store.threadedView {
store.runThreadBuilder() store.runThreadBuilder()
} }
store.Reselect()
return return
} }
store.Sort(store.sortCriteria, nil) store.Sort(store.sortCriteria, nil)
@ -508,11 +513,11 @@ func (store *MessageStore) Select(index int) {
store.updateVisual() store.updateVisual()
} }
func (store *MessageStore) Reselect(info *models.MessageInfo) { func (store *MessageStore) Reselect() {
if info == nil { if store.reselect == nil {
return return
} }
uid := info.Uid uid := store.reselect.Uid
newIdx := 0 newIdx := 0
for idx, uidStore := range store.Uids() { for idx, uidStore := range store.Uids() {
if uidStore == uid { if uidStore == uid {
@ -520,9 +525,14 @@ func (store *MessageStore) Reselect(info *models.MessageInfo) {
break break
} }
} }
store.reselect = nil
store.Select(newIdx) store.Select(newIdx)
} }
func (store *MessageStore) SetReselect(info *models.MessageInfo) {
store.reselect = info
}
// Mark sets the marked state on a MessageInfo // Mark sets the marked state on a MessageInfo
func (store *MessageStore) Mark(uid uint32) { func (store *MessageStore) Mark(uid uint32) {
if store.visualMarkMode { if store.visualMarkMode {
@ -718,11 +728,21 @@ func (store *MessageStore) SetFilter(args []string) {
} }
func (store *MessageStore) ApplyClear() { func (store *MessageStore) ApplyClear() {
if store.reselect == nil {
store.SetReselect(store.Selected())
}
store.filter = []string{"filter"} store.filter = []string{"filter"}
store.results = nil
if store.onFilterChange != nil { if store.onFilterChange != nil {
store.onFilterChange(store) store.onFilterChange(store)
} }
store.Sort(nil, nil) cb := func(msg types.WorkerMessage) {
switch msg.(type) {
case *types.Done:
store.Reselect()
}
}
store.Sort(nil, cb)
} }
func (store *MessageStore) nextPrevResult(delta int) { func (store *MessageStore) nextPrevResult(delta int) {

View File

@ -345,27 +345,7 @@ func (ml *MessageList) storeUpdate(store *lib.MessageStore) {
if ml.Store() != store { if ml.Store() != store {
return return
} }
uids := store.Uids() store.Reselect()
if len(uids) > 0 {
// When new messages come in, advance the cursor accordingly
// Note that this assumes new messages are appended to the top, which
// isn't necessarily true once we implement SORT... ideally we'd look
// for the previously selected UID.
if len(uids) > ml.nmsgs && ml.nmsgs != 0 {
for i := 0; i < len(uids)-ml.nmsgs; i++ {
ml.Store().Next()
}
}
if len(uids) < ml.nmsgs && ml.nmsgs != 0 {
for i := 0; i < ml.nmsgs-len(uids); i++ {
ml.Store().Prev()
}
}
ml.nmsgs = len(uids)
}
ml.Invalidate()
} }
func (ml *MessageList) SetStore(store *lib.MessageStore) { func (ml *MessageList) SetStore(store *lib.MessageStore) {