Antonio Mika
·
2025-04-30
signup.go
1package tui
2
3import (
4 "fmt"
5
6 "git.sr.ht/~rockorager/vaxis"
7 "git.sr.ht/~rockorager/vaxis/vxfw"
8 "git.sr.ht/~rockorager/vaxis/vxfw/button"
9 "git.sr.ht/~rockorager/vaxis/vxfw/richtext"
10 "git.sr.ht/~rockorager/vaxis/vxfw/text"
11 "github.com/picosh/pico/pkg/db"
12 "github.com/picosh/pico/pkg/pssh"
13 "github.com/picosh/utils"
14 "golang.org/x/crypto/ssh"
15)
16
17type SignupPage struct {
18 shared *SharedModel
19 focus string
20 err error
21
22 input *TextInput
23 btn *button.Button
24}
25
26func NewSignupPage(shrd *SharedModel) *SignupPage {
27 btn := button.New("SIGNUP", func() (vxfw.Command, error) { return nil, nil })
28 btn.Style = button.StyleSet{
29 Default: vaxis.Style{Background: grey},
30 Focus: vaxis.Style{Background: oj, Foreground: black},
31 }
32 input := NewTextInput("signup")
33 return &SignupPage{shared: shrd, btn: btn, input: input}
34}
35
36func (m *SignupPage) Footer() []Shortcut {
37 return []Shortcut{
38 {Shortcut: "tab", Text: "focus"},
39 {Shortcut: "enter", Text: "create user"},
40 }
41}
42
43func (m *SignupPage) createAccount(name string) (*db.User, error) {
44 if name == "" {
45 return nil, fmt.Errorf("name cannot be empty")
46 }
47 key := utils.KeyForKeyText(m.shared.Session.PublicKey())
48 return m.shared.Dbpool.RegisterUser(name, key, "")
49}
50
51func (m *SignupPage) CaptureEvent(ev vaxis.Event) (vxfw.Command, error) {
52 switch msg := ev.(type) {
53 case vaxis.Key:
54 if msg.Matches(vaxis.KeyEnter) {
55 user, err := m.createAccount(m.input.GetValue())
56 if err != nil {
57 m.err = err
58 return vxfw.RedrawCmd{}, nil
59 }
60
61 m.shared.User = user
62
63 pssh.SetUser(m.shared.Session, user)
64
65 m.shared.Logger = m.shared.Logger.With(
66 "user", user.Name,
67 "userId", user.ID,
68 )
69
70 pssh.SetLogger(m.shared.Session, m.shared.Logger)
71
72 m.shared.App.PostEvent(Navigate{To: HOME})
73 }
74 }
75 return nil, nil
76}
77
78func (m *SignupPage) HandleEvent(ev vaxis.Event, phase vxfw.EventPhase) (vxfw.Command, error) {
79 switch msg := ev.(type) {
80 case PageIn:
81 return m.input.FocusIn()
82 case vaxis.Key:
83 if msg.Matches(vaxis.KeyTab) {
84 if m.focus == "button" {
85 m.focus = "input"
86 return m.input.FocusIn()
87 }
88 m.focus = "button"
89 cmd, _ := m.input.FocusOut()
90 return vxfw.BatchCmd([]vxfw.Command{
91 cmd,
92 vxfw.FocusWidgetCmd(m.btn),
93 }), nil
94 }
95 }
96
97 return nil, nil
98}
99
100func (m *SignupPage) Draw(ctx vxfw.DrawContext) (vxfw.Surface, error) {
101 w := ctx.Max.Width
102 h := ctx.Max.Height
103
104 root := vxfw.NewSurface(w, h, m)
105
106 fp := ssh.FingerprintSHA256(m.shared.Session.PublicKey())
107 intro := richtext.New([]vaxis.Segment{
108 {Text: "Welcome to pico.sh's management TUI!\n\n"},
109 {Text: "By creating an account you get access to our pico services. We have free and paid services."},
110 {Text: " After you create an account, you can go to our docs site to get started:\n\n "},
111 {Text: "https://pico.sh/getting-started\n\n", Style: vaxis.Style{Hyperlink: "https://pico.sh/getting-started"}},
112 {Text: fmt.Sprintf("pubkey: %s\n\n", fp), Style: vaxis.Style{Foreground: purp}},
113 })
114 introSurf, _ := intro.Draw(ctx)
115 ah := 0
116 root.AddChild(0, ah, introSurf)
117 ah += int(introSurf.Size.Height)
118
119 inpSurf, _ := m.input.Draw(vxfw.DrawContext{
120 Characters: ctx.Characters,
121 Max: vxfw.Size{Width: ctx.Max.Width, Height: 4},
122 })
123 root.AddChild(0, ah, inpSurf)
124 ah += int(inpSurf.Size.Height)
125
126 btnSurf, _ := m.btn.Draw(vxfw.DrawContext{
127 Characters: ctx.Characters,
128 Max: vxfw.Size{Width: 10, Height: 1},
129 })
130 root.AddChild(0, ah, btnSurf)
131 ah += int(btnSurf.Size.Height)
132
133 if m.err != nil {
134 errTxt := text.New(m.err.Error())
135 errTxt.Style = vaxis.Style{Foreground: red}
136 errSurf, _ := errTxt.Draw(ctx)
137 root.AddChild(0, ah, errSurf)
138 }
139
140 return root, nil
141}