package modes import ( "github.com/patriceckhart/zot/packages/tui" ) // sessionOpsDialog is the picker shown when the user runs `/session` // without an argument. It offers timeline inspection, portable-file // operations, and branch navigation for the current conversation. // // Shape mirrors telegramDialog and logoutDialog: tiny list, arrow // keys to move, enter to pick, esc to cancel. type sessionOpsDialog struct { active bool items []sessionOpsItem cursor int } type sessionOpsItem struct { label string action string // "timeline" | "export" | "import" | "fork" | "tree" hint string } type sessionOpsAction struct { Select bool Action string Close bool } func newSessionOpsDialog() *sessionOpsDialog { return &sessionOpsDialog{} } // Open shows the picker with the actions supplied by the caller. func (d *sessionOpsDialog) Open(items []sessionOpsItem) bool { if len(items) == 0 { return false } d.items = items d.cursor = 0 d.active = true return true } // Close hides the dialog. func (d *sessionOpsDialog) Close() { d.active = false } // Active reports whether the dialog is consuming input. func (d *sessionOpsDialog) Active() bool { return d != nil && d.active } // HandleKey advances the selection or resolves the dialog. func (d *sessionOpsDialog) HandleKey(k tui.Key) sessionOpsAction { switch k.Kind { case tui.KeyUp: if d.cursor > 0 { d.cursor-- } case tui.KeyDown: if d.cursor < len(d.items)-1 { d.cursor++ } case tui.KeyEsc: d.Close() return sessionOpsAction{Close: true} case tui.KeyEnter: if len(d.items) == 0 { d.Close() return sessionOpsAction{Close: true} } it := d.items[d.cursor] d.Close() return sessionOpsAction{Select: true, Action: it.action} } return sessionOpsAction{} } // Render returns the dialog lines. func (d *sessionOpsDialog) Render(th tui.Theme, width int) []string { if !d.Active() { return nil } var lines []string lines = append(lines, frameHeader(th, "session", width)) lines = append(lines, th.FG256(th.Muted, "pick an action (\u2191/\u2193, enter, esc to cancel):")) for i, it := range d.items { text := " " + it.label if it.hint != "" { text += " (" + it.hint + ")" } if i == d.cursor { lines = append(lines, th.PadHighlight(text, width)) } else { lines = append(lines, th.FG256(th.Muted, text)) } } lines = append(lines, frameRule(th, width)) return lines }