burterm/internal/tui/proxyview.go
2026-09-14 10:55:07 +03:00

121 lines
3.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package tui
import (
"fmt"
"strings"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
"github.com/r3g1tpr0cs/burterm/internal/proxy"
)
// proxyModel — список перехваченных прокси-транзакций с курсором выбора.
// Enter на выбранной строке отправляет её сырой запрос в Request Builder
// (через loadEntryMsg, обрабатывается в корневой модели).
type proxyModel struct {
entries []proxy.Entry
cursor int
viewport viewport.Model
}
func newProxyView() proxyModel {
return proxyModel{viewport: viewport.New(0, 0)}
}
func (m *proxyModel) SetSize(width, height int) {
if width < 0 {
width = 0
}
if height < 0 {
height = 0
}
m.viewport.Width = width
// 6 строк вокруг viewport, которые View() добавляет сам: "Перехвачено:
// N" + пустая строка сверху, пустая строка + две строки подсказки
// снизу (футер теперь гарантированно на двух строках, не на одной).
vh := height - 6
if vh < 3 {
vh = 3
}
m.viewport.Height = vh
m.refresh()
}
// AddEntry дописывает новую перехваченную транзакцию в список.
func (m *proxyModel) AddEntry(e proxy.Entry) {
m.entries = append(m.entries, e)
m.refresh()
}
func (m *proxyModel) refresh() {
if len(m.entries) == 0 {
m.viewport.SetContent("Пока пусто. Направь браузер на прокси-адрес и походи по нужному сайту.")
return
}
var b strings.Builder
for i, e := range m.entries {
marker := " "
if i == m.cursor {
marker = "▸ "
}
ct := contentTypeLabel(e.Headers)
if ct == "" {
ct = "-"
}
var status string
if e.Err != nil {
status = styleErrStatus.Render(fmt.Sprintf("%-4s", "ERR"))
} else {
status = statusStyle(e.StatusCode).Render(fmt.Sprintf("%-4d", e.StatusCode))
}
b.WriteString(fmt.Sprintf("%s#%-4d %-6s %s %-6s %s\n", marker, e.ID, e.Method, status, ct, e.URL))
}
m.viewport.SetContent(b.String())
}
func (m proxyModel) Update(msg tea.Msg) (proxyModel, tea.Cmd) {
if key, ok := msg.(tea.KeyMsg); ok {
switch key.String() {
case "up", "k":
if m.cursor > 0 {
m.cursor--
m.refresh()
}
return m, nil
case "down", "j":
if m.cursor < len(m.entries)-1 {
m.cursor++
m.refresh()
}
return m, nil
case "enter":
if m.cursor >= 0 && m.cursor < len(m.entries) {
entry := m.entries[m.cursor]
return m, func() tea.Msg { return loadEntryMsg{entry: entry, target: targetBuilder} }
}
return m, nil
case "s":
if m.cursor >= 0 && m.cursor < len(m.entries) {
entry := m.entries[m.cursor]
return m, func() tea.Msg { return loadEntryMsg{entry: entry, target: targetRepeater} }
}
return m, nil
}
}
var cmd tea.Cmd
m.viewport, cmd = m.viewport.Update(msg)
return m, cmd
}
func (m proxyModel) View() string {
return fmt.Sprintf(
"Перехвачено: %d\n\n%s\n\n↑/↓ — выбор · enter — в Request Builder · s — в Repeater\nf1-f12, pgup — вкладки",
len(m.entries), m.viewport.View(),
)
}