logout_dialog.go RawHistoryFolder
1package modes
2
3import (
4 "github.com/bnema/zut/packages/tui"
5)
6
7// logoutDialog is the picker shown when the user runs `/logout`
8// without an argument. Lists each provider the user is currently
9// logged into (apikey or oauth), plus an "all" entry and a cancel.
10// Up/down to move, enter to pick, esc to cancel.
11type logoutDialog struct {
12 active bool
13 items []logoutItem
14 cursor int
15}
16
17// logoutItem is one row in the picker. target is what gets passed
18// to doLogout ("anthropic", "openai", or "all"); method is the
19// short tag shown in muted text next to the provider ("apikey" or
20// "oauth"), empty for the "all" row.
21type logoutItem struct {
22 label string
23 target string
24 method string
25}
26
27// logoutAction is the outcome of a key press.
28type logoutAction struct {
29 Select bool
30 Target string // one of: "anthropic", "openai", "all"
31 Close bool
32}
33
34func newLogoutDialog() *logoutDialog { return &logoutDialog{} }
35
36// Open populates the picker with whichever providers are currently
37// logged in. Returns false if nothing to log out of; the caller
38// should fall back to showing a status message instead of opening
39// an empty dialog.
40func (d *logoutDialog) Open(items []logoutItem) bool {
41 if len(items) == 0 {
42 return false
43 }
44 d.items = items
45 d.cursor = 0
46 d.active = true
47 return true
48}
49
50// Close hides the dialog.
51func (d *logoutDialog) Close() { d.active = false }
52
53// Active reports whether the dialog is consuming input.
54func (d *logoutDialog) Active() bool { return d != nil && d.active }
55
56// HandleKey advances the selection or resolves the dialog.
57func (d *logoutDialog) HandleKey(k tui.Key) logoutAction {
58 switch k.Kind {
59 case tui.KeyUp:
60 if d.cursor > 0 {
61 d.cursor--
62 }
63 case tui.KeyDown:
64 if d.cursor < len(d.items)-1 {
65 d.cursor++
66 }
67 case tui.KeyEsc:
68 d.Close()
69 return logoutAction{Close: true}
70 case tui.KeyEnter:
71 if len(d.items) == 0 {
72 d.Close()
73 return logoutAction{Close: true}
74 }
75 it := d.items[d.cursor]
76 d.Close()
77 return logoutAction{Select: true, Target: it.target}
78 }
79 return logoutAction{}
80}
81
82// Render returns the dialog lines.
83func (d *logoutDialog) Render(th tui.Theme, width int) []string {
84 if !d.Active() {
85 return nil
86 }
87 var lines []string
88 lines = append(lines, frameHeader(th, "logout", width))
89 lines = append(lines, th.FGColor(th.Muted, "choose what to log out of (\u2191/\u2193, enter, esc to cancel):"))
90 for i, it := range d.items {
91 plain := " " + it.label
92 if it.method != "" {
93 plain += " (" + it.method + ")"
94 }
95 if i == d.cursor {
96 lines = append(lines, th.PadHighlight(plain, width))
97 } else {
98 lines = append(lines, th.FGColor(th.Muted, plain))
99 }
100 }
101 lines = append(lines, frameRule(th, width))
102 return lines
103}