Eric Bower
·
01 Nov 24
plus.go
1package plus
2
3import (
4 "fmt"
5 "net/url"
6
7 "github.com/charmbracelet/bubbles/viewport"
8 tea "github.com/charmbracelet/bubbletea"
9 "github.com/charmbracelet/glamour"
10 "github.com/picosh/pico/tui/common"
11 "github.com/picosh/pico/tui/pages"
12)
13
14func PlusView(username string, w int) string {
15 paymentLink := "https://auth.pico.sh/checkout"
16 url := fmt.Sprintf("%s/%s", paymentLink, url.QueryEscape(username))
17 md := fmt.Sprintf(`Signup to get premium access
18
19## $2/month (billed annually)
20
21- tuns
22 - full access
23- pages
24 - full access
25 - per-site analytics
26- prose
27 - increased storage limits
28 - blog analytics
29- docker registry
30 - full access
31- 10GB total storage
32
33There are a few ways to purchase a membership. We try our best to
34provide immediate access to <code>pico+</code> regardless of payment
35method.
36
37## Online Payment (credit card, paypal)
38
39%s
40
41## Snail Mail
42
43Send cash (USD) or check to:
44- pico.sh LLC
45- 206 E Huron St STE 103
46- Ann Arbor MI 48104
47
48## Notes
49
50Have any questions not covered here? [Email](mailto:hello@pico.sh)
51us or join [IRC](https://pico.sh/irc), we will promptly respond.
52
53We do not maintain active subscriptions for pico+.
54Every year you must pay again. We do not take monthly payments, you
55must pay for a year up-front. Pricing is subject to change because
56we plan on continuing to include more services as we build them.`, url)
57
58 r, _ := glamour.NewTermRenderer(
59 // detect background color and pick either the default dark or light theme
60 glamour.WithAutoStyle(),
61 glamour.WithWordWrap(w-20),
62 )
63 out, _ := r.Render(md)
64 return out
65}
66
67// Model holds the state of the username UI.
68type Model struct {
69 shared common.SharedModel
70 viewport viewport.Model
71}
72
73func headerHeight(shrd common.SharedModel) int {
74 return shrd.HeaderHeight
75}
76
77func headerWidth(w int) int {
78 return w - 2
79}
80
81// NewModel returns a new username model in its initial state.
82func NewModel(shared common.SharedModel) Model {
83 hh := headerHeight(shared)
84 ww := headerWidth(shared.Width)
85 viewport := viewport.New(ww, shared.Height-hh)
86 if shared.User != nil {
87 viewport.SetContent(PlusView(shared.User.Name, ww))
88 }
89
90 return Model{
91 shared: shared,
92 viewport: viewport,
93 }
94}
95
96func (m Model) Init() tea.Cmd {
97 return nil
98}
99
100// Update is the Bubble Tea update loop.
101func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
102 switch msg := msg.(type) {
103 case tea.WindowSizeMsg:
104 m.viewport.Width = headerWidth(msg.Width)
105 hh := headerHeight(m.shared)
106 m.viewport.Height = msg.Height - hh
107 case tea.KeyMsg:
108 switch msg.String() {
109 case "q", "esc":
110 return m, pages.Navigate(pages.MenuPage)
111 }
112 }
113
114 var cmd tea.Cmd
115 m.viewport, cmd = m.viewport.Update(msg)
116 return m, cmd
117}
118
119// View renders current view from the model.
120func (m Model) View() string {
121 return m.viewport.View()
122}