diff --git a/src/Web/autopilot-monitor-web/app/sessions/network-timeline/NetworkBand.tsx b/src/Web/autopilot-monitor-web/app/sessions/network-timeline/NetworkBand.tsx index 3927e45a..da122589 100644 --- a/src/Web/autopilot-monitor-web/app/sessions/network-timeline/NetworkBand.tsx +++ b/src/Web/autopilot-monitor-web/app/sessions/network-timeline/NetworkBand.tsx @@ -41,12 +41,15 @@ export default function NetworkBand({ model }: { model: NetworkModel }) { const { segments, colors, scale, phases, checks, lifeMarkers } = model; - const PHASE_Y = 8; + // Headroom above the phase lane for the slanted lifecycle-marker labels + // (Reboot / Desktop / Completed …) written directly at their dots. + const MARKER_LABEL_H = 32; + const PHASE_Y = 8 + MARKER_LABEL_H; const PHASE_H = 22; - const BAND_Y = 40; + const BAND_Y = PHASE_Y + 32; const BAND_H = 58; const TICK_Y = BAND_Y + BAND_H; - const H = 172; + const H = 172 + MARKER_LABEL_H; // Boundary ticks: real times at every segment boundary, staggered rows, // labels suppressed when they would collide. @@ -61,6 +64,17 @@ export default function NetworkBand({ model }: { model: NetworkModel }) { } }); + // Lifecycle-marker label layout: a marker's slanted label is suppressed when + // the previous shown label sits closer than 30 units (tooltip still works). + const markerXs = lifeMarkers.map((m) => Math.min(Math.max(scale.x(m.t), 6), W - 6)); + const markerLabelVisible: boolean[] = []; + const lastLabelX = [-100]; + for (const x of markerXs) { + const show = x - lastLabelX[0] >= 30; + if (show) lastLabelX[0] = x; + markerLabelVisible.push(show); + } + // Legend entries in first-seen order; the strongest hotspot hint wins. const legend: { identity: string; label: string; color: string; kind: SegmentKind; hotspot?: HotspotHint }[] = []; for (const seg of segments) { @@ -249,38 +263,56 @@ export default function NetworkBand({ model }: { model: NetworkModel }) { ); })} - {/* Lifecycle markers (reboot / desktop / terminal) */} + {/* Lifecycle markers (reboot / desktop / terminal) — labeled directly + at the dot, slanted up-right; near the right edge the label flips + to up-left so it never leaves the drawing. A label is suppressed + (tooltip still works) when its neighbor's label sits too close. */} {lifeMarkers.map((m, i) => { - const x = Math.min(Math.max(scale.x(m.t), 6), W - 6); - const tip = ( -