summaryrefslogtreecommitdiff
path: root/internal/tui/eventstream/exportmodal.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-26 23:33:55 +0200
committerPaul Buetow <paul@buetow.org>2026-02-26 23:33:55 +0200
commit4ca34f040203c8e31603bbb39fd38632b68067d8 (patch)
treeeed81b39e169eb6d0cd7d2eca6b338c7c0914ba4 /internal/tui/eventstream/exportmodal.go
parente5cb5db2292ae84680935767d455a777125e0fe9 (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.go105
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)
+}