-
Notifications
You must be signed in to change notification settings - Fork 0
/
storage_view.go
157 lines (135 loc) · 3.91 KB
/
storage_view.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package storage
import (
"errors"
"path"
"sync"
tb "github.com/nsf/termbox-go"
)
type ViewStorage struct {
filename string
itemBufferedCap int
itemLock sync.RWMutex
channelInfoLock sync.RWMutex
saved *SavedViewStorage
}
const (
CollapsedEntryState RssEntryState = iota
StandardEntryState
ExpandedEntryState
BrowserEntryState /* Temporary state; should get lowered immediately */
)
// ExpandEntryState returns the next largest entry state.
func ExpandEntryState(state RssEntryState) RssEntryState {
switch state {
case CollapsedEntryState:
return StandardEntryState
case StandardEntryState:
return ExpandedEntryState
default:
return BrowserEntryState
}
}
// CollapseEntryState returns the next smallest entry state.
func CollapseEntryState(state RssEntryState) RssEntryState {
switch state {
case BrowserEntryState:
return ExpandedEntryState
case ExpandedEntryState:
return StandardEntryState
default:
return CollapsedEntryState
}
}
func MakeViewStorage(key string, cap int) *ViewStorage {
s := &ViewStorage{
filename: "data/" + path.Clean(key),
itemBufferedCap: cap,
}
if !s.LoadFromStorage() {
s.saved = &SavedViewStorage{
ItemList: make([]*RssEntry, 0),
ChannelInfoMap: make(map[string]*ChannelInfo),
}
}
return s
}
func (s *ViewStorage) GetCopyOfSomeItems(n int) []RssEntry {
s.itemLock.RLock()
defer s.itemLock.RUnlock()
if len(s.saved.ItemList) < n {
n = len(s.saved.ItemList)
}
itemListCopy := make([]RssEntry, n)
for i := range itemListCopy {
itemListCopy[i] = *s.saved.ItemList[i]
}
return itemListCopy
}
func (s *ViewStorage) AddItem(item *RssEntry) {
s.itemLock.Lock()
defer s.itemLock.Unlock()
// Place new items at the BACK of the itemList.
s.saved.ItemList = append(s.saved.ItemList, item)
if len(s.saved.ItemList) > s.itemBufferedCap {
s.saved.ItemList = s.saved.ItemList[1:]
}
s.DumpToStorage()
}
func (s *ViewStorage) DeleteItem(index int) error {
s.itemLock.Lock()
defer s.itemLock.Unlock()
if index < 0 || len(s.saved.ItemList) <= index {
return errors.New("DeleteItem: Attempting to access out of range item")
}
s.saved.ItemList = append(s.saved.ItemList[:index], s.saved.ItemList[index+1:]...)
s.DumpToStorage()
return nil
}
func (s *ViewStorage) ChangeColor(index int) error {
s.itemLock.RLock()
defer s.itemLock.RUnlock()
s.channelInfoLock.Lock()
defer s.channelInfoLock.Unlock()
if index < 0 || len(s.saved.ItemList) <= index {
return errors.New("ChangeColor: Attempting to access out of range item")
}
if chInfo, ok := s.saved.ChannelInfoMap[s.saved.ItemList[index].FeedTitle]; ok {
// TODO(smklein): Better color selection than cycling!
chInfo.ChannelColor = (chInfo.ChannelColor + 1) % tb.ColorWhite
s.DumpToStorage()
return nil
} else {
return errors.New("ChangeColor: Channel not registered in channelInfoMap")
}
}
func (s *ViewStorage) ChangeItemState(index int, expand bool) (RssEntryState, string) {
s.itemLock.Lock()
defer s.itemLock.Unlock()
if index >= len(s.saved.ItemList) {
return 0, ""
}
if expand {
s.saved.ItemList[index].State = ExpandEntryState(s.saved.ItemList[index].State)
} else {
s.saved.ItemList[index].State = CollapseEntryState(s.saved.ItemList[index].State)
}
if s.saved.ItemList[index].State == BrowserEntryState {
// Edge case: When opening in browser, set to "non-browser"
// state immediately following the state change.
s.saved.ItemList[index].State = CollapseEntryState(s.saved.ItemList[index].State)
return BrowserEntryState, s.saved.ItemList[index].URL
}
return s.saved.ItemList[index].State, ""
}
func (s *ViewStorage) GetChannelInfo(title string) *ChannelInfo {
s.channelInfoLock.RLock()
defer s.channelInfoLock.RUnlock()
info := s.saved.ChannelInfoMap[title]
return info
}
func (s *ViewStorage) SetChannelInfo(title string, info *ChannelInfo) {
s.channelInfoLock.Lock()
defer s.channelInfoLock.Unlock()
s.saved.ChannelInfoMap[title] = info
s.DumpToStorage()
}