mirror of
https://github.com/anotherhadi/usbguard-tui.git
synced 2026-10-05 10:18:25 +02:00
Min-width, style & mouse support
Signed-off-by: Hadi <[email protected]>
This commit is contained in:
@@ -4,23 +4,33 @@ import (
|
|||||||
tea "charm.land/bubbletea/v2"
|
tea "charm.land/bubbletea/v2"
|
||||||
"charm.land/lipgloss/v2"
|
"charm.land/lipgloss/v2"
|
||||||
"github.com/anotherhadi/ilovetui/app"
|
"github.com/anotherhadi/ilovetui/app"
|
||||||
|
"github.com/anotherhadi/ilovetui/minsize"
|
||||||
"github.com/anotherhadi/ilovetui/modal"
|
"github.com/anotherhadi/ilovetui/modal"
|
||||||
"github.com/anotherhadi/ilovetui/notification"
|
"github.com/anotherhadi/ilovetui/notification"
|
||||||
"github.com/anotherhadi/usbguard-tui/ui"
|
"github.com/anotherhadi/usbguard-tui/ui"
|
||||||
|
zone "github.com/lrstanley/bubblezone/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
minWidth = 40
|
||||||
|
minHeight = 15
|
||||||
)
|
)
|
||||||
|
|
||||||
type appModel struct {
|
type appModel struct {
|
||||||
core ui.Model
|
core ui.Model
|
||||||
modals modal.Model
|
modals modal.Model
|
||||||
notif notification.Model
|
notif notification.Model
|
||||||
|
minsize minsize.Model
|
||||||
width, height int
|
width, height int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newApp() appModel {
|
func newApp() appModel {
|
||||||
|
zone.NewGlobal()
|
||||||
return appModel{
|
return appModel{
|
||||||
core: ui.New(),
|
core: ui.New(),
|
||||||
modals: modal.New(),
|
modals: modal.New(),
|
||||||
notif: notification.New(),
|
notif: notification.New(),
|
||||||
|
minsize: minsize.New(minWidth, minHeight),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,9 +58,18 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a appModel) View() tea.View {
|
func (a appModel) View() tea.View {
|
||||||
|
if !a.minsize.Fits(a.width, a.height) {
|
||||||
|
return tea.View{
|
||||||
|
Content: a.minsize.View(a.width, a.height),
|
||||||
|
AltScreen: true,
|
||||||
|
WindowTitle: "USBGuard TUI",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bg := lipgloss.Place(a.width, a.height, lipgloss.Left, lipgloss.Top, a.core.View())
|
bg := lipgloss.Place(a.width, a.height, lipgloss.Left, lipgloss.Top, a.core.View())
|
||||||
bg = a.modals.Render(bg)
|
bg = a.modals.Render(bg)
|
||||||
bg = a.notif.Render(bg)
|
bg = a.notif.Render(bg)
|
||||||
|
bg = zone.Scan(bg)
|
||||||
return tea.View{
|
return tea.View{
|
||||||
Content: bg,
|
Content: bg,
|
||||||
AltScreen: true,
|
AltScreen: true,
|
||||||
|
|||||||
@@ -3,42 +3,43 @@ module github.com/anotherhadi/usbguard-tui
|
|||||||
go 1.26.2
|
go 1.26.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
charm.land/bubbles/v2 v2.1.0
|
charm.land/bubbles/v2 v2.2.0
|
||||||
charm.land/bubbletea/v2 v2.0.6
|
charm.land/bubbletea/v2 v2.0.9
|
||||||
charm.land/lipgloss/v2 v2.0.3
|
charm.land/lipgloss/v2 v2.0.6
|
||||||
github.com/anotherhadi/ilovetui v0.2.2
|
github.com/anotherhadi/ilovetui v0.2.4
|
||||||
github.com/charmbracelet/x/ansi v0.11.7
|
github.com/charmbracelet/x/ansi v0.11.8
|
||||||
|
github.com/lrstanley/bubblezone/v2 v2.0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
charm.land/glamour/v2 v2.0.0 // indirect
|
charm.land/glamour/v2 v2.0.1 // indirect
|
||||||
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
|
github.com/alecthomas/chroma/v2 v2.27.0 // indirect
|
||||||
github.com/atotto/clipboard v0.1.4 // indirect
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.4.3 // indirect
|
github.com/charmbracelet/colorprofile v0.4.3 // indirect
|
||||||
github.com/charmbracelet/harmonica v0.2.0 // indirect
|
github.com/charmbracelet/harmonica v0.2.0 // indirect
|
||||||
github.com/charmbracelet/ultraviolet v0.0.0-20260416155717-489999b90468 // indirect
|
github.com/charmbracelet/ultraviolet v0.0.0-20260812204455-68fa937c71be // indirect
|
||||||
github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect
|
github.com/charmbracelet/x/exp/slice v0.0.0-20260823001701-96af6d2cb5f6 // indirect
|
||||||
github.com/charmbracelet/x/term v0.2.2 // indirect
|
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||||
github.com/charmbracelet/x/termios v0.1.1 // indirect
|
github.com/charmbracelet/x/termios v0.1.1 // indirect
|
||||||
github.com/charmbracelet/x/windows v0.2.2 // indirect
|
github.com/charmbracelet/x/windows v0.2.2 // indirect
|
||||||
github.com/clipperhouse/displaywidth v0.11.0 // indirect
|
github.com/clipperhouse/displaywidth v0.11.0 // indirect
|
||||||
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
||||||
github.com/dlclark/regexp2 v1.11.0 // indirect
|
github.com/dlclark/regexp2/v2 v2.7.1 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/gorilla/css v1.0.1 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.4.1 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.23 // indirect
|
github.com/mattn/go-runewidth v0.0.28 // indirect
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
|
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
|
||||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/sahilm/fuzzy v0.1.1 // indirect
|
github.com/sahilm/fuzzy v0.1.3 // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v1.0.0 // indirect
|
||||||
github.com/yuin/goldmark v1.7.8 // indirect
|
github.com/yuin/goldmark v1.8.5 // indirect
|
||||||
github.com/yuin/goldmark-emoji v1.0.5 // indirect
|
github.com/yuin/goldmark-emoji v1.0.6 // indirect
|
||||||
golang.org/x/net v0.39.0 // indirect
|
golang.org/x/net v0.58.0 // indirect
|
||||||
golang.org/x/sync v0.20.0 // indirect
|
golang.org/x/sync v0.22.0 // indirect
|
||||||
golang.org/x/sys v0.43.0 // indirect
|
golang.org/x/sys v0.47.0 // indirect
|
||||||
golang.org/x/text v0.24.0 // indirect
|
golang.org/x/text v0.41.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
charm.land/bubbles/v2 v2.1.0 h1:YSnNh5cPYlYjPxRrzs5VEn3vwhtEn3jVGRBT3M7/I0g=
|
charm.land/bubbles/v2 v2.2.0 h1:9GEMewcejrNtVIxZ9Y2wSsWJamsWNsXa8MpMLnH4yI4=
|
||||||
charm.land/bubbles/v2 v2.1.0/go.mod h1:l97h4hym2hvWBVfmJDtrEHHCtkIKeTEb3TTJ4ZOB3wY=
|
charm.land/bubbles/v2 v2.2.0/go.mod h1:wdMgn+sje1KNXdwFizIWjbf328fIUBxqEmJ/vYPo8yc=
|
||||||
charm.land/bubbletea/v2 v2.0.6 h1:UHN/91OyuhaOFGSrBXQ/hMZD8IO1Uc4BvHlgHXL2WJo=
|
charm.land/bubbletea/v2 v2.0.9 h1:DpJCMWKgzQK8SJv4zbKKFHAI10ymWy/evClPFk0k0f8=
|
||||||
charm.land/bubbletea/v2 v2.0.6/go.mod h1:MH/D8ZLlN3op37vQvijKuU29g3rqTp+aQapURFonF9g=
|
charm.land/bubbletea/v2 v2.0.9/go.mod h1:2SkdgoTXluXJHOUwAoRlRXF/28vklb1rFl6GcgV1/ss=
|
||||||
charm.land/glamour/v2 v2.0.0 h1:IDBoqLEy7Hdpb9VOXN+khLP/XSxtJy1VsHuW/yF87+U=
|
charm.land/glamour/v2 v2.0.1 h1:xl+r00A4aJWU0z8fgwKd9fQQ4rsphqGUzuEiXZP5n+c=
|
||||||
charm.land/glamour/v2 v2.0.0/go.mod h1:kjq9WB0s8vuUYZNYey2jp4Lgd9f4cKdzAw88FZtpj/w=
|
charm.land/glamour/v2 v2.0.1/go.mod h1:jo9z8XqVKPeEFMVdvCRLGk++RyJ3CdUwgNr7EvXLw3k=
|
||||||
charm.land/lipgloss/v2 v2.0.3 h1:yM2zJ4Cf5Y51b7RHIwioil4ApI/aypFXXVHSwlM6RzU=
|
charm.land/lipgloss/v2 v2.0.6 h1:EaGKeuA8FvF+v2BT5VmZd2LoYLaMZJXA5n34th8nCIQ=
|
||||||
charm.land/lipgloss/v2 v2.0.3/go.mod h1:7myLU9iG/3xluAWzpY/fSxYYHCgoKTie7laxk6ATwXA=
|
charm.land/lipgloss/v2 v2.0.6/go.mod h1:ipDDJNSGa1hlwDtSfW1s2/xR8Vdhbut4PXh2zEKZd0Q=
|
||||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||||
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||||
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||||
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
|
github.com/alecthomas/chroma/v2 v2.27.0 h1:FodwmyOBgJULFYmDqibcp9pvfDLWdtPRh9v/r5BXYZs=
|
||||||
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
|
github.com/alecthomas/chroma/v2 v2.27.0/go.mod h1:NjJ3ciIgrqBNeIkWZ4e46nseoLDslxU1LmfCoL+wcY8=
|
||||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
|
||||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||||
github.com/anotherhadi/ilovetui v0.2.2 h1:ZOwyZRxFBZKVJeEAR+lg0xeQfsMZuymtKLwBV0MnBYY=
|
github.com/anotherhadi/ilovetui v0.2.4 h1:8D2jp/37vOJBRI3DKIHHt9PFsnIyfRxs3R58HuCh0tA=
|
||||||
github.com/anotherhadi/ilovetui v0.2.2/go.mod h1:gAn69amLM3z0x8PV4obyf5bJntL/PTZusEuhu/xdFIY=
|
github.com/anotherhadi/ilovetui v0.2.4/go.mod h1:gAn69amLM3z0x8PV4obyf5bJntL/PTZusEuhu/xdFIY=
|
||||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||||
github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o=
|
github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o=
|
||||||
@@ -26,14 +26,14 @@ github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex
|
|||||||
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
||||||
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
|
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
|
||||||
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
|
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
|
||||||
github.com/charmbracelet/ultraviolet v0.0.0-20260416155717-489999b90468 h1:Q9fO0y1Zo5KB/5Vu8JZoLGm1N3RzF9bNj3Ao3xoR+Ac=
|
github.com/charmbracelet/ultraviolet v0.0.0-20260812204455-68fa937c71be h1:qEvkJy1sjJXP+yf8IH2o13NV+Rh4nIUHjaLNJ+pWxpI=
|
||||||
github.com/charmbracelet/ultraviolet v0.0.0-20260416155717-489999b90468/go.mod h1:bAAz7dh/FTYfC+oiHavL4mX1tOIBZ0ZwYjSi3qE6ivM=
|
github.com/charmbracelet/ultraviolet v0.0.0-20260812204455-68fa937c71be/go.mod h1:nAw0d9PhFp1qdzi2xhQU5YOu5sVpDIHWlaW2Uz/bCro=
|
||||||
github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
|
github.com/charmbracelet/x/ansi v0.11.8 h1:JMFwp0CgDC2+jcOB162HH5k7I3FVbgFSMMYg7dSPBQQ=
|
||||||
github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ=
|
github.com/charmbracelet/x/ansi v0.11.8/go.mod h1:ZNN+3mXny/516oTQPLMPIBeSINvNJJQ8uQXDgbeJxY0=
|
||||||
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA=
|
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA=
|
||||||
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I=
|
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I=
|
||||||
github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Yb6MQSDKdB52aGX55JT1oi0P0Kuaj7wi1bLUpnI=
|
github.com/charmbracelet/x/exp/slice v0.0.0-20260823001701-96af6d2cb5f6 h1:je2x9scjVLOqRwO5JbFyRzyG5aCLg64DSOvd463cm04=
|
||||||
github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU=
|
github.com/charmbracelet/x/exp/slice v0.0.0-20260823001701-96af6d2cb5f6/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA=
|
||||||
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||||
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
||||||
github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
|
github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
|
||||||
@@ -44,8 +44,8 @@ github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSE
|
|||||||
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
|
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
|
||||||
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
|
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
|
||||||
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
github.com/dlclark/regexp2/v2 v2.7.1 h1:yqDtwI1ptXXvEUNpYTk2lad4jLtAcKqkzepn4savSk4=
|
||||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2/v2 v2.7.1/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||||
@@ -54,35 +54,36 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq
|
|||||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
|
github.com/lrstanley/bubblezone/v2 v2.0.0 h1:pMb9fHKs0slJF6OrzQ2hEgWusqyl9VU/S0UZ5hyh7ZA=
|
||||||
github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lrstanley/bubblezone/v2 v2.0.0/go.mod h1:yV/QTjcm4Zu5cqvGvdHi7xVUfnB36w/SafOuDp57dgY=
|
||||||
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
|
github.com/lucasb-eyer/go-colorful v1.4.1 h1:1EO+WB73+EH8EVbzlrG3KLAfEypQWVHIBqlTf+2hNss=
|
||||||
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
github.com/lucasb-eyer/go-colorful v1.4.1/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/mattn/go-runewidth v0.0.28 h1:rPyg2ybwEKPebvpzVWe1gKBkH8EQFkxO4Y0hjBeLaBU=
|
||||||
|
github.com/mattn/go-runewidth v0.0.28/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
github.com/sahilm/fuzzy v0.1.3 h1:juByESSS32nVD81vr6tHmKmA/8zde7gE+x5CLxrzXPU=
|
||||||
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
github.com/sahilm/fuzzy v0.1.3/go.mod h1:au6//VbVSqu6DFrkL2CfjlJ5iURpNCPeE+1GwY3XsT8=
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
github.com/xo/terminfo v1.0.0 h1:2ZpYzqWzyyytjk3TP6aJVDhkMAkc99/1xKQdA3TDTBY=
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
github.com/xo/terminfo v1.0.0/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA=
|
||||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
github.com/yuin/goldmark v1.8.5/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs=
|
||||||
github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk=
|
github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA=
|
||||||
github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
|
|
||||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
|
||||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
|
||||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
|
||||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
+24
-7
@@ -8,6 +8,8 @@ import (
|
|||||||
"charm.land/bubbles/v2/list"
|
"charm.land/bubbles/v2/list"
|
||||||
tea "charm.land/bubbletea/v2"
|
tea "charm.land/bubbletea/v2"
|
||||||
"charm.land/lipgloss/v2"
|
"charm.land/lipgloss/v2"
|
||||||
|
zone "github.com/lrstanley/bubblezone/v2"
|
||||||
|
|
||||||
"github.com/anotherhadi/ilovetui/modal"
|
"github.com/anotherhadi/ilovetui/modal"
|
||||||
"github.com/anotherhadi/ilovetui/style"
|
"github.com/anotherhadi/ilovetui/style"
|
||||||
"github.com/anotherhadi/usbguard-tui/internal/guard"
|
"github.com/anotherhadi/usbguard-tui/internal/guard"
|
||||||
@@ -37,6 +39,15 @@ func actionModalStyle(status guard.Status) modal.Styles {
|
|||||||
|
|
||||||
func (a actionModal) Init() tea.Cmd { return nil }
|
func (a actionModal) Init() tea.Cmd { return nil }
|
||||||
|
|
||||||
|
func (a actionModal) confirmCmd(it actionItem) tea.Cmd {
|
||||||
|
if it.nixos {
|
||||||
|
rule := guard.NixOSRule(a.dev, it.status)
|
||||||
|
key := a.dev.VidPid
|
||||||
|
return tea.Batch(modal.Close(), func() tea.Msg { return nixRuleMsg{key: key, rule: rule} })
|
||||||
|
}
|
||||||
|
return tea.Batch(modal.Close(), doAction(a.dev.ID, it.fn, it.permanent))
|
||||||
|
}
|
||||||
|
|
||||||
func (a actionModal) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (a actionModal) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.KeyPressMsg:
|
case tea.KeyPressMsg:
|
||||||
@@ -48,13 +59,7 @@ func (a actionModal) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
if item == nil {
|
if item == nil {
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
it := item.(actionItem)
|
return a, a.confirmCmd(item.(actionItem))
|
||||||
if it.nixos {
|
|
||||||
rule := guard.NixOSRule(a.dev, it.status)
|
|
||||||
key := a.dev.VidPid
|
|
||||||
return a, tea.Batch(modal.Close(), func() tea.Msg { return nixRuleMsg{key: key, rule: rule} })
|
|
||||||
}
|
|
||||||
return a, tea.Batch(modal.Close(), doAction(a.dev.ID, it.fn, it.permanent))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case tea.MouseWheelMsg:
|
case tea.MouseWheelMsg:
|
||||||
@@ -65,6 +70,18 @@ func (a actionModal) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
a.list.CursorDown()
|
a.list.CursorDown()
|
||||||
}
|
}
|
||||||
return a, nil
|
return a, nil
|
||||||
|
|
||||||
|
case tea.MouseClickMsg:
|
||||||
|
if msg.Mouse().Button != tea.MouseLeft {
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
for i, item := range a.list.VisibleItems() {
|
||||||
|
if zone.Get(actionZoneID(i)).InBounds(msg) {
|
||||||
|
a.list.Select(i)
|
||||||
|
return a, a.confirmCmd(item.(actionItem))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd tea.Cmd
|
var cmd tea.Cmd
|
||||||
|
|||||||
+22
-6
@@ -3,14 +3,23 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"charm.land/bubbles/v2/list"
|
"charm.land/bubbles/v2/list"
|
||||||
tea "charm.land/bubbletea/v2"
|
tea "charm.land/bubbletea/v2"
|
||||||
"charm.land/lipgloss/v2"
|
"charm.land/lipgloss/v2"
|
||||||
|
zone "github.com/lrstanley/bubblezone/v2"
|
||||||
|
|
||||||
"github.com/anotherhadi/ilovetui/style"
|
"github.com/anotherhadi/ilovetui/style"
|
||||||
"github.com/anotherhadi/usbguard-tui/internal/guard"
|
"github.com/anotherhadi/usbguard-tui/internal/guard"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// deviceZoneID returns the bubblezone marker ID used to detect mouse clicks
|
||||||
|
// on a given device's row in the list.
|
||||||
|
func deviceZoneID(dev guard.Device) string {
|
||||||
|
return "device-" + strconv.Itoa(dev.ID)
|
||||||
|
}
|
||||||
|
|
||||||
var ruleStateIndicators = map[guard.RuleState]string{
|
var ruleStateIndicators = map[guard.RuleState]string{
|
||||||
guard.RulePermanent: "● perm",
|
guard.RulePermanent: "● perm",
|
||||||
guard.RuleTemporary: "○ tmp",
|
guard.RuleTemporary: "○ tmp",
|
||||||
@@ -65,10 +74,9 @@ func (d deviceDelegate) Render(w io.Writer, m list.Model, index int, item list.I
|
|||||||
|
|
||||||
permIndicator := ruleStateIndicators[dev.RuleState]
|
permIndicator := ruleStateIndicators[dev.RuleState]
|
||||||
width := m.Width()
|
width := m.Width()
|
||||||
fmt.Fprintf(w, "%s\n%s",
|
line1 := clampToWidth(nameStyle.Render(name), width)
|
||||||
clampToWidth(nameStyle.Render(name), width),
|
line2 := clampToWidth(descStyle.Render(fmt.Sprintf("id:%-3d %s %s %s", dev.ID, dev.VidPid, string(dev.Status), permIndicator)), width)
|
||||||
clampToWidth(descStyle.Render(fmt.Sprintf("id:%-3d %s %s %s", dev.ID, dev.VidPid, string(dev.Status), permIndicator)), width),
|
fmt.Fprint(w, zone.Mark(deviceZoneID(dev), line1+"\n"+line2))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type actionItem struct {
|
type actionItem struct {
|
||||||
@@ -89,18 +97,26 @@ func (d actionDelegate) Height() int { return 1 }
|
|||||||
func (d actionDelegate) Spacing() int { return 0 }
|
func (d actionDelegate) Spacing() int { return 0 }
|
||||||
func (d actionDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil }
|
func (d actionDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil }
|
||||||
|
|
||||||
|
// actionZoneID returns the bubblezone marker ID used to detect mouse clicks
|
||||||
|
// on a given row of the action modal's list.
|
||||||
|
func actionZoneID(index int) string {
|
||||||
|
return "action-" + strconv.Itoa(index)
|
||||||
|
}
|
||||||
|
|
||||||
func (d actionDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
|
func (d actionDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
|
||||||
a, ok := item.(actionItem)
|
a, ok := item.(actionItem)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var content string
|
||||||
if index == m.Index() {
|
if index == m.Index() {
|
||||||
clr, ok := statusColorsSelected[a.status]
|
clr, ok := statusColorsSelected[a.status]
|
||||||
if !ok {
|
if !ok {
|
||||||
clr = style.S.Primary
|
clr = style.S.Primary
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, " %s", lipgloss.NewStyle().Bold(true).Foreground(clr).Render("> "+a.label))
|
content = fmt.Sprintf(" %s", lipgloss.NewStyle().Bold(true).Foreground(clr).Render("> "+a.label))
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(w, " %s", a.label)
|
content = fmt.Sprintf(" %s", a.label)
|
||||||
}
|
}
|
||||||
|
fmt.Fprint(w, zone.Mark(actionZoneID(index), content))
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-5
@@ -11,6 +11,7 @@ import (
|
|||||||
tea "charm.land/bubbletea/v2"
|
tea "charm.land/bubbletea/v2"
|
||||||
"charm.land/lipgloss/v2"
|
"charm.land/lipgloss/v2"
|
||||||
"github.com/charmbracelet/x/ansi"
|
"github.com/charmbracelet/x/ansi"
|
||||||
|
zone "github.com/lrstanley/bubblezone/v2"
|
||||||
|
|
||||||
"github.com/anotherhadi/ilovetui/app"
|
"github.com/anotherhadi/ilovetui/app"
|
||||||
"github.com/anotherhadi/ilovetui/bubbles"
|
"github.com/anotherhadi/ilovetui/bubbles"
|
||||||
@@ -41,6 +42,7 @@ type deviceSummary struct {
|
|||||||
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
list list.Model
|
list list.Model
|
||||||
|
devices []guard.Device
|
||||||
help helpbar.Model
|
help helpbar.Model
|
||||||
daemonStatus string
|
daemonStatus string
|
||||||
defaultPolicy guard.Status
|
defaultPolicy guard.Status
|
||||||
@@ -64,6 +66,10 @@ func New() Model {
|
|||||||
l.DisableQuitKeybindings()
|
l.DisableQuitKeybindings()
|
||||||
l.KeyMap.CursorUp = key.NewBinding(key.WithKeys("up", "k"), key.WithHelp("↑/k", "up"))
|
l.KeyMap.CursorUp = key.NewBinding(key.WithKeys("up", "k"), key.WithHelp("↑/k", "up"))
|
||||||
l.KeyMap.CursorDown = key.NewBinding(key.WithKeys("down", "j"), key.WithHelp("↓/j", "down"))
|
l.KeyMap.CursorDown = key.NewBinding(key.WithKeys("down", "j"), key.WithHelp("↓/j", "down"))
|
||||||
|
l.Styles.TitleBar = l.Styles.TitleBar.PaddingLeft(1)
|
||||||
|
l.Styles.Filter.Focused.Prompt = l.Styles.Filter.Focused.Prompt.Foreground(style.S.Muted)
|
||||||
|
l.Styles.Filter.Blurred.Prompt = l.Styles.Filter.Blurred.Prompt.Foreground(style.S.Muted)
|
||||||
|
l.FilterInput.SetStyles(l.Styles.Filter)
|
||||||
|
|
||||||
h := helpbar.New(
|
h := helpbar.New(
|
||||||
helpbar.WithToggle(listKeys.Help),
|
helpbar.WithToggle(listKeys.Help),
|
||||||
@@ -131,10 +137,8 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
|||||||
return m, tea.Batch(fetchDevices, fetchDaemonStatus, fetchDefaultPolicy, tickCmd())
|
return m, tea.Batch(fetchDevices, fetchDaemonStatus, fetchDefaultPolicy, tickCmd())
|
||||||
|
|
||||||
case devicesMsg:
|
case devicesMsg:
|
||||||
items := make([]list.Item, len(msg))
|
|
||||||
summary := deviceSummary{total: len(msg)}
|
summary := deviceSummary{total: len(msg)}
|
||||||
for i, d := range msg {
|
for _, d := range msg {
|
||||||
items[i] = d
|
|
||||||
switch d.Status {
|
switch d.Status {
|
||||||
case guard.Allowed:
|
case guard.Allowed:
|
||||||
summary.allowed++
|
summary.allowed++
|
||||||
@@ -145,6 +149,14 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.deviceCounts = summary
|
m.deviceCounts = summary
|
||||||
|
if slices.Equal(m.devices, msg) {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
m.devices = msg
|
||||||
|
items := make([]list.Item, len(msg))
|
||||||
|
for i, d := range msg {
|
||||||
|
items[i] = d
|
||||||
|
}
|
||||||
cmd := m.list.SetItems(items)
|
cmd := m.list.SetItems(items)
|
||||||
m.resizeList()
|
m.resizeList()
|
||||||
return m, cmd
|
return m, cmd
|
||||||
@@ -192,6 +204,24 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
|||||||
m.list.CursorDown()
|
m.list.CursorDown()
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
|
case tea.MouseClickMsg:
|
||||||
|
if m.ModalOpen || msg.Mouse().Button != tea.MouseLeft {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
for i, item := range m.list.VisibleItems() {
|
||||||
|
dev := item.(guard.Device)
|
||||||
|
if zone.Get(deviceZoneID(dev)).InBounds(msg) {
|
||||||
|
alreadyFocused := i == m.list.Index()
|
||||||
|
m.list.Select(i)
|
||||||
|
if alreadyFocused {
|
||||||
|
return m, modal.Show(dev.Name, newActionModal(dev, m.rulesManaged),
|
||||||
|
modal.WithModalStyle(actionModalStyle(dev.Status)))
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.ModalOpen {
|
if m.ModalOpen {
|
||||||
@@ -245,8 +275,12 @@ func (m Model) updateList(msg tea.KeyPressMsg) (Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
prevFilterState := m.list.FilterState()
|
||||||
var cmd tea.Cmd
|
var cmd tea.Cmd
|
||||||
m.list, cmd = m.list.Update(msg)
|
m.list, cmd = m.list.Update(msg)
|
||||||
|
if m.list.FilterState() != prevFilterState {
|
||||||
|
m.resizeList()
|
||||||
|
}
|
||||||
return m, cmd
|
return m, cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +288,19 @@ func (m Model) View() string {
|
|||||||
header := m.renderHeader()
|
header := m.renderHeader()
|
||||||
listView := strings.TrimRight(m.list.View(), "\n")
|
listView := strings.TrimRight(m.list.View(), "\n")
|
||||||
helpView := strings.TrimRight(m.help.View(m.helpBindings()...), "\n")
|
helpView := strings.TrimRight(m.help.View(m.helpBindings()...), "\n")
|
||||||
return strings.Join([]string{header, listView, helpView}, "\n")
|
lines := []string{header}
|
||||||
|
if filterLine := m.renderFilterLine(); filterLine != "" {
|
||||||
|
lines = append(lines, filterLine)
|
||||||
|
}
|
||||||
|
lines = append(lines, listView, helpView)
|
||||||
|
return strings.Join(lines, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Model) renderFilterLine() string {
|
||||||
|
if m.list.FilterState() != list.FilterApplied {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return filterLabelStyle.Render("Filter: ") + m.list.FilterValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Model) helpBindings() []key.Binding {
|
func (m Model) helpBindings() []key.Binding {
|
||||||
@@ -367,7 +413,11 @@ func (m Model) renderPendingRulesLine() string {
|
|||||||
func (m Model) listHeight() int {
|
func (m Model) listHeight() int {
|
||||||
headerH := lipgloss.Height(m.renderHeader())
|
headerH := lipgloss.Height(m.renderHeader())
|
||||||
helpH := m.help.Height(m.helpBindings()...)
|
helpH := m.help.Height(m.helpBindings()...)
|
||||||
return m.height - headerH - helpH
|
h := m.height - headerH - helpH
|
||||||
|
if m.list.FilterState() == list.FilterApplied {
|
||||||
|
h--
|
||||||
|
}
|
||||||
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) resizeList() {
|
func (m *Model) resizeList() {
|
||||||
|
|||||||
@@ -36,5 +36,9 @@ var (
|
|||||||
PaddingLeft(1).
|
PaddingLeft(1).
|
||||||
Width(16)
|
Width(16)
|
||||||
|
|
||||||
|
filterLabelStyle = lipgloss.NewStyle().
|
||||||
|
Foreground(style.S.Muted).
|
||||||
|
PaddingLeft(1)
|
||||||
|
|
||||||
warnStyle = lipgloss.NewStyle().Foreground(style.S.Warning)
|
warnStyle = lipgloss.NewStyle().Foreground(style.S.Warning)
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user