1package screens
2
3import (
4 "charm.land/bubbles/v2/key"
5 tea "charm.land/bubbletea/v2"
6
7 "git.secluded.site/keld/internal/ui"
8)
9
10// PreviewFunc returns the formatted command preview text. It is
11// called asynchronously from Init via a tea.Cmd. The returned string
12// should match the format of [restic.DryRun].
13type PreviewFunc func() string
14
15// previewMsg carries the result of the async preview generation.
16type previewMsg struct {
17 text string
18}
19
20// Confirm is a Screen adapter that shows the resolved restic command
21// and waits for the user to confirm execution. Enter proceeds,
22// Esc goes back.
23//
24// When showCommand is true, Init returns DoneCmd immediately without
25// calling the preview function — the session completes and the caller
26// prints the dry-run output through the normal --show-command path.
27type Confirm struct {
28 previewFn PreviewFunc
29 showCommand bool
30 preview string
31 selection string
32}
33
34// NewConfirm creates a confirmation screen. The previewFn is called
35// to generate the command preview text. When showCommand is true,
36// the screen auto-completes without user interaction.
37func NewConfirm(previewFn PreviewFunc, showCommand bool) *Confirm {
38 return &Confirm{
39 previewFn: previewFn,
40 showCommand: showCommand,
41 }
42}
43
44// Init starts the preview generation. In --show-command mode, it
45// skips the preview and returns DoneCmd immediately.
46func (c *Confirm) Init() tea.Cmd {
47 c.selection = ""
48
49 if c.showCommand {
50 return ui.DoneCmd
51 }
52
53 return func() tea.Msg {
54 return previewMsg{text: c.previewFn()}
55 }
56}
57
58// Update handles messages. Esc navigates back, Enter confirms.
59func (c *Confirm) Update(msg tea.Msg) (ui.Screen, tea.Cmd) {
60 switch msg := msg.(type) {
61 case previewMsg:
62 c.preview = msg.text
63 return c, nil
64
65 case tea.KeyPressMsg:
66 if msg.Code == tea.KeyEscape {
67 return c, ui.BackCmd
68 }
69 if msg.Code == tea.KeyEnter && c.preview != "" {
70 c.selection = "confirmed"
71 return c, ui.DoneCmd
72 }
73 }
74
75 return c, nil
76}
77
78// View renders the command preview.
79func (c *Confirm) View() string {
80 return c.preview
81}
82
83// Title returns the screen's display title.
84func (c *Confirm) Title() string { return "Confirm execution" }
85
86// KeyBindings returns bindings for the help bar.
87func (c *Confirm) KeyBindings() []key.Binding {
88 return []key.Binding{
89 key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "execute")),
90 }
91}
92
93// Selection returns "confirmed" after the user presses Enter, or ""
94// if the screen has not been confirmed yet.
95func (c *Confirm) Selection() string { return c.selection }