1
0

Additional logging, accessibility

This commit is contained in:
2026-03-22 12:06:28 +01:00
parent 396e148733
commit ce07449cae
4 changed files with 34 additions and 27 deletions

View File

@@ -41,13 +41,13 @@
</header> </header>
<!-- Shown until JS initialises --> <!-- Shown until JS initialises -->
<div id="initial-loader" class="initial-loader"> <div id="initial-loader" class="initial-loader" role="status" aria-label="Loading">
<div class="spinner"></div> <div class="spinner" aria-hidden="true"></div>
<p>Loading&hellip;</p> <p>Loading&hellip;</p>
</div> </div>
<!-- Step indicator (populated dynamically by app.js) --> <!-- Step indicator (populated dynamically by app.js) -->
<nav id="step-nav" class="step-nav" hidden> <nav id="step-nav" class="step-nav" aria-label="Progress" hidden>
<ol></ol> <ol></ol>
</nav> </nav>
@@ -89,13 +89,13 @@
<p class="fallback-hint"> <p class="fallback-hint">
<strong>Select the version number currently installed on your device.</strong> If it does not appear in this list, your software version is not supported for custom patching. You can go back and choose NickelMenu instead, which works with all versions. <strong>Select the version number currently installed on your device.</strong> If it does not appear in this list, your software version is not supported for custom patching. You can go back and choose NickelMenu instead, which works with all versions.
</p> </p>
<select id="manual-version"> <select id="manual-version" aria-label="Software version">
<option value="">-- Select software version --</option> <option value="">-- Select software version --</option>
</select> </select>
<p id="manual-version-hint" class="fallback-hint"> <p id="manual-version-hint" class="fallback-hint">
You can find the version number on your Kobo under <strong>More &gt; Settings &gt; Device information</strong> &gt; <strong>Software version</strong>. You can find the version number on your Kobo under <strong>More &gt; Settings &gt; Device information</strong> &gt; <strong>Software version</strong>.
</p> </p>
<select id="manual-model" hidden> <select id="manual-model" aria-label="Kobo model" hidden>
<option value="">-- Select your Kobo model --</option> <option value="">-- Select your Kobo model --</option>
</select> </select>
<p id="manual-model-hint" class="fallback-hint" hidden> <p id="manual-model-hint" class="fallback-hint" hidden>
@@ -142,7 +142,7 @@
<!-- Step 2: Mode selection --> <!-- Step 2: Mode selection -->
<section id="step-mode" class="step" hidden> <section id="step-mode" class="step" hidden>
<p>What would you like to do?</p> <p>What would you like to do?</p>
<div class="mode-cards"> <div class="mode-cards" role="radiogroup" aria-label="Mode selection">
<label class="mode-card mode-card-selected"> <label class="mode-card mode-card-selected">
<input type="radio" name="mode" value="nickelmenu" checked> <input type="radio" name="mode" value="nickelmenu" checked>
<div class="mode-card-body"> <div class="mode-card-body">
@@ -168,7 +168,7 @@
<!-- Step 2b: NickelMenu configuration --> <!-- Step 2b: NickelMenu configuration -->
<section id="step-nickelmenu" class="step" hidden> <section id="step-nickelmenu" class="step" hidden>
<p>Choose what to do with your Kobo.</p> <p>Choose what to do with your Kobo.</p>
<div class="nm-options"> <div class="nm-options" role="radiogroup" aria-label="NickelMenu options">
<label class="nm-option"> <label class="nm-option">
<input type="radio" name="nm-option" value="preset"> <input type="radio" name="nm-option" value="preset">
<div class="nm-option-body"> <div class="nm-option-body">
@@ -224,8 +224,8 @@
<!-- NickelMenu installing --> <!-- NickelMenu installing -->
<section id="step-nm-installing" class="step" hidden> <section id="step-nm-installing" class="step" hidden>
<div class="build-header"> <div class="build-header" role="status" aria-live="polite">
<div class="spinner"></div> <div class="spinner" aria-hidden="true"></div>
<p id="nm-progress">Starting...</p> <p id="nm-progress">Starting...</p>
</div> </div>
</section> </section>
@@ -293,8 +293,8 @@
<!-- Step 4: Building --> <!-- Step 4: Building -->
<section id="step-building" class="step" hidden> <section id="step-building" class="step" hidden>
<div class="build-header"> <div class="build-header" role="status" aria-live="polite">
<div class="spinner"></div> <div class="spinner" aria-hidden="true"></div>
<p id="build-progress">Starting...</p> <p id="build-progress">Starting...</p>
</div> </div>
<pre id="build-log" class="build-log"></pre> <pre id="build-log" class="build-log"></pre>
@@ -362,10 +362,10 @@
</p> </p>
</footer> </footer>
<dialog id="how-it-works-dialog" class="modal"> <dialog id="how-it-works-dialog" class="modal" aria-labelledby="how-it-works-title">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h2>Disclaimer</h2> <h2 id="how-it-works-title">Disclaimer</h2>
<button id="btn-close-dialog" class="modal-close" aria-label="Close">&times;</button> <button id="btn-close-dialog" class="modal-close" aria-label="Close">&times;</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@@ -425,10 +425,10 @@
</div> </div>
</dialog> </dialog>
<dialog id="privacy-dialog" class="modal"> <dialog id="privacy-dialog" class="modal" aria-labelledby="privacy-title">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h2>Privacy</h2> <h2 id="privacy-title">Privacy</h2>
<button id="btn-close-privacy" class="modal-close" aria-label="Close">&times;</button> <button id="btn-close-privacy" class="modal-close" aria-label="Close">&times;</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">

