feat: RAM operations run behind a blocking modal (v3.6.34)
A CAP install is a long chain of LOAD commands whose progress and results were only visible at the bottom of a large form - and an interrupted install can leave a half-loaded package. - Server: _RAM_PROGRESS (+ _ram_progress_begin/step/end) records the live step of the running RAM operation; /api/ram-install and /api/ram-install-app wrap their chains in it (total = steps + 1 for the format check) and /api/status carries it as ram_progress - lock-free, so the 2 s poll works while the request holds _CARD_LOCK. - PWA: #ram-op-modal (the STK panel pattern) blocks everything while a RAM operation runs: title, spinner, status line, progress bar, per-step result lines, Close disabled until it finishes; a beforeunload guard protects the window during the run. install-cap, install-app / make-selectable and Explore all use the shared helpers (ramOpModalBegin/Status/Finish); the install results stay in the form area as before once the modal is closed. The status poll feeds the modal via ramOpProgress (headline from the pure ramOpProgressText). - Tests: ramOpProgressText (JS) + the progress lifecycle (Python); the card-state and capmem suites stub the DOM-bound hooks. - Stylesheet rebuilt; version 3.6.34; sw simple-v307.
This commit is contained in:
@@ -25,7 +25,7 @@ function extractFunc(src, name) {
|
||||
const FNS = ['berLenStr', 'buildApdu', 'escHtml', 'esc', 'chainInit', 'chainRamBuildRowHex', 'ramFmtLifecycle', 'ramFmtPrivileges', 'ramRenderExploreHtml', 'ramStepLine', 'ramGetStatusApdu', 'ramDeleteApdu',
|
||||
'stkParamsBuild', 'ramRemoteSwOk', 'spPorAccepted', 'ramIncrementCntr', 'ramDeleteFromExplorer', 'ramListingSpi2', 'ramRemoveFromExplorer', 'ramHasInstance', 'ramExpandedQueryApdu',
|
||||
'_parseRawElfEntry', '_parseRawAppEntry', 'ramParseElfStatus', 'ramParseAppStatus', 'parseTLV', '_parseE3Entry',
|
||||
'ramCardIdxAfterRemove', 'ramClearResults', 'ramHideProgress', 'ramOpChanged', 'ramRender', 'ramApplyCard', 'ramExecute', 'decodePrivileges', 'ramActionBtn', 'ramCapToolkitMode',
|
||||
'ramCardIdxAfterRemove', 'ramClearResults', 'ramHideProgress', 'ramOpChanged', 'ramRender', 'ramApplyCard', 'ramExecute', 'decodePrivileges', 'ramActionBtn', 'ramCapToolkitMode', 'ramOpProgressText',
|
||||
'jcAidNorm', 'jcAidName', 'jcAidSuffix', 'jcAidHtml'];
|
||||
let code = '';
|
||||
for (const f of FNS) {
|
||||
@@ -274,6 +274,16 @@ test('ramFmtPrivileges decodes the GP privilege bytes (live ISD values)', () =>
|
||||
delete global.t;
|
||||
});
|
||||
|
||||
test('ramOpProgressText renders the step headline', () => {
|
||||
global.t = s => s;
|
||||
assert.strictEqual(
|
||||
ramOpProgressText({ step: 3, total: 11, name: 'LOAD (2/9)', elapsed: 4.2 }),
|
||||
'Step 3/11 \u2014 LOAD (2/9) \u2014 4.2 s');
|
||||
assert.strictEqual(ramOpProgressText({ step: 0, total: 0, name: '' }), 'Working...');
|
||||
assert.strictEqual(ramOpProgressText(null), '');
|
||||
delete global.t;
|
||||
});
|
||||
|
||||
test('ramCapToolkitMode picks CA/EA from the CAP linked libraries', () => {
|
||||
// sim.toolkit / sim.access (A0000000090003...) -> SIM Toolkit (CA field)
|
||||
assert.strictEqual(ramCapToolkitMode([{ aid: 'A0000000090003FFFFFFFF8910710002' }]), 'ca');
|
||||
|
||||
Reference in New Issue
Block a user