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