From 9391116d536afb1af5d37f522c144fa0ab489470 Mon Sep 17 00:00:00 2001 From: Jack Kingsman Date: Thu, 11 Jun 2026 22:13:41 -0700 Subject: [PATCH] Compact the trace panes. Closes #285. --- frontend/src/components/TracePane.tsx | 160 +++++++++++--------------- frontend/src/test/tracePane.test.tsx | 17 ++- 2 files changed, 78 insertions(+), 99 deletions(-) diff --git a/frontend/src/components/TracePane.tsx b/frontend/src/components/TracePane.tsx index 2d90a96..82b7298 100644 --- a/frontend/src/components/TracePane.tsx +++ b/frontend/src/components/TracePane.tsx @@ -190,49 +190,45 @@ function nextDraftHopId(prefix: string, currentLength: number): string { function TraceNodeRow({ title, subtitle, + badge, meta, - note, fixed = false, - compact = false, actions, snr, }: { title: string; subtitle: string; + badge?: string; meta?: string | null; - note?: string | null; fixed?: boolean; - compact?: boolean; actions?: ReactNode; snr?: string | null; }) { return ( -
+
- {fixed ? 'Self' : 'Hop'} + {fixed ? 'Self' : (badge ?? 'Hop')}
-
-
{title}
-
{subtitle}
- {meta ?
{meta}
: null} - {note ?
{note}
: null} +
+ {title} + {subtitle} + {meta ? ( + + {meta} + + ) : null}
{snr ? ( -
-
SNR
-
{snr}
+
+ SNR + {snr}
) : null} {actions ?
{actions}
: null} @@ -772,7 +768,6 @@ export function TracePane({ contacts, config, onRunTracePath }: TracePaneProps) subtitle={getShortKey(localRadioKey)} meta="Origin" fixed - compact /> {draftHops.length === 0 ? (
@@ -799,13 +794,7 @@ export function TracePane({ contacts, config, onRunTracePath }: TracePaneProps)
-
+
{draftHops.length === 0 ? 'No hops selected' - : `${draftHops.length} hop${draftHops.length === 1 ? '' : 's'} selected · ${effectiveHopHashBytes}-byte trace`} + : `${draftHops.length} hop${draftHops.length === 1 ? '' : 's'} selected · ${effectiveHopHashBytes}-byte trace · you must be able to hear the final repeater for trace success`}
-
-
-

- Results{result ? ` (${result.timeout_seconds.toFixed(1)}s)` : ''} -

- {result || error ? ( + {result || error ? ( +
+
+

+ Results{result ? ` (${result.timeout_seconds.toFixed(1)}s)` : ''} +

- ) : null} +
+
+ {error ? ( +
+ {error} +
+ ) : null} + {result + ? resultNodes.map((node, index) => { + const title = + node.name || + (node.role === 'custom' + ? 'Custom hop' + : node.role === 'local' + ? localRadioName + : getShortKey(node.public_key)); + const subtitle = + node.role === 'custom' + ? `Key prefix ${node.observed_hash?.toUpperCase() ?? 'unknown'}` + : node.observed_hash && + node.public_key && + node.observed_hash.toLowerCase() !== + getShortKey(node.public_key).toLowerCase() + ? `${getShortKey(node.public_key)} · key prefix ${node.observed_hash.toUpperCase()}` + : getShortKey(node.public_key); + return ( +
+ +
+ ); + }) + : null} +
-
- {error ? ( -
- {error} -
- ) : null} - {!error && !result ? ( -
- Send a trace to see the returned hop-by-hop SNR values. -
- ) : null} - {result - ? resultNodes.map((node, index) => { - const title = - node.name || - (node.role === 'custom' - ? 'Custom hop' - : node.role === 'local' - ? localRadioName - : getShortKey(node.public_key)); - const subtitle = - node.role === 'custom' - ? `Key prefix ${node.observed_hash?.toUpperCase() ?? 'unknown'}` - : node.observed_hash && - node.public_key && - node.observed_hash.toLowerCase() !== - getShortKey(node.public_key).toLowerCase() - ? `${getShortKey(node.public_key)} · key prefix ${node.observed_hash.toUpperCase()}` - : getShortKey(node.public_key); - return ( -
- -
- ); - }) - : null} -
-
+ ) : null}
diff --git a/frontend/src/test/tracePane.test.tsx b/frontend/src/test/tracePane.test.tsx index 288a7be..8aedd2d 100644 --- a/frontend/src/test/tracePane.test.tsx +++ b/frontend/src/test/tracePane.test.tsx @@ -116,7 +116,7 @@ describe('TracePane', () => { fireEvent.click(screen.getByRole('button', { name: /^add repeater relay alpha/i })); fireEvent.click(screen.getByRole('button', { name: /^add repeater relay beta/i })); - expect(screen.getByText('2 hops selected · 4-byte trace')).toBeInTheDocument(); + expect(screen.getByText(/2 hops selected · 4-byte trace/)).toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: /move relay beta up/i })); fireEvent.click(screen.getByRole('button', { name: /send trace/i })); @@ -133,7 +133,7 @@ describe('TracePane', () => { expect(screen.getByText('+5.0 dB')).toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: /remove relay alpha/i })); - expect(screen.getByText('1 hop selected · 4-byte trace')).toBeInTheDocument(); + expect(screen.getByText(/1 hop selected · 4-byte trace/)).toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: /remove relay beta/i })); expect(screen.getByText('No hops selected')).toBeInTheDocument(); }); @@ -167,7 +167,7 @@ describe('TracePane', () => { fireEvent.click(screen.getByRole('button', { name: /^add repeater relay charlie/i })); fireEvent.click(screen.getByRole('button', { name: /reverse link/i })); - expect(screen.getByText('5 hops selected · 4-byte trace')).toBeInTheDocument(); + expect(screen.getByText(/5 hops selected · 4-byte trace/)).toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: /send trace/i })); await waitFor(() => { @@ -189,7 +189,7 @@ describe('TracePane', () => { fireEvent.click(screen.getByRole('button', { name: /^add repeater relay alpha/i })); fireEvent.click(screen.getByRole('button', { name: /^add repeater relay alpha/i })); - expect(screen.getByText('2 hops selected · 4-byte trace')).toBeInTheDocument(); + expect(screen.getByText(/2 hops selected · 4-byte trace/)).toBeInTheDocument(); expect(screen.getByText('Added 2 times')).toBeInTheDocument(); }); @@ -232,7 +232,7 @@ describe('TracePane', () => { fireEvent.change(screen.getByLabelText('Repeater prefix'), { target: { value: 'ae' } }); fireEvent.click(screen.getByRole('button', { name: 'Add custom hop' })); - expect(screen.getByText('1 hop selected · 1-byte trace')).toBeInTheDocument(); + expect(screen.getByText(/1 hop selected · 1-byte trace/)).toBeInTheDocument(); expect(screen.getByText('AE (1-byte)')).toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: /^add repeater relay alpha/i })); @@ -397,7 +397,7 @@ describe('TracePane', () => { fireEvent.click(screen.getByRole('button', { name: /^add repeater relay beta/i })); - expect(screen.getByText('2 hops selected · 4-byte trace')).toBeInTheDocument(); + expect(screen.getByText(/2 hops selected · 4-byte trace/)).toBeInTheDocument(); expect(screen.getByRole('button', { name: /send trace/i })).toBeEnabled(); await act(async () => { @@ -425,8 +425,7 @@ describe('TracePane', () => { expect(screen.queryByRole('heading', { name: 'Results (6.0s)' })).not.toBeInTheDocument(); expect(screen.queryByText('+7.5 dB')).not.toBeInTheDocument(); - expect( - screen.getByText('Send a trace to see the returned hop-by-hop SNR values.') - ).toBeInTheDocument(); + // The Results section stays hidden entirely until a result or error lands. + expect(screen.queryByRole('heading', { name: /^results/i })).not.toBeInTheDocument(); }); });