feat(tui): theme system with 5 curated dark palettes #24
@@ -319,7 +319,7 @@ func (m *Model) initAlertHuhForm() tea.Cmd {
|
|||||||
).Title("Gotify Settings").WithHideFunc(func() bool {
|
).Title("Gotify Settings").WithHideFunc(func() bool {
|
||||||
return m.alertFormData.AlertType != "gotify"
|
return m.alertFormData.AlertType != "gotify"
|
||||||
}),
|
}),
|
||||||
).WithTheme(huh.ThemeDracula())
|
).WithTheme(m.theme.HuhTheme())
|
||||||
|
|
||||||
return m.huhForm.Init()
|
return m.huhForm.Init()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
)
|
)
|
||||||
|
|
||||||
var maintStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#bb9af7"))
|
var maintStyle lipgloss.Style
|
||||||
|
|
||||||
type maintFormData struct {
|
type maintFormData struct {
|
||||||
Title string
|
Title string
|
||||||
@@ -187,7 +187,7 @@ func (m *Model) initMaintHuhForm() tea.Cmd {
|
|||||||
).Title("Duration").WithHideFunc(func() bool {
|
).Title("Duration").WithHideFunc(func() bool {
|
||||||
return m.maintFormData.Type == "incident"
|
return m.maintFormData.Type == "incident"
|
||||||
}),
|
}),
|
||||||
).WithTheme(huh.ThemeDracula())
|
).WithTheme(m.theme.HuhTheme())
|
||||||
|
|
||||||
return m.huhForm.Init()
|
return m.huhForm.Init()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,7 @@ func typeIcon(siteType string, collapsed bool) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var siteGroupStyle = lipgloss.NewStyle().
|
var siteGroupStyle lipgloss.Style
|
||||||
Padding(0, 1).
|
|
||||||
Bold(true).
|
|
||||||
Foreground(lipgloss.Color("#7D56F4"))
|
|
||||||
|
|
||||||
type siteFormData struct {
|
type siteFormData struct {
|
||||||
Name string
|
Name string
|
||||||
@@ -340,7 +337,7 @@ func (m Model) viewSitesTab() string {
|
|||||||
if len(m.sites) == 0 {
|
if len(m.sites) == 0 {
|
||||||
welcome := lipgloss.NewStyle().
|
welcome := lipgloss.NewStyle().
|
||||||
Border(lipgloss.RoundedBorder()).
|
Border(lipgloss.RoundedBorder()).
|
||||||
BorderForeground(lipgloss.Color("#7D56F4")).
|
BorderForeground(m.theme.Accent).
|
||||||
Padding(1, 3).
|
Padding(1, 3).
|
||||||
Render(
|
Render(
|
||||||
titleStyle.Render("Go-Upkeep") + "\n\n" +
|
titleStyle.Render("Go-Upkeep") + "\n\n" +
|
||||||
@@ -651,7 +648,7 @@ func (m *Model) initSiteHuhForm() tea.Cmd {
|
|||||||
).Title("Advanced").WithHideFunc(func() bool {
|
).Title("Advanced").WithHideFunc(func() bool {
|
||||||
return m.siteFormData.SiteType == "group"
|
return m.siteFormData.SiteType == "group"
|
||||||
}),
|
}),
|
||||||
).WithTheme(huh.ThemeDracula())
|
).WithTheme(m.theme.HuhTheme())
|
||||||
|
|
||||||
return m.huhForm.Init()
|
return m.huhForm.Init()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ func (m *Model) initUserHuhForm() tea.Cmd {
|
|||||||
huh.NewOption("Admin", "admin"),
|
huh.NewOption("Admin", "admin"),
|
||||||
).Value(&m.userFormData.Role),
|
).Value(&m.userFormData.Role),
|
||||||
).Title("SSH Access"),
|
).Title("SSH Access"),
|
||||||
).WithTheme(huh.ThemeDracula())
|
).WithTheme(m.theme.HuhTheme())
|
||||||
|
|
||||||
return m.huhForm.Init()
|
return m.huhForm.Init()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,25 +6,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tableHeaderStyle = lipgloss.NewStyle().
|
tableHeaderStyle lipgloss.Style
|
||||||
Foreground(lipgloss.Color("#7D56F4")).
|
tableCellStyle lipgloss.Style
|
||||||
Bold(true).
|
tableSelectedStyle lipgloss.Style
|
||||||
Padding(0, 1)
|
tableBorderStyle lipgloss.Style
|
||||||
|
tableZebraStyle lipgloss.Style
|
||||||
tableCellStyle = lipgloss.NewStyle().Padding(0, 1)
|
|
||||||
|
|
||||||
tableSelectedStyle = lipgloss.NewStyle().
|
|
||||||
Padding(0, 1).
|
|
||||||
Bold(true).
|
|
||||||
Foreground(lipgloss.Color("#ffffff")).
|
|
||||||
Background(lipgloss.Color("#3b3b5c"))
|
|
||||||
|
|
||||||
tableBorderStyle = lipgloss.NewStyle().
|
|
||||||
Foreground(lipgloss.Color("#444"))
|
|
||||||
|
|
||||||
tableZebraStyle = lipgloss.NewStyle().
|
|
||||||
Padding(0, 1).
|
|
||||||
Background(lipgloss.Color("#1a1a2e"))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StyleOverride func(row, col int) *lipgloss.Style
|
type StyleOverride func(row, col int) *lipgloss.Style
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/charmbracelet/huh"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Theme struct {
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Base layers
|
||||||
|
Bg lipgloss.Color
|
||||||
|
Surface lipgloss.Color
|
||||||
|
Panel lipgloss.Color
|
||||||
|
Border lipgloss.Color
|
||||||
|
|
||||||
|
// Text
|
||||||
|
Fg lipgloss.Color
|
||||||
|
Muted lipgloss.Color
|
||||||
|
Subtle lipgloss.Color
|
||||||
|
|
||||||
|
// Semantic
|
||||||
|
Success lipgloss.Color
|
||||||
|
Warning lipgloss.Color
|
||||||
|
Danger lipgloss.Color
|
||||||
|
Info lipgloss.Color
|
||||||
|
Accent lipgloss.Color
|
||||||
|
Purple lipgloss.Color
|
||||||
|
|
||||||
|
// Table
|
||||||
|
ZebraBg lipgloss.Color
|
||||||
|
|
||||||
|
// Selection
|
||||||
|
SelectedFg lipgloss.Color
|
||||||
|
SelectedBg lipgloss.Color
|
||||||
|
}
|
||||||
|
|
||||||
|
var themes = []Theme{
|
||||||
|
themeFlexokiDark,
|
||||||
|
themeFlexokiLight,
|
||||||
|
themeCatppuccinMocha,
|
||||||
|
themeNord,
|
||||||
|
}
|
||||||
|
|
||||||
|
var themeFlexokiDark = Theme{
|
||||||
|
Name: "Flexoki Dark",
|
||||||
|
Bg: "#1C1B1A",
|
||||||
|
Surface: "#282726",
|
||||||
|
Panel: "#343331",
|
||||||
|
Border: "#575653",
|
||||||
|
Fg: "#CECDC3",
|
||||||
|
Muted: "#878580",
|
||||||
|
Subtle: "#6F6E69",
|
||||||
|
Success: "#879A39",
|
||||||
|
Warning: "#D0A215",
|
||||||
|
Danger: "#D14D41",
|
||||||
|
Info: "#4385BE",
|
||||||
|
Accent: "#3AA99F",
|
||||||
|
Purple: "#8B7EC8",
|
||||||
|
ZebraBg: "#222120",
|
||||||
|
SelectedFg: "#FFFCF0",
|
||||||
|
SelectedBg: "#403E3C",
|
||||||
|
}
|
||||||
|
|
||||||
|
var themeFlexokiLight = Theme{
|
||||||
|
Name: "Flexoki Light",
|
||||||
|
Bg: "#FFFCF0",
|
||||||
|
Surface: "#F2F0E5",
|
||||||
|
Panel: "#E6E4D9",
|
||||||
|
Border: "#B7B5AC",
|
||||||
|
Fg: "#100F0F",
|
||||||
|
Muted: "#6F6E69",
|
||||||
|
Subtle: "#878580",
|
||||||
|
Success: "#66800B",
|
||||||
|
Warning: "#AD8301",
|
||||||
|
Danger: "#AF3029",
|
||||||
|
Info: "#205EA6",
|
||||||
|
Accent: "#24837B",
|
||||||
|
Purple: "#5E409D",
|
||||||
|
ZebraBg: "#F7F5EA",
|
||||||
|
SelectedFg: "#100F0F",
|
||||||
|
SelectedBg: "#DAD8CE",
|
||||||
|
}
|
||||||
|
|
||||||
|
var themeCatppuccinMocha = Theme{
|
||||||
|
Name: "Catppuccin Mocha",
|
||||||
|
Bg: "#1e1e2e",
|
||||||
|
Surface: "#313244",
|
||||||
|
Panel: "#45475a",
|
||||||
|
Border: "#585b70",
|
||||||
|
Fg: "#cdd6f4",
|
||||||
|
Muted: "#a6adc8",
|
||||||
|
Subtle: "#6c7086",
|
||||||
|
Success: "#a6e3a1",
|
||||||
|
Warning: "#f9e2af",
|
||||||
|
Danger: "#f38ba8",
|
||||||
|
Info: "#89b4fa",
|
||||||
|
Accent: "#94e2d5",
|
||||||
|
Purple: "#cba6f7",
|
||||||
|
ZebraBg: "#232334",
|
||||||
|
SelectedFg: "#cdd6f4",
|
||||||
|
SelectedBg: "#45475a",
|
||||||
|
}
|
||||||
|
|
||||||
|
var themeNord = Theme{
|
||||||
|
Name: "Nord",
|
||||||
|
Bg: "#2e3440",
|
||||||
|
Surface: "#3b4252",
|
||||||
|
Panel: "#434c5e",
|
||||||
|
Border: "#4c566a",
|
||||||
|
Fg: "#d8dee9",
|
||||||
|
Muted: "#d8dee9",
|
||||||
|
Subtle: "#4c566a",
|
||||||
|
Success: "#a3be8c",
|
||||||
|
Warning: "#ebcb8b",
|
||||||
|
Danger: "#bf616a",
|
||||||
|
Info: "#81a1c1",
|
||||||
|
Accent: "#88c0d0",
|
||||||
|
Purple: "#b48ead",
|
||||||
|
ZebraBg: "#323845",
|
||||||
|
SelectedFg: "#eceff4",
|
||||||
|
SelectedBg: "#434c5e",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Theme) HuhTheme() *huh.Theme {
|
||||||
|
ht := huh.ThemeBase()
|
||||||
|
|
||||||
|
ht.Focused.Base = ht.Focused.Base.BorderForeground(t.Border)
|
||||||
|
ht.Focused.Card = ht.Focused.Base
|
||||||
|
ht.Focused.Title = ht.Focused.Title.Foreground(t.Accent).Bold(true)
|
||||||
|
ht.Focused.NoteTitle = ht.Focused.NoteTitle.Foreground(t.Accent).Bold(true).MarginBottom(1)
|
||||||
|
ht.Focused.Description = ht.Focused.Description.Foreground(t.Muted)
|
||||||
|
ht.Focused.ErrorIndicator = ht.Focused.ErrorIndicator.Foreground(t.Danger)
|
||||||
|
ht.Focused.ErrorMessage = ht.Focused.ErrorMessage.Foreground(t.Danger)
|
||||||
|
ht.Focused.SelectSelector = ht.Focused.SelectSelector.Foreground(t.Purple)
|
||||||
|
ht.Focused.NextIndicator = ht.Focused.NextIndicator.Foreground(t.Purple)
|
||||||
|
ht.Focused.PrevIndicator = ht.Focused.PrevIndicator.Foreground(t.Purple)
|
||||||
|
ht.Focused.Option = ht.Focused.Option.Foreground(t.Fg)
|
||||||
|
ht.Focused.MultiSelectSelector = ht.Focused.MultiSelectSelector.Foreground(t.Purple)
|
||||||
|
ht.Focused.SelectedOption = ht.Focused.SelectedOption.Foreground(t.Success)
|
||||||
|
ht.Focused.SelectedPrefix = lipgloss.NewStyle().Foreground(t.Success).SetString("✓ ")
|
||||||
|
ht.Focused.UnselectedPrefix = lipgloss.NewStyle().Foreground(t.Subtle).SetString("• ")
|
||||||
|
ht.Focused.UnselectedOption = ht.Focused.UnselectedOption.Foreground(t.Fg)
|
||||||
|
ht.Focused.FocusedButton = ht.Focused.FocusedButton.Foreground(t.Bg).Background(t.Accent)
|
||||||
|
ht.Focused.Next = ht.Focused.FocusedButton
|
||||||
|
ht.Focused.BlurredButton = ht.Focused.BlurredButton.Foreground(t.Fg).Background(t.Surface)
|
||||||
|
ht.Focused.TextInput.Cursor = ht.Focused.TextInput.Cursor.Foreground(t.Accent)
|
||||||
|
ht.Focused.TextInput.Placeholder = ht.Focused.TextInput.Placeholder.Foreground(t.Subtle)
|
||||||
|
ht.Focused.TextInput.Prompt = ht.Focused.TextInput.Prompt.Foreground(t.Purple)
|
||||||
|
|
||||||
|
ht.Blurred = ht.Focused
|
||||||
|
ht.Blurred.Base = ht.Focused.Base.BorderStyle(lipgloss.HiddenBorder())
|
||||||
|
ht.Blurred.Card = ht.Blurred.Base
|
||||||
|
ht.Blurred.NextIndicator = lipgloss.NewStyle()
|
||||||
|
ht.Blurred.PrevIndicator = lipgloss.NewStyle()
|
||||||
|
|
||||||
|
ht.Group.Title = ht.Focused.Title
|
||||||
|
ht.Group.Description = ht.Focused.Description
|
||||||
|
|
||||||
|
return ht
|
||||||
|
}
|
||||||
|
|
||||||
|
func themeByName(name string) Theme {
|
||||||
|
for _, t := range themes {
|
||||||
|
if t.Name == name {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return themes[0]
|
||||||
|
}
|
||||||
+57
-17
@@ -20,16 +20,34 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
subtleStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#9ca0b0", Dark: "#565f89"})
|
subtleStyle lipgloss.Style
|
||||||
specialStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#43BF6D", Dark: "#73F59F"})
|
specialStyle lipgloss.Style
|
||||||
warnStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#F0E442", Dark: "#F0E442"})
|
warnStyle lipgloss.Style
|
||||||
dangerStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#F25D94", Dark: "#F25D94"})
|
dangerStyle lipgloss.Style
|
||||||
titleStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#7D56F4")).Bold(true)
|
titleStyle lipgloss.Style
|
||||||
|
activeTab lipgloss.Style
|
||||||
activeTab = lipgloss.NewStyle().Border(lipgloss.NormalBorder(), false, false, true, false).BorderForeground(lipgloss.Color("#7D56F4")).Foreground(lipgloss.Color("#7D56F4")).Bold(true).Padding(0, 1)
|
inactiveTab lipgloss.Style
|
||||||
inactiveTab = lipgloss.NewStyle().Padding(0, 1).Foreground(lipgloss.AdaptiveColor{Light: "#AAA", Dark: "#555"})
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func applyTheme(t Theme) {
|
||||||
|
subtleStyle = lipgloss.NewStyle().Foreground(t.Subtle)
|
||||||
|
specialStyle = lipgloss.NewStyle().Foreground(t.Success)
|
||||||
|
warnStyle = lipgloss.NewStyle().Foreground(t.Warning)
|
||||||
|
dangerStyle = lipgloss.NewStyle().Foreground(t.Danger)
|
||||||
|
titleStyle = lipgloss.NewStyle().Foreground(t.Accent).Bold(true)
|
||||||
|
activeTab = lipgloss.NewStyle().Border(lipgloss.NormalBorder(), false, false, true, false).BorderForeground(t.Accent).Foreground(t.Accent).Bold(true).Padding(0, 1)
|
||||||
|
inactiveTab = lipgloss.NewStyle().Padding(0, 1).Foreground(t.Muted)
|
||||||
|
|
||||||
|
tableHeaderStyle = lipgloss.NewStyle().Foreground(t.Accent).Bold(true).Padding(0, 1)
|
||||||
|
tableCellStyle = lipgloss.NewStyle().Padding(0, 1)
|
||||||
|
tableSelectedStyle = lipgloss.NewStyle().Padding(0, 1).Bold(true).Foreground(t.SelectedFg).Background(t.SelectedBg)
|
||||||
|
tableBorderStyle = lipgloss.NewStyle().Foreground(t.Border)
|
||||||
|
tableZebraStyle = lipgloss.NewStyle().Padding(0, 1).Background(t.ZebraBg)
|
||||||
|
|
||||||
|
siteGroupStyle = lipgloss.NewStyle().Padding(0, 1).Bold(true).Foreground(t.Accent)
|
||||||
|
maintStyle = lipgloss.NewStyle().Foreground(t.Purple)
|
||||||
|
}
|
||||||
|
|
||||||
var pulseFrames = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
|
var pulseFrames = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -81,9 +99,11 @@ type Model struct {
|
|||||||
deleteName string
|
deleteName string
|
||||||
deleteTab int
|
deleteTab int
|
||||||
|
|
||||||
collapsed map[int]bool
|
collapsed map[int]bool
|
||||||
store store.Store
|
store store.Store
|
||||||
engine *monitor.Engine
|
engine *monitor.Engine
|
||||||
|
theme Theme
|
||||||
|
themeIndex int
|
||||||
|
|
||||||
// harmonica animation state
|
// harmonica animation state
|
||||||
pulseSpring harmonica.Spring
|
pulseSpring harmonica.Spring
|
||||||
@@ -107,6 +127,19 @@ func InitialModel(isAdmin bool, s store.Store, eng *monitor.Engine) Model {
|
|||||||
z := zone.New()
|
z := zone.New()
|
||||||
spring := harmonica.NewSpring(harmonica.FPS(10), 6.0, 0.4)
|
spring := harmonica.NewSpring(harmonica.FPS(10), 6.0, 0.4)
|
||||||
collapsed := loadCollapsed(s)
|
collapsed := loadCollapsed(s)
|
||||||
|
|
||||||
|
themeName, _ := s.GetPreference("theme")
|
||||||
|
theme := themeByName(themeName)
|
||||||
|
themeIdx := 0
|
||||||
|
for i, t := range themes {
|
||||||
|
if t.Name == theme.Name {
|
||||||
|
themeIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
applyTheme(theme)
|
||||||
|
|
||||||
return Model{
|
return Model{
|
||||||
state: stateDashboard,
|
state: stateDashboard,
|
||||||
logViewport: vpLogs,
|
logViewport: vpLogs,
|
||||||
@@ -117,6 +150,8 @@ func InitialModel(isAdmin bool, s store.Store, eng *monitor.Engine) Model {
|
|||||||
zones: z,
|
zones: z,
|
||||||
pulseSpring: spring,
|
pulseSpring: spring,
|
||||||
collapsed: collapsed,
|
collapsed: collapsed,
|
||||||
|
theme: theme,
|
||||||
|
themeIndex: themeIdx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,6 +493,11 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.refreshData()
|
m.refreshData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "T":
|
||||||
|
m.themeIndex = (m.themeIndex + 1) % len(themes)
|
||||||
|
m.theme = themes[m.themeIndex]
|
||||||
|
applyTheme(m.theme)
|
||||||
|
_ = m.store.SetPreference("theme", m.theme.Name)
|
||||||
case "d", "backspace":
|
case "d", "backspace":
|
||||||
if m.currentTab == 0 && len(m.sites) > 0 {
|
if m.currentTab == 0 && len(m.sites) > 0 {
|
||||||
m.deleteID = m.sites[m.cursor].ID
|
m.deleteID = m.sites[m.cursor].ID
|
||||||
@@ -723,7 +763,7 @@ func (m Model) View() string {
|
|||||||
hint := subtleStyle.Render("[y] Confirm [n] Cancel")
|
hint := subtleStyle.Render("[y] Confirm [n] Cancel")
|
||||||
box := lipgloss.NewStyle().
|
box := lipgloss.NewStyle().
|
||||||
Border(lipgloss.RoundedBorder()).
|
Border(lipgloss.RoundedBorder()).
|
||||||
BorderForeground(lipgloss.Color("#F25D94")).
|
BorderForeground(m.theme.Danger).
|
||||||
Padding(1, 3).
|
Padding(1, 3).
|
||||||
Render(msg + "\n\n" + hint)
|
Render(msg + "\n\n" + hint)
|
||||||
return lipgloss.NewStyle().Padding(2, 4).Render(box)
|
return lipgloss.NewStyle().Padding(2, 4).Render(box)
|
||||||
@@ -875,19 +915,19 @@ func (m Model) viewDashboard() string {
|
|||||||
|
|
||||||
var footer string
|
var footer string
|
||||||
if m.filterMode {
|
if m.filterMode {
|
||||||
cursor := lipgloss.NewStyle().Foreground(lipgloss.Color("#7D56F4")).Render("│")
|
cursor := lipgloss.NewStyle().Foreground(m.theme.Accent).Render("│")
|
||||||
footer = "\n" + titleStyle.Render("/") + " " + m.filterText + cursor + " " + subtleStyle.Render("[Enter]Apply [Esc]Clear")
|
footer = "\n" + titleStyle.Render("/") + " " + m.filterText + cursor + " " + subtleStyle.Render("[Enter]Apply [Esc]Clear")
|
||||||
} else {
|
} else {
|
||||||
var keys string
|
var keys string
|
||||||
switch m.currentTab {
|
switch m.currentTab {
|
||||||
case 0:
|
case 0:
|
||||||
keys = "[/]Filter [n]New [e]Edit [i]Info [d]Del [p]Pause [Tab]Switch [q]Quit"
|
keys = "[/]Filter [n]New [e]Edit [i]Info [d]Del [p]Pause [T]Theme [Tab]Switch [q]Quit"
|
||||||
case 4:
|
case 4:
|
||||||
keys = "[n]New [x]End [d]Del [Tab]Switch [q]Quit"
|
keys = "[n]New [x]End [d]Del [T]Theme [Tab]Switch [q]Quit"
|
||||||
case 5:
|
case 5:
|
||||||
keys = "[n]Add [d]Revoke [Tab]Switch [q]Quit"
|
keys = "[n]Add [d]Revoke [T]Theme [Tab]Switch [q]Quit"
|
||||||
default:
|
default:
|
||||||
keys = "[Tab]Switch [q]Quit"
|
keys = "[T]Theme [Tab]Switch [q]Quit"
|
||||||
}
|
}
|
||||||
footer = "\n" + statusLine + " " + subtleStyle.Render(keys)
|
footer = "\n" + statusLine + " " + subtleStyle.Render(keys)
|
||||||
if m.filterText != "" && m.currentTab == 0 {
|
if m.filterText != "" && m.currentTab == 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user