Commit Graph
907 Commits
Author SHA1 Message Date
jpirnay e0e3bd4251 Fix reindexing on toc-page-break 2026-04-23 13:15:30 +02:00
Arthur TazhitdinovandCopilot c867669560 feat: Support for multiple OPDS servers (#1209)
* Add support for configuring and using multiple OPDS servers, replacing
the previous single-server limitation. Closes
https://github.com/crosspoint-reader/crosspoint-reader/issues/1178
* New OpdsServerStore singleton (modeled after WifiCredentialStore) that
persists up to 8 OPDS servers to /.crosspoint/opds.json with MAC-based
password obfuscation.
* One-time migration from legacy single-server fields in
CrossPointSettings to the new store on first boot.
* New OpdsServerListActivity for the device UI — works in two modes: a
settings list (add/edit/delete servers) and a picker (select which
server to browse). When only one server is configured, the picker is
skipped automatically.
* Renamed CalibreSettingsActivity → OpdsSettingsActivity for clarity. It
now edits individual OpdsServer entries (name, URL, username, password,
delete).
* OpdsBookBrowserActivity now receives an OpdsServer at construction and
uses its credentials for all fetches/downloads, and shows the server
name in the header.
* HttpDownloader::fetchUrl and downloadToFile accept optional per-call
username/password parameters instead of reading from global settings.
* REST API endpoints on CrossPointWebServer: GET /api/opds, POST
/api/opds, POST /api/opds/delete — passwords are never exposed over the
API (only a hasPassword flag), and omitting the password field on update
preserves the existing one.
* Web UI (SettingsPage.html) with dynamic OPDS server management cards —
add, edit, save, and delete servers from the browser.
<img width="932" height="906" alt="SCR-20260416-stvu"
src="https://github.com/user-attachments/assets/a8f18d84-4204-46a0-bb31-b73d24b3255f"
/>

* The OpdsServerStore JSON format and obfuscation scheme are identical
to WifiCredentialStore, so the same JsonSettingsIO infrastructure
handles both.
* The web API uses POST /api/opds/delete instead of DELETE /api/opds
because the ESP32 WebServer doesn't support the DELETE method with a
request body.
* Existing single-server configurations are migrated automatically — no
user action required. After migration the legacy CrossPointSettings
fields are cleared so it only runs once.
* The HttpDownloader changes are backward-compatible: the credential
parameters default to empty strings, so existing callers are unaffected.

---

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**< YES >**_

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-23 11:14:50 +02:00
jpirnay 7c6e4728f4 Add swedish keyboard translations (#1726) 2026-04-23 09:42:01 +02:00
jpirnay 700d7b442b fix: Erroneous navigation with long filenames in footnote links (#1723) 2026-04-23 09:39:58 +02:00
jpirnay e5e825e7a5 Update Italian according to #1718 2026-04-23 09:25:50 +02:00
jpirnay 9116070335 Update Spanish according to upstream #1717 2026-04-23 09:24:39 +02:00
jpirnayandClaude Sonnet 4.6 23a77c6aa5 fontconvert.py: cap group uncompressed size at 64 KB
Script-range boundaries alone don't bound group size — dense Unicode
blocks (CJK, user fonts) can produce groups of hundreds of KB. Add a
64 KB hard cap: when adding the next glyph would exceed it, close the
current group and start a new one with the same script ID.

64 KB is well above the largest current built-in group (~50 KB for
notosans_18 Cyrillic) and a safe transient malloc on the ESP32-C3.
The decompressor side already handles any number of groups per font.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 08:36:36 +02:00
jpirnayandClaude Sonnet 4.6 e76118dff0 FontDecompressor: eliminate persistent hot group buffer
The hot group buffer (formerly up to 50 KB BSS / heap) is removed.
During prewarm, each group is now decompressed into a transient malloc
that is freed immediately after its glyphs are extracted — only one
group buffer and the page buffer coexist at a time.

For getBitmap() cache misses (rare: only hit when a glyph wasn't
covered by prewarm), the group is also decompressed transiently and
freed after the single glyph is compacted into _hotGlyphBuf.

Peak heap during prewarm is now: page buffer + one group buffer.
Outside of prewarm, heap usage is only the page buffer itself.
Works correctly for large future fonts (Vietnamese, CJK) regardless
of group size, with no permanent allocation overhead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 08:31:44 +02:00
jpirnayandClaude Sonnet 4.6 80722118a2 FontDecompressor: heap-allocate hot group buffer sized to active font
Replace the 50 KB static BSS _hotGroupBuf array with a heap pointer
allocated once per font (ensureHotGroupBuf). The buffer is sized to the
largest group in the active font — 6 KB for small fonts, ~50 KB for 18pt
— so no memory is wasted when rendering body text at typical sizes.

The buffer persists across pages (freed only in freeHotGroup/deinit),
so there is exactly one malloc per font session rather than one per page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 08:14:04 +02:00
jpirnayandClaude Sonnet 4.6 e4170e2272 Font rendering performance improvements
- FontDecompressor: replace heap-allocated std::vector hot-group and glyph
  scratch buffers with static BSS arrays, eliminating per-page malloc/free
  and the heap fragmentation it causes during rendering
- FontDecompressor: add bounds checks on group/glyph buffer sizes; sort
  prewarm group list by ascending index for sequential flash reads
- ParsedText: upgrade line-break cost function to Knuth-Plass cubic badness
  (strongly penalises very loose lines, lenient on moderate looseness)
- ParsedText: exclude gaps before closing punctuation (. , ) » etc.) from
  justification distribution so they stay at natural space width

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 07:33:39 +02:00
jpirnay e30b7a551a Introduction of small helper routines 2026-04-22 07:18:28 +02:00
jpirnay b7928a86e3 Add hotel Wifi connection 2026-04-21 17:15:56 +02:00
jpirnay 425c1db132 Review comments 2026-04-20 21:16:31 +02:00
jpirnay a00712a085 Adjust warnings for x3 2026-04-20 20:50:33 +02:00
jpirnay a6aed8d30e Add additional timezones 2026-04-20 20:40:38 +02:00
jpirnay 966ba71a90 Embrace utf8-counting helpers 2026-04-20 20:16:40 +02:00
jpirnay 5b31d49036 One more safety net 2026-04-20 17:42:27 +02:00
jpirnay 9f95567212 Fix x3 boot issue 2026-04-20 17:33:46 +02:00
jpirnay a7638bb7d3 Merge pull request #87 from jgoguen/opds-multi-format-select
feat(opds): Allow selecting the download format
2026-04-20 14:26:00 +02:00
jpirnay 83fe041a6b Merge pull request #109 from jpirnay/kosync_extension
refactor: Picking up some itsthisjustin ideas for KOreader synchronisation
2026-04-20 14:21:31 +02:00
jpirnay 440d64e48e Nitpick comments 2026-04-20 14:16:13 +02:00
jpirnay 6f52aec95d Merge pull request #107 from jgoguen/fix-parser-not-freed
fix: free parser on error
2026-04-20 14:07:23 +02:00
jpirnay 3e2f80f8ca Merge pull request #105 from jgoguen/fix-parser-use-after-free
fix: harden OPDS parser cleanup after errors
2026-04-20 14:06:54 +02:00
jpirnay 36931aaa25 Merge pull request #108 from jpirnay/feature-webui-update
feat: webui update (integrate some ideas from upstream #1715 by pablohc)
2026-04-20 14:05:43 +02:00
jpirnay 29284c85c9 Review comments 2026-04-20 13:28:56 +02:00
jpirnay 3fb9ac9e29 Finetuning 2 2026-04-20 13:15:05 +02:00
jpirnay 5e4f78f7be Finetuning 2026-04-20 12:28:00 +02:00
jpirnay fd72941cd4 Treat body[1] properly 2026-04-20 11:53:46 +02:00
jpirnay 38e90a818b Make json field check more lenient 2026-04-20 11:39:21 +02:00
jpirnay ec90d46a02 Fix omission 2026-04-20 10:44:34 +02:00
jpirnay bbafd4ce62 Display error reason on ntp time sync fail 2026-04-20 10:32:52 +02:00
jpirnay 8941ab9a1e Always provide datetime 2026-04-20 10:11:14 +02:00
jpirnay 87b5776648 Wire clock to fil date times 2026-04-20 09:07:56 +02:00
Joel Goguen 1986092522 feat(opds): Allow selecting the download format
When downloading a book via OPDS, the last acquisition link is chosen when there are multiple. This allows choosing which format to download when there are many. Having only one format will automatically download that.
2026-04-19 23:15:54 -04:00
Joel Goguen 828999cae3 fix: free parser on error
Found while looking into #105 but the opposite problem. This frees the parser after an error has occurred and early return.
2026-04-19 22:27:34 -04:00
Joel Goguen c06bf51afb fix: harden OPDS parser cleanup after errors
Fix potential use-after-free or double-free issue in the OPDS parser by
nulling it after free and guarding against using a nullptr parser in
`flush()`.
2026-04-19 21:26:45 -04:00
jpirnay d6292920d9 Picking up some itsthisjutin ideas 2026-04-19 19:03:43 +02:00
jpirnay f31159b430 Temperature sanity check 2026-04-17 23:32:26 +02:00
jpirnay 9492984850 Remove wire init 2026-04-17 23:27:38 +02:00
jpirnay 134527de5f Dont hammer the bus 2026-04-17 23:21:03 +02:00
jpirnay f68fbc39e4 Dont write guesstimates into RTC 2026-04-17 23:19:42 +02:00
jpirnay 141ec02746 Fix comments 2026-04-17 23:17:42 +02:00
jpirnay b6c3774de9 Proper timezone conversion 2026-04-17 23:14:40 +02:00
jpirnay 4d0af7331c X4 quick exit 2026-04-17 22:57:56 +02:00
jpirnay f7d970fe44 implement DS3231 clock support 2026-04-17 22:47:08 +02:00
jpirnay 0a4dabef45 Add debug info 2026-04-17 21:44:36 +02:00
jpirnay de314182f7 mitigating fragmented heap 2026-04-17 17:02:50 +02:00
jpirnay e3145439fc Make chunk size variable depending on available heap size 2026-04-17 16:34:33 +02:00
jpirnay feda048dfa Fix missing X3 serial output 2026-04-17 16:20:40 +02:00
jpirnay 2d6898362b Update Turkish 2026-04-16 14:59:36 +02:00