Prevent integer overflow when validating large image dimensions by using 64-bit arithmetic. Add periodic yielding during JPEG/PNG decode to prevent watchdog timeouts on multi-second operations. Clamp image top margins to prevent full-height images from overflowing page bottom and failing bounds checks. Increase max source pixels from 3MP to 8MP to support high-resolution ebook covers while keeping decode times reasonable.
## Summary
Build action take too much time.
Lets see if splitting it to two seperate action would speed things up.
---
### AI Usage
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? _**< PARTIALLY >**_
## Summary
* **What is the goal of this PR?** Fix a reproducible crash: opening the
web UI's Settings page reliably crashes the device (silent reboot to
Home) under real-world conditions.
* **What changes are included?** `SettingsPage.html` fired three
unawaited `fetch()` calls on page load (`/api/settings`, `/api/wifi`,
`/api/opds`), opening simultaneous connections to the device's web
server. That server (Arduino's `WebServer`) handles one client at a
time; a genuinely concurrent second/third connection can stall a
response mid-stream for multiple seconds — long enough to trip the
firmware's watchdogs (300ms interrupt WDT / 5s task WDT, both
panic-on-timeout in this project's config). This PR makes the three
initial loads run sequentially via a small async IIFE instead of firing
them concurrently. Same end state for the page, no visible behavior
change.
## Scope Check
CrossPoint is intentionally narrow. See
[SCOPE.md](../blob/master/SCOPE.md) and
[ROADMAP.md](../blob/master/ROADMAP.md).
- [x] I have read SCOPE.md and ROADMAP.md.
- [x] This PR is **not** a new built-in theme.
- [x] This PR is **not** a new external network connector.
- [x] This PR is **not** an interactive app, writing tool,
RSS/news/browser, media playback, or PDF feature.
- [x] This is a bug fix for a reproducible crash, not new functionality.
- [x] Does not touch `freeink-sdk/`, `lib/hal/`, the bootloader, OTA, or
recovery code.
## Testing performed
Verified live on an X4 (driven via the `CMD:WIFI` serial debug command
from the companion PR, since I didn't have physical access to the device
for part of this investigation):
- Root-caused via a temporary per-entry heap/timing log in
`handleGetSettings()` (not included in this diff): under concurrent
load, individual `sendContent()` calls stalled 1-3+ seconds between
simple, static settings entries that should serialize in well under a
millisecond each.
- Reproduced the crash directly: firing `/api/settings`, `/api/wifi`,
and `/api/opds` concurrently (mirroring the page's old JS behavior)
crashed the device in 2/2 attempts. The companion PR (watchdog reset
detection) let the second crash actually get logged: reset reason
`ESP_RST_TASK_WDT`, panic confirmed.
- After the fix: same three endpoints, hit sequentially (matching the
new JS), succeeded cleanly across dozens of repeats (single-shot and a
60-request hammer loop) with no crashes and stable free-heap.
- Confirmed the live device served the updated, gzip-compressed
generated header after a normal `pio run` (source HTML →
`SettingsPageHtml.generated.h` via the existing `scripts/build_html.py`
build step).
## Additional Context
Memory/flash impact: none — same JS logic, just sequenced instead of
concurrent. No new allocations, no change to the generated header's size
beyond the few added bytes of source text.
Risk: low. This only changes the *order* three existing fetches happen
in on page load; no new endpoints, no changed request/response shapes.
---
### AI Usage
YES — diagnosed and fixed by Claude (Sonnet 5), including live
reproduction and verification against real hardware.
Ties bookmarks to the actual text on the page rather than to a page number. Page numbers shift whenever the book gets re-laid-out — changing font size, margins, line spacing, or rotating the screen — which could previously land you on the wrong spot.
This is a followup of #2805, making bookmarks use the same mechanism. Several minor improvments ride along.