// Package response renders response-specific views. Right now that is
// just the Timing tab; in principle a cookies inspector belongs here too.
//
// mercemay.top/src/httptap/
package response
import (
"fmt"
"strings"
"time"
"mercemay.top/httptap/internal/parser"
"mercemay.top/httptap/internal/tui/theme"
)
// RenderTiming draws a small waterfall chart of the message lifecycle.
// Durations are taken from parser.Timings when present.
func RenderTiming(pal theme.Palette, msg parser.Message) string {
ts := parser.Timings(msg)
if ts == nil {
return pal.Detail.Render("(no timing info)")
}
total := ts.Total()
if total == 0 {
return pal.Detail.Render("(zero-length capture)")
}
rows := []struct {
label string
dur time.Duration
}{
{"DNS", ts.DNS},
{"Connect", ts.Connect},
{"TLS", ts.TLS},
{"Wait", ts.Wait},
{"Receive", ts.Receive},
}
const barWidth = 40
var b strings.Builder
for _, r := range rows {
frac := float64(r.dur) / float64(total)
filled := int(frac*float64(barWidth) + 0.5)
if filled > barWidth {
filled = barWidth
}
bar := strings.Repeat("█", filled) + strings.Repeat("·", barWidth-filled)
fmt.Fprintf(&b, "%-8s %s %v\n", r.label, bar, r.dur)
}
fmt.Fprintf(&b, "%-8s %s %v\n", "Total", strings.Repeat("█", barWidth), total)
return strings.TrimRight(b.String(), "\n")
}
// FormatDuration formats d with units that vary smoothly across scales.
func FormatDuration(d time.Duration) string {
switch {
case d >= time.Second:
return fmt.Sprintf("%.2fs", d.Seconds())
case d >= time.Millisecond:
return fmt.Sprintf("%dms", d.Milliseconds())
case d >= time.Microsecond:
return fmt.Sprintf("%dµs", d/time.Microsecond)
default:
return fmt.Sprintf("%dns", d.Nanoseconds())
}
}
// Sparkline returns a compact horizontal bar proportional to d/max.
// Used by the list view's optional timing column.
func Sparkline(d, max time.Duration, width int) string {
if max <= 0 || width <= 0 {
return strings.Repeat(" ", width)
}
frac := float64(d) / float64(max)
if frac > 1 {
frac = 1
}
n := int(frac*float64(width) + 0.5)
if n < 1 && d > 0 {
n = 1
}
return strings.Repeat("▮", n) + strings.Repeat(" ", width-n)
}