Separate configuration step
All checks were successful
Build and test project / build-and-test (push) Successful in 1m37s
All checks were successful
Build and test project / build-and-test (push) Successful in 1m37s
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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">‹ Back</button>
|
||||
<button id="btn-nm-features-next" class="primary">Continue ›</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Step 2c: NickelMenu review -->
|
||||
<section id="step-nm-review" class="step" hidden>
|
||||
<p id="nm-review-summary"></p>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user