Skip to content

Commit 4c0cc94

Browse files
fix(admin): restore SDK column (readable text) + Esc closes top-most popup
SDK column: re-add the SDK column to the results table as plain short text (JS/C#/TKD) in a 64px col, first column in both the split header and the body table. Reuses sdkColors short labels — no badge, no truncation. Counts stay aligned at 13 col/th/td. Esc nesting: NEW TEST chooser → P2P-settings drawer; Esc now closes the top-most popup. The drawer registers its own onEsc (stopImmediatePropagation + self-removing close); the chooser's onKey bails while p2pSettingsBackdrop exists. Also plug two listener leaks found in adversarial review: the chooser's onKey is now removed on EVERY close path (×/backdrop/tile/Esc), and the drawer's teardown removes a prior leaked onEsc — otherwise an orphaned listener could silently swallow a later Escape.
1 parent 5c2de82 commit 4c0cc94

1 file changed

Lines changed: 24 additions & 8 deletions

File tree

admin.html

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,7 @@ <h1 style="margin:0;flex:0 0 auto">SENTINEL NODE TEST</h1>
10311031
<div class="results-head-wrap">
10321032
<table class="results-table">
10331033
<colgroup>
1034+
<col style="width:64px"> <!-- SDK -->
10341035
<col style="width:130px"> <!-- Transport -->
10351036
<col> <!-- Moniker (flex) -->
10361037
<col style="width:150px"> <!-- Node -->
@@ -1046,6 +1047,7 @@ <h1 style="margin:0;flex:0 0 auto">SENTINEL NODE TEST</h1>
10461047
</colgroup>
10471048
<thead>
10481049
<tr>
1050+
<th style="text-align:center">SDK</th>
10491051
<th style="text-align:left">Transport</th>
10501052
<th style="text-align:left">Moniker</th>
10511053
<th style="text-align:left">Node</th>
@@ -1065,6 +1067,7 @@ <h1 style="margin:0;flex:0 0 auto">SENTINEL NODE TEST</h1>
10651067
<div class="table-wrap">
10661068
<table class="results-table">
10671069
<colgroup>
1070+
<col style="width:64px"> <!-- SDK -->
10681071
<col style="width:130px"> <!-- Transport -->
10691072
<col> <!-- Moniker (flex) -->
10701073
<col style="width:150px"> <!-- Node -->
@@ -1997,11 +2000,12 @@ <h1 style="margin:0;flex:0 0 auto">SENTINEL NODE TEST</h1>
19972000
}
19982001
}
19992002

2000-
// sdkLabel/sdkColors are retained for the "Other SDKs" cross-reference
2001-
// column below. The per-row SDK badge was removed (it lived in a 54px
2002-
// column that truncated and duplicated the WG/V2 transport badge).
2003+
// sdkLabel/sdkColors are used by both the per-row SDK column and the
2004+
// "Other SDKs" cross-reference column below. The SDK column renders the
2005+
// short label as plain readable text (no badge background, no truncation).
20032006
const sdkLabel = r.sdk || state.activeSDK || 'js';
20042007
const sdkColors = { js: { bg: 'var(--bg-input)', fg: 'var(--text)', label: 'JS' }, csharp: { bg: 'var(--bg-input)', fg: 'var(--text)', label: 'C#' }, tkd: { bg: 'var(--bg-input)', fg: 'var(--text)', label: 'TKD' } };
2008+
const sdkShort = (sdkColors[sdkLabel] || sdkColors.js).label;
20052009

20062010
// ─── Other SDKs column: cross-reference this node against other run results ──
20072011
let otherSdkHtml = '<span style="color:var(--text-muted)">-</span>';
@@ -2040,6 +2044,7 @@ <h1 style="margin:0;flex:0 0 auto">SENTINEL NODE TEST</h1>
20402044
: '<span style="color:var(--text-muted)">—</span>';
20412045

20422046
tr.innerHTML = `
2047+
<td style="text-align:center;font-size:10px;color:var(--text-dim);white-space:nowrap">${sdkShort}</td>
20432048
<td>${proto} ${transportHtml}</td>
20442049
<td style="font-weight:500">${escHtml(monikerText)}</td>
20452050
<td style="font-family:var(--font-mono);font-size:11px;color:var(--text-secondary)">${addr}</td>
@@ -2401,9 +2406,9 @@ <h1 style="margin:0;flex:0 0 auto">SENTINEL NODE TEST</h1>
24012406
}
24022407

24032408
async function openP2pSettingsDrawer() {
2404-
// Tear down any previous drawer
2409+
// Tear down any previous drawer (and its leaked keydown listener)
24052410
const existing = document.getElementById('p2pSettingsBackdrop');
2406-
if (existing) existing.remove();
2411+
if (existing) { if (existing._onEsc) document.removeEventListener('keydown', existing._onEsc); existing.remove(); }
24072412

24082413
let payload = { settings: {}, defaults: {} };
24092414
try {
@@ -2420,7 +2425,12 @@ <h1 style="margin:0;flex:0 0 auto">SENTINEL NODE TEST</h1>
24202425
const panel = document.createElement('div');
24212426
panel.style.cssText = 'background:var(--bg-card-solid);border:1px solid var(--border-hover);border-radius:12px;padding:20px;width:min(520px,92vw);max-height:88vh;overflow:auto;color:var(--text);font-family:var(--font-display)';
24222427

2423-
const close = () => backdrop.remove();
2428+
const close = () => { document.removeEventListener('keydown', onEsc); backdrop.remove(); };
2429+
// Esc closes THIS drawer (the top-most popup). stopImmediatePropagation so the
2430+
// underlying chooser's own keydown listener doesn't also fire on the same Esc.
2431+
const onEsc = (e) => { if (e.key === 'Escape') { e.stopImmediatePropagation(); close(); } };
2432+
backdrop._onEsc = onEsc;
2433+
document.addEventListener('keydown', onEsc);
24242434
const _esc = (v) => String(v).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[c]));
24252435

24262436
panel.innerHTML = `
@@ -2851,9 +2861,15 @@ <h3 style="font-size:10px;font-weight:700;letter-spacing:1.4px;text-transform:up
28512861
const modal = document.createElement('div');
28522862
modal.style.cssText = 'background:var(--bg-card-solid);border:1px solid var(--border-hover);border-radius:10px;padding:28px;max-width:920px;width:92%;max-height:90vh;overflow:auto;color:var(--text);font-family:var(--font-display);';
28532863

2854-
const close = () => backdrop.remove();
2864+
// close() always removes onKey so the listener never leaks on ANY close path
2865+
// (×, backdrop click, tile click, Esc). A leaked onKey would otherwise linger
2866+
// on document and — via the bail below — silently swallow a later Escape.
2867+
const close = () => { document.removeEventListener('keydown', onKey); backdrop.remove(); };
28552868
backdrop.addEventListener('click', (e) => { if (e.target === backdrop) close(); });
2856-
const onKey = (e) => { if (e.key === 'Escape') { close(); document.removeEventListener('keydown', onKey); } };
2869+
// Bail if the P2P-settings drawer is open on top of us: its own Esc handler
2870+
// closes that drawer first. This listener is registered before the drawer's,
2871+
// so it fires first — returning here leaves the top-most popup to be closed.
2872+
const onKey = (e) => { if (e.key === 'Escape') { if (document.getElementById('p2pSettingsBackdrop')) return; close(); } };
28572873
document.addEventListener('keydown', onKey);
28582874

28592875
modal.innerHTML = `

0 commit comments

Comments
 (0)