From bd0c9a2c4a6c63dfa1da2a7160b79c6d2b779ed4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?=
=?UTF-8?q?=D0=B8=D0=BD?=
Date: Sat, 17 Oct 2026 21:40:50 +0300
Subject: [PATCH] Files view: widen the change-details modal again and keep the
legend on one row
- modal max-width 900px -> 1100px
- the legend's swatch and label were separate flex children, so a line break
could split them and the three entries wrapped; each pair is now one
`.hex-legend-item` (nowrap, no shrink) and the legend itself is
`flex-wrap: nowrap` with `overflow-x: auto`, so it stays on a single row
- Node test: the modal test now checks the path header and that the legend
follows the views as three grouped items
- SW cache simtrace-analyser-v70 (cosmetic, no version bump)
---
frontend/index.html | 11 ++++++-----
frontend/sw.js | 2 +-
frontend/tests/comprion.test.js | 6 +++++-
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/frontend/index.html b/frontend/index.html
index 7fbffed..a3adea9 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -190,9 +190,10 @@ body { font: 14px/1.5 system-ui, sans-serif; background: var(--bg); color: var(-
.file-op-card { color: var(--warn); }
.file-op .file-op-diff { margin-left: auto; background: none; border: none; color: var(--accent); cursor: pointer; font-size: 12px; padding: 0 2px; flex: 0 0 auto; text-decoration: underline; }
.file-op .file-op-diff:hover { color: var(--warn); }
-.file-diff-modal { max-width: 900px; }
+.file-diff-modal { max-width: 1100px; }
.file-diff-body { max-height: 60vh; overflow-y: auto; margin-bottom: 16px; }
-.hex-legend { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); margin-top: 10px; flex-wrap: wrap; }
+.hex-legend { display: flex; align-items: center; gap: 14px; font-size: 11px; color: var(--text-muted); margin-top: 10px; flex-wrap: nowrap; overflow-x: auto; }
+.hex-legend-item { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; flex: 0 0 auto; }
.hex-summary { font-size: 12px; color: var(--text-muted); margin-bottom: 10px; }
.hex-pair { display: flex; gap: 16px; flex-wrap: wrap; }
.hex-pair > div { flex: 1 1 320px; min-width: 0; }
@@ -2253,9 +2254,9 @@ function renderFileDiff(image) {
${t('After')}
${hexImageHtml(image, 'after')}
${t('The image is frozen (size cap reached) — later changes are not tracked.')}
` : ''); } diff --git a/frontend/sw.js b/frontend/sw.js index bf4eb3b..d44d407 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'simtrace-analyser-v69'; +const CACHE = 'simtrace-analyser-v70'; const PRECACHE = [ 'index.html', diff --git a/frontend/tests/comprion.test.js b/frontend/tests/comprion.test.js index 3b39201..a5676eb 100644 --- a/frontend/tests/comprion.test.js +++ b/frontend/tests/comprion.test.js @@ -466,6 +466,7 @@ eval( test('Change details modal: header, summary, legend and both views', () => { renderFileDiff({ name: 'EF_ICCID', + path: 'MF/EF_ICCID (2FE2)', op: 'READ BINARY', record: null, n_records: null, @@ -478,7 +479,7 @@ test('Change details modal: header, summary, legend and both views', () => { image_truncated: false, }); const sub = el('file-diff-sub').textContent; - assert.match(sub, /EF_ICCID — READ BINARY/); + assert.match(sub, /MF\/EF_ICCID \(2FE2\) — READ BINARY/); assert.match(sub, /#12/); const body = el('file-diff-body').innerHTML; assert.match(body, /2 bytes changed, 4 bytes newly observed/); @@ -488,6 +489,9 @@ test('Change details modal: header, summary, legend and both views', () => { assert.match(body, /Before/); assert.match(body, /After/); assert.equal((body.match(/class="hex-view"/g) || []).length, 2); + // The legend sits below the two views, each swatch bound to its label. + assert.ok(body.indexOf('hex-legend') > body.lastIndexOf('hex-view')); + assert.equal((body.match(/class="hex-legend-item"/g) || []).length, 3); // The record header variant and the frozen-image note. renderFileDiff({ name: 'EF_IMSI', op: 'READ RECORD', record: 2, n_records: 5, index: 40,