1
0

Separate configuration step
All checks were successful
Build and test project / build-and-test (push) Successful in 1m37s

This commit is contained in:
2026-03-22 11:39:30 +01:00
parent 17fcbf4d93
commit aebfe59a01
8 changed files with 125 additions and 67 deletions

View File

@@ -184,6 +184,13 @@ h2 {
gap: 0.75rem;
}
.mode-card-icon {
width: 28px;
height: 28px;
flex-shrink: 0;
color: var(--text-secondary);
}
.mode-card {
display: flex;
align-items: flex-start;
@@ -278,14 +285,14 @@ h2 {
.nm-options {
display: flex;
flex-direction: column;
gap: 0.6rem;
gap: 0.75rem;
}
.nm-option {
display: flex;
align-items: flex-start;
gap: 0.75rem;
padding: 0.85rem 1rem;
padding: 1rem 1.25rem;
background: var(--card-bg);
border: 2px solid var(--border-light);
border-radius: 10px;
@@ -330,7 +337,9 @@ h2 {
}
#nm-uninstall-options {
padding: 0 0.25rem;
display: flex;
flex-direction: column;
margin-top: 0.5rem;
margin-left: 1.5rem;
}
@@ -338,18 +347,17 @@ h2 {
accent-color: var(--error-text) !important;
}
/* NickelMenu config checkboxes */
/* NickelMenu feature checkboxes */
.nm-config-options {
padding: 0 0.25rem;
margin-left: 1.5rem;
display: flex;
flex-direction: column;
}
.nm-config-item {
display: flex;
align-items: flex-start;
gap: 0.6rem;
padding: 0.5rem 0;
font-size: 0.88rem;
gap: 0.75rem;
padding: 0.6rem 0;
color: var(--text);
cursor: pointer;
}
@@ -360,7 +368,7 @@ h2 {
.nm-config-item input[type="checkbox"] {
flex-shrink: 0;
margin-top: 0.15rem;
margin-top: 0.2rem;
accent-color: var(--primary);
}
@@ -370,32 +378,23 @@ h2 {
.nm-config-text {
user-select: none;
margin-top: -2px;
}
.nm-config-title {
display: block;
font-weight: 600;
font-size: 0.93rem;
color: var(--text);
}
.nm-config-desc {
display: block;
font-size: 0.75rem;
font-size: 0.83rem;
color: var(--text-secondary);
line-height: 1.4;
line-height: 1.5;
margin-top: 0.1rem;
}
.nm-config-link {
display: block;
margin-top: 0.75rem;
padding-top: 0.75rem;
padding-bottom: 0.75rem;
border-top: 1px solid var(--border-light);
font-size: 0.8rem;
color: var(--primary);
text-decoration: none;
}
.nm-config-link:hover {
text-decoration: underline;
}
.nm-option input[type="radio"] {
margin-top: 0.2rem;
flex-shrink: 0;
@@ -403,14 +402,14 @@ h2 {
}
.nm-option-title {
font-weight: 500;
font-size: 0.88rem;
font-weight: 600;
font-size: 0.93rem;
color: var(--text);
margin-bottom: 0.15rem;
margin-bottom: 0.25rem;
}
.nm-option-desc {
font-size: 0.78rem;
font-size: 0.83rem;
color: var(--text-secondary);
line-height: 1.5;
}

View File

@@ -60,7 +60,7 @@
<p>How would you like to set up your Kobo?</p>
<div class="mode-cards">
<button id="btn-connect" class="mode-card mode-card-btn">
<svg class="mode-card-icon" xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 16 16" fill="currentColor"><path d="m7.792.312-1.533 2.3A.25.25 0 0 0 6.467 3H7.5v7.319a2.5 2.5 0 0 0-.515-.298L5.909 9.56A1.5 1.5 0 0 1 5 8.18v-.266a1.5 1.5 0 1 0-1 0v.266a2.5 2.5 0 0 0 1.515 2.298l1.076.461a1.5 1.5 0 0 1 .888 1.129 2.001 2.001 0 1 0 1.021-.006v-.902a1.5 1.5 0 0 1 .756-1.303l1.484-.848A2.5 2.5 0 0 0 11.995 7h.755a.25.25 0 0 0 .25-.25v-2.5a.25.25 0 0 0-.25-.25h-2.5a.25.25 0 0 0-.25.25v2.5c0 .138.112.25.25.25h.741a1.5 1.5 0 0 1-.747 1.142L8.76 8.99a2.584 2.584 0 0 0-.26.17V3h1.033a.25.25 0 0 0 .208-.389L8.208.312a.25.25 0 0 0-.416 0Z"/></svg>
<svg class="mode-card-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M15,7V11H16V13H13V5H15L12,1L9,5H11V13H8V10.93C8.66,10.59 9.1,9.87 9.1,9A2.1,2.1 0 0,0 7,6.9C5.84,6.9 4.9,7.84 4.9,9C4.9,9.87 5.34,10.59 6,10.93V13A2,2 0 0,0 8,15H11V18.05C10.29,18.32 9.75,18.93 9.75,19.75A1.75,1.75 0 0,0 11.5,21.5C12.47,21.5 13.25,20.72 13.25,19.75C13.25,18.93 12.71,18.32 12,18.05V15H16A2,2 0 0,0 18,13V11H19V7H15Z"/></svg>
<div class="mode-card-body">
<div class="mode-card-title">
Connect my Kobo
@@ -70,7 +70,7 @@
</div>
</button>
<button id="btn-manual" class="mode-card mode-card-btn">
<svg class="mode-card-icon" xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
<svg class="mode-card-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z"/></svg>
<div class="mode-card-body">
<div class="mode-card-title">
Build downloadable archive
@@ -176,9 +176,6 @@
<div class="nm-option-desc">Installs NickelMenu with a curated set of menu options. You get to decide which optional features you'd like to enable.</div>
</div>
</label>
<div id="nm-config-options" class="nm-config-options" hidden>
<!-- Populated dynamically from feature modules by app.js -->
</div>
<label class="nm-option">
<input type="radio" name="nm-option" value="nickelmenu-only">
<div class="nm-option-body">
@@ -201,6 +198,16 @@
</div>
</section>
<!-- Step 2b-2: NickelMenu feature selection (preset only) -->
<section id="step-nm-features" class="step" hidden>
<p>Select which features you'd like to enable.</p>
<div id="nm-config-options" class="nm-config-options"></div>
<div class="step-actions">
<button id="btn-nm-features-back" class="secondary">&#x2039; Back</button>
<button id="btn-nm-features-next" class="primary">Continue &#x203A;</button>
</div>
</section>
<!-- Step 2c: NickelMenu review -->
<section id="step-nm-review" class="step" hidden>
<p id="nm-review-summary"></p>

View File

@@ -86,6 +86,7 @@ import JSZip from 'jszip';
const stepDevice = $('step-device');
const stepMode = $('step-mode');
const stepNickelMenu = $('step-nickelmenu');
const stepNmFeatures = $('step-nm-features');
const stepNmInstalling = $('step-nm-installing');
const stepNmDone = $('step-nm-done');
const stepPatches = $('step-patches');
@@ -106,6 +107,8 @@ import JSZip from 'jszip';
const btnModeNext = $('btn-mode-next');
const btnNmBack = $('btn-nm-back');
const btnNmNext = $('btn-nm-next');
const btnNmFeaturesBack = $('btn-nm-features-back');
const btnNmFeaturesNext = $('btn-nm-features-next');
const btnNmReviewBack = $('btn-nm-review-back');
const btnNmWrite = $('btn-nm-write');
const btnNmDownload = $('btn-nm-download');
@@ -138,7 +141,7 @@ import JSZip from 'jszip';
const allSteps = [
stepConnect, stepManualVersion, stepDevice,
stepMode, stepNickelMenu, stepNmReview, stepNmInstalling, stepNmDone,
stepMode, stepNickelMenu, stepNmFeatures, stepNmReview, stepNmInstalling, stepNmDone,
stepPatches, stepFirmware, stepBuilding, stepDone,
stepError,
];
@@ -501,6 +504,7 @@ import JSZip from 'jszip';
textDiv.className = 'nm-config-text';
const titleSpan = document.createElement('span');
titleSpan.className = 'nm-config-title';
let titleText = feature.title;
if (feature.required) titleText += ' (required)';
if (feature.version) titleText += ' ' + feature.version;
@@ -518,10 +522,9 @@ import JSZip from 'jszip';
}
}
// Show/hide config checkboxes based on radio selection, enable Continue
// Show/hide uninstall options based on radio selection, enable Continue
for (const radio of $qa('input[name="nm-option"]', stepNickelMenu)) {
radio.addEventListener('change', () => {
nmConfigOptions.hidden = radio.value !== 'preset' || !radio.checked;
nmUninstallOptions.hidden = radio.value !== 'remove' || !radio.checked || detectedUninstallFeatures.length === 0;
btnNmNext.disabled = false;
});
@@ -587,6 +590,7 @@ import JSZip from 'jszip';
textDiv.className = 'nm-config-text';
const titleSpan = document.createElement('span');
titleSpan.className = 'nm-config-title';
titleSpan.textContent = 'Also remove ' + feature.uninstall.title;
const descSpan = document.createElement('span');
@@ -625,9 +629,7 @@ import JSZip from 'jszip';
async function goToNickelMenuConfig() {
await checkNickelMenuInstalled();
renderFeatureCheckboxes();
const currentOption = $q('input[name="nm-option"]:checked', stepNickelMenu);
nmConfigOptions.hidden = !currentOption || currentOption.value !== 'preset';
nmUninstallOptions.hidden = !currentOption || currentOption.value !== 'remove' || detectedUninstallFeatures.length === 0;
btnNmNext.disabled = !currentOption;
setNavStep(3);
@@ -638,13 +640,34 @@ import JSZip from 'jszip';
goToModeSelection();
});
// Continue from configure to review
// Continue from NM option selection
btnNmNext.addEventListener('click', () => {
const selected = $q('input[name="nm-option"]:checked', stepNickelMenu);
if (!selected) return;
nickelMenuOption = selected.value;
track('nm-option', { option: nickelMenuOption });
if (nickelMenuOption === 'preset') {
goToNmFeatures();
} else {
goToNmReview();
}
});
function goToNmFeatures() {
// Only render checkboxes if they haven't been created yet
if (!nmConfigOptions.children.length) {
renderFeatureCheckboxes();
}
setNavStep(3);
showStep(stepNmFeatures);
}
btnNmFeaturesBack.addEventListener('click', async () => {
await goToNickelMenuConfig();
});
btnNmFeaturesNext.addEventListener('click', () => {
goToNmReview();
});
@@ -702,7 +725,11 @@ import JSZip from 'jszip';
}
btnNmReviewBack.addEventListener('click', async () => {
await goToNickelMenuConfig();
if (nickelMenuOption === 'preset') {
goToNmFeatures();
} else {
await goToNickelMenuConfig();
}
});
async function executeNmInstall(writeToDevice) {

View File

@@ -1,7 +1,7 @@
export default {
id: 'custom-menu',
title: 'Set up custom menu',
description: 'Adds menu items for dark mode, screenshots, and more. A new tab will be added in the bottom navigation that is labelled "Tweak".',
title: 'Set up NickelMenu preset',
description: 'Adds menu items for dark mode, screenshots, and more. A new tab will be added in the bottom navigation that is labelled "Tweak". (Preset made by the author of this website.)',
default: true,
required: true,

View File

@@ -1,7 +1,7 @@
export default {
id: 'hide-recommendations',
title: 'Hide home screen recommendations',
description: 'Hides the recommendations column next to your current read on the home screen. Useful if you are only reading one book at a time.',
description: 'Hides the recommendations next to your current read on the home screen.',
default: false,
postProcess(files) {

View File

@@ -3,7 +3,7 @@ import JSZip from 'jszip';
export default {
id: 'koreader',
title: 'Install KOReader',
description: 'Installs KOReader, an alternative e-book reader with advanced features like PDF reflow, customizable fonts, and more. Installing this requires many files to be copied and that can take a bit, so please be patient when transferring this to your Kobo.',
description: 'Installs KOReader, an alternative e-book reader with advanced features like PDF reflow, customizable fonts, and more. Installing this requires many files to be copied and that can take a bit, so please be patient when transferring this to your Kobo. You can start KOReader via the Tweak menu, it does not replace the built-in reader functionality.',
default: false,
available: false, // set to true at runtime if KOReader assets exist

View File

@@ -13,8 +13,8 @@ const TAB_CONFIG = [
export default {
id: 'simplify-tabs',
title: 'Hide certain navigation tabs',
description: 'This will hide the Notebook and Discover tabs from the bottom navigation. For minimalists who want fewer distractions.',
title: 'Simplify navigation tabs',
description: 'Hides the "My Notebooks" and "Discover" tabs from the bottom navigation tab bar.',
default: false,
postProcess(files) {