* feat(reader): add search button and search input for word search
* fix(reader): make keyboard close on hideHeader
* chore(reader): format reader files
* chore(strings): regenerate string types
* feat(reader): add chapter word search
* fix(reader): improve chapter search reliability
* fix(reader): hide ReaderFooter when search is open
* fix(reader): add support for search in bionic reading mode
* fix(reader): localize chapter search placeholder
* feat(reader): block short word search queries
* feat(reader): make android back button exit search
* feat(reader): add exception for special character search
* refactor(reader): split chapter search script from core
* feat(downloads): make chapter download cooldown configurable
The chapter download service used a hard-coded 1s sleep between
sequential chapter writes. That worked as a polite default but is
either too long for users with patient sources or too short for
sources that 429 on tight loops. Surface the value as a single
global setting instead.
- AppSettings.chapterDownloadCooldownMs (optional, ms)
- getChapterDownloadCooldownMs(): synchronous fallback used by the
background task runner; returns the historical 1000ms when the
user has not configured an override (no regression on upgrade)
- downloadChapter.ts: sleep(getChapterDownloadCooldownMs()) replaces
the previous hard-coded sleep(1000)
- New "Chapter download cooldown" entry in General Settings, placed
directly above "Disable haptic feedback". Tapping opens a modal
that takes seconds (decimal allowed) and writes back as ms
- The input is sanitised on every keystroke to digits + a single
decimal point so paste / hardware keyboard input cannot smuggle
in non-numeric characters
- Reset writes the default explicitly so the user sees feedback
even when the override happened to equal the default
* feat(downloads): warn about source rate limits in cooldown modal
Per review feedback (#1834): the cooldown modal should make the
trade-off explicit so users don't lower the value below what their
sources can take. Add a single error-coloured line under the input.
fix(native-file): prevent crash when unlinking missing files
NativeFileSpec.unlink is codegened as a void-returning TurboModule
method, which dispatches asynchronously on the mqt_v_native thread.
Throwing "File does not exist" there bypasses every JS try/catch and
surfaces as a fatal AndroidRuntime exception, killing the process.
Make unlink idempotent (POSIX rm -f semantics): no-op when the path
does not exist. The Downloads "delete all" and individual delete
flows previously crashed whenever a chapter row had isDownloaded=true
while its on-disk folder had already been removed (e.g. after backup
restore or external cleanup). The same fix also protects useNovel,
pluginManager, fetch, epub/import, backup/local, backup/utils, and
AdvancedTab call sites that share the same native handler.
- patches/@rock-js__plugin-metro@0.12.12.patch: wrap absolute paths
in pathToFileURL() so dynamic imports work on Windows
- pnpm-workspace.yaml: register the patch and pin nodeLinker: hoisted
- pnpm-lock.yaml: lock the patched version with hash
- android/settings.gradle: invoke npx.cmd on Windows for rock autolink