repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

pico / pkg / tui
Eric Bower  ·  2025-03-17

plus.go

  1package tui
  2
  3import (
  4	"fmt"
  5	"math"
  6	"net/url"
  7
  8	"git.sr.ht/~rockorager/vaxis"
  9	"git.sr.ht/~rockorager/vaxis/vxfw"
 10	"git.sr.ht/~rockorager/vaxis/vxfw/richtext"
 11)
 12
 13type PlusPage struct {
 14	shared *SharedModel
 15
 16	pager *Pager
 17}
 18
 19func NewPlusPage(shrd *SharedModel) *PlusPage {
 20	page := &PlusPage{
 21		shared: shrd,
 22	}
 23	page.pager = NewPager()
 24	return page
 25}
 26
 27func (m *PlusPage) HandleEvent(ev vaxis.Event, phase vxfw.EventPhase) (vxfw.Command, error) {
 28	switch ev.(type) {
 29	case PageIn:
 30		return vxfw.FocusWidgetCmd(m.pager), nil
 31	}
 32	return nil, nil
 33}
 34
 35func (m *PlusPage) header(ctx vxfw.DrawContext) vxfw.Surface {
 36	intro := richtext.New([]vaxis.Segment{
 37		{
 38			Text: "$2/mo\n",
 39			Style: vaxis.Style{
 40				UnderlineStyle: vaxis.UnderlineCurly,
 41				UnderlineColor: oj,
 42				Foreground:     oj,
 43			},
 44		},
 45		{
 46			Text: "(billed yearly)\n\n",
 47		},
 48
 49		{Text: "• tuns\n"},
 50		{Text: "  • per-site analytics\n"},
 51		{Text: "• pgs\n"},
 52		{Text: "  • per-site analytics\n"},
 53		{Text: "• prose\n"},
 54		{Text: "  • blog analytics\n"},
 55		{Text: "• irc bouncer\n"},
 56		{Text: "• 10GB total storage\n"},
 57	})
 58	brd := NewBorder(intro)
 59	brd.Label = "pico+"
 60	surf, _ := brd.Draw(ctx)
 61	return surf
 62}
 63
 64func (m *PlusPage) payment(ctx vxfw.DrawContext) vxfw.Surface {
 65	paymentLink := "https://auth.pico.sh/checkout"
 66	link := fmt.Sprintf("%s/%s", paymentLink, url.QueryEscape(m.shared.User.Name))
 67	header := vaxis.Style{Foreground: oj, UnderlineColor: oj, UnderlineStyle: vaxis.UnderlineDashed}
 68	pay := richtext.New([]vaxis.Segment{
 69		{Text: "You can use this same flow to add additional years to your membership, including if you are already a pico+ user.\n\n", Style: vaxis.Style{Foreground: green}},
 70
 71		{Text: "There are a few ways to purchase a membership. We try our best to provide immediate access to pico+ regardless of payment method.\n"},
 72
 73		{Text: "\nOnline payment\n\n", Style: header},
 74
 75		{Text: link + "\n", Style: vaxis.Style{Hyperlink: link}},
 76
 77		{Text: "\nSnail mail\n\n", Style: header},
 78
 79		{Text: "Send cash (USD) or check to:\n\n"},
 80		{Text: "• pico.sh LLC\n"},
 81		{Text: "• 206 E Huron St\n"},
 82		{Text: "• Ann Arbor MI 48104\n\n"},
 83		{Text: "Have any questions? Feel free to reach out:\n\n"},
 84		{Text: "• "}, {Text: "mailto:hello@pico.sh\n", Style: vaxis.Style{Hyperlink: "mailto:hello@pico.sh"}},
 85		{Text: "• "}, {Text: "https://pico.sh/irc\n", Style: vaxis.Style{Hyperlink: "https://pico.sh/irc"}},
 86	})
 87	brd := NewBorder(pay)
 88	brd.Label = "payment"
 89	surf, _ := brd.Draw(vxfw.DrawContext{
 90		Characters: ctx.Characters,
 91		Max:        vxfw.Size{Width: 50, Height: math.MaxUint16},
 92	})
 93	return surf
 94}
 95
 96func (m *PlusPage) notes(ctx vxfw.DrawContext) vxfw.Surface {
 97	wdgt := richtext.New([]vaxis.Segment{
 98		{Text: "We do not maintain active subscriptions. "},
 99		{Text: "Every year you must pay again. We do not take monthly payments, you must pay for a year up-front. Pricing is subject to change."},
100	})
101	brd := NewBorder(wdgt)
102	brd.Label = "notes"
103	surf, _ := brd.Draw(vxfw.DrawContext{
104		Characters: ctx.Characters,
105		Max:        vxfw.Size{Width: 50, Height: math.MaxUint16},
106	})
107	return surf
108}
109
110func (m *PlusPage) Draw(ctx vxfw.DrawContext) (vxfw.Surface, error) {
111	stack := NewGroupStack([]vxfw.Surface{
112		m.header(ctx),
113		m.notes(ctx),
114		m.payment(ctx),
115	})
116	stack.Gap = 1
117	surf, _ := stack.Draw(createDrawCtx(ctx, math.MaxUint16))
118	m.pager.Surface = surf
119	return m.pager.Draw(ctx)
120}