mirror of
https://github.com/anotherhadi/usbguard-tui.git
synced 2026-08-21 12:05:50 +02:00
e77eaf4e2c
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
107 lines
2.8 KiB
Go
107 lines
2.8 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
|
|
"charm.land/bubbles/v2/list"
|
|
tea "charm.land/bubbletea/v2"
|
|
"charm.land/lipgloss/v2"
|
|
"github.com/anotherhadi/ilovetui/style"
|
|
"github.com/anotherhadi/usbguard-tui/internal/guard"
|
|
)
|
|
|
|
var ruleStateIndicators = map[guard.RuleState]string{
|
|
guard.RulePermanent: "● perm",
|
|
guard.RuleTemporary: "○ tmp",
|
|
guard.RuleDefault: "· default",
|
|
}
|
|
|
|
type deviceDelegate struct{}
|
|
|
|
func (d deviceDelegate) Height() int { return 2 }
|
|
func (d deviceDelegate) Spacing() int { return 0 }
|
|
func (d deviceDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil }
|
|
|
|
func (d deviceDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
|
|
dev, ok := item.(guard.Device)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
selected := index == m.Index()
|
|
|
|
colorMap := statusColors
|
|
if selected {
|
|
colorMap = statusColorsSelected
|
|
}
|
|
clr, ok := colorMap[dev.Status]
|
|
if !ok {
|
|
clr = style.S.Muted
|
|
}
|
|
|
|
var nameStyle, descStyle lipgloss.Style
|
|
if selected {
|
|
nameStyle = lipgloss.NewStyle().
|
|
Border(lipgloss.NormalBorder(), false, false, false, true).
|
|
BorderForeground(style.S.Primary).
|
|
Foreground(clr).
|
|
Bold(true).
|
|
PaddingLeft(1)
|
|
descStyle = lipgloss.NewStyle().
|
|
Border(lipgloss.NormalBorder(), false, false, false, true).
|
|
BorderForeground(style.S.Primary).
|
|
Foreground(style.S.Muted).
|
|
PaddingLeft(1)
|
|
} else {
|
|
nameStyle = lipgloss.NewStyle().Foreground(clr).PaddingLeft(2)
|
|
descStyle = lipgloss.NewStyle().Foreground(style.S.Muted).PaddingLeft(2)
|
|
}
|
|
|
|
name := dev.Name
|
|
if icon := deviceIcon(dev.Name); icon != "" {
|
|
name = icon + " " + name
|
|
}
|
|
|
|
permIndicator := ruleStateIndicators[dev.RuleState]
|
|
width := m.Width()
|
|
fmt.Fprintf(w, "%s\n%s",
|
|
clampToWidth(nameStyle.Render(name), width),
|
|
clampToWidth(descStyle.Render(fmt.Sprintf("id:%-3d %s %s %s", dev.ID, dev.VidPid, string(dev.Status), permIndicator)), width),
|
|
)
|
|
}
|
|
|
|
type actionItem struct {
|
|
label string
|
|
fn func(int, bool) error
|
|
permanent bool
|
|
status guard.Status
|
|
nixos bool
|
|
}
|
|
|
|
func (a actionItem) Title() string { return a.label }
|
|
func (a actionItem) Description() string { return "" }
|
|
func (a actionItem) FilterValue() string { return a.label }
|
|
|
|
type actionDelegate struct{}
|
|
|
|
func (d actionDelegate) Height() int { return 1 }
|
|
func (d actionDelegate) Spacing() int { return 0 }
|
|
func (d actionDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil }
|
|
|
|
func (d actionDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
|
|
a, ok := item.(actionItem)
|
|
if !ok {
|
|
return
|
|
}
|
|
if index == m.Index() {
|
|
clr, ok := statusColorsSelected[a.status]
|
|
if !ok {
|
|
clr = style.S.Primary
|
|
}
|
|
fmt.Fprintf(w, " %s", lipgloss.NewStyle().Bold(true).Foreground(clr).Render("> "+a.label))
|
|
} else {
|
|
fmt.Fprintf(w, " %s", a.label)
|
|
}
|
|
}
|