v3.25.0 review: the collapsible access-rules block

The access-rules form is large for every file rule, so the block now
collapses to its header (a toggle carrying the rule count) and hides
entirely when None is selected - the header keeps the title and the
None/Check radios, so re-enabling is one click (Check also reopens the
block).  The expanded state is transient editor UI state (a module map
keyed by the rule index), kept across the editor's re-renders; a rule
without accessRules starts hidden and Check creates the empty block to
build rules in.

Tests: collapsed by default (header + count, no rows), expanded rows,
None and no-accessRules hidden, the enabled-but-empty hint, and the
radio driving the visibility.  882 frontend + 858 Python; sw cache
simple-v424.
This commit is contained in:
2026-10-11 00:02:20 +03:00
parent c69a779ca4
commit b00d533f03
4 changed files with 59 additions and 17 deletions
+22 -3
View File
@@ -19812,19 +19812,27 @@ function profilerRenderRule(i, r) {
// built the same way; every change re-encodes the canonical decoded line the
// check compares. Forms outside the supported subset stay raw (read-only,
// removable). Capture fills the lines when a profile is created from a card
// or a snapshot; the radio toggles the check.
// or a snapshot; the radio toggles the check, None hides the whole block and
// the block collapses to its header (the rules are kept either way).
function profilerRenderAccessRulesEditor(i, r) {
const ar = r.accessRules || null;
const lines = (ar && ar.expected) || [];
const on = !!(ar && ar.enabled !== false);
const open = on && !!_profilerArrOpen[i];
let html = '<div class="flex items-center justify-between mb-1 mt-1">';
html += '<span class="text-xs text-gray-600 dark:text-slate-400">' + esc(t('Check access rules')) + '</span>';
if (on) {
html += '<button onclick="profilerArrToggleOpen(' + i + ')" class="text-xs text-gray-600 dark:text-slate-400 hover:text-gray-800 dark:hover:text-slate-200">' +
esc((open ? '\u25be ' : '\u25b8 ') + t('Check access rules') + (lines.length ? ' (' + lines.length + ')' : '')) + '</button>';
} else {
html += '<span class="text-xs text-gray-600 dark:text-slate-400">' + esc(t('Check access rules')) + '</span>';
}
html += '<div class="flex items-center gap-3">';
html += '<label class="text-xs flex items-center gap-1"><input type="radio" name="profiler-ar-' + i + '" value="none"' + (!on ? ' checked' : '') + ' onchange="profilerSetAccessRules(' + i + ',false)"> ' + esc(t('None')) + '</label>';
html += '<label class="text-xs flex items-center gap-1"><input type="radio" name="profiler-ar-' + i + '" value="check"' + (on ? ' checked' : '') + ' onchange="profilerSetAccessRules(' + i + ',true)"> ' + esc(t('Check')) + '</label>';
html += '</div></div>';
if (!open) return html;
if (r.fciMode === 'exact') {
html += '<label class="text-xs flex items-center gap-1 mb-1' + (on ? '' : ' opacity-50') + '"><input type="checkbox"' + (ar && ar.ignoreFciRef ? ' checked' : '') + (on ? '' : ' disabled') + ' onchange="profilerSetAccessRulesIgnore(' + i + ',this.checked)"> ' + esc(t('Ignore the EF.ARR reference in the exact FCI')) + '</label>';
html += '<label class="text-xs flex items-center gap-1 mb-1"><input type="checkbox"' + (ar && ar.ignoreFciRef ? ' checked' : '') + ' onchange="profilerSetAccessRulesIgnore(' + i + ',this.checked)"> ' + esc(t('Ignore the EF.ARR reference in the exact FCI')) + '</label>';
}
for (let ri = 0; ri < lines.length; ri++) {
html += profilerArrRuleHtml(i, ri, lines[ri]);
@@ -19836,6 +19844,15 @@ function profilerRenderAccessRulesEditor(i, r) {
return html;
}
// The expanded access-rule blocks of the profile editor (transient UI state,
// kept across the editor re-renders; None hides the block entirely).
let _profilerArrOpen = {};
function profilerArrToggleOpen(i) {
_profilerArrOpen[i] = !_profilerArrOpen[i];
profilerRenderEditor();
}
// One expected rule row: the operation form + bit checkboxes (or the RESIZE /
// INCREASE command), the condition rows and the canonical preview line.
function profilerArrRuleHtml(i, ri, line) {
@@ -19972,6 +19989,8 @@ function profilerSetAccessRules(i, on) {
const r = profilerDraft.rules[i];
if (!r.accessRules) r.accessRules = { expected: [] };
r.accessRules.enabled = on;
// Check opens the block, None hides it (the rules are kept either way)
_profilerArrOpen[i] = on;
profilerRenderEditor();
}