Eric Bower
·
2025-03-17
info.go
1package tui
2
3import (
4 "fmt"
5 "time"
6
7 "git.sr.ht/~rockorager/vaxis"
8 "git.sr.ht/~rockorager/vaxis/vxfw"
9 "github.com/picosh/pico/pkg/db"
10)
11
12type UsageInfo struct {
13 stats *db.UserServiceStats
14 Label string
15}
16
17func NewUsageInfo(label string, stats *db.UserServiceStats) *UsageInfo {
18 return &UsageInfo{Label: label, stats: stats}
19}
20
21func (m *UsageInfo) HandleEvent(ev vaxis.Event, phase vxfw.EventPhase) (vxfw.Command, error) {
22 return nil, nil
23}
24
25func (m *UsageInfo) Draw(ctx vxfw.DrawContext) (vxfw.Surface, error) {
26 info := NewKv(m.getKv())
27 brd := NewBorder(info)
28 brd.Label = m.Label
29 brd.Style = vaxis.Style{Foreground: purp}
30 return brd.Draw(vxfw.DrawContext{
31 Characters: ctx.Characters,
32 Max: vxfw.Size{
33 Width: 30,
34 Height: 3 + 3,
35 },
36 })
37}
38
39func (m *UsageInfo) getKv() []Kv {
40 label := "posts"
41 if m.Label == "pages" {
42 label = "sites"
43 }
44 kv := []Kv{
45 {Key: label, Value: fmt.Sprintf("%d", m.stats.Num)},
46 {Key: "oldest", Value: m.stats.FirstCreatedAt.Format(time.DateOnly)},
47 {Key: "newest", Value: m.stats.LastestCreatedAt.Format(time.DateOnly)},
48 }
49 return kv
50}
51
52type UserInfo struct {
53 shared *SharedModel
54}
55
56func NewUserInfo(shrd *SharedModel) *UserInfo {
57 return &UserInfo{shrd}
58}
59
60func (m *UserInfo) HandleEvent(ev vaxis.Event, phase vxfw.EventPhase) (vxfw.Command, error) {
61 return nil, nil
62}
63
64func (m *UserInfo) Draw(ctx vxfw.DrawContext) (vxfw.Surface, error) {
65 features := NewKv(m.getKv())
66 brd := NewBorder(features)
67 brd.Label = "info"
68 brd.Style = vaxis.Style{Foreground: purp}
69 h := 1
70 if m.shared.PlusFeatureFlag != nil {
71 h += 1
72 }
73 return brd.Draw(vxfw.DrawContext{
74 Characters: ctx.Characters,
75 Max: vxfw.Size{
76 Width: 30,
77 Height: uint16(h) + 3,
78 },
79 })
80}
81
82func (m *UserInfo) getKv() []Kv {
83 createdAt := m.shared.User.CreatedAt.Format(time.DateOnly)
84 kv := []Kv{
85 {Key: "joined", Value: createdAt},
86 }
87
88 if m.shared.PlusFeatureFlag != nil {
89 expiresAt := m.shared.PlusFeatureFlag.ExpiresAt.Format(time.DateOnly)
90 kv = append(kv, Kv{Key: "pico+ expires", Value: expiresAt})
91 }
92
93 return kv
94}
95
96type FeaturesList struct {
97 shared *SharedModel
98 features []*db.FeatureFlag
99 err error
100}
101
102func NewFeaturesList(shrd *SharedModel) *FeaturesList {
103 return &FeaturesList{shared: shrd}
104}
105
106func (m *FeaturesList) HandleEvent(ev vaxis.Event, phase vxfw.EventPhase) (vxfw.Command, error) {
107 switch ev.(type) {
108 case vxfw.Init:
109 m.err = m.fetchFeatures()
110 return vxfw.RedrawCmd{}, nil
111 }
112 return nil, nil
113}
114
115func (m *FeaturesList) Draw(ctx vxfw.DrawContext) (vxfw.Surface, error) {
116 features := NewKv(m.getFeaturesKv())
117 brd := NewBorder(features)
118 brd.Label = "features"
119 brd.Style = vaxis.Style{Foreground: purp}
120 return brd.Draw(vxfw.DrawContext{
121 Characters: ctx.Characters,
122 Max: vxfw.Size{
123 Width: 30,
124 Height: uint16(len(m.features)) + 4,
125 },
126 })
127}
128
129func (m *FeaturesList) fetchFeatures() error {
130 features, err := m.shared.Dbpool.FindFeaturesForUser(m.shared.User.ID)
131 m.features = features
132 return err
133}
134
135func (m *FeaturesList) getFeaturesKv() []Kv {
136 kv := []Kv{
137 {
138 Key: "name",
139 Value: "expires at",
140 Style: vaxis.Style{
141 UnderlineColor: purp,
142 UnderlineStyle: vaxis.UnderlineDashed,
143 Foreground: purp,
144 },
145 },
146 }
147
148 for _, feature := range m.features {
149 kv = append(kv, Kv{Key: feature.Name, Value: feature.ExpiresAt.Format(time.DateOnly)})
150 }
151
152 return kv
153}
154
155type ServicesList struct {
156 ff *db.FeatureFlag
157}
158
159func NewServicesList(ff *db.FeatureFlag) *ServicesList {
160 return &ServicesList{ff}
161}
162
163func (m *ServicesList) HandleEvent(ev vaxis.Event, phase vxfw.EventPhase) (vxfw.Command, error) {
164 return nil, nil
165}
166
167func (m *ServicesList) Draw(ctx vxfw.DrawContext) (vxfw.Surface, error) {
168 services := NewKv(m.getServiceKv())
169 brd := NewBorder(services)
170 brd.Label = "services"
171 brd.Style = vaxis.Style{Foreground: purp}
172 servicesHeight := 8
173 return brd.Draw(vxfw.DrawContext{
174 Characters: ctx.Characters,
175 Max: vxfw.Size{
176 Width: 30,
177 Height: uint16(servicesHeight) + 3,
178 },
179 })
180}
181
182func (m *ServicesList) getServiceKv() []Kv {
183 hasPlus := m.ff != nil
184 data := [][]string{
185 {"name", "status"},
186 {"prose", "active"},
187 {"pipe", "active"},
188 {"pastes", "active"},
189 {"rss-to-email", "active"},
190 }
191
192 if hasPlus {
193 data = append(
194 data,
195 []string{"pages", "active"},
196 []string{"tuns", "active"},
197 []string{"irc bouncer", "active"},
198 )
199 } else {
200 data = append(
201 data,
202 []string{"pages", "free tier"},
203 []string{"tuns", "pico+"},
204 []string{"irc bouncer", "pico+"},
205 )
206 }
207
208 kv := []Kv{}
209 for idx, d := range data {
210 value := d[1]
211 var style vaxis.Style
212 if idx == 0 {
213 style = vaxis.Style{
214 UnderlineColor: purp,
215 UnderlineStyle: vaxis.UnderlineDashed,
216 Foreground: purp,
217 }
218 } else if value == "active" {
219 style = vaxis.Style{Foreground: green}
220 } else if value == "free tier" {
221 style = vaxis.Style{Foreground: oj}
222 } else {
223 style = vaxis.Style{Foreground: red}
224 }
225
226 kv = append(kv, Kv{
227 Key: d[0],
228 Value: value,
229 Style: style,
230 })
231
232 }
233
234 return kv
235}