Eric Bower
·
2025-03-17
menu.go
1package tui
2
3import (
4 "git.sr.ht/~rockorager/vaxis"
5 "git.sr.ht/~rockorager/vaxis/vxfw"
6 "git.sr.ht/~rockorager/vaxis/vxfw/list"
7 "git.sr.ht/~rockorager/vaxis/vxfw/text"
8 "github.com/picosh/pico/pkg/db"
9)
10
11var menuChoices = []string{
12 "pubkeys",
13 "tokens",
14 "logs",
15 "analytics",
16 "tuns",
17 "pico+",
18 "chat",
19}
20
21type LoadedUsageStats struct{}
22
23type MenuPage struct {
24 shared *SharedModel
25
26 list list.Dynamic
27 features *FeaturesList
28 stats *db.UserStats
29}
30
31func getMenuWidget(i uint, cursor uint) vxfw.Widget {
32 if int(i) >= len(menuChoices) {
33 return nil
34 }
35 var style vaxis.Style
36 if i == cursor {
37 style.Attribute = vaxis.AttrReverse
38 }
39 content := menuChoices[i]
40 return &text.Text{
41 Content: content,
42 Style: style,
43 }
44}
45
46func NewMenuPage(shrd *SharedModel) *MenuPage {
47 m := &MenuPage{shared: shrd}
48 m.list = list.Dynamic{Builder: getMenuWidget, DrawCursor: true}
49 m.features = NewFeaturesList(shrd)
50 return m
51}
52
53func loadChat(shrd *SharedModel) {
54 sp := &SenpaiCmd{
55 Shared: shrd,
56 }
57 _ = sp.Run()
58}
59
60func (m *MenuPage) fetchUsageStats() error {
61 stats, err := m.shared.Dbpool.FindUserStats(m.shared.User.ID)
62 if err != nil {
63 return err
64 }
65 m.stats = stats
66 return nil
67}
68
69func (m *MenuPage) HandleEvent(ev vaxis.Event, phase vxfw.EventPhase) (vxfw.Command, error) {
70 switch msg := ev.(type) {
71 case PageIn:
72 _ = m.fetchUsageStats()
73 cmd, _ := m.features.HandleEvent(vxfw.Init{}, phase)
74 return vxfw.BatchCmd([]vxfw.Command{
75 cmd,
76 vxfw.FocusWidgetCmd(&m.list),
77 }), nil
78 case vaxis.Key:
79 if msg.Matches(vaxis.KeyEnter) {
80 choice := menuChoices[m.list.Cursor()]
81 m.shared.App.PostEvent(Navigate{To: choice})
82 }
83 }
84 return nil, nil
85}
86
87func (m *MenuPage) Draw(ctx vxfw.DrawContext) (vxfw.Surface, error) {
88 info, _ := NewUserInfo(m.shared).Draw(ctx)
89
90 brd := NewBorder(&m.list)
91 brd.Label = "menu"
92 brd.Style = vaxis.Style{Foreground: oj}
93 menuSurf, _ := brd.Draw(vxfw.DrawContext{
94 Characters: ctx.Characters,
95 Max: vxfw.Size{
96 Width: 30,
97 Height: uint16(len(menuChoices)) + 3,
98 },
99 })
100
101 services, _ := NewServicesList(m.shared.PlusFeatureFlag).Draw(ctx)
102 features, _ := m.features.Draw(ctx)
103
104 leftPane := NewGroupStack([]vxfw.Surface{
105 menuSurf,
106 info,
107 services,
108 })
109 leftSurf, _ := leftPane.Draw(ctx)
110
111 right := []vxfw.Surface{}
112 if len(m.features.features) > 0 {
113 right = append(right, features)
114 }
115
116 if m.stats != nil {
117 pages, _ := NewUsageInfo("pages", &m.stats.Pages).Draw(ctx)
118 prose, _ := NewUsageInfo("prose", &m.stats.Prose).Draw(ctx)
119 pastes, _ := NewUsageInfo("pastes", &m.stats.Pastes).Draw(ctx)
120 feeds, _ := NewUsageInfo("rss-to-email", &m.stats.Feeds).Draw(ctx)
121 right = append(right,
122 pages,
123 prose,
124 pastes,
125 feeds,
126 )
127 }
128 rightPane := NewGroupStack(right)
129 rightSurf, _ := rightPane.Draw(ctx)
130
131 root := vxfw.NewSurface(ctx.Max.Width, ctx.Max.Height, m)
132 root.AddChild(0, 0, leftSurf)
133 root.AddChild(30, 0, rightSurf)
134 return root, nil
135}