diff --git a/.gitignore b/.gitignore index 6c0aa60..ffb9d27 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,9 @@ tests/e2e/node_modules/ tests/e2e/test-results/ tests/e2e/playwright-report/ +# NickelMenu build artifacts +nickelmenu/kobo-config/ +web/public/nickelmenu/ + # Claude .claude \ No newline at end of file diff --git a/nickelmenu/setup.sh b/nickelmenu/setup.sh new file mode 100755 index 0000000..750643d --- /dev/null +++ b/nickelmenu/setup.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PUBLIC_DIR="$SCRIPT_DIR/../web/public/nickelmenu" + +mkdir -p "$PUBLIC_DIR" + +# --- NickelMenu.zip --- +NICKELMENU_URL="https://github.com/nicoverbruggen/NickelMenu/releases/download/experimental/NickelMenu.zip" +echo "Downloading NickelMenu.zip..." +curl -fSL -o "$PUBLIC_DIR/NickelMenu.zip" "$NICKELMENU_URL" +echo " -> $(du -h "$PUBLIC_DIR/NickelMenu.zip" | cut -f1)" + +# --- kobo-config --- +KOBO_CONFIG_DIR="$SCRIPT_DIR/kobo-config" +if [ -d "$KOBO_CONFIG_DIR" ]; then + echo "Updating kobo-config..." + cd "$KOBO_CONFIG_DIR" + git pull +else + echo "Cloning kobo-config..." + git clone https://github.com/nicoverbruggen/kobo-config.git "$KOBO_CONFIG_DIR" +fi + +# Copy the relevant assets into a zip for the web app. +# Includes: .adds/, .kobo/screensaver/, fonts/ +echo "Bundling kobo-config.zip..." +cd "$KOBO_CONFIG_DIR" +zip -r "$PUBLIC_DIR/kobo-config.zip" \ + .adds/ \ + .kobo/screensaver/ \ + fonts/ \ + -x "*.DS_Store" + +echo " -> $(du -h "$PUBLIC_DIR/kobo-config.zip" | cut -f1)" + +echo "" +echo "Done. Assets written to: $PUBLIC_DIR" diff --git a/run-locally.sh b/run-locally.sh index c6dc08a..4dd17e3 100755 --- a/run-locally.sh +++ b/run-locally.sh @@ -4,6 +4,11 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" WASM_DIR="$SCRIPT_DIR/kobopatch-wasm" +if [ ! -f "$SCRIPT_DIR/web/public/nickelmenu/NickelMenu.zip" ]; then + echo "NickelMenu assets not found, downloading..." + "$SCRIPT_DIR/nickelmenu/setup.sh" +fi + if [ ! -f "$SCRIPT_DIR/web/public/wasm/kobopatch.wasm" ]; then echo "WASM binary not found, building..." if [ ! -d "$WASM_DIR/kobopatch-src" ]; then diff --git a/web/public/css/style.css b/web/public/css/style.css index 85a64e0..885f217 100644 --- a/web/public/css/style.css +++ b/web/public/css/style.css @@ -162,6 +162,206 @@ h2 { background: var(--success-text); } +/* Mode selection cards */ +.mode-cards { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.mode-card { + display: flex; + align-items: flex-start; + gap: 0.75rem; + padding: 1rem 1.25rem; + background: var(--card-bg); + border: 2px solid var(--border-light); + border-radius: 10px; + cursor: pointer; + transition: border-color 0.15s, box-shadow 0.15s; + box-shadow: var(--shadow); +} + +#mode-patches-hint { + margin-top: 15px; +} + +.mode-card:hover { + border-color: var(--border); +} + +.mode-card-selected { + border-color: var(--primary); + box-shadow: 0 0 0 1px var(--primary), var(--shadow); +} + +.mode-card-btn { + text-align: left; + width: 100%; +} + +.mode-card-btn:hover { + border-color: var(--primary); + box-shadow: 0 0 0 1px var(--primary), var(--shadow); +} + +.mode-card-btn:disabled { + opacity: 0.45; + cursor: not-allowed; + box-shadow: var(--shadow); +} + +.mode-card-btn:disabled:hover { + border-color: var(--border-light); + box-shadow: var(--shadow); +} + +.mode-card input[type="radio"] { + margin-top: 0.2rem; + flex-shrink: 0; + accent-color: var(--primary); +} + +.mode-card-title { + display: flex; + align-items: center; + gap: 0.5rem; + font-weight: 600; + font-size: 0.93rem; + color: var(--text); + margin-bottom: 0.25rem; +} + +.mode-card-desc { + font-size: 0.83rem; + color: var(--text-secondary); + line-height: 1.5; +} + +.recommended-pill { + margin-left: auto; + font-size: 10px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + background: var(--success-text); + color: #fff; + padding: 0.2rem 0.6rem; + border-radius: 8px; + white-space: nowrap; +} + +/* NickelMenu option radio cards */ +.nm-options { + display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.nm-option { + display: flex; + align-items: flex-start; + gap: 0.75rem; + padding: 0.85rem 1rem; + background: var(--card-bg); + border: 2px solid var(--border-light); + border-radius: 10px; + cursor: pointer; + transition: border-color 0.15s, box-shadow 0.15s; + box-shadow: var(--shadow); +} + +.nm-option:hover { + border-color: var(--border); +} + +.nm-option-selected { + border-color: var(--primary); + box-shadow: 0 0 0 1px var(--primary), var(--shadow); +} + +.nm-option-disabled { + opacity: 0.45; + cursor: not-allowed; +} + +.nm-option-disabled:hover { + border-color: var(--border-light); +} + +.nm-option-remove:not(.nm-option-disabled) { + border-color: var(--error-border); +} + +.nm-option-remove:not(.nm-option-disabled):hover { + border-color: var(--error-text); +} + +.nm-option-remove.nm-option-selected { + border-color: var(--error-text); + box-shadow: 0 0 0 1px var(--error-text), var(--shadow); +} + +.nm-option-remove input[type="radio"] { + accent-color: var(--error-text); +} + +/* NickelMenu config checkboxes */ +.nm-config-options { + margin-top: 0.75rem; + padding: 0.75rem 1rem; + background: var(--card-bg); + border: 1px solid var(--border-light); + border-radius: 10px; + box-shadow: var(--shadow); +} + +.nm-config-item { + display: flex; + align-items: center; + gap: 0.6rem; + padding: 0.4rem 0; + font-size: 0.88rem; + color: var(--text); + cursor: pointer; +} + +.nm-config-item + .nm-config-item { + border-top: 1px solid var(--border-light); +} + +.nm-config-item input[type="checkbox"] { + flex-shrink: 0; + accent-color: var(--primary); +} + +.nm-config-item input[type="checkbox"]:disabled { + opacity: 0.6; +} + +.nm-config-item span { + user-select: none; +} + +.nm-option input[type="radio"] { + margin-top: 0.2rem; + flex-shrink: 0; + accent-color: var(--primary); +} + +.nm-option-title { + font-weight: 500; + font-size: 0.88rem; + color: var(--text); + margin-bottom: 0.15rem; +} + +.nm-option-desc { + font-size: 0.78rem; + color: var(--text-secondary); + line-height: 1.5; +} + /* Steps */ .step { margin-bottom: 1rem; @@ -182,7 +382,8 @@ h2 { margin-top: 1.25rem; } -.step-actions .primary:first-child { +.step-actions .primary:first-child, +.step-actions > [hidden] + .primary { margin-left: auto; } diff --git a/web/public/index.html b/web/public/index.html index 9d3a5d8..f7ec31d 100644 --- a/web/public/index.html +++ b/web/public/index.html @@ -26,7 +26,7 @@

KoboPatch Web UI beta

-

Apply patches to your Kobo Libra Colour, Kobo Clara Colour and Kobo Clara BW.

+

Customise your Kobo e-reader with NickelMenu or custom patches.

@@ -35,60 +35,59 @@

Loading…

- + - + - - - + + + + + + + + + + + + + + + +