settings_theme.go

  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 "down", "j":
 21		if len(themes) > 0 {
 22			m.themeCursor = (m.themeCursor + 1) % len(themes)
 23		}
 24	case "enter", "space", "right", "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		cursor := "  "
 50		style := accountItemStyle
 51		if m.themeCursor == i {
 52			cursor = "> "
 53			style = selectedAccountItemStyle
 54		}
 55
 56		b.WriteString(style.Render(cursor+label) + "\n")
 57	}
 58
 59	b.WriteString("\n")
 60
 61	// Preview
 62	var previewTheme theme.Theme
 63	if m.themeCursor < len(themes) {
 64		previewTheme = themes[m.themeCursor]
 65	} else {
 66		previewTheme = theme.ActiveTheme
 67	}
 68
 69	previewWidth := m.width - 34 - 4
 70	if previewWidth < 30 {
 71		previewWidth = 30
 72	}
 73
 74	b.WriteString(renderThemePreview(previewTheme, previewWidth) + "\n\n")
 75
 76	if !m.cfg.HideTips {
 77		b.WriteString(TipStyle.Render("Tip: Custom themes can be added as JSON files in ~/.config/matcha/themes/") + "\n\n")
 78	}
 79
 80	b.WriteString(helpStyle.Render(t("settings_theme.help")))
 81
 82	return b.String()
 83}
 84
 85// renderThemePreview renders a small mockup showing how a theme looks.
 86func renderThemePreview(t theme.Theme, previewWidth int) string {
 87	if previewWidth > 60 {
 88		previewWidth = 60
 89	}
 90
 91	accent := lipgloss.NewStyle().Foreground(t.Accent)
 92	accentBold := lipgloss.NewStyle().Foreground(t.Accent).Bold(true)
 93	secondary := lipgloss.NewStyle().Foreground(t.Secondary)
 94	muted := lipgloss.NewStyle().Foreground(t.MutedText)
 95	dim := lipgloss.NewStyle().Foreground(t.DimText)
 96	danger := lipgloss.NewStyle().Foreground(t.Danger)
 97	warn := lipgloss.NewStyle().Foreground(t.Warning)
 98	tip := lipgloss.NewStyle().Foreground(t.Tip).Italic(true)
 99	link := lipgloss.NewStyle().Foreground(t.Link)
100	title := lipgloss.NewStyle().Foreground(t.AccentText).Background(t.AccentDark).Padding(0, 1)
101	activeTab := lipgloss.NewStyle().Foreground(t.Accent).Bold(true).Underline(true)
102	activeFolder := lipgloss.NewStyle().Background(t.Accent).Foreground(t.Contrast).Bold(true).Padding(0, 1)
103
104	var b strings.Builder
105
106	b.WriteString(title.Render("Preview: "+t.Name) + "\n\n")
107	b.WriteString(activeTab.Render("Inbox") + "  " + secondary.Render("Sent") + "  " + secondary.Render("Drafts") + "\n")
108	b.WriteString(secondary.Render(strings.Repeat("─", previewWidth)) + "\n")
109
110	b.WriteString(accentBold.Render("> ") + dim.Render("Alice  ") + accent.Render("Meeting tomorrow") + "  " + muted.Render("2m ago") + "\n")
111	b.WriteString("  " + dim.Render("Bob    ") + secondary.Render("Re: Project update") + "  " + muted.Render("1h ago") + "\n")
112	b.WriteString("  " + dim.Render("Carol  ") + secondary.Render("Quick question") + "    " + muted.Render("3h ago") + "\n\n")
113
114	b.WriteString(accentBold.Render("Folders") + "\n")
115	b.WriteString(activeFolder.Render(" INBOX ") + "  " + secondary.Render("Sent") + "  " + secondary.Render("Trash") + "\n\n")
116
117	b.WriteString(accentBold.Render("Success: ") + accent.Render("Email sent!") + "\n")
118	b.WriteString(danger.Render("Error: ") + danger.Render("Connection failed") + "\n")
119	b.WriteString(warn.Render("Update available: v2.0") + "\n")
120	b.WriteString(tip.Render("Tip: Press ? for help") + "\n")
121	b.WriteString(link.Render("https://example.com") + "\n")
122
123	box := lipgloss.NewStyle().
124		Border(lipgloss.RoundedBorder()).
125		BorderForeground(t.AccentDark).
126		Padding(1, 2).
127		Width(previewWidth).
128		Render(b.String())
129
130	return box
131}