diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-26 23:33:55 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-26 23:33:55 +0200 |
| commit | 4ca34f040203c8e31603bbb39fd38632b68067d8 (patch) | |
| tree | eed81b39e169eb6d0cd7d2eca6b338c7c0914ba4 /internal/tui/eventstream/exportmodal.go | |
| parent | e5cb5db2292ae84680935767d455a777125e0fe9 (diff) | |
tui: add paused stream CSV export and foreground editor open
Diffstat (limited to 'internal/tui/eventstream/exportmodal.go')
| -rw-r--r-- | internal/tui/eventstream/exportmodal.go | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/internal/tui/eventstream/exportmodal.go b/internal/tui/eventstream/exportmodal.go new file mode 100644 index 0000000..cf020f7 --- /dev/null +++ b/internal/tui/eventstream/exportmodal.go @@ -0,0 +1,105 @@ +package eventstream + +import ( + "strings" + + "github.com/charmbracelet/bubbles/textinput" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" +) + +type ExportModal struct { + visible bool + textInput textinput.Model + err string +} + +func NewExportModal() ExportModal { + input := textinput.New() + input.Prompt = "" + input.CharLimit = 0 + input.Width = 44 + return ExportModal{textInput: input} +} + +func (m ExportModal) Visible() bool { + return m.visible +} + +func (m ExportModal) Open(defaultName string) ExportModal { + m.visible = true + m.err = "" + m.textInput.SetValue(defaultName) + m.textInput.CursorEnd() + m.textInput.Focus() + return m +} + +func (m ExportModal) Close() ExportModal { + m.visible = false + m.err = "" + m.textInput.Blur() + return m +} + +// Update returns updated modal, submitted filename, and whether submit occurred. +func (m ExportModal) Update(msg tea.Msg) (ExportModal, string, bool) { + if !m.visible { + return m, "", false + } + if keyMsg, ok := msg.(tea.KeyMsg); ok { + switch keyMsg.String() { + case "esc": + return m.Close(), "", false + case "enter": + filename := strings.TrimSpace(m.textInput.Value()) + if filename == "" { + m.err = "filename is required" + return m, "", false + } + return m.Close(), filename, true + } + } + var cmd tea.Cmd + m.textInput, cmd = m.textInput.Update(msg) + _ = cmd + return m, "", false +} + +func (m ExportModal) View(width, height int) string { + if !m.visible { + return "" + } + if width <= 0 { + width = 80 + } + if height <= 0 { + height = 24 + } + modalWidth := 74 + if width < modalWidth+4 { + modalWidth = width - 4 + if modalWidth < 44 { + modalWidth = 44 + } + } + + lines := []string{ + "Export Stream CSV", + "", + "Filename:", + m.textInput.View(), + } + if m.err != "" { + lines = append(lines, "Error: "+m.err) + } + lines = append(lines, "", "Enter save • Esc cancel") + + box := lipgloss.NewStyle(). + Border(lipgloss.RoundedBorder()). + Padding(1, 2). + Width(modalWidth). + Render(strings.Join(lines, "\n")) + + return lipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, box) +} |
