1package tui
2
3import (
4 "strings"
5
6 tea "charm.land/bubbletea/v2"
7 "charm.land/lipgloss/v2"
8 "github.com/floatpane/matcha/config"
9 "github.com/floatpane/matcha/theme"
10)
11
12func (m *Settings) updateTheme(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
13 themes := theme.AllThemes()
14
15 switch msg.String() {
16 case "up", "k":
17 if len(themes) > 0 {
18 m.themeCursor = (m.themeCursor - 1 + len(themes)) % len(themes)
19 }
20 case keyDown, "j":
21 if len(themes) > 0 {
22 m.themeCursor = (m.themeCursor + 1) % len(themes)
23 }
24 case keyEnter, "space", keyRight, "l":
25 if m.themeCursor < len(themes) {
26 selected := themes[m.themeCursor]
27 theme.SetTheme(selected.Name)
28 RebuildStyles()
29 m.cfg.Theme = selected.Name
30 _ = config.SaveConfig(m.cfg)
31 }
32 }
33 return m, nil
34}
35
36func (m *Settings) viewTheme() string {
37 themes := theme.AllThemes()
38 var b strings.Builder
39
40 b.WriteString(titleStyle.Render(t("settings_theme.title")) + "\n\n")
41
42 for i, thm := range themes {
43 isActive := thm.Name == theme.ActiveTheme.Name
44 label := thm.Name
45 if isActive {
46 label += " (" + t("settings_theme.current") + ")"
47 }
48
49 selected := m.themeCursor == i
50 cursor := m.contentCursor(selected)
51 style := m.contentItemStyle(selected)
52
53 b.WriteString(style.Render(cursor+label) + "\n")
54 }
55
56 b.WriteString("\n")
57
58 // Preview
59 var previewTheme theme.Theme
60 if m.themeCursor < len(themes) {
61 previewTheme = themes[m.themeCursor]
62 } else {
63 previewTheme = theme.ActiveTheme
64 }
65
66 previewWidth := m.width - 34 - 4
67 if previewWidth < 30 {
68 previewWidth = 30
69 }
70
71 b.WriteString(renderThemePreview(previewTheme, previewWidth) + "\n\n")
72
73 if !m.cfg.HideTips {
74 b.WriteString(TipStyle.Render("Tip: Custom themes can be added as JSON files in ~/.config/matcha/themes/") + "\n\n")
75 }
76
77 b.WriteString(helpStyle.Render(t("settings_theme.help")))
78
79 return b.String()
80}
81
82// renderThemePreview renders a small mockup showing how a theme looks.
83func renderThemePreview(t theme.Theme, previewWidth int) string {
84 if previewWidth > 60 {
85 previewWidth = 60
86 }
87
88 accent := lipgloss.NewStyle().Foreground(t.Accent)
89 accentBold := lipgloss.NewStyle().Foreground(t.Accent).Bold(true)
90 secondary := lipgloss.NewStyle().Foreground(t.Secondary)
91 muted := lipgloss.NewStyle().Foreground(t.MutedText)
92 dim := lipgloss.NewStyle().Foreground(t.DimText)
93 danger := lipgloss.NewStyle().Foreground(t.Danger)
94 warn := lipgloss.NewStyle().Foreground(t.Warning)
95 tip := lipgloss.NewStyle().Foreground(t.Tip).Italic(true)
96 link := lipgloss.NewStyle().Foreground(t.Link)
97 title := lipgloss.NewStyle().Foreground(t.AccentText).Background(t.AccentDark).Padding(0, 1)
98 activeTab := lipgloss.NewStyle().Foreground(t.Accent).Bold(true).Underline(true)
99 activeFolder := lipgloss.NewStyle().Background(t.Accent).Foreground(t.Contrast).Bold(true).Padding(0, 1)
100
101 var b strings.Builder
102
103 b.WriteString(title.Render("Preview: "+t.Name) + "\n\n")
104 b.WriteString(activeTab.Render("Inbox") + " " + secondary.Render("Sent") + " " + secondary.Render("Drafts") + "\n")
105 b.WriteString(secondary.Render(strings.Repeat("─", previewWidth)) + "\n")
106
107 b.WriteString(accentBold.Render("> ") + dim.Render("Alice ") + accent.Render("Meeting tomorrow") + " " + muted.Render("2m ago") + "\n")
108 b.WriteString(" " + dim.Render("Bob ") + secondary.Render("Re: Project update") + " " + muted.Render("1h ago") + "\n")
109 b.WriteString(" " + dim.Render("Carol ") + secondary.Render("Quick question") + " " + muted.Render("3h ago") + "\n\n")
110
111 b.WriteString(accentBold.Render("Folders") + "\n")
112 b.WriteString(activeFolder.Render(" INBOX ") + " " + secondary.Render("Sent") + " " + secondary.Render("Trash") + "\n\n")
113
114 b.WriteString(accentBold.Render("Success: ") + accent.Render("Email sent!") + "\n")
115 b.WriteString(danger.Render("Error: ") + danger.Render("Connection failed") + "\n")
116 b.WriteString(warn.Render("Update available: v2.0") + "\n")
117 b.WriteString(tip.Render("Tip: Press ? for help") + "\n")
118 b.WriteString(link.Render("https://example.com") + "\n")
119
120 box := lipgloss.NewStyle().
121 Border(lipgloss.RoundedBorder()).
122 BorderForeground(t.AccentDark).
123 Padding(1, 2).
124 Width(previewWidth).
125 Render(b.String())
126
127 return box
128}