You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit dd3b4d7
Browse filesBrowse the repository at this point in the historyBrowse files
feat(webui): Tools tab as left-nav sidebar + stop-instead-of-pause on tag removal
Tools tab now uses the same vertical UniFi-style sidebar as Settings:
Command / File sync / RFID sync / NVS / EQ rules / Backup / Firmware are
individual sub-panes (icon-only on mobile, pinned while scrolling) instead
of one long stacked scroll. The jump-to-section helpers (sync runner, RFID
sync, firmware update) now activate the matching sub-pane.
New "Stop instead of pause on removal" option (General -> options, a
sub-option of "Pause when RFID tag is removed"): pulling the tag fully
stops playback and clears the playlist rather than just pausing, and
re-applying the tag restarts it from the beginning. Persisted in NVS
(stopRfidRem) and applied live without a reboot; covers both the PN5180
and MFRC522 readers. UI checkbox is only enabled while pause-on-removal
is on. Demo mock + i18n (de/en/fr) updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -134,6 +134,7 @@ neon logo that doubles as the SVG favicon ([`7be5254`](../../commit/7be5254)):
134
134
|**Browser demo on GitHub Pages** ([live](https://fhirschmann.github.io/leoino/)): a device-free static build of the management page with a mock WebSocket/REST layer and copyright-free content, auto-deployed on every push so the UI can be tried without hardware. A CI check (`tools/check_demo_endpoints.py`) fails the build if a new firmware HTTP endpoint is added without a matching demo-mock handler (or an explicit allow-list entry), so the demo can't silently break |[`8bf93da`](../../commit/8bf93da)|
135
135
|**Consolidated, auto-saving Settings tab**: WiFi/MQTT/FTP/Bluetooth merged with the general settings into one tab; the sub-tabs are a **vertical UniFi-style sidebar** (icon-only on mobile; stays pinned while scrolling) with flat, consistent sections, split into General / **Buttons** / **LEDs** / **Power** / **RFID** / … . General/Buttons/LEDs/Power/RFID auto-save (debounced); the credential tabs keep an explicit submit on purpose |[`8b01876`](../../commit/8b01876) · [`1944cf4`](../../commit/1944cf4) · [`c284d0e`](../../commit/c284d0e) · [`32aabfd`](../../commit/32aabfd)|
136
136
|**Configurable branding**: re-brand the navbar header *and* footer from a single **Brand name** field (General → Branding) with a live preview as you type — empty keeps the "Leo Industries" default, so the fork is easy to re-brand |[`fd57fcb`](../../commit/fd57fcb)|
137
+
|**Tools tab as a left-nav sidebar**: the Tools tab now uses the same **vertical UniFi-style sidebar** as Settings — Command / File sync / RFID sync / NVS / EQ rules / Backup / Firmware are individual sub-panes (icon-only on mobile, pinned while scrolling) instead of one long stacked scroll |[`PENDING`](../../commit/PENDING)|
137
138
|**Password protection**: single password (no username), 90-day `HttpOnly` session cookie, brute-force lockout, logout entry; off in hotspot mode. Scripts/API clients authenticate with the password as an **API key** (`X-API-Key` header) |[`e74e712`](../../commit/e74e712)|
138
139
|**One shared device password (Security tab)**: the password fields were pulled out of the WiFi/FTP/WebDAV tabs into a single **Security** sub-tab — one password now protects the web interface, FTP *and* WebDAV (set once, applies everywhere; applied live without a reboot). An **empty password is accepted** and disables protection for all three. The **hostname** moved to the top of the **General** tab (saved on its own; `/wificonfig` now does partial updates) and the navbar brand reads just **Leo Industries**|[`c6dfc67`](../../commit/c6dfc67)|
139
140
|**FTP/WebDAV accept any username**: with one shared password the username is pointless, so both servers now authenticate by **password only — any username is accepted** (wrong password still rejected; empty device password = open). The username fields are gone from both tabs. FTP uses a **vendored, patched copy** of ESP-FTP-Server-Lib in [`lib/`](lib/ESP-FTP-Server-Lib) (password-only auth); WebDAV's self-contained server decodes the HTTP-Basic header and compares only the password |[`be96850`](../../commit/be96850)|
@@ -229,6 +230,7 @@ neon logo that doubles as the SVG favicon ([`7be5254`](../../commit/7be5254)):
229
230
| Change | Commit |
230
231
| --- | --- |
231
232
| Tag removal detected via consecutive-miss counter instead of a wall-clock timeout: pause after ~0.5 s, immune to phantom dropouts and task starvation |[`1fad9cd`](../../commit/1fad9cd)|
233
+
|**Stop instead of pause when the tag is removed** (General → options, sub-option of "Pause when RFID tag is removed"): pulling the card fully stops playback (clears the playlist) rather than just pausing; re-applying the card starts it again from the beginning. Persisted in NVS (`stopRfidRem`) and applied live without a reboot |[`PENDING`](../../commit/PENDING)|
232
234
| Vendored PN5180 library with fast no-card detection: read attempts on an empty field take ~25 ms instead of ~230 ms (no more 200 ms timeout) |[`8762784`](../../commit/8762784)|
233
235
| SLIX2 password support for protected ICODE-SLIX2 tags |[`d3cc69c`](../../commit/d3cc69c)|
234
236
| Configurable idle LED and progress bar colors |[`bdc54e5`](../../commit/bdc54e5)|
Copy file name to clipboardExpand all lines: html/locales/de.json
+11Lines changed: 11 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -696,6 +696,8 @@
696
696
"restartFreshHrsExp": "Wird ein Hörbuch länger als die angegebene Stundenzahl nicht abgespielt, startet es beim nächsten Auflegen wieder von vorn statt an der gespeicherten Stelle. Praktisch für Kinder, die sich nach einem Tag Pause nicht mehr erinnern, wo sie waren. 0 = aus (immer fortsetzen). Standard: 24. Benötigt eine gültige Uhrzeit (NTP/RTC). Fork-Funktion.",
697
697
"pauseIfRfidRemoved": "Pause wenn RFID-Tag entfernt",
698
698
"pauseIfRfidRemovedExp": "Pausieren wenn RFID-Tag entfernt wird. Mehr Infos <a href='https://forum.espuino.de/t/welche-optionen-beim-kompilieren-gibt-es/120' target='_blank'>hier</a> unter <code>PAUSE_WHEN_RFID_REMOVED</code>.",
"stopIfRfidRemovedExp": "Wenn aktiv (nur in Kombination mit „Pause wenn RFID-Tag entfernt“): Beim Abziehen der Karte wird die Wiedergabe vollständig gestoppt statt nur pausiert. Erneutes Auflegen startet die Karte von vorn.",
699
701
"dontAcceptRfidTwice": "Denselben RFID-Tag nicht erneut akzeptieren",
700
702
"resumeOnSameRfidExp": "Wenn die Wiedergabe pausiert ist und derselbe RFID-Tag erneut aufgelegt wird, wird die Wiedergabe fortgesetzt. Funktioniert nur, wenn <em>Denselben RFID-Tag nicht erneut akzeptieren</em> aktiv ist.",
701
703
"playLastRfidOnReboot": "Letzten RFID-Tag nach Neustart abspielen",
@@ -813,6 +815,15 @@
813
815
"started": "Gerät installiert die Firmware und startet neu – die Seite lädt gleich automatisch neu…",
Copy file name to clipboardExpand all lines: html/locales/en.json
+11Lines changed: 11 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -696,6 +696,8 @@
696
696
"restartFreshHrsExp": "If an audiobook has not been played for more than the given number of hours, it starts over from the beginning the next time the card is placed, instead of resuming the saved position. Handy for kids who, after a day's break, no longer remember where they were. 0 = off (always resume). Default: 24. Requires a valid clock (NTP/RTC). Fork feature.",
697
697
"pauseIfRfidRemoved": "Pause when RFID tag is removed",
698
698
"pauseIfRfidRemovedExp": "Playback is paused when the RFID tag is removed. More information <a href='https://forum.espuino.de/t/welche-optionen-beim-kompilieren-gibt-es/120' target='_blank'>here</a> under <code>PAUSE_IF_RFID_REMOVED</code>.",
699
+
"stopIfRfidRemoved": "Stop instead of pause on removal",
700
+
"stopIfRfidRemovedExp": "When enabled (only together with “Pause when RFID tag is removed”): removing the tag fully stops playback instead of just pausing. Re-applying the tag starts it again from the beginning.",
699
701
"dontAcceptRfidTwice": "Don't accept the same RFID twice",
700
702
"dontAcceptRfidTwiceExp": "RFID tags are not accepted twice in a row. Cannot be used together with <em>Pause when RFID tag is removed</em>.",
701
703
"playLastRfidOnReboot": "Play last RFID tag on restart",
@@ -813,6 +815,15 @@
813
815
"started": "Device is installing the firmware and will restart – the page will reload shortly…",
Copy file name to clipboardExpand all lines: html/locales/fr.json
+11Lines changed: 11 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -685,6 +685,8 @@
685
685
"restartFreshHrsExp": "Si un livre audio n'a pas été lu depuis plus que le nombre d'heures indiqué, il recommence depuis le début lors de la prochaine pose de la carte, au lieu de reprendre à la position enregistrée. Pratique pour les enfants qui, après une journée de pause, ne se souviennent plus où ils en étaient. 0 = désactivé (toujours reprendre). Par défaut : 24. Nécessite une horloge valide (NTP/RTC). Fonction du fork.",
686
686
"pauseIfRfidRemoved": "Mettre en pause si la balise RFID est retirée",
687
687
"pauseIfRfidRemovedExp": "Mettre en pause la lecture si la balise RFID est retirée. Plus d'informations <a href='https://forum.espuino.de/t/welche-optionen-beim-kompilieren-gibt-es/120' target='_blank'>ici</a> sous <code>PAUSE_IF_RFID_REMOVED</code>.",
688
+
"stopIfRfidRemoved": "Arrêter au lieu de mettre en pause",
689
+
"stopIfRfidRemovedExp": "Si activé (uniquement avec « Mettre en pause si la balise RFID est retirée ») : retirer la balise arrête complètement la lecture au lieu de la mettre en pause. Reposer la balise redémarre depuis le début.",
688
690
"dontAcceptRfidTwice": "Ne pas accepter la balise RFID deux fois",
689
691
"dontAcceptRfidTwiceExp": "Ne pas accepter la même balise RFID deux fois. Ne peut pas être utilisé avec <em>Mettre en pause si la balise RFID est retirée</em>.",
690
692
"playLastRfidOnReboot": "Lire la dernière balise RFID au redémarrage",
@@ -802,6 +804,15 @@
802
804
"started": "L'appareil installe le micrologiciel et va redémarrer – la page se rechargera sous peu…",
803
805
"error": "Échec de la mise à jour (voir la console/le journal)."
0 commit comments