viewDebugModal renders the full-screen modal that takes over while the user is inspecting one event. The conversation viewport and input box are hidden — Esc returns to the panel, Tab goes straight back to the input.
()
| 995 | // user is inspecting one event. The conversation viewport and input box are |
| 996 | // hidden — Esc returns to the panel, Tab goes straight back to the input. |
| 997 | func (m harness) viewDebugModal() string { |
| 998 | modalW, modalH := m.modalSize() |
| 999 | |
| 1000 | var titleText, pairHint string |
| 1001 | hasPair := false |
| 1002 | if e, ok := debug.FindByID(m.debugSelected); ok { |
| 1003 | titleText = fmt.Sprintf("#%d %s %s %s", |
| 1004 | e.ID, |
| 1005 | e.Time.Format("15:04:05.000"), |
| 1006 | e.Source, |
| 1007 | e.Message) |
| 1008 | if p, pok := debug.Pair(e.ID); pok { |
| 1009 | hasPair = true |
| 1010 | arrow := "→ response" |
| 1011 | if e.CorrelatedID != 0 { |
| 1012 | arrow = "← request" |
| 1013 | } |
| 1014 | pairHint = fmt.Sprintf(" %s #%d", arrow, p.ID) |
| 1015 | } |
| 1016 | } else { |
| 1017 | titleText = fmt.Sprintf("#%d (event no longer in the ring)", m.debugSelected) |
| 1018 | } |
| 1019 | |
| 1020 | titleStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("36")).Bold(true) |
| 1021 | pairStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("141")).Bold(true) |
| 1022 | sep := lipgloss.NewStyle().Foreground(lipgloss.Color("240")). |
| 1023 | Render(strings.Repeat("─", max(modalW-4, 1))) |
| 1024 | |
| 1025 | titleLine := titleStyle.Render(titleText) |
| 1026 | if pairHint != "" { |
| 1027 | titleLine += pairStyle.Render(pairHint) |
| 1028 | } |
| 1029 | inner := titleLine + "\n" + sep + "\n" + m.debugView.View() |
| 1030 | |
| 1031 | modal := lipgloss.NewStyle(). |
| 1032 | Border(lipgloss.RoundedBorder()). |
| 1033 | BorderForeground(lipgloss.Color("36")). |
| 1034 | Padding(0, 1). |
| 1035 | Width(modalW). |
| 1036 | Height(modalH). |
| 1037 | Render(inner) |
| 1038 | |
| 1039 | hintText := " esc: close · pgup/pgdn: scroll · home/end: top/bottom · tab: input" |
| 1040 | if hasPair { |
| 1041 | hintText += " · ←/→: jump to pair" |
| 1042 | } |
| 1043 | hint := Dimmed(hintText) |
| 1044 | |
| 1045 | modalLine := lipgloss.PlaceHorizontal(m.width, lipgloss.Center, modal) |
| 1046 | hintLine := lipgloss.PlaceHorizontal(m.width, lipgloss.Center, hint) |
| 1047 | content := modalLine + "\n" + hintLine |
| 1048 | |
| 1049 | // Vertically center the modal in the alt-screen so it feels overlaid. |
| 1050 | pad := (m.height - lipgloss.Height(content)) / 2 |
| 1051 | if pad < 0 { |
| 1052 | pad = 0 |
| 1053 | } |
| 1054 | return strings.Repeat("\n", pad) + content |