Eric Bower
·
29 Nov 24
notifications.go
1package notifications
2
3import (
4 "fmt"
5
6 "github.com/charmbracelet/bubbles/viewport"
7 tea "github.com/charmbracelet/bubbletea"
8 "github.com/charmbracelet/glamour"
9 "github.com/picosh/pico/db"
10 "github.com/picosh/pico/tui/common"
11 "github.com/picosh/pico/tui/pages"
12)
13
14func NotificationsView(dbpool db.DB, userID string, w int) string {
15 pass, err := dbpool.UpsertToken(userID, "pico-rss")
16 if err != nil {
17 return err.Error()
18 }
19 url := fmt.Sprintf("https://auth.pico.sh/rss/%s", pass)
20 md := fmt.Sprintf(`We provide a special RSS feed for all pico users where we can send
21user-specific notifications. This is where we will send pico+
22expiration notices, among other alerts. To be clear, this is
23optional but **highly** recommended.
24
25Add this URL to your RSS feed reader:
26
27%s
28
29## Using our [rss-to-email](https://pico.sh/feeds) service
30
31Create a feeds file (e.g. pico.txt):`, url)
32
33 md += "\n```\n"
34 md += fmt.Sprintf(`=: email rss@myemail.com
35=: digest_interval 1day
36=> %s
37`, url)
38 md += "\n```\n"
39 md += "Then copy the file to us:\n"
40 md += "```\nrsync pico.txt feeds.pico.sh:/\n```"
41
42 r, _ := glamour.NewTermRenderer(
43 // detect background color and pick either the default dark or light theme
44 glamour.WithAutoStyle(),
45 glamour.WithWordWrap(w-20),
46 )
47 out, err := r.Render(md)
48 if err != nil {
49 return err.Error()
50 }
51 return out
52}
53
54// Model holds the state of the username UI.
55type Model struct {
56 shared *common.SharedModel
57
58 Done bool // true when it's time to exit this view
59 Quit bool // true when the user wants to quit the whole program
60
61 viewport viewport.Model
62}
63
64func headerHeight(shrd *common.SharedModel) int {
65 return shrd.HeaderHeight
66}
67
68func headerWidth(w int) int {
69 return w - 2
70}
71
72func NewModel(shared *common.SharedModel) Model {
73 hh := headerHeight(shared)
74 ww := headerWidth(shared.Width)
75 viewport := viewport.New(ww, shared.Height-hh)
76 viewport.YPosition = hh
77 if shared.User != nil {
78 viewport.SetContent(NotificationsView(shared.Dbpool, shared.User.ID, ww))
79 }
80
81 return Model{
82 shared: shared,
83
84 Done: false,
85 Quit: false,
86 viewport: viewport,
87 }
88}
89
90func (m Model) Init() tea.Cmd {
91 return nil
92}
93
94func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
95 switch msg := msg.(type) {
96 case tea.WindowSizeMsg:
97 m.viewport.Width = headerWidth(msg.Width)
98 hh := headerHeight(m.shared)
99 m.viewport.Height = msg.Height - hh
100
101 case tea.KeyMsg:
102 switch msg.String() {
103 case "q", "esc":
104 return m, pages.Navigate(pages.MenuPage)
105 }
106 }
107
108 var cmd tea.Cmd
109 m.viewport, cmd = m.viewport.Update(msg)
110 return m, cmd
111}
112
113func (m Model) View() string {
114 return m.viewport.View()
115}