View File

@@ -181,8 +181,12 @@ import JSZip from 'jszip';
items.forEach((li, i) => { items.forEach((li, i) => {
const stepNum = i + 1; const stepNum = i + 1;
li.classList.remove('active', 'done'); li.classList.remove('active', 'done');
li.removeAttribute('aria-current');
if (stepNum < num) li.classList.add('done'); if (stepNum < num) li.classList.add('done');
else if (stepNum === num) li.classList.add('active'); else if (stepNum === num) {
li.classList.add('active');
li.setAttribute('aria-current', 'step');
}
}); });
stepNav.hidden = false; stepNav.hidden = false;
} }
@@ -746,13 +750,13 @@ import JSZip from 'jszip';
nmProgress.textContent = 'Removing NickelMenu assets...'; nmProgress.textContent = 'Removing NickelMenu assets...';
try { try {
await device.removeEntry(['.adds', 'nm'], { recursive: true }); await device.removeEntry(['.adds', 'nm'], { recursive: true });
} catch { } catch (err) {
// ignore — folder may already be gone console.warn('Could not remove .adds/nm:', err);
} }
try { try {
await device.removeEntry(['.adds', 'scripts'], { recursive: true }); await device.removeEntry(['.adds', 'scripts'], { recursive: true });
} catch { } catch (err) {
// ignore — folder may already be gone console.warn('Could not remove .adds/scripts:', err);
} }
nmProgress.textContent = 'Creating uninstall marker...'; nmProgress.textContent = 'Creating uninstall marker...';
await device.writeFile(['.adds', 'nm', 'uninstall'], new Uint8Array(0)); await device.writeFile(['.adds', 'nm', 'uninstall'], new Uint8Array(0));
@@ -763,8 +767,8 @@ import JSZip from 'jszip';
for (const entry of feature.uninstall.paths) { for (const entry of feature.uninstall.paths) {
try { try {
await device.removeEntry(entry.path, { recursive: !!entry.recursive }); await device.removeEntry(entry.path, { recursive: !!entry.recursive });
} catch { } catch (err) {
// ignore — file may already be gone console.warn(`Could not remove ${entry.path.join('/')}:`, err);
} }
} }
} }

View File

@@ -62,18 +62,20 @@ class KoboDevice {
let koboDir; let koboDir;
try { try {
koboDir = await this.directoryHandle.getDirectoryHandle('.kobo'); koboDir = await this.directoryHandle.getDirectoryHandle('.kobo');
} catch { } catch (err) {
throw new Error( throw new Error(
'This does not appear to be a Kobo device. Could not find the .kobo directory.' 'This does not appear to be a Kobo device. Could not find the .kobo directory.',
{ cause: err }
); );
} }
let versionFile; let versionFile;
try { try {
versionFile = await koboDir.getFileHandle('version'); versionFile = await koboDir.getFileHandle('version');
} catch { } catch (err) {
throw new Error( throw new Error(
'Could not find .kobo/version. Is this the root of your Kobo drive?' 'Could not find .kobo/version. Is this the root of your Kobo drive?',
{ cause: err }
); );
} }

View File

@@ -155,7 +155,8 @@ async function scanAvailablePatches() {
} }
} }
return result; return result;
} catch { } catch (err) {
console.error('Failed to load patch index:', err);
return []; return [];
} }
} }