viewApprovalModal renders the full-screen modal that takes over while the user is reviewing a write_file proposal. Same shape as the debug modal but with a yellow border so it's unmistakably a "you need to decide" state, and a different hint line (y/n instead of esc/tab).
()
| 963 | // modal but with a yellow border so it's unmistakably a "you need to |
| 964 | // decide" state, and a different hint line (y/n instead of esc/tab). |
| 965 | func (m harness) viewApprovalModal() string { |
| 966 | modalW, modalH := m.modalSize() |
| 967 | |
| 968 | titleStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("220")).Bold(true) |
| 969 | sep := lipgloss.NewStyle().Foreground(lipgloss.Color("240")). |
| 970 | Render(strings.Repeat("─", max(modalW-4, 1))) |
| 971 | |
| 972 | inner := titleStyle.Render(m.approvalPrompt) + "\n" + sep + "\n" + m.debugView.View() |
| 973 | |
| 974 | modal := lipgloss.NewStyle(). |
| 975 | Border(lipgloss.RoundedBorder()). |
| 976 | BorderForeground(lipgloss.Color("220")). |
| 977 | Padding(0, 1). |
| 978 | Width(modalW). |
| 979 | Height(modalH). |
| 980 | Render(inner) |
| 981 | |
| 982 | hint := Dimmed(" y: approve · n / esc: deny · pgup/pgdn / ↑↓: scroll") |
| 983 | modalLine := lipgloss.PlaceHorizontal(m.width, lipgloss.Center, modal) |
| 984 | hintLine := lipgloss.PlaceHorizontal(m.width, lipgloss.Center, hint) |
| 985 | content := modalLine + "\n" + hintLine |
| 986 | |
| 987 | pad := (m.height - lipgloss.Height(content)) / 2 |
| 988 | if pad < 0 { |
| 989 | pad = 0 |
| 990 | } |
| 991 | return strings.Repeat("\n", pad) + content |
| 992 | } |
| 993 | |
| 994 | // viewDebugModal renders the full-screen modal that takes over while the |
| 995 | // user is inspecting one event. The conversation viewport and input box are |