summaryrefslogtreecommitdiff
path: root/internal/client/ui/tosscreen/tosscreen.go
diff options
context:
space:
mode:
authorKyren223 <Kyren223@proton.me>2025-07-08 17:53:36 +0300
committerKyren223 <Kyren223@proton.me>2025-07-08 17:53:36 +0300
commita34919da2f3c3102434635276250cc4d398c8492 (patch)
tree827268e8f90be84cd8b38d6aa07682477f65cc91 /internal/client/ui/tosscreen/tosscreen.go
parent8362d835eed8f7f552a3aa433ea4f02dd1dbde88 (diff)
Refactored client side to comply with protocol changes, implemnted tos
screen model, still missing accept/decline and authentication
Diffstat (limited to 'internal/client/ui/tosscreen/tosscreen.go')
-rw-r--r--internal/client/ui/tosscreen/tosscreen.go332
1 files changed, 332 insertions, 0 deletions
diff --git a/internal/client/ui/tosscreen/tosscreen.go b/internal/client/ui/tosscreen/tosscreen.go
new file mode 100644
index 0000000..317a724
--- /dev/null
+++ b/internal/client/ui/tosscreen/tosscreen.go
@@ -0,0 +1,332 @@
+package tosscreen
+
+import (
+ "strings"
+
+ "github.com/charmbracelet/bubbles/viewport"
+ tea "github.com/charmbracelet/bubbletea"
+ "github.com/charmbracelet/glamour"
+ "github.com/charmbracelet/glamour/ansi"
+ "github.com/charmbracelet/lipgloss"
+
+ // "github.com/charmbracelet/glamour"
+ "github.com/kyren223/eko/internal/client/ui"
+ "github.com/kyren223/eko/internal/client/ui/colors"
+ "github.com/kyren223/eko/pkg/assert"
+)
+
+const MarginPercentage = 0.25
+
+var style = func() lipgloss.Style {
+ return lipgloss.NewStyle().
+ Border(lipgloss.ThickBorder()).
+ BorderBackground(colors.Background).
+ Background(colors.Background).
+ MarginBackground(colors.BackgroundDimmer).
+ Padding(0, 3).
+ Margin(1, int(float32(ui.Width)*MarginPercentage), 0)
+}
+
+type Model struct {
+ content string
+ vp viewport.Model
+}
+
+func New(content string) Model {
+ m := Model{
+ content: content,
+ vp: viewport.New(ui.Width, ui.Height),
+ }
+ m.SetContent(content)
+
+ return m
+}
+
+func (m Model) Init() tea.Cmd {
+ return nil
+}
+
+func (m Model) View() string {
+ footer := "-- 󰳝 Accept | ^C Decline | ↑↓ or J/K Scroll | ^D/^U PgDn/PgUp --"
+
+ fWidth := lipgloss.Width(footer)
+ paddingLeft := (ui.Width - fWidth) / 2
+ paddingRight := ui.Width - fWidth - paddingLeft
+ footerStyle := lipgloss.NewStyle().
+ Padding(0, paddingLeft, 0, paddingRight).
+ Background(colors.BackgroundDimmer).
+ MarginBackground(colors.BackgroundDimmer)
+ footer = footerStyle.Render(footer)
+
+ view := m.vp.View()
+
+ return lipgloss.JoinVertical(lipgloss.Center, view, footer)
+}
+
+func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
+ var cmd tea.Cmd
+
+ if m.vp.Width != ui.Width {
+ m.vp.Width = ui.Width
+ m.updateContent()
+ }
+ if m.vp.Height != ui.Height-1 {
+ m.vp.Height = ui.Height - 1
+ m.updateContent()
+ }
+
+ m.vp.Style = style()
+ m.vp, cmd = m.vp.Update(msg)
+
+ return m, cmd
+}
+
+func (m *Model) updateContent() {
+ style := style()
+ margin := style.GetMarginLeft() + style.GetMarginRight()
+ padding := style.GetPaddingLeft() + style.GetPaddingRight()
+ border := 2
+ lineWidth := ui.Width - margin - padding - border
+
+ r, _ := glamour.NewTermRenderer(
+ glamour.WithStyles(MdStyle()),
+ glamour.WithWordWrap(lineWidth),
+ )
+ content := m.content
+ content = strings.ReplaceAll(content, "@", "") // HACK: workaround to remove mailto links
+ content, err := r.Render(content)
+ assert.NoError(err, "this should never error")
+ content = strings.ReplaceAll(content, "", "@") // HACK: workaround to remove mailto links
+ m.vp.SetContent(content)
+}
+
+func (m *Model) SetContent(content string) {
+ m.content = content
+ m.updateContent()
+}
+
+func MdStyle() ansi.StyleConfig {
+ mdStyle := ansi.StyleConfig{
+ Document: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ BlockPrefix: "\n",
+ BlockSuffix: "\n",
+ Color: stringPtr(colors.White),
+ BackgroundColor: stringPtr(colors.Background),
+ },
+ Margin: uintPtr(defaultMargin),
+ },
+ BlockQuote: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{},
+ Indent: uintPtr(1),
+ IndentToken: stringPtr("│ "),
+ },
+ List: ansi.StyleList{
+ LevelIndent: defaultListIndent,
+ },
+ Heading: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ BlockSuffix: "\n",
+ Color: stringPtr(colors.LightBlue),
+ Bold: boolPtr(true),
+ },
+ },
+ H1: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ Prefix: " ",
+ Suffix: " ",
+ Color: stringPtr(colors.Black),
+ BackgroundColor: stringPtr(colors.LightBlue),
+ Bold: boolPtr(true),
+ },
+ },
+ H2: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ Prefix: "## ",
+ },
+ },
+ H3: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ Prefix: "### ",
+ },
+ },
+ H4: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ Prefix: "#### ",
+ },
+ },
+ H5: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ Prefix: "##### ",
+ },
+ },
+ H6: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ Prefix: "###### ",
+ Bold: boolPtr(false),
+ },
+ },
+ Strikethrough: ansi.StylePrimitive{
+ CrossedOut: boolPtr(true),
+ },
+ Emph: ansi.StylePrimitive{
+ Italic: boolPtr(true),
+ },
+ Strong: ansi.StylePrimitive{
+ Color: stringPtr(colors.Orange),
+ Bold: boolPtr(true),
+ },
+ HorizontalRule: ansi.StylePrimitive{
+ Color: stringPtr(colors.Gray),
+ Format: "\n--------\n",
+ },
+ Item: ansi.StylePrimitive{
+ BlockPrefix: " ",
+ },
+ Enumeration: ansi.StylePrimitive{
+ BlockPrefix: ". ",
+ },
+ Task: ansi.StyleTask{
+ StylePrimitive: ansi.StylePrimitive{},
+ Ticked: "[✓] ",
+ Unticked: "[ ] ",
+ },
+ Link: ansi.StylePrimitive{
+
+ // Format: "Bozo",
+ },
+ LinkText: ansi.StylePrimitive{
+ Color: stringPtr(colors.Gold),
+ Bold: boolPtr(true),
+ Conceal: boolPtr(true),
+ Faint: boolPtr(true),
+ },
+ Image: ansi.StylePrimitive{
+ Color: stringPtr(colors.Purple),
+ Underline: boolPtr(true),
+ },
+ ImageText: ansi.StylePrimitive{
+ Color: stringPtr(colors.LightGray),
+ Format: "Image: {{.text}} →",
+ },
+ Code: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ Prefix: " ",
+ Suffix: " ",
+ Color: stringPtr(colors.Purple),
+ BackgroundColor: stringPtr(colors.BackgroundHighlight),
+ },
+ },
+ CodeBlock: ansi.StyleCodeBlock{
+ StyleBlock: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{
+ Color: stringPtr(colors.LightGray),
+ },
+ Margin: uintPtr(defaultMargin),
+ },
+ Chroma: &ansi.Chroma{
+ Text: ansi.StylePrimitive{
+ Color: stringPtr(colors.White),
+ },
+ Error: ansi.StylePrimitive{
+ Color: stringPtr(colors.White),
+ BackgroundColor: stringPtr(colors.Red),
+ },
+ Comment: ansi.StylePrimitive{
+ Color: stringPtr(colors.Gray),
+ },
+ CommentPreproc: ansi.StylePrimitive{
+ Color: stringPtr(colors.Orange),
+ },
+ Keyword: ansi.StylePrimitive{
+ Color: stringPtr(colors.Red),
+ },
+ KeywordReserved: ansi.StylePrimitive{
+ Color: stringPtr(colors.Red),
+ },
+ KeywordNamespace: ansi.StylePrimitive{
+ Color: stringPtr(colors.Red),
+ },
+ KeywordType: ansi.StylePrimitive{
+ Color: stringPtr(colors.Turquoise),
+ },
+ Operator: ansi.StylePrimitive{
+ Color: stringPtr(colors.Red),
+ },
+ Punctuation: ansi.StylePrimitive{
+ Color: stringPtr(colors.White),
+ },
+ Name: ansi.StylePrimitive{
+ Color: stringPtr(colors.Purple),
+ },
+ NameBuiltin: ansi.StylePrimitive{
+ Color: stringPtr(colors.Red),
+ },
+ NameTag: ansi.StylePrimitive{
+ Color: stringPtr(colors.Purple),
+ },
+ NameAttribute: ansi.StylePrimitive{
+ Color: stringPtr(colors.LightBlue),
+ },
+ NameClass: ansi.StylePrimitive{
+ Color: stringPtr(colors.White),
+ Underline: boolPtr(true),
+ Bold: boolPtr(true),
+ },
+ NameDecorator: ansi.StylePrimitive{
+ Color: stringPtr(colors.Gold),
+ },
+ NameFunction: ansi.StylePrimitive{
+ Color: stringPtr(colors.LightBlue),
+ },
+ LiteralNumber: ansi.StylePrimitive{
+ Color: stringPtr(colors.Purple),
+ },
+ LiteralString: ansi.StylePrimitive{
+ Color: stringPtr(colors.Orange),
+ },
+ LiteralStringEscape: ansi.StylePrimitive{
+ Color: stringPtr(colors.Purple),
+ },
+ GenericDeleted: ansi.StylePrimitive{
+ Color: stringPtr(colors.Red),
+ },
+ GenericEmph: ansi.StylePrimitive{
+ Italic: boolPtr(true),
+ },
+ GenericInserted: ansi.StylePrimitive{
+ Color: stringPtr(colors.Turquoise),
+ },
+ GenericStrong: ansi.StylePrimitive{
+ Bold: boolPtr(true),
+ },
+ GenericSubheading: ansi.StylePrimitive{
+ Color: stringPtr(colors.LightGray),
+ },
+ Background: ansi.StylePrimitive{
+ BackgroundColor: stringPtr(colors.BackgroundDim),
+ },
+ },
+ },
+ Table: ansi.StyleTable{
+ StyleBlock: ansi.StyleBlock{
+ StylePrimitive: ansi.StylePrimitive{},
+ },
+ },
+ DefinitionDescription: ansi.StylePrimitive{
+ BlockPrefix: "\n🠶 ",
+ },
+ }
+
+ return mdStyle
+}
+
+const (
+ defaultListIndent = 2
+ defaultListLevelIndent = 4
+ defaultMargin = 0
+)
+
+func stringPtr(c lipgloss.Color) *string { return (*string)(&c) }
+func boolPtr(b bool) *bool { return &b }
+func uintPtr(u uint) *uint { return &u }