diff --git a/go.mod b/go.mod index b3e872a..5aec5d2 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/lukaszraczylo/lolcathost go 1.26.0 require ( - github.com/charmbracelet/bubbles v1.0.0 - github.com/charmbracelet/bubbletea v1.3.10 - github.com/charmbracelet/lipgloss v1.1.0 + charm.land/bubbles/v2 v2.2.1 + charm.land/bubbletea/v2 v2.0.10 + charm.land/lipgloss/v2 v2.0.6 github.com/fsnotify/fsnotify v1.10.1 github.com/lukaszraczylo/oss-telemetry v0.2.5 github.com/stretchr/testify v1.12.1 @@ -15,23 +15,19 @@ require ( require ( github.com/atotto/clipboard v0.1.4 // indirect - github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/charmbracelet/colorprofile v0.4.3 // indirect + github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 // indirect github.com/charmbracelet/x/ansi v0.11.8 // indirect - github.com/charmbracelet/x/cellbuf v0.0.15 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect + github.com/charmbracelet/x/termios v0.1.1 // indirect + github.com/charmbracelet/x/windows v0.2.2 // indirect github.com/clipperhouse/displaywidth v0.11.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect - github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/lucasb-eyer/go-colorful v1.4.1 // indirect - github.com/mattn/go-isatty v0.0.24 // indirect - github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.30 // indirect - github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/termenv v0.16.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/xo/terminfo v1.2.0 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect - golang.org/x/text v0.42.0 // indirect + golang.org/x/sync v0.23.0 // indirect ) diff --git a/go.sum b/go.sum index 1fe2f6c..962cc0d 100644 --- a/go.sum +++ b/go.sum @@ -1,49 +1,41 @@ +charm.land/bubbles/v2 v2.2.1 h1:Fq1+qm5hV6GkvzLQDhCBpXXE5tLgvh1PRriCLwSvIQU= +charm.land/bubbles/v2 v2.2.1/go.mod h1:wdMgn+sje1KNXdwFizIWjbf328fIUBxqEmJ/vYPo8yc= +charm.land/bubbletea/v2 v2.0.10 h1:oolvo20VBpI0PfqE7iFjkZ1bx0WpmXGfnKz5Yldjq5o= +charm.land/bubbletea/v2 v2.0.10/go.mod h1:QOatcnhOjYIfxzUSTz6raF7Ex4R/rIuHa3SnBdCCpMc= +charm.land/lipgloss/v2 v2.0.6 h1:EaGKeuA8FvF+v2BT5VmZd2LoYLaMZJXA5n34th8nCIQ= +charm.land/lipgloss/v2 v2.0.6/go.mod h1:ipDDJNSGa1hlwDtSfW1s2/xR8Vdhbut4PXh2zEKZd0Q= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= -github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY= -github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= -github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= -github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= -github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= -github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= +github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= +github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q= github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q= -github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= -github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 h1:rdnVWKgJpTVXKuKuJyxDJ+NFJdUaUqGvyGy61OcvlbA= +github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886/go.mod h1:nAw0d9PhFp1qdzi2xhQU5YOu5sVpDIHWlaW2Uz/bCro= github.com/charmbracelet/x/ansi v0.11.8 h1:JMFwp0CgDC2+jcOB162HH5k7I3FVbgFSMMYg7dSPBQQ= github.com/charmbracelet/x/ansi v0.11.8/go.mod h1:ZNN+3mXny/516oTQPLMPIBeSINvNJJQ8uQXDgbeJxY0= -github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= -github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +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/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= 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/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= +github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM= +github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k= github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8= 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/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/lucasb-eyer/go-colorful v1.4.1 h1:1EO+WB73+EH8EVbzlrG3KLAfEypQWVHIBqlTf+2hNss= github.com/lucasb-eyer/go-colorful v1.4.1/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lukaszraczylo/oss-telemetry v0.2.5 h1:W6Qgwp7IY4yBRO361MmnEAmM59motdQpbAFAx8v6fJM= github.com/lukaszraczylo/oss-telemetry v0.2.5/go.mod h1:+Cn78qZo8rc3T9eZt0v3oICYRdd75wORtSidc8lNjDQ= -github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= -github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= -github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= -github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.30 h1:+KUuiDA4fF0R1p5FeueHefjDm+GIM+kWfFnDjybOPgk= github.com/mattn/go-runewidth v0.0.30/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= 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/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= -github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= @@ -52,11 +44,10 @@ github.com/xo/terminfo v1.2.0 h1:d0ZTOCpuGE0lwSAOs0zcJjwz3jWQyqcRt9XbGJpCOl4= github.com/xo/terminfo v1.2.0/go.mod h1:lGzkSo8Fe7IRh/w+Gqz7n5mDog4FVXCj3gy/DYTBqio= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= +golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= -golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= -golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= 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/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/tui/app.go b/internal/tui/app.go index 6f4e6f4..59318cf 100644 --- a/internal/tui/app.go +++ b/internal/tui/app.go @@ -7,9 +7,9 @@ import ( "strings" "time" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "charm.land/bubbles/v2/textinput" + tea "charm.land/bubbletea/v2" + "charm.land/lipgloss/v2" "github.com/lukaszraczylo/lolcathost/internal/client" "github.com/lukaszraczylo/lolcathost/internal/config" @@ -143,7 +143,7 @@ func NewModel(socketPath string) *Model { searchInput := textinput.New() searchInput.Placeholder = "Search..." searchInput.CharLimit = 100 - searchInput.Width = 50 + searchInput.SetWidth(50) return &Model{ client: client.New(socketPath), @@ -161,7 +161,6 @@ func NewModel(socketPath string) *Model { func (m *Model) Init() tea.Cmd { return tea.Batch( m.connect(), - tea.SetWindowTitle("lolcathost"), m.tick(), m.checkForUpdate(), ) @@ -330,9 +329,9 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if searchWidth > 60 { searchWidth = 60 } - m.searchInput.Width = searchWidth + m.searchInput.SetWidth(searchWidth) - case tea.KeyMsg: + case tea.KeyPressMsg: cmd := m.handleKey(msg) if cmd != nil { cmds = append(cmds, cmd) @@ -505,7 +504,7 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, tea.Batch(cmds...) } -func (m *Model) handleKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleKey(msg tea.KeyPressMsg) tea.Cmd { // Global keys switch msg.String() { case "ctrl+c": @@ -535,7 +534,7 @@ func (m *Model) handleKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleListKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleListKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "q": return tea.Quit @@ -549,7 +548,7 @@ func (m *Model) handleListKey(msg tea.KeyMsg) tea.Cmd { m.list.MoveUp() case "down", "j": m.list.MoveDown() - case " ", "enter": + case "space", "enter": return m.toggleSelected() case "n": m.mode = ViewForm @@ -587,7 +586,7 @@ func (m *Model) handleListKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleFormKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleFormKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "esc": m.mode = ViewList @@ -615,7 +614,7 @@ func (m *Model) handleFormKey(msg tea.KeyMsg) tea.Cmd { return m.form.Update(msg) } -func (m *Model) handlePresetKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handlePresetKey(msg tea.KeyPressMsg) tea.Cmd { // Handle based on preset picker mode switch m.presetPicker.Mode() { case PresetModeSelect: @@ -630,7 +629,7 @@ func (m *Model) handlePresetKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handlePresetSelectKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handlePresetSelectKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "esc", "q": m.mode = ViewList @@ -652,7 +651,7 @@ func (m *Model) handlePresetSelectKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handlePresetFormKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handlePresetFormKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "esc": m.presetPicker.CancelForm() @@ -690,7 +689,7 @@ func (m *Model) handlePresetFormKey(msg tea.KeyMsg) tea.Cmd { return m.presetPicker.Update(msg) } -func (m *Model) handlePresetPickerKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handlePresetPickerKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "esc": m.presetPicker.ClosePicker() @@ -700,13 +699,13 @@ func (m *Model) handlePresetPickerKey(msg tea.KeyMsg) tea.Cmd { m.presetPicker.PickerMoveUp() case "down", "j": m.presetPicker.PickerMoveDown() - case " ": + case "space": m.presetPicker.TogglePickerSelection() } return nil } -func (m *Model) handlePresetDeleteKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handlePresetDeleteKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "y", "Y": if preset := m.presetPicker.Selected(); preset != "" { @@ -719,7 +718,7 @@ func (m *Model) handlePresetDeleteKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleGroupKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleGroupKey(msg tea.KeyPressMsg) tea.Cmd { // Handle based on group picker mode switch m.groupPicker.Mode() { case GroupModeSelect: @@ -732,7 +731,7 @@ func (m *Model) handleGroupKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleGroupSelectKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleGroupSelectKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "esc", "q": m.mode = ViewList @@ -750,7 +749,7 @@ func (m *Model) handleGroupSelectKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleGroupFormKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleGroupFormKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "esc": m.groupPicker.CancelForm() @@ -770,7 +769,7 @@ func (m *Model) handleGroupFormKey(msg tea.KeyMsg) tea.Cmd { return m.groupPicker.Update(msg) } -func (m *Model) handleGroupDeleteKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleGroupDeleteKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "y", "Y": if group := m.groupPicker.Selected(); group != "" { @@ -783,7 +782,7 @@ func (m *Model) handleGroupDeleteKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleBackupKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleBackupKey(msg tea.KeyPressMsg) tea.Cmd { switch m.backupPicker.Mode() { case BackupModeSelect: return m.handleBackupSelectKey(msg) @@ -793,7 +792,7 @@ func (m *Model) handleBackupKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleBackupSelectKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleBackupSelectKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "esc", "q": m.mode = ViewList @@ -821,7 +820,7 @@ func (m *Model) handleBackupSelectKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleBackupRestoreKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleBackupRestoreKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "y", "Y": if backup := m.backupPicker.Selected(); backup != "" { @@ -834,7 +833,7 @@ func (m *Model) handleBackupRestoreKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleHelpKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleHelpKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "esc", "q", "?": m.mode = ViewList @@ -842,7 +841,7 @@ func (m *Model) handleHelpKey(msg tea.KeyMsg) tea.Cmd { return nil } -func (m *Model) handleSearchKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleSearchKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "esc": m.mode = ViewList @@ -860,7 +859,7 @@ func (m *Model) handleSearchKey(msg tea.KeyMsg) tea.Cmd { return cmd } -func (m *Model) handleConfirmDeleteKey(msg tea.KeyMsg) tea.Cmd { +func (m *Model) handleConfirmDeleteKey(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "y", "Y": alias := m.pendingDeleteAlias @@ -900,7 +899,14 @@ func (m *Model) setSuccess(msg string) { } // View renders the UI. -func (m *Model) View() string { +func (m *Model) View() tea.View { + v := tea.NewView(m.render()) + v.AltScreen = true + v.WindowTitle = "lolcathost" + return v +} + +func (m *Model) render() string { var sb strings.Builder // Title with version @@ -1142,7 +1148,7 @@ func RunWithVersion(socketPath, version, githubOwner, githubRepo string) error { m.version = version m.githubOwner = githubOwner m.githubRepo = githubRepo - p := tea.NewProgram(m, tea.WithAltScreen()) + p := tea.NewProgram(m) _, err := p.Run() return err diff --git a/internal/tui/app_test.go b/internal/tui/app_test.go new file mode 100644 index 0000000..5476c4b --- /dev/null +++ b/internal/tui/app_test.go @@ -0,0 +1,25 @@ +package tui + +import ( + "testing" + + tea "charm.land/bubbletea/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestModel_View_UsesAltScreenAndTitle(t *testing.T) { + m := NewModel("/nonexistent.sock") + + v := m.View() + + assert.True(t, v.AltScreen) + assert.Equal(t, "lolcathost", v.WindowTitle) + assert.Contains(t, v.Content, "lolcathost - Host Management") +} + +func TestModel_SpaceKeyIsNamedSpace(t *testing.T) { + msg := tea.KeyPressMsg{Code: tea.KeySpace, Text: " "} + + require.Equal(t, "space", msg.String()) +} diff --git a/internal/tui/backups.go b/internal/tui/backups.go index 2c4b943..25e0f9d 100644 --- a/internal/tui/backups.go +++ b/internal/tui/backups.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/charmbracelet/lipgloss" + "charm.land/lipgloss/v2" "github.com/lukaszraczylo/lolcathost/internal/protocol" ) diff --git a/internal/tui/form.go b/internal/tui/form.go index b9b54f7..11660ba 100644 --- a/internal/tui/form.go +++ b/internal/tui/form.go @@ -5,8 +5,8 @@ import ( "fmt" "strings" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" + "charm.land/bubbles/v2/textinput" + tea "charm.land/bubbletea/v2" "github.com/lukaszraczylo/lolcathost/internal/config" ) @@ -127,14 +127,14 @@ func (f *Form) SetSize(width, height int) { inputWidth := min(50, width-10) for i := range f.fields { - f.fields[i].Width = inputWidth + f.fields[i].SetWidth(inputWidth) } } // Update handles input events. func (f *Form) Update(msg tea.Msg) tea.Cmd { switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: // Handle group dropdown navigation if f.focus == FieldGroup { switch msg.String() { diff --git a/internal/tui/groups.go b/internal/tui/groups.go index 79da20f..0d98413 100644 --- a/internal/tui/groups.go +++ b/internal/tui/groups.go @@ -4,8 +4,8 @@ package tui import ( "strings" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" + "charm.land/bubbles/v2/textinput" + tea "charm.land/bubbletea/v2" ) // GroupMode represents the group view mode. @@ -53,7 +53,7 @@ func (g *GroupPicker) SetGroups(groups []string) { func (g *GroupPicker) SetSize(width, height int) { g.width = width g.height = height - g.input.Width = min(50, width-10) + g.input.SetWidth(min(50, width-10)) } // MoveUp moves the cursor up. @@ -126,7 +126,7 @@ func (g *GroupPicker) CancelForm() { } // Update handles input events for form mode. -func (g *GroupPicker) Update(msg tea.KeyMsg) tea.Cmd { +func (g *GroupPicker) Update(msg tea.KeyPressMsg) tea.Cmd { var cmd tea.Cmd g.input, cmd = g.input.Update(msg) return cmd diff --git a/internal/tui/list.go b/internal/tui/list.go index 828398e..6125a39 100644 --- a/internal/tui/list.go +++ b/internal/tui/list.go @@ -5,8 +5,8 @@ import ( "fmt" "strings" - "github.com/charmbracelet/lipgloss" - "github.com/charmbracelet/lipgloss/table" + "charm.land/lipgloss/v2" + "charm.land/lipgloss/v2/table" "github.com/lukaszraczylo/lolcathost/internal/protocol" ) diff --git a/internal/tui/presets.go b/internal/tui/presets.go index dda707d..58c96f7 100644 --- a/internal/tui/presets.go +++ b/internal/tui/presets.go @@ -4,8 +4,8 @@ package tui import ( "strings" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" + "charm.land/bubbles/v2/textinput" + tea "charm.land/bubbletea/v2" "github.com/lukaszraczylo/lolcathost/internal/protocol" ) @@ -108,7 +108,7 @@ func (p *PresetPicker) SetSize(width, height int) { inputWidth := min(60, width-10) for i := range p.fields { - p.fields[i].Width = inputWidth + p.fields[i].SetWidth(inputWidth) } } @@ -223,7 +223,7 @@ func (p *PresetPicker) CancelForm() { } // Update handles input events for form mode. -func (p *PresetPicker) Update(msg tea.KeyMsg) tea.Cmd { +func (p *PresetPicker) Update(msg tea.KeyPressMsg) tea.Cmd { switch msg.String() { case "tab", "down": p.nextField() diff --git a/internal/tui/styles.go b/internal/tui/styles.go index 16df6d1..4b80ebf 100644 --- a/internal/tui/styles.go +++ b/internal/tui/styles.go @@ -4,7 +4,7 @@ package tui import ( "strings" - "github.com/charmbracelet/lipgloss" + "charm.land/lipgloss/v2" ) // Colors - matching kportal style, optimized for dark terminals