diff --git a/frontend/help-ru.html b/frontend/help-ru.html index 133eac2..5b14eeb 100644 --- a/frontend/help-ru.html +++ b/frontend/help-ru.html @@ -497,7 +497,7 @@

8.8 eSIM / LPA (локальные операции)

Для eUICC (SGP.22/SGP.32) подвкладка «eSIM» читает чип и управляет установленными профилями через локальный интерфейс ES10 (через pySim, без обращения к SM-DP+):

diff --git a/frontend/help.html b/frontend/help.html index ecb9762..4c67929 100644 --- a/frontend/help.html +++ b/frontend/help.html @@ -497,7 +497,7 @@

8.8 eSIM / LPA (local operations)

For an eUICC (SGP.22/SGP.32) the eSIM pill reads the chip and manages the installed profiles through the local ES10 interface (via pySim, no SM-DP+ contact):

diff --git a/frontend/index.html b/frontend/index.html index 448ac5f..20287c2 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1678,16 +1678,30 @@ function esimChipSectionRows(data) { return esimFieldRows(data, ''); } -// One bordered chip-info box; no rows -> no box. -function esimChipBox(title, rows) { +// A chip-info row needs the full box width when its value is a list or a +// long token (hex identifiers, capability lists); short scalars share a row. +function esimChipValueWide(label, value) { + const v = String(value); + return v.length > 24 || v.indexOf(', ') >= 0; +} + +// One bordered chip-info box; no rows -> no box. With `twoColumns` the short +// fields are laid out in a 2-column grid (single column on narrow screens) +// and long values span the full width, which keeps the big EUICCInfo2 box +// compact. +function esimChipBox(title, rows, twoColumns) { if (!rows || !rows.length) return ''; let html = '
'; html += '
' + esc(title) + '
'; + if (twoColumns) html += '
'; for (const [k, v] of rows) { - html += '
'; + const cls = twoColumns ? 'flex gap-2 min-w-0' : 'flex gap-2 mb-0.5'; + html += '
'; if (k) html += '' + esc(k) + ''; html += '' + esc(v) + '
'; } + if (twoColumns) html += '
'; return html + '
'; } @@ -1701,7 +1715,7 @@ function esimRenderChip() { esimChipBox(t('Addresses'), esimChipSectionRows(c.addresses)), esimChipBox(t('Rules authorisation table'), esimChipSectionRows(c.rat)), ].filter(Boolean); - const right = esimChipBox('EUICCInfo2', esimChipSectionRows(c.info2)); + const right = esimChipBox('EUICCInfo2', esimChipSectionRows(c.info2), true); if (!left.length && !right) { el.innerHTML = '' + esc(t('No data')) + ''; return; diff --git a/frontend/style.css b/frontend/style.css index 1d31825..63be6ee 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -1977,6 +1977,16 @@ video { color: rgb(203 213 225 / var(--tw-text-opacity, 1)); } +@media (min-width: 640px) { + .sm\:col-span-2 { + grid-column: span 2 / span 2; + } + + .sm\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + @media (min-width: 1024px) { .lg\:col-span-1 { grid-column: span 1 / span 1; diff --git a/frontend/sw.js b/frontend/sw.js index a434e5a..ae902e2 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'simple-v232'; +const CACHE = 'simple-v233'; const URLS = [ 'index.html', 'help.html', diff --git a/frontend/tests/esim.test.js b/frontend/tests/esim.test.js index c131064..fcfee77 100644 --- a/frontend/tests/esim.test.js +++ b/frontend/tests/esim.test.js @@ -24,7 +24,7 @@ function extractFunc(src, name) { let code = ''; for (const fn of ['esimLabel', 'esimGroupEid', 'esimFieldRows', 'esimResultText', 'esimStateLabel', 'esimOperationsText', 'esimProfileRows', 'esimIconDataUrl', - 'esimChipSectionRows', 'esimChipBox', 'esimSwitchStatus']) { + 'esimChipSectionRows', 'esimChipValueWide', 'esimChipBox', 'esimSwitchStatus']) { code += extractFunc(html, fn) + '\n'; } for (const c of ['ESIM_CHIP_LABELS', 'ESIM_RESULT_KEYS']) { @@ -179,6 +179,40 @@ test('the chip boxes prefer wrapping at spaces over breaking words', () => { assert.doesNotMatch(render, /break-all/); }); +test('esimChipValueWide keeps short scalars in one column', () => { + assert.strictEqual(esimChipValueWide('Profile version', '2.3.1'), false); + assert.strictEqual( + esimChipValueWide('Card resource / Free non-volatile memory', '439084'), false); + assert.strictEqual(esimChipValueWide('SS accreditation number', 'ED-ZI-UP-0826'), false); + assert.strictEqual( + esimChipValueWide('RSP capability', 'additionalProfile, testProfileSupport'), true); + assert.strictEqual( + esimChipValueWide('CI PKI (verification) / Subject key identifier', + '81370F5125D0B1D408D4C3B232E6D25E795BEBFB'), true); +}); + +test('esimChipBox lays short fields out in two columns', () => { + const box = esimChipBox('EUICCInfo2', [ + ['Profile version', '2.3.1'], ['SVN', '2.2.2'], + ['UICC capability', 'usimSupport, isimSupport'], + ], true); + assert.match(box, /sm:grid-cols-2/); + const cells = box.match(/
{ + const fn = extractFunc(html, 'esimRenderChip'); + assert.match(fn, /esimChipBox\('EUICCInfo2', esimChipSectionRows\(c\.info2\), true\)/); +}); + test('the chip view groups the sections into a grid', () => { const fn = extractFunc(html, 'esimRenderChip'); assert.match(fn, /lg:grid-cols-3/);