diff options
author | Koni Marti <koni.marti@gmail.com> | 2022-07-26 11:30:26 +0200 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2022-07-26 11:34:19 +0200 |
commit | 8f7695fde5cd84b7f6b8f3193270eda2fd62448c (patch) | |
tree | 27d2b58969b841f957fdbb8ad703f3d116eb5f9c /lib | |
parent | 3b90b3b0ddfd8134daa1d417bdd7acd8c39781b7 (diff) | |
download | aerc-8f7695fde5cd84b7f6b8f3193270eda2fd62448c.tar.gz |
msgstore: implement a uid-based architecture
Change the message store architecture from an index-based to a uid-based
one. Key advantage of this design approach is that no reselect mechanism
is required anymore since it comes with the design for free.
Fixes: https://todo.sr.ht/~rjarry/aerc/43
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Tested-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/msgstore.go | 127 |
1 files changed, 51 insertions, 76 deletions
diff --git a/lib/msgstore.go b/lib/msgstore.go index 34c26761..61a6dd44 100644 --- a/lib/msgstore.go +++ b/lib/msgstore.go @@ -20,7 +20,7 @@ type MessageStore struct { uids []uint32 Threads []*types.Thread - selected int + selectedUid uint32 reselect *models.MessageInfo bodyCallbacks map[uint32][]func(*types.FullMessage) headerCallbacks map[uint32][]func(*types.MessageInfo) @@ -57,6 +57,8 @@ type MessageStore struct { dirInfoUpdateDelay time.Duration } +const MagicUid = 0xFFFFFFFF + func NewMessageStore(worker *types.Worker, dirInfo *models.DirectoryInfo, defaultSortCriteria []*types.SortCriterion, @@ -75,7 +77,7 @@ func NewMessageStore(worker *types.Worker, DirInfo: *dirInfo, Messages: make(map[uint32]*models.MessageInfo), - selected: 0, + selectedUid: MagicUid, marked: make(map[uint32]struct{}), bodyCallbacks: make(map[uint32][]func(*types.FullMessage)), headerCallbacks: make(map[uint32][]func(*types.MessageInfo)), @@ -197,9 +199,6 @@ func merge(to *models.MessageInfo, from *models.MessageInfo) { func (store *MessageStore) Update(msg types.WorkerMessage) { update := false directoryChange := false - if store.reselect == nil { - store.SetReselect(store.Selected()) - } switch msg := msg.(type) { case *types.DirectoryInfo: store.DirInfo = *msg.Info @@ -367,7 +366,6 @@ func (store *MessageStore) SetThreadedView(thread bool) { if store.threadedView { store.runThreadBuilder() } - store.Reselect() return } store.Sort(store.sortCriteria, nil) @@ -490,54 +488,20 @@ func (store *MessageStore) Uids() []uint32 { } func (store *MessageStore) Selected() *models.MessageInfo { - uids := store.Uids() - idx := len(uids) - store.selected - 1 - if len(uids) == 0 || idx < 0 || idx >= len(uids) { - return nil - } - return store.Messages[uids[idx]] -} - -func (store *MessageStore) SelectedIndex() int { - return store.selected + return store.Messages[store.selectedUid] } -func (store *MessageStore) Select(index int) { - l := len(store.Uids()) - switch { - case l+index < 0: - // negative index overruns length of list - store.selected = 0 - case index < 0: - // negative index, select from bottom - store.selected = l + index - case index >= l: - // index greater than length, select last - store.selected = l - 1 - default: - store.selected = index +func (store *MessageStore) SelectedUid() uint32 { + if store.selectedUid == MagicUid && len(store.Uids()) > 0 { + uids := store.Uids() + store.selectedUid = uids[len(uids)-1] } - store.updateVisual() + return store.selectedUid } -func (store *MessageStore) Reselect() { - if store.reselect == nil { - return - } - uid := store.reselect.Uid - newIdx := 0 - for idx, uidStore := range store.Uids() { - if uidStore == uid { - newIdx = len(store.Uids()) - idx - 1 - break - } - } - store.reselect = nil - store.Select(newIdx) -} - -func (store *MessageStore) SetReselect(info *models.MessageInfo) { - store.reselect = info +func (store *MessageStore) Select(uid uint32) { + store.selectedUid = uid + store.updateVisual() } // Mark sets the marked state on a MessageInfo @@ -648,15 +612,20 @@ func (store *MessageStore) updateVisual() { store.ClearVisualMark() return } - uidLen := len(store.Uids()) - // store.selected is the inverted form of the actual array - selectedIdx := uidLen - store.selected - 1 + + selectedIdx := store.FindIndexByUid(store.SelectedUid()) + if selectedIdx < 0 { + store.ClearVisualMark() + return + } + var visUids []uint32 if selectedIdx > startIdx { visUids = store.Uids()[startIdx : selectedIdx+1] } else { visUids = store.Uids()[selectedIdx : startIdx+1] } + store.resetMark() for _, uid := range visUids { store.marked[uid] = struct{}{} @@ -675,20 +644,31 @@ func (store *MessageStore) NextPrev(delta int) { if len(uids) == 0 { return } - idx := store.SelectedIndex() + delta - if idx < 0 { - store.Select(0) - } else { - store.Select(idx) + + uid := store.SelectedUid() + + newIdx := store.FindIndexByUid(uid) + if newIdx < 0 { + store.Select(uids[len(uids)-1]) + } + + newIdx -= delta + if newIdx >= len(uids) { + newIdx = len(uids) - 1 + } else if newIdx < 0 { + newIdx = 0 } + + store.Select(uids[newIdx]) + store.updateVisual() + nextResultIndex := len(store.results) - store.resultIndex - 2*delta if nextResultIndex < 0 || nextResultIndex >= len(store.results) { return } nextResultUid := store.results[nextResultIndex] - selectedUid := uids[len(uids)-store.selected-1] - if nextResultUid == selectedUid { + if nextResultUid == store.SelectedUid() { store.resultIndex += delta } } @@ -734,21 +714,12 @@ func (store *MessageStore) SetFilter(args []string) { } func (store *MessageStore) ApplyClear() { - if store.reselect == nil { - store.SetReselect(store.Selected()) - } store.filter = []string{"filter"} store.results = nil if store.onFilterChange != nil { store.onFilterChange(store) } - cb := func(msg types.WorkerMessage) { - switch msg.(type) { - case *types.Done: - store.Reselect() - } - } - store.Sort(nil, cb) + store.Sort(nil, nil) } func (store *MessageStore) nextPrevResult(delta int) { @@ -762,13 +733,7 @@ func (store *MessageStore) nextPrevResult(delta int) { if store.resultIndex < 0 { store.resultIndex = len(store.results) - 1 } - uids := store.Uids() - for i, uid := range uids { - if store.results[len(store.results)-store.resultIndex-1] == uid { - store.Select(len(uids) - i - 1) - break - } - } + store.Select(store.results[len(store.results)-store.resultIndex-1]) store.update() } @@ -826,3 +791,13 @@ func (store *MessageStore) visualStartIdx() int { } return -1 } + +// FindIndexByUid returns the index in store.Uids() or -1 if not found +func (store *MessageStore) FindIndexByUid(uid uint32) int { + for idx, u := range store.Uids() { + if u == uid { + return idx + } + } + return -1 +} |