msgstore: add marking functionality
This commit is contained in:
parent
3e535f49b3
commit
cf43066d5b
1 changed files with 127 additions and 4 deletions
131
lib/msgstore.go
131
lib/msgstore.go
|
@ -21,6 +21,11 @@ type MessageStore struct {
|
||||||
bodyCallbacks map[uint32][]func(io.Reader)
|
bodyCallbacks map[uint32][]func(io.Reader)
|
||||||
headerCallbacks map[uint32][]func(*types.MessageInfo)
|
headerCallbacks map[uint32][]func(*types.MessageInfo)
|
||||||
|
|
||||||
|
//marking
|
||||||
|
marked map[uint32]struct{}
|
||||||
|
visualStartUid uint32
|
||||||
|
visualMarkMode bool
|
||||||
|
|
||||||
// Search/filter results
|
// Search/filter results
|
||||||
results []uint32
|
results []uint32
|
||||||
resultIndex int
|
resultIndex int
|
||||||
|
@ -51,6 +56,7 @@ func NewMessageStore(worker *types.Worker,
|
||||||
Messages: make(map[uint32]*models.MessageInfo),
|
Messages: make(map[uint32]*models.MessageInfo),
|
||||||
|
|
||||||
selected: 0,
|
selected: 0,
|
||||||
|
marked: make(map[uint32]struct{}),
|
||||||
bodyCallbacks: make(map[uint32][]func(io.Reader)),
|
bodyCallbacks: make(map[uint32][]func(io.Reader)),
|
||||||
headerCallbacks: make(map[uint32][]func(*types.MessageInfo)),
|
headerCallbacks: make(map[uint32][]func(*types.MessageInfo)),
|
||||||
|
|
||||||
|
@ -223,6 +229,7 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
|
||||||
toDelete[uid] = nil
|
toDelete[uid] = nil
|
||||||
delete(store.Messages, uid)
|
delete(store.Messages, uid)
|
||||||
delete(store.Deleted, uid)
|
delete(store.Deleted, uid)
|
||||||
|
delete(store.marked, uid)
|
||||||
}
|
}
|
||||||
uids := make([]uint32, len(store.uids)-len(msg.Uids))
|
uids := make([]uint32, len(store.uids)-len(msg.Uids))
|
||||||
j := 0
|
j := 0
|
||||||
|
@ -345,12 +352,114 @@ func (store *MessageStore) SelectedIndex() int {
|
||||||
func (store *MessageStore) Select(index int) {
|
func (store *MessageStore) Select(index int) {
|
||||||
uids := store.Uids()
|
uids := store.Uids()
|
||||||
store.selected = index
|
store.selected = index
|
||||||
for ; store.selected < 0; store.selected = len(uids) + store.selected {
|
if store.selected < 0 {
|
||||||
/* This space deliberately left blank */
|
store.selected = len(uids) - 1
|
||||||
}
|
} else if store.selected > len(uids) {
|
||||||
if store.selected > len(uids) {
|
|
||||||
store.selected = len(uids)
|
store.selected = len(uids)
|
||||||
}
|
}
|
||||||
|
store.updateVisual()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark sets the marked state on a MessageInfo
|
||||||
|
func (store *MessageStore) Mark(uid uint32) {
|
||||||
|
if store.visualMarkMode {
|
||||||
|
// visual mode has override, bogus input from user
|
||||||
|
return
|
||||||
|
}
|
||||||
|
store.marked[uid] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmark removes the marked state on a MessageInfo
|
||||||
|
func (store *MessageStore) Unmark(uid uint32) {
|
||||||
|
if store.visualMarkMode {
|
||||||
|
// user probably wanted to clear the visual marking
|
||||||
|
store.ClearVisualMark()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(store.marked, uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleMark toggles the marked state on a MessageInfo
|
||||||
|
func (store *MessageStore) ToggleMark(uid uint32) {
|
||||||
|
if store.visualMarkMode {
|
||||||
|
// visual mode has override, bogus input from user
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if store.IsMarked(uid) {
|
||||||
|
store.Unmark(uid)
|
||||||
|
} else {
|
||||||
|
store.Mark(uid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resetMark removes the marking from all messages
|
||||||
|
func (store *MessageStore) resetMark() {
|
||||||
|
store.marked = make(map[uint32]struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
//IsMarked checks whether a MessageInfo has been marked
|
||||||
|
func (store *MessageStore) IsMarked(uid uint32) bool {
|
||||||
|
_, marked := store.marked[uid]
|
||||||
|
return marked
|
||||||
|
}
|
||||||
|
|
||||||
|
//ToggleVisualMark enters or leaves the visual marking mode
|
||||||
|
func (store *MessageStore) ToggleVisualMark() {
|
||||||
|
store.visualMarkMode = !store.visualMarkMode
|
||||||
|
switch store.visualMarkMode {
|
||||||
|
case true:
|
||||||
|
// just entered visual mode, reset whatever marking was already done
|
||||||
|
store.resetMark()
|
||||||
|
store.visualStartUid = store.Selected().Uid
|
||||||
|
store.marked[store.visualStartUid] = struct{}{}
|
||||||
|
case false:
|
||||||
|
// visual mode ended, nothing to do
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ClearVisualMark leaves the visual marking mode and resets any marking
|
||||||
|
func (store *MessageStore) ClearVisualMark() {
|
||||||
|
store.resetMark()
|
||||||
|
store.visualMarkMode = false
|
||||||
|
store.visualStartUid = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marked returns the uids of all marked messages
|
||||||
|
func (store *MessageStore) Marked() []uint32 {
|
||||||
|
marked := make([]uint32, len(store.marked))
|
||||||
|
i := 0
|
||||||
|
for uid := range store.marked {
|
||||||
|
marked[i] = uid
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return marked
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *MessageStore) updateVisual() {
|
||||||
|
if !store.visualMarkMode {
|
||||||
|
// nothing to do
|
||||||
|
return
|
||||||
|
}
|
||||||
|
startIdx := store.visualStartIdx()
|
||||||
|
if startIdx < 0 {
|
||||||
|
// something deleted the startuid, abort the marking process
|
||||||
|
store.ClearVisualMark()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uidLen := len(store.Uids())
|
||||||
|
// store.selected is the inverted form of the actual array
|
||||||
|
selectedIdx := uidLen - store.selected - 1
|
||||||
|
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{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) NextPrev(delta int) {
|
func (store *MessageStore) NextPrev(delta int) {
|
||||||
|
@ -365,6 +474,7 @@ func (store *MessageStore) NextPrev(delta int) {
|
||||||
if store.selected >= len(uids) {
|
if store.selected >= len(uids) {
|
||||||
store.selected = len(uids) - 1
|
store.selected = len(uids) - 1
|
||||||
}
|
}
|
||||||
|
store.updateVisual()
|
||||||
nextResultIndex := len(store.results) - store.resultIndex - 2*delta
|
nextResultIndex := len(store.results) - store.resultIndex - 2*delta
|
||||||
if nextResultIndex < 0 || nextResultIndex >= len(store.results) {
|
if nextResultIndex < 0 || nextResultIndex >= len(store.results) {
|
||||||
return
|
return
|
||||||
|
@ -406,6 +516,9 @@ func (store *MessageStore) ApplyFilter(results []uint32) {
|
||||||
store.results = results
|
store.results = results
|
||||||
store.filter = true
|
store.filter = true
|
||||||
store.update()
|
store.update()
|
||||||
|
// any marking is now invalid
|
||||||
|
// TODO: could save that probably
|
||||||
|
store.ClearVisualMark()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) ApplyClear() {
|
func (store *MessageStore) ApplyClear() {
|
||||||
|
@ -457,3 +570,13 @@ func (store *MessageStore) Sort(criteria []*types.SortCriterion, cb func()) {
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns the index of needle in haystack or -1 if not found
|
||||||
|
func (store *MessageStore) visualStartIdx() int {
|
||||||
|
for idx, u := range store.Uids() {
|
||||||
|
if u == store.visualStartUid {
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue