From 2f1330ec32832c646f0bb085405144f8b0df061a Mon Sep 17 00:00:00 2001 From: Nico Verbruggen Date: Sun, 22 Mar 2026 12:38:37 +0100 Subject: [PATCH] Minor cleanup --- web/eslint.config.mjs | 1 + web/src/css/style.css | 5 +++ web/src/js/app.js | 62 +++++++++++------------------------ web/src/js/nickelmenu-flow.js | 2 +- web/src/js/patches-flow.js | 2 +- web/src/js/strings.js | 4 +-- 6 files changed, 29 insertions(+), 47 deletions(-) diff --git a/web/eslint.config.mjs b/web/eslint.config.mjs index 8c60c91..ca771e1 100644 --- a/web/eslint.config.mjs +++ b/web/eslint.config.mjs @@ -21,6 +21,7 @@ export default [ HTMLElement: 'readonly', Worker: 'readonly', requestAnimationFrame: 'readonly', + location: 'readonly', // JSZip loaded via script tag JSZip: 'readonly', }, diff --git a/web/src/css/style.css b/web/src/css/style.css index ff1ef85..e5efcf4 100644 --- a/web/src/css/style.css +++ b/web/src/css/style.css @@ -212,6 +212,11 @@ h2 { border-color: var(--border); } +.mode-card-disabled { + opacity: 0.5; + cursor: not-allowed; +} + .mode-card-selected { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary), var(--shadow); diff --git a/web/src/js/app.js b/web/src/js/app.js index bbd0b3a..b302681 100644 --- a/web/src/js/app.js +++ b/web/src/js/app.js @@ -185,8 +185,7 @@ function goToModeSelection() { const patchesHint = $('mode-patches-hint'); if (autoModeNoPatchesAvailable) { patchesRadio.disabled = true; - patchesCard.style.opacity = '0.5'; - patchesCard.style.cursor = 'not-allowed'; + patchesCard.classList.add('mode-card-disabled'); patchesHint.hidden = false; // Auto-select NickelMenu since it's the only available option. const nmRadio = $q('input[value="nickelmenu"]', stepMode); @@ -194,8 +193,7 @@ function goToModeSelection() { nmRadio.dispatchEvent(new Event('change')); } else { patchesRadio.disabled = false; - patchesCard.style.opacity = ''; - patchesCard.style.cursor = ''; + patchesCard.classList.remove('mode-card-disabled'); patchesHint.hidden = true; } @@ -468,24 +466,9 @@ btnErrorBack.addEventListener('click', () => { showStep(stepPatches); }); -// "Start Over" — full reset of all state, back to step 1. +// "Start Over" — reload the page for a guaranteed clean slate. btnRetry.addEventListener('click', () => { - state.device.disconnect(); - state.firmwareURL = null; - state.resultTgz = null; - state.resultNmZip = null; - state.manualMode = false; - state.selectedPrefix = null; - state.patchesLoaded = false; - state.isRestore = false; - state.selectedMode = null; - state.nickelMenuOption = null; - btnDeviceNext.hidden = false; - btnDeviceRestore.hidden = false; - - setNavLabels(TL.NAV_DEFAULT); - setNavStep(1); - showStep(stepConnect); + location.reload(); }); // ============================================================================= @@ -494,31 +477,24 @@ btnRetry.addEventListener('click', () => { // Modal dialogs for "How It Works" (disclaimer) and "Privacy" (analytics info). // Clicking the backdrop (the element itself) also closes them. -const dialog = $('how-it-works-dialog'); -$('btn-how-it-works').addEventListener('click', (e) => { - e.preventDefault(); - dialog.showModal(); -}); -$('btn-close-dialog').addEventListener('click', () => { - dialog.close(); -}); -dialog.addEventListener('click', (e) => { - if (e.target === dialog) dialog.close(); -}); +/** Wire up a : open button, close button, and backdrop click to close. */ +function setupDialog(dialogId, openBtnId, closeBtnId) { + const dlg = $(dialogId); + $(openBtnId).addEventListener('click', (e) => { + e.preventDefault(); + dlg.showModal(); + }); + $(closeBtnId).addEventListener('click', () => dlg.close()); + dlg.addEventListener('click', (e) => { + if (e.target === dlg) dlg.close(); + }); +} + +setupDialog('how-it-works-dialog', 'btn-how-it-works', 'btn-close-dialog'); // Privacy dialog is only shown when analytics are enabled. if (analyticsEnabled()) { $('btn-privacy').hidden = false; $('privacy-link-separator').hidden = false; } -const privacyDialog = $('privacy-dialog'); -$('btn-privacy').addEventListener('click', (e) => { - e.preventDefault(); - privacyDialog.showModal(); -}); -$('btn-close-privacy').addEventListener('click', () => { - privacyDialog.close(); -}); -privacyDialog.addEventListener('click', (e) => { - if (e.target === privacyDialog) privacyDialog.close(); -}); +setupDialog('privacy-dialog', 'btn-privacy', 'btn-close-privacy'); diff --git a/web/src/js/nickelmenu-flow.js b/web/src/js/nickelmenu-flow.js index c70a338..35df6cc 100644 --- a/web/src/js/nickelmenu-flow.js +++ b/web/src/js/nickelmenu-flow.js @@ -383,7 +383,7 @@ export function initNickelMenu(state) { showNmDone('download'); } } catch (err) { - state.showError(TL.STATUS.NM_INSTALL_FAILED + err.message); + state.showError(TL.STATUS.NM_INSTALL_FAILED(err.message)); } } diff --git a/web/src/js/patches-flow.js b/web/src/js/patches-flow.js index ca83779..57f7d1b 100644 --- a/web/src/js/patches-flow.js +++ b/web/src/js/patches-flow.js @@ -331,7 +331,7 @@ export function initPatchesFlow(state) { } catch (err) { btnWrite.disabled = false; btnWrite.textContent = TL.BUTTON.WRITE_TO_KOBO; - state.showError(TL.STATUS.WRITE_FAILED + err.message); + state.showError(TL.STATUS.WRITE_FAILED(err.message)); } }); diff --git a/web/src/js/strings.js b/web/src/js/strings.js index 0d81c4f..3bac11a 100644 --- a/web/src/js/strings.js +++ b/web/src/js/strings.js @@ -35,8 +35,8 @@ export const TL = { EXTRACTING: 'Extracting KoboRoot.tgz...', APPLYING_PATCHES: 'Applying patches...', NO_FIRMWARE_URL: 'No download URL available for this device.', - WRITE_FAILED: 'Failed to write KoboRoot.tgz: ', - NM_INSTALL_FAILED: 'NickelMenu installation failed: ', + WRITE_FAILED: (msg) => `Failed to write KoboRoot.tgz: ${msg}`, + NM_INSTALL_FAILED: (msg) => `NickelMenu installation failed: ${msg}`, EXTRACT_FAILED: 'KoboRoot.tgz not found in software update', },