feat: clean up the Explore UX (v3.6.45)
- Explore runs inline: no blocking modal (that stays for the install operations, which can leave a half-loaded package; Explore leaves the card consistent). A test guards that ramExplore never calls the modal. - Minimal success line: just OK - the details live in the explorer below; error runs keep the detailed 'Partial - ...' line. - Counts moved into the section headings (Applications / Applet Instances (n), Executable Load Files (ELFs) / Packages (n)); the redundant '1 ISD' count is gone (P1=80 returns the ISD as a single occurrence, GP 11.4.2.1). - The RAM command format line gained a tooltip: compact = TS 102 226 5.2.1 command string, expanded = the AA/22 scripting template (5.2.1.0), detected per operation with a read-only GET STATUS probe. - The expanded-registry checkbox is relabelled 'Fetch expanded registry details (load-file / SD associations)' with a tooltip (extra secured packets, card support varies, the fallback is automatic) and is now a sticky per-browser preference (simple_ram_expanded). sw cache simple-v318; tests: 531 Python / 681 Node.
This commit is contained in:
+30
-13
@@ -703,7 +703,7 @@
|
||||
<button data-needs="card" data-cap-gate="ram" onclick="ramExecute()" class="px-5 py-1.5 bg-blue-600 text-white text-sm font-medium rounded hover:bg-blue-700 disabled:opacity-40 disabled:cursor-not-allowed" data-l10n="Execute">Execute</button>
|
||||
</div>
|
||||
|
||||
<label class="flex items-center gap-1 mb-3 text-sm text-gray-700 dark:text-slate-300"><input type="checkbox" id="ram-expanded-details" class="rounded border-gray-300 dark:border-slate-600"> <span data-l10n="Query expanded registry details (E3)">Query expanded registry details (E3)</span></label>
|
||||
<label class="flex items-center gap-1 mb-3 text-sm text-gray-700 dark:text-slate-300" data-l10n-title="Runs one extra expanded query per listing (P2=02, tag list 4F 9F70 C5 C4 CC CE EA). The compact listing carries AID/lifecycle/privileges/version only; the expanded pass adds the Load File AID, Security Domain AID and module lists. It costs extra secured packets and some cards reject it - the Explore already uses it automatically when the compact listing returns nothing."><input type="checkbox" id="ram-expanded-details" class="rounded border-gray-300 dark:border-slate-600" onchange="ramExpandedDetailsChanged()"> <span data-l10n="Fetch expanded registry details (load-file / SD associations)">Fetch expanded registry details (load-file / SD associations)</span></label>
|
||||
|
||||
<div id="ram-install-params" class="hidden mb-3">
|
||||
<div id="ram-cap-rows">
|
||||
@@ -1747,7 +1747,7 @@
|
||||
// ===== Version =====
|
||||
// Single source of truth for the PWA version: shown in the header and used
|
||||
// by the server version check in pysimConnect().
|
||||
const SIMPLE_VERSION = '3.6.44';
|
||||
const SIMPLE_VERSION = '3.6.45';
|
||||
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
||||
|
||||
// ===== Tab switching =====
|
||||
@@ -8262,6 +8262,23 @@ function ramRender() {
|
||||
});
|
||||
if (keep !== null && keep !== undefined && cards[keep]) sel.value = String(keep);
|
||||
ramOpChanged();
|
||||
ramExpandedDetailsInit();
|
||||
}
|
||||
|
||||
// The "Fetch expanded registry details" checkbox is a sticky preference: the
|
||||
// expanded query costs extra secured packets and not every card accepts it,
|
||||
// so it stays off unless the user asked for it (stored per browser).
|
||||
function ramExpandedDetailsInit() {
|
||||
const el = document.getElementById('ram-expanded-details');
|
||||
if (!el) return;
|
||||
let v = null;
|
||||
try { v = localStorage.getItem('simple_ram_expanded'); } catch (e) { /* private mode */ }
|
||||
if (v !== null) el.checked = v === '1';
|
||||
}
|
||||
|
||||
function ramExpandedDetailsChanged() {
|
||||
const el = document.getElementById('ram-expanded-details');
|
||||
try { localStorage.setItem('simple_ram_expanded', el && el.checked ? '1' : '0'); } catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function ramApplyCard(idx) {
|
||||
@@ -9003,7 +9020,10 @@ function ramRenderExploreHtml(mem, isd, apps, elfs, fmt) {
|
||||
html += '<div>' + esc(t('Applications:')) + ' ' + (mem.appCount != null ? mem.appCount : '?') + '</div>';
|
||||
html += '<div>' + esc(t('Free NV:')) + ' ' + (mem.freeNV != null ? mem.freeNV + ' B' : '?') + '</div>';
|
||||
html += '<div>' + esc(t('Free Volatile:')) + ' ' + (mem.freeV != null ? mem.freeV + ' B' : '?') + '</div>';
|
||||
if (fmt) html += '<div>' + esc(t('RAM command format:')) + ' ' + esc(fmt) + '</div>';
|
||||
if (fmt) {
|
||||
html += '<div title="' + esc(t('compact = the TS 102 226 5.2.1 command string (one C-APDU per secured packet, e.g. GET STATUS + GET RESPONSE); expanded = the AA/22 Command Scripting template (5.2.1.0). Detected per operation with a read-only GET STATUS probe; a card that rejects the deprecated compact P2.b2=0 form answers the expanded one.')) + '">' +
|
||||
esc(t('RAM command format:')) + ' ' + esc(fmt) + '</div>';
|
||||
}
|
||||
html += '</div>';
|
||||
}
|
||||
if (isd && isd.length) {
|
||||
@@ -9021,7 +9041,7 @@ function ramRenderExploreHtml(mem, isd, apps, elfs, fmt) {
|
||||
}
|
||||
if (apps && apps.length) {
|
||||
html += '<div class="mb-4">';
|
||||
html += '<div class="font-semibold text-sm mb-1">' + esc(t('Applications / Applet Instances')) + '</div>';
|
||||
html += '<div class="font-semibold text-sm mb-1">' + esc(t('Applications / Applet Instances')) + ' (' + apps.length + ')</div>';
|
||||
apps.forEach(o => {
|
||||
html += '<div class="mb-1 pl-2 pr-2 py-1 rounded bg-gray-50 dark:bg-slate-800/60 hover:bg-gray-100 dark:hover:bg-slate-700/50 border-l-2 border-green-400 flex items-start gap-3">';
|
||||
html += '<div class="flex-1 min-w-0">';
|
||||
@@ -9045,7 +9065,7 @@ function ramRenderExploreHtml(mem, isd, apps, elfs, fmt) {
|
||||
}
|
||||
if (elfs && elfs.length) {
|
||||
html += '<div class="mb-4">';
|
||||
html += '<div class="font-semibold text-sm mb-1">' + esc(t('Executable Load Files (ELFs) / Packages')) + '</div>';
|
||||
html += '<div class="font-semibold text-sm mb-1">' + esc(t('Executable Load Files (ELFs) / Packages')) + ' (' + elfs.length + ')</div>';
|
||||
elfs.forEach(o => {
|
||||
html += '<div class="mb-1 pl-2 pr-2 py-1 rounded bg-gray-50 dark:bg-slate-800/60 hover:bg-gray-100 dark:hover:bg-slate-700/50 border-l-2 border-purple-400 flex items-start gap-3">';
|
||||
html += '<div class="flex-1 min-w-0">';
|
||||
@@ -9107,8 +9127,6 @@ async function ramExplore(sp) {
|
||||
const mem = { appCount: null, freeNV: null, freeV: null };
|
||||
const isd = [], apps = [], elfs = [];
|
||||
|
||||
ramOpModalBegin(t('Explore Card (all GP data)'));
|
||||
|
||||
async function paginate(p1, collector, parser, label, quiet) {
|
||||
// Compact listing format (GP 11.4.2.2: P2.b2=0) with the chained GET
|
||||
// RESPONSE - see ramGetStatusApdu(). The card's SCP80 layer runs both
|
||||
@@ -9122,7 +9140,6 @@ async function ramExplore(sp) {
|
||||
while (guard++ < 32) {
|
||||
const apdu = ramGetStatusApdu(p1, p2);
|
||||
ramShowProgress(label + ' P1=' + p1 + ' P2=' + p2 + '...');
|
||||
ramOpModalStatus(label + ' P1=' + p1 + ' P2=' + p2);
|
||||
const res = await ramSendOta(apdu, Object.assign({}, sp, { cntr, spi2 }));
|
||||
// Reuse the format detected for the first packet of this run
|
||||
if (res.ram_format) sp.ram_format = res.ram_format;
|
||||
@@ -9173,7 +9190,7 @@ async function ramExplore(sp) {
|
||||
// Expanded pass: the fallback when the compact listing produced
|
||||
// nothing (a card may reject P2.b2=0 - it is deprecated), and the
|
||||
// optional details source (privileges, ELF/SD associations) behind the
|
||||
// "Query expanded registry details (E3)" checkbox.
|
||||
// "Fetch expanded registry details" checkbox.
|
||||
const wantDetails = !!(document.getElementById('ram-expanded-details') || {}).checked;
|
||||
if (collector.length === before || wantDetails) {
|
||||
ramShowProgress(label + ' P1=' + p1 + ' P2=02 (expanded)...');
|
||||
@@ -9207,7 +9224,6 @@ async function ramExplore(sp) {
|
||||
}
|
||||
|
||||
ramShowProgress(t('Card resources (GET DATA FF21)') + '...');
|
||||
ramOpModalStatus(t('Card resources (GET DATA FF21)'));
|
||||
try {
|
||||
const memRes = await ramSendOta('80CAFF2100', Object.assign({}, sp, { spi2: '01' }));
|
||||
if (memRes.ram_format) sp.ram_format = memRes.ram_format;
|
||||
@@ -9257,13 +9273,12 @@ async function ramExplore(sp) {
|
||||
stepsEl.classList.remove('hidden');
|
||||
stepsEl.textContent = errors.join('\n');
|
||||
} else {
|
||||
resultEl.textContent = t('OK') + ' — ' + isd.length + ' ' + t('ISD') + ', ' + apps.length + ' ' + t('Apps') + ', ' + elfs.length + ' ' + t('ELFs') + (mem.freeNV ? ', ' + mem.freeNV + ' ' + t('free NV') : '') + (sp.ram_format ? ' — ' + t('RAM command format:') + ' ' + sp.ram_format : '');
|
||||
resultEl.textContent = t('OK');
|
||||
resultEl.classList.remove('hidden', 'text-red-600'); resultEl.classList.add('text-green-600');
|
||||
}
|
||||
|
||||
_ramExplorerData = { mem: mem, isd: isd, apps: apps, elfs: elfs, fmt: sp.ram_format || '' };
|
||||
ramRenderExplorer();
|
||||
ramOpModalFinish(resultEl.textContent, errors.length === 0, errors.join('\n'));
|
||||
}
|
||||
|
||||
// GP DELETE (Card Spec v2.3.1 11.2, Tables 11-20/11-23): P1=00 (last/only
|
||||
@@ -18067,7 +18082,9 @@ const LANG_RU = {
|
||||
'KIc and KID are required': 'Укажите KIc и KID',
|
||||
'KIc key and KID key are required': 'Укажите ключ KIc и ключ KID',
|
||||
'RAM command format:': 'Формат команд RAM:',
|
||||
'Query expanded registry details (E3)': 'Запрашивать расширенные данные реестра (E3)',
|
||||
'Fetch expanded registry details (load-file / SD associations)': 'Запрашивать расширенные данные реестра (связи load-файла и SD)',
|
||||
'Runs one extra expanded query per listing (P2=02, tag list 4F 9F70 C5 C4 CC CE EA). The compact listing carries AID/lifecycle/privileges/version only; the expanded pass adds the Load File AID, Security Domain AID and module lists. It costs extra secured packets and some cards reject it - the Explore already uses it automatically when the compact listing returns nothing.': 'Запускает дополнительный расширенный запрос для каждого списка (P2=02, список тегов 4F 9F70 C5 C4 CC CE EA). Компактный список содержит только AID/состояние/привилегии/версию; расширенный проход добавляет AID load-файла, AID Security Domain и списки модулей. Он расходует дополнительные защищённые пакеты, и не все карты его поддерживают — Explore и так применяет его автоматически, когда компактный список ничего не вернул.',
|
||||
'compact = the TS 102 226 5.2.1 command string (one C-APDU per secured packet, e.g. GET STATUS + GET RESPONSE); expanded = the AA/22 Command Scripting template (5.2.1.0). Detected per operation with a read-only GET STATUS probe; a card that rejects the deprecated compact P2.b2=0 form answers the expanded one.': 'compact = командная строка по TS 102 226 5.2.1 (один C-APDU на защищённый пакет, например GET STATUS + GET RESPONSE); expanded = шаблон Command Scripting AA/22 (5.2.1.0). Определяется для каждой операции пробным чтением GET STATUS; карта, отклоняющая устаревшую компактную форму P2.b2=0, отвечает в расширенной.',
|
||||
'Card resources (GET DATA FF21)': 'Ресурсы карты (GET DATA FF21)',
|
||||
'Extended Card Resources (GP tag FF21, ETSI TS 102 226 8.2.1.7.2): installed applications, free non-volatile and free volatile memory': 'Расширенные ресурсы карты (тег GP FF21, ETSI TS 102 226 8.2.1.7.2): число установленных приложений, свободная энергонезависимая и свободная энергозависимая память',
|
||||
'No secured packet to send. Generate a secure packet first.': 'Нет защищённого пакета для отправки. Сначала соберите пакет.',
|
||||
|
||||
Reference in New Issue
Block a user