* 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
* use new ids
* refactor in appearance settings
* fix lint
* remove setThemeMode from handleThemeSelect
* fix type logic
* use context for theme
* shorten animation
* adjusted LanguagePickerModal
* Fix Accent Color picker
* fix bottom navigation coloring
* log error instead of crashing when no theme context is available
The plugin row sits inside a react-native-gesture-handler Swipeable but
used the React Native Pressable, whose JS responder lost mouse-derived
tap events on WSA. Switch to the gesture-handler Pressable so taps share
the same responder system as the surrounding Swipeable.
* fix: Apply active filters to chapter count display (Closes#1793)
getChapterCount was always returning the total count regardless of
the active filter. When filtering by unread/downloaded/bookmarked,
the count shown in the novel header stayed the same as the total.
Added an optional filter parameter to getChapterCount and pass the
current settingsFilter from useNovel so the displayed count matches
the filtered chapter list.
* fix lint warning and add tests for filtered chapter count
- Use settingsFilter instead of novelSettings.filter in useNovel
to fix the react-hooks/exhaustive-deps warning
- Add tests for getChapterCount with filter parameter
- Update chapterFilterToSQL mock in test setup to actually apply
filter conditions so filtered count tests work correctly
* init
* Change from react-native-dotenv to react-native-config as dotenv leaks
env variables that set mmkv in test mode.
* upgrade debs
* upgrade mmkv
* fix db migration for new app builds
* update reanimated
* fix tests
* fix lint
* cleanup
* Update JumpToChapterModal.tsx
* fix settings.gradle
* first attempt
* first attempt
* added first useNovel tests
* more tests
* more tests
* resolved all test issues
* added test-utils
* add a few component tests
* add TESTIGN.md
* add testing gh action
* fixed minor issues
* fixed minor issues
Replace expo-notifications based TTS controls with a native
NativeTTSMediaControl TurboModule using Android's MediaSessionCompat
and MediaStyle notification. This provides proper media integration
with lock screen controls, cover art display, and seekbar.
- Add NativeTTSMediaControl Kotlin TurboModule with MediaSession
- Support Prev, Rewind, Play/Pause, Next notification buttons
- Show novel cover as notification album art
- Add seekbar with seek-to-element support
- Replace MMKV polling with NativeEventEmitter for instant response
- Add rewind and seekTo methods to TTS in core.js
- Clean up expo-notifications TTS setup from App.tsx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* added .jj to .gitignore
* chore: Add drizzle-orm and drizzle-kit dependencies to package.json and pnpm-lock.yaml
* update debs
* Edit configs
* create drizzle schema
* generate drizzle migration
* db manager stuff
* Delete unused files
* Update DB Manager
* Rework CategoryQueries and related
* rewrite chapterQueries
* Type safety for chapter order and filter
* Better filter handling
* added queue
* added back database triggers
* Refactor HistoryQueries and LibraryQueries
* fix type issues
* refactor StatsQueries
* refactor NovelQueries
* renamed schemas
* refactor more db calls
* refactor libraryUpdateQueries
* removed deprecated code
* added extracted queries
* fix updates screen issue
* change to op-sqlite
* Update manager.ts
* Update RepositoryQueries
* update packages
* Update NovelQueries
* Update CategoryQueries.ts
* db testing environment v1 (AI)
* Refactor App component to use Suspense for loading state and update database initialization logic. Change drizzle-orm version to 0.45.1 and adjust related database queries for improved error handling and async operations. Clean up unused code and update types for better type safety.
* updated tests
* change db location to default expo-sqlite location
* fix async/sync bugs
* resolve rebase problems
* Added tests for db creation + migration
* update drizzle
* add missing journals to migrations.js
* wrap testDbManager in Proxy to be async
* add db initialization test
* fix lint errors
* improved dbManager.batch function
* remove unused file
* fix rebase conflicts
* use getColumns instead of getTableColumns
* fix lint errors
* fix release build not being able to start
* remove disable lint rule
* improved useLiveQuery
* Resolve issue with the db queue constructor options
* Fix database query issues in library and stats
- Add missing await to all stats query functions
- Remove unnecessary type casts on query results
- Fix downloaded-only filter to use gt(0) instead of eq(1)
---------
Co-authored-by: CD-Z <github.verify097@passmail.com>
LegendList's extraData only included downloadingChapterIds, so chapter
items weren't re-rendered when selection state changed via long press.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>