This commit is contained in:
2026-04-22 16:12:50 +02:00
parent 26a098baec
commit 0ee35713a4
11 changed files with 853 additions and 0 deletions
+151
View File
@@ -0,0 +1,151 @@
package main
import (
"time"
"charm.land/bubbles/v2/help"
"charm.land/bubbles/v2/key"
"charm.land/bubbles/v2/textinput"
tea "charm.land/bubbletea/v2"
)
type model struct {
err error
width int
height int
amount int
keys keyMap
services []Service
filtered []Service
query textinput.Model
cursor int
offset int
help help.Model
system System
detail Detail
}
func initModel() model {
query := textinput.New()
query.Placeholder = "Search..."
return model{
keys: keys,
query: query,
help: help.New(),
}
}
func (m model) Init() tea.Cmd {
return tea.Batch(LoadSystem, m.TickDetails())
}
type DetailTickMsg struct{}
func (m *model) TickDetails() tea.Cmd {
return tea.Tick(1*time.Second, func(time.Time) tea.Msg {
return DetailTickMsg{}
})
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.query.SetWidth(msg.Width)
m.help.SetWidth(msg.Width)
m.width = msg.Width
m.height = msg.Height
m.calcAmount()
return m, nil
case ServicesLoadedMsg:
m.services = msg.services
m.err = msg.err
m.filterServices()
return m, m.LoadDetail
case SystemLoadedMsg:
m.system = msg.System
m.err = msg.Err
return m, LoadServices
case DetailLoadedMsg:
m.detail = msg.Detail
m.err = msg.Err
for si, s := range m.services {
if s.Name == msg.Detail.Name && s.Active != msg.Detail.Active {
m.services[si].Active = msg.Detail.Active
for fi, f := range m.filtered {
if f.Name == msg.Detail.Name {
m.filtered[fi].Active = msg.Detail.Active
}
}
}
}
return m, nil
case DetailTickMsg:
return m, tea.Batch(m.LoadDetail, m.TickDetails())
case tea.KeyPressMsg:
if m.query.Focused() {
switch {
case key.Matches(msg, m.keys.Back), key.Matches(msg, m.keys.Enter):
m.query.Blur()
case key.Matches(msg, m.keys.Help):
m.help.ShowAll = !m.help.ShowAll
}
m.query, cmd = m.query.Update(msg)
m.filterServices()
return m, tea.Batch(cmd, m.LoadDetail)
}
switch {
case key.Matches(msg, m.keys.Up):
if m.cursor > 0 {
m.cursor--
if m.cursor < m.offset {
m.offset--
}
}
return m, m.LoadDetail
case key.Matches(msg, m.keys.Down):
if m.cursor < len(m.filtered)-1 {
m.cursor++
if m.cursor >= m.offset+m.amount {
m.offset++
}
}
return m, m.LoadDetail
case key.Matches(msg, m.keys.Search):
m.query.Focus()
case key.Matches(msg, m.keys.Back):
m.query.Blur()
case key.Matches(msg, m.keys.Enter):
s := m.filtered[m.cursor]
if s.Active != "active" {
m.StartService()
} else {
m.StopService()
}
case key.Matches(msg, m.keys.Reload):
return m, LoadServices
case key.Matches(msg, m.keys.Help):
m.help.ShowAll = !m.help.ShowAll
m.calcAmount()
case key.Matches(msg, m.keys.Quit):
return m, tea.Quit
}
}
return m, cmd
}
func (m *model) calcAmount() {
m.amount = (m.height - 2 - If(m.help.ShowAll, 2, 1)) / 3
}