3.1.1: EPUB import fixes, minor UI fix
A patch release focused on UX rough edges introduced after 3.1.0. EPUB import is now consolidated into the New Text page, the navbar theme toggle actually works again, and the navigation behaviour after saving any setting is no longer hidden behind stale-cache HTML.
Highlights
EPUB import consolidated onto /texts/new
Picking an .epub under Source → File → From computer now imports inline as a book. The standalone /book/import page still works for legacy bookmarks but shows a deprecation banner. Action-card buttons that pointed there now go to /texts/new. The receiving handler accepts both the legacy field names (LgID, thefile) and the new-text form's names (TxLgID, importFile), so existing direct POSTs keep working.
Tabbed file source
From computer and From server are now tabs instead of stacked sections, so the unused option is hidden by default.
Bug fixes
- EPUB upload (#232): the original filename is now forwarded to the parser. PHP upload temp paths (
/tmp/phpXXXXXX) carry no extension, which used to makekiwilan/php-ebookbail with "File has no extension". - Tagify chunk crash on
/texts/new: Vite 8 / Rolldown was emitting a brokentagify_exportsnamed export when the CSS was dynamically imported. Switched to a static CSS import. setTheFocus()crash: the EPUB form's language<select class="setfocus">was triggeringTypeError: e.select is not a function. The helper now only calls.select()on<input>/<textarea>.- Spurious "1 field(s) must not be empty" alert during EPUB import: the
.notemptyvalidator now skips fields hidden via Alpinex-showor thehiddenattribute. - Theme / language change appearing only after navigation: the service worker used stale-while-revalidate for HTML, so a setting save + reload silently served the previous render. Navigation requests now use network-first; static assets stay cache-first. Service-worker
CACHE_VERSIONbumped tov2, so the old cache is dropped on activate. Existing tabs pick up the change on next load. - Navbar theme toggle click ignored under CSP-build Alpine:
@alpinejs/cspdoes not bind@clickreliably on the same element asx-data. The listener is now attached imperatively in the component'sinit(). Cypress regression test added. - Theme save with no visible change: when in auto mode and the OS preference matches the would-be light/dark target, the saved value is a no-op. The toggle now shows a confirmation toast after reload, and the toast explains the auto-mode case.