feat: add inbox
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
package inbox
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type tuiModel struct {
|
||||
store Store
|
||||
records []Record
|
||||
cursor int
|
||||
detail bool
|
||||
message string
|
||||
}
|
||||
|
||||
func RunTUI(store Store) error {
|
||||
_, err := tea.NewProgram(newTUIModel(store)).Run()
|
||||
return err
|
||||
}
|
||||
|
||||
func newTUIModel(store Store) tuiModel {
|
||||
model := tuiModel{store: store}
|
||||
model.reload()
|
||||
return model
|
||||
}
|
||||
|
||||
func (m tuiModel) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m tuiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
key, ok := msg.(tea.KeyMsg)
|
||||
if !ok {
|
||||
return m, nil
|
||||
}
|
||||
switch key.String() {
|
||||
case "q", "ctrl+c":
|
||||
return m, tea.Quit
|
||||
case "up", "k":
|
||||
if m.cursor > 0 {
|
||||
m.cursor--
|
||||
}
|
||||
case "down", "j":
|
||||
if m.cursor < len(m.records)-1 {
|
||||
m.cursor++
|
||||
}
|
||||
case "enter":
|
||||
m.detail = !m.detail
|
||||
case "r":
|
||||
m.reload()
|
||||
case "d":
|
||||
if len(m.records) == 0 {
|
||||
return m, nil
|
||||
}
|
||||
rec := m.records[m.cursor]
|
||||
n, err := m.store.MarkDone([]string{rec.ID})
|
||||
if err != nil {
|
||||
m.message = err.Error()
|
||||
return m, nil
|
||||
}
|
||||
m.message = fmt.Sprintf("marked %d done", n)
|
||||
m.reload()
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m tuiModel) View() string {
|
||||
var b strings.Builder
|
||||
b.WriteString("agent-notify inbox\n")
|
||||
b.WriteString("j/k move enter details d done r reload q quit\n\n")
|
||||
if m.message != "" {
|
||||
b.WriteString(m.message)
|
||||
b.WriteString("\n\n")
|
||||
}
|
||||
if len(m.records) == 0 {
|
||||
b.WriteString("No pending notifications.\n")
|
||||
return b.String()
|
||||
}
|
||||
for i, rec := range m.records {
|
||||
prefix := " "
|
||||
if i == m.cursor {
|
||||
prefix = "> "
|
||||
}
|
||||
fmt.Fprintf(&b, "%s%s %s %s/%s %s %s\n", prefix, rec.ID, rec.Host, rec.Agent, rec.Event, rec.CWD, rec.Title)
|
||||
if i == m.cursor && m.detail {
|
||||
if rec.Body != "" {
|
||||
fmt.Fprintf(&b, " body: %s\n", rec.Body)
|
||||
}
|
||||
if !rec.Time.IsZero() {
|
||||
fmt.Fprintf(&b, " time: %s\n", rec.Time.Local().Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
if rec.Tmux.Pane != "" {
|
||||
fmt.Fprintf(&b, " tmux pane: %s\n", rec.Tmux.Pane)
|
||||
}
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (m *tuiModel) reload() {
|
||||
records, err := m.store.Pending()
|
||||
if err != nil {
|
||||
m.message = err.Error()
|
||||
return
|
||||
}
|
||||
m.records = records
|
||||
if m.cursor >= len(m.records) {
|
||||
m.cursor = len(m.records) - 1
|
||||
}
|
||||
if m.cursor < 0 {
|
||||
m.cursor = 0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user