Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
1168 commits
Select commit Hold shift + click to select a range
d0359ed
feat(epub): native <ruby> support for Chinese, Japanese (#2665)
brianhuster Jul 25, 2026
be554a9
fix: prevent web server from crashing on fonts tab
uxjulia Jul 25, 2026
c541401
fix: avoid Arduino HEX macro collision
uxjulia Jul 25, 2026
c85e021
fix: free SD font caches before epub relayout
uxjulia Jul 25, 2026
a8791ed
chore: update freeink-sdk
uxjulia Jul 25, 2026
52af172
chore: Migrate Settings/State onto PersistableStore
uxjulia Jul 25, 2026
48248f2
feat: unified Text Settings screen with live preview (#2605)
PaulDelestrac Jul 22, 2026
4ea6a85
fix: Move sunlight fading fix setting to different group (#2689)
itsthisjustin Jul 23, 2026
cabf732
feat: cjk UI font fallback (#2521)
szetszho Jul 23, 2026
233e11d
Optimize font cache by persisting data across scopes
itsthisjustin Jul 23, 2026
ff20d81
fix: Warp around in Percent Selection (#2677)
Uri-Tauber Jul 23, 2026
f2f7741
fix: avoid X3 Quick Resume flashes (#2698)
Sichroteph Jul 24, 2026
3f6802f
feat(epub): native <ruby> support for Chinese, Japanese (#2665)
brianhuster Jul 25, 2026
91cea57
Add capacitive home key support to HalGPIO
itsthisjustin Jul 22, 2026
82b1260
Make frontlight panel a dismissible overlay
itsthisjustin Jul 23, 2026
e7c7236
Reduce horizontal padding in settings tab bar
itsthisjustin Jul 24, 2026
af21f67
Add X4 Pro power button double-click frontlight toggle
itsthisjustin Jul 24, 2026
f7b4308
Add long-press gesture support for touch interactions
itsthisjustin Jul 24, 2026
fbb6708
test: add X4 Pro simulator environment
uxjulia Jul 25, 2026
36ac29e
fix(i18n): add missing strings in PT-PT translation (#2701)
CookieCaptainD Jul 25, 2026
f970bcf
feat: simulate X4 Pro home key
uxjulia Jul 25, 2026
324c37c
feat: move frontlight reader tabs to bottom
uxjulia Jul 25, 2026
fc0363f
fix: extend reader tabs to touch edge
uxjulia Jul 25, 2026
0701683
chore: small Italian translation fixes (#2703)
matteoscopel Jul 25, 2026
e4817ba
chore: sync upstream Crosspoint
uxjulia Jul 25, 2026
08198b8
feat: allow full-screen reader vertical swipes
uxjulia Jul 25, 2026
d26d5f7
fix: add touch controls for nearby transfer offers
uxjulia Jul 25, 2026
7eb71f8
feat: Add UC8279 panel controller detection for X3 devices (#2707)
itsthisjustin Jul 25, 2026
78c1c8e
Merge branch 'release/1.5.0' into develop
uxjulia Jul 25, 2026
dde7e03
fix: ignore ambiguous EPUB guide text so books open at the right loca…
uxjulia Jul 25, 2026
1cf265a
fix: Lower TLS minimum free memory threshold to 35KB for kosync (#2719)
itsthisjustin Jul 25, 2026
9190048
feat: point-size font selection (#2720)
Uri-Tauber Jul 25, 2026
92be5c1
fix: return text settings focus to active tab
uxjulia Jul 25, 2026
2d6ad44
fix: preserve short button presses in low-power mode
uxjulia Jul 26, 2026
9ec7767
fix: preserve custom font ligatures (#2673)
thiagokokada Jul 26, 2026
82d780d
docs: update dictionary docs
uxjulia Jul 26, 2026
9cff12b
docs: Add StarDict sources list
Uri-Tauber Jul 26, 2026
2dc4ba7
fix: show receiving screen before accepting nearby transfer
uxjulia Jul 26, 2026
8954a85
chore: changelog cleanup
uxjulia Jul 26, 2026
6ce9f35
fix: add on-screen buttons in nearby file transfer for touch devices
uxjulia Jul 26, 2026
105676c
fix: allow full-screen reader page swipes
uxjulia Jul 26, 2026
e23f78b
chore: changelog cleanup
uxjulia Jul 26, 2026
35abc72
fix: improve nearby file transfer confirmations and buttons
uxjulia Jul 26, 2026
55cd5fd
fix: allow full-screen reader page swipes
uxjulia Jul 26, 2026
d556a29
Revert "feat: unified Text Settings screen with live preview (#2605)"…
uxjulia Jul 26, 2026
b25e57d
test: repair malformed section-break EPUB fixture (#2728)
lpla Jul 26, 2026
a02cffe
chore: Update czech.yaml (#2726)
Pitel Jul 26, 2026
c9164ac
fix: translate BMP viewer error messages (#2730)
lpla Jul 26, 2026
c731d51
fix: fixing german translation inconsistencies (#2702)
dasrecht Jul 26, 2026
ef3d980
feat: Add packages to nix dev shell required for clang-format-fix and…
Katherine1 Jul 26, 2026
e582ed9
fix: add touch controls for filename conflicts during nearby file tra…
uxjulia Jul 27, 2026
016dd3a
docs: add nearby file transfer docs
uxjulia Jul 27, 2026
a2c2649
fix: ignore ambiguous EPUB guide text so books open at the right loca…
uxjulia Jul 25, 2026
087c3da
fix: name dictionary lookup failures (low-memory vs decompress vs rea…
W-Floyd Jul 27, 2026
eea75d5
fix: bind settings labels to enum values (#2644)
lpla Jul 27, 2026
a71b215
docs: explain EPUB indexing methods
uxjulia Jul 27, 2026
c6cf134
fix: map reading stats hints to assigned buttons (fixes issue 411)
uxjulia Jul 27, 2026
68447ae
docs: document EPUB word spacing
uxjulia Jul 27, 2026
99c0e50
fix: TextSettingsActivity default to selected font (#2739)
Uri-Tauber Jul 27, 2026
87207a7
fix: align Lyra header battery indicator
uxjulia Jul 27, 2026
d576825
fix: allow switching dictionary after misses
uxjulia Jul 27, 2026
bb7bdf3
fix: convert icons to lucide
uxjulia Jul 27, 2026
971191c
docs: document EPUB word spacing
uxjulia Jul 27, 2026
783e15b
docs: explain EPUB indexing methods
uxjulia Jul 27, 2026
ac0d770
feat: UI and touch enhancements
uxjulia Jul 28, 2026
a4e813c
chore: update freeink sdk to allow virtual list scrolling
uxjulia Jul 28, 2026
9321dd0
feat: add footnotes header and defer dictionary check until touch loo…
uxjulia Jul 28, 2026
f39d35d
docs: Add instructions to fix a bricked Xteink (#2622) (#2682)
paulporto Jul 28, 2026
78e4715
fix: dictionary and UI updates for touch devices
uxjulia Jul 28, 2026
b508f75
fix: treat <br> in CJK flowing text as a paragraph separator (#2710)
szetszho Jul 28, 2026
52ff942
perf: drop all-empty ruby vectors from TextBlock (#2772)
Uri-Tauber Jul 28, 2026
5965dc6
chore: remove redundant wolfSSL TLS defines (#2727)
lpla Jul 28, 2026
6382231
chore: update freeink sdk
uxjulia Jul 28, 2026
5713432
fix: Gyro not powering down on x3 and newer x4 battery latch issues (…
itsthisjustin Jul 28, 2026
4afc65e
fix: connect strikethrough line across words
uxjulia Jul 28, 2026
fe37bf8
perf: skip ruby scratch allocations on ruby-less lines (#2735)
W-Floyd Jul 28, 2026
187feda
fix: derive file-transfer WebSocket port from HTTP (#2729)
lpla Jul 28, 2026
bec6365
build: simulate web server
uxjulia Jul 28, 2026
3ba8701
fix: Lower TLS minimum free memory threshold to 35KB for kosync (#2719)
itsthisjustin Jul 25, 2026
3deb0d5
fix: preserve custom font ligatures (#2673)
thiagokokada Jul 26, 2026
ff7cc46
docs: Add StarDict sources list
Uri-Tauber Jul 26, 2026
f4d1752
test: repair malformed section-break EPUB fixture (#2728)
lpla Jul 26, 2026
73dc819
feat: Add packages to nix dev shell required for clang-format-fix and…
Katherine1 Jul 26, 2026
764f2d1
fix: name dictionary lookup failures (low-memory vs decompress vs rea…
W-Floyd Jul 27, 2026
3cf3a5a
fix: preserve paragraph spacing after EPUB br tags
szetszho Jul 28, 2026
f067283
perf: drop all-empty ruby vectors from TextBlock (#2772)
Uri-Tauber Jul 28, 2026
1b75661
chore: remove redundant wolfSSL TLS defines (#2727)
lpla Jul 28, 2026
4d53914
fix: Gyro not powering down on x3 and newer x4 battery latch issues (…
itsthisjustin Jul 28, 2026
e78c66b
Merge remote-tracking branch 'origin/main' into development
uxjulia Jul 29, 2026
9163149
fix: restore spaces between CJK words (#2768)
Uri-Tauber Jul 29, 2026
dadc8ec
fix: clean image page after sync return (#2747)
thiagokokada Jul 29, 2026
67e608e
feat: Access text settings from epub reader (#2788)
Uri-Tauber Jul 29, 2026
8c5763f
docs: replace contributing guides with development docs
uxjulia Jul 29, 2026
2ceeecc
fix: Restrict CrossPoint position extension to official server (#2790)
itsthisjustin Jul 29, 2026
3f8f645
fix: updates to UI/UX of dictionary, clippings, and bookmarks
uxjulia Jul 29, 2026
da21cfa
fix: derive file-transfer WebSocket port from HTTP (#2729)
lpla Jul 28, 2026
5399474
fix: restore spaces between CJK words (#2768)
Uri-Tauber Jul 29, 2026
811aab5
fix: clean image page after sync return (#2747)
thiagokokada Jul 29, 2026
2d7c4eb
fix: Restrict CrossPoint position extension to official server (#2790)
itsthisjustin Jul 29, 2026
bffd1e3
chore: sync upstream Crosspoint
uxjulia Jul 30, 2026
65c41ba
fix: keep reader settings clear of landscape button hints
uxjulia Jul 30, 2026
3eeb6ac
fix: order languages by native name instead of language code (#2803)
dasrecht Jul 30, 2026
1ef23ac
fix: improve File Transfer menu
uxjulia Jul 30, 2026
67af95c
docs: update device guidance
uxjulia Jul 30, 2026
617e374
fix: improve file transfer menu
uxjulia Jul 30, 2026
9fb2475
fix: prevent CSS rule OOM reboot (issue 423)
uxjulia Jul 30, 2026
62301a6
fix: add epub section splitting toggle
uxjulia Jul 30, 2026
13a077d
fix: Save text settings immediately on each change (#2806)
itsthisjustin Jul 30, 2026
b19503b
fix: Properly power down SD power rails on x3 (#2808)
itsthisjustin Jul 30, 2026
cee24e8
fix: prevent CSS rule OOM reboot (issue 423)
uxjulia Jul 30, 2026
5c26fa7
fix: orient dictionary navigation buttons (#2749)
thiagokokada Jul 30, 2026
cb25dee
chore: update freeink sdk
uxjulia Jul 30, 2026
b215ed8
make OptionPopup orientation-aware
Uri-Tauber Jul 30, 2026
74065f1
fix: avoid duplicate OTA update actions (#2807)
ed-fruty Jul 30, 2026
e55702a
fix: port touch UI compatibility updates
uxjulia Jul 31, 2026
d0b70b3
fix: Replace vector with deque for text token storage (#2814)
itsthisjustin Jul 31, 2026
47466c7
fix: dictionary lookup OOM on .dict.dz definitions (#2791)
W-Floyd Jul 31, 2026
bf253b1
perf: open dictionary index files once per lookup (#2733)
W-Floyd Jul 31, 2026
5933da8
perf: check dictionary sidecar freshness once per open
Uri-Tauber Jul 31, 2026
62f4b7d
fix: show more of truncated file names
uxjulia Jul 31, 2026
59daf47
fix: refresh dashboard progress after reading
uxjulia Jul 31, 2026
8d0659f
fix: various UI fixes
uxjulia Jul 31, 2026
749f0a1
fix: refresh UI scale fonts immediately
uxjulia Jul 31, 2026
51a0238
fix: order languages by native name instead of language code (#2803)
dasrecht Jul 30, 2026
260da07
make OptionPopup orientation-aware
Uri-Tauber Jul 30, 2026
38fc754
fix: avoid duplicate OTA update actions (#2807)
ed-fruty Jul 30, 2026
ff2a060
fix: Replace vector with deque for text token storage (#2814)
itsthisjustin Jul 31, 2026
47b088a
chore: update freeink sdk
uxjulia Jul 31, 2026
1fbac6d
fix: restore option popup navigation build
uxjulia Jul 31, 2026
b680f2f
perf: prewarm next-page SD font glyphs
uxjulia Jul 31, 2026
e7ffca4
perf: reuse dictionary files across lookup probes
uxjulia Jul 31, 2026
1d6b82f
perf: batch web file list responses
uxjulia Jul 31, 2026
1a7f5a9
perf: share one static bidi scratch buffer to save ~1.5 KB RAM (#2554)
pillarsdotnet Jul 31, 2026
f4996a8
chore: update freeink sdk
uxjulia Jul 31, 2026
ca83607
fix: apply book style setting before EPUB load
uxjulia Jul 31, 2026
70de1da
fix: show more of truncated file names
uxjulia Jul 31, 2026
e813480
fix: apply book style setting before EPUB load
uxjulia Jul 31, 2026
d749809
fix: preserve clipping highlights across font changes (issue 426)
uxjulia Jul 31, 2026
c1e63f8
chore: prepare v1.5.0 release
uxjulia Jul 29, 2026
4291966
chore: sync upstream Crosspoint
uxjulia Jul 31, 2026
7fe8e41
fix: fall back to plain text for malformed dictionary HTML
uxjulia Jul 31, 2026
8f7c7a3
fix: keep clipping markers visible in dark mode (issue 431)
uxjulia Jul 31, 2026
703b553
fix: keep clipping markers visible in dark mode (issue 431)
uxjulia Jul 31, 2026
5ab4a2b
fix: avoid file list callback allocation (issue 432)
uxjulia Jul 31, 2026
273e704
fix: port touch UI compatibility updates
uxjulia Aug 1, 2026
8a1e129
fix: restore dictionary left and right button hints
uxjulia Aug 1, 2026
a9d0b80
fix: avoid file list callback allocation (issue 432)
uxjulia Aug 1, 2026
6caea34
fix: improvements to epup opening pipeline
uxjulia Aug 1, 2026
b34f73b
fix: match SD card font generation to built-in fonts and add dictiona…
uxjulia Aug 1, 2026
590d12b
fix: match SD card font generation to built-in fonts and add dictiona…
uxjulia Aug 1, 2026
49d4947
fix: preserve dictionary screenshot context (issue 437)
uxjulia Aug 1, 2026
c536294
fix: guarantee screenshot confirmation border (issue 437)
uxjulia Aug 1, 2026
1858a22
fix: display screenshot confirmation border and pass in book metadata…
uxjulia Aug 1, 2026
aa9e0d3
build: update version labels
uxjulia Aug 1, 2026
0b7b865
fix: avoid crashing during a clock sync (issue 436)
uxjulia Aug 1, 2026
0f747b8
fix: make EPUB sync positions content-based (#2805)
thiagokokada Aug 1, 2026
9f637f7
fix: CJK dictionary selection and lookups not working correcctly
uxjulia Aug 1, 2026
f62285b
build: honor local PlatformIO version override
uxjulia Aug 1, 2026
51798a5
Merge branch 'development' into release/v1.5.0
uxjulia Aug 1, 2026
9c48609
Make bookmarks survive re-pagination
Uri-Tauber Aug 1, 2026
17d3b03
fix: hide unsupported web settings
uxjulia Aug 2, 2026
f5948a4
fix: open reading stats date editor
uxjulia Aug 2, 2026
2d3afbe
perf: various performance improvements, a few borrowed from Sichrotep…
uxjulia Aug 2, 2026
345cde8
fix: prevent dictionary suggestion lookup freezes
uxjulia Aug 2, 2026
0eac072
fix: landscape button labels in dictionary
uxjulia Aug 2, 2026
4ac933c
fix: clear reader menu headings from landscape hints
uxjulia Aug 2, 2026
119f0f3
fix: avoid web task watchdog timeout (issue 432)
uxjulia Aug 2, 2026
ffc365e
fix: prevent bionic letter overlap (issue 442)
uxjulia Aug 2, 2026
fd6aebb
chore: sync upstream Crosspoint
uxjulia Aug 2, 2026
00051ca
fix: load EPUB locations before reader handoff
uxjulia Aug 2, 2026
a41811c
fix: make EPUB sync positions content-based
uxjulia Aug 2, 2026
b77244f
fix: avoid duplicate EPUB image display
uxjulia Aug 2, 2026
d8f5599
fix: limit EPUB image clean refresh to sync return
uxjulia Aug 2, 2026
c93e563
docs: update docs for touch devices
uxjulia Aug 3, 2026
f21a4cf
fix: restore book cover placeholder icon
uxjulia Aug 3, 2026
1677034
fix: preserve X3 power-button wake (issue 445)
uxjulia Aug 3, 2026
85cd0e5
fix: allow clipping selection past arbitrary chapter-end limit (issue…
uxjulia Aug 3, 2026
1a6c1bf
fix: localize Russian dashboard stats (issue 450)
uxjulia Aug 3, 2026
9f74c14
fix: stream table rendering to reduce maxAlloc required
uxjulia Aug 3, 2026
5c4e25f
fix: preserve button clicks after clearing recent book cache
uxjulia Aug 3, 2026
5df8549
fix: stabilize EPUB indexing and prioritize reader input
uxjulia Aug 3, 2026
fff975e
Add NVS-backed wake verification before SD mount
itsthisjustin Aug 2, 2026
fc7c9d0
chore: update freeink sdk
uxjulia Aug 3, 2026
295b3f9
feat: custom dictionary font and size along with dictionary performan…
uxjulia Aug 3, 2026
d887ea7
refactor: remove stale web watchdog resets
uxjulia Aug 4, 2026
0b6ae34
fix: improve dark clipping highlight contrast (issue 431)
uxjulia Aug 4, 2026
eeb4bea
fix: avoid XTCH settings memory errors (issue 457)
uxjulia Aug 4, 2026
4ac9a07
chore: update freeink sdk
uxjulia Aug 4, 2026
24753d8
fix: restore precise cached EPUB sync positions
uxjulia Aug 4, 2026
e564208
docs: add dictionary folder structure example
uxjulia Aug 4, 2026
17d1060
fix: keep saved clipping text legible in dark mode
uxjulia Aug 4, 2026
95a26f7
Merge branch 'development' into release/v1.5.0
uxjulia Aug 4, 2026
7e9bda2
chore: use GitHub Actions token for releases
uxjulia Aug 4, 2026
fd0c44a
fix: hide dictionary font options without dictionaries and update dic…
uxjulia Aug 4, 2026
15e7c01
feat: add global dictionary font setting
uxjulia Aug 4, 2026
428860f
ci: update github token
uxjulia Aug 4, 2026
14c0a0d
fix: clear inactive dictionary button hints
uxjulia Aug 4, 2026
99cc599
fix: avod manage fonts screen from crashing
uxjulia Aug 4, 2026
e61071b
fix: honor side-button layout in dictionary suggestions
uxjulia Aug 4, 2026
d313b2e
fix: load Wi-Fi credentials on first access (issue 421)
uxjulia Aug 4, 2026
231e8cf
perf: avoid copying reader settings at construction
uxjulia Aug 4, 2026
d888071
fix: cache EPUB books without covers (issue 465)
uxjulia Aug 4, 2026
c1a6717
Merge branch 'release/v1.5.0' into development
uxjulia Aug 4, 2026
4bad5c1
fix: distinguish missing EPUB covers (issue 465)
uxjulia Aug 4, 2026
357f4a3
fix: preserve EPUB page on reopen (issue 466)
uxjulia Aug 5, 2026
805ac48
fix: improve custom dictionary font persistence
uxjulia Aug 5, 2026
a06daac
fix: reflow dictionary font after switching dictionaries
uxjulia Aug 5, 2026
ef73058
fix: improve x4 screen refreshes after using wifi (issue 470 and 462)
uxjulia Aug 5, 2026
c54c9ab
fix: preserve wake button release before sleep (issue 453)
uxjulia Aug 5, 2026
550292a
fix: consume wake power release (issue 453)
uxjulia Aug 5, 2026
a611a67
fix: bold book titles in recent books list and bookmarks/clippings
uxjulia Aug 5, 2026
559eca5
fix: cleanly redraw home after a silent restart after wifi usage
uxjulia Aug 5, 2026
98309b7
fix: align Lyra settings tab underline
uxjulia Aug 6, 2026
a551739
chore: update freeink sdk
uxjulia Aug 6, 2026
435816d
fix: guard dictionary lookup against low heap
uxjulia Aug 6, 2026
be3a977
fix: retain dictionary lookup cache path
uxjulia Aug 6, 2026
e1cc3f5
chore: update bug report template
uxjulia Aug 6, 2026
123a707
fix: dictionary font falling back to reader font
uxjulia Aug 6, 2026
4c02c42
fix: speed up random sleep image selection (issue 473)
uxjulia Aug 6, 2026
93fedc9
fix: lend framebuffer during next chapter indexing (issue 475)
uxjulia Aug 6, 2026
28753d7
fix: allow cancellation of silent full section pre-indexing
uxjulia Aug 6, 2026
aade684
fix: render EPUB overlay images above text
uxjulia Aug 6, 2026
2a47cbc
fix: chained dictionary lookups showing missing glyph diamond
uxjulia Aug 6, 2026
88977e9
fix: silent restart into Manage Fonts with a fresh heap
uxjulia Aug 6, 2026
fefb4c6
fix: unify theme battery icons (fixes #471)
uxjulia Aug 6, 2026
4531b9d
chore: update freeink sdk
uxjulia Aug 7, 2026
a2d42ff
Add USB host detection and battery poll on charge
itsthisjustin Aug 7, 2026
e920388
fix: size translated-label buffers for UTF-8
winst0niuss Aug 7, 2026
4bfbb55
fix: recognize watchdog-triggered resets as panics
obra Aug 7, 2026
39aad64
fix(epub): prevent ruby overflow in justified CJK text
brianhuster Aug 7, 2026
813a808
fix: make Wi-Fi credential storage thread-safe
itsthisjustin Aug 7, 2026
6de9409
fix: reject firmware for a different chip family
Uri-Tauber Aug 7, 2026
532d34f
fix: serialize KOReader network time sync (issue 480)
uxjulia Aug 7, 2026
c6457ae
fix: load end-of-book suggestions before moving
uxjulia Aug 7, 2026
9800d3d
chore: update freeink sdk
uxjulia Aug 7, 2026
de239f8
fix: wrap long UI error messages
uxjulia Aug 7, 2026
b20bf90
fix: resolve dictionary word selection cppcheck warnings
uxjulia Aug 7, 2026
998ddcf
fix: use selected image for sleep cover
uxjulia Aug 7, 2026
1eaf334
fix: release reader font cache before overlay PNG
uxjulia Aug 7, 2026
6af3eb4
chore: clang-format
uxjulia Aug 7, 2026
7e8471c
Merge branch 'development' into release/v1.5.0
uxjulia Aug 7, 2026
79f4552
fix: switch book menu tabs on held navigation (issue 483)
uxjulia Aug 7, 2026
719303d
chore: remove Sticky side button diagnostics
uxjulia Aug 8, 2026
f94b2f0
fix: include silent restart helper in reader options
uxjulia Aug 8, 2026
4dc795e
Merge branch 'development' into release/v1.5.0
uxjulia Aug 8, 2026
473435a
fix: build v1.5 default and sticky releases
uxjulia Aug 8, 2026
28955f5
chore: prepare for release
uxjulia Aug 8, 2026
99b70f6
ci: update build scripts
uxjulia Aug 8, 2026
c259724
docs: update docs for release
uxjulia Aug 8, 2026
4de5edf
docs: add link to inky
uxjulia Aug 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
21 changes: 19 additions & 2 deletions .claude/CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

Keep this file focused on repo-specific gotchas that are worth reusing in future sessions.

## FreeInk SDK

Refer to https://freeink.org/llms.txt for guidance.

## Simulator

- Simulator patches belong in the adjacent `crosspoint-simulator` repo.
- Simulator patches belong in the adjacent `crossink-simulator` repo.
- The valid local simulator env in this repo is `simulator`, and `pio run -e simulator` currently builds cleanly.
- The simulator `PNGdec` stub in `crosspoint-simulator/src/PNGdec.h` needs to mirror the real API shape used by app code, including `hasAlpha()` and `getTransparentColor()`, even though decode still fails intentionally.
- The simulator `PNGdec` stub in `crossink-simulator/src/PNGdec.h` needs to mirror the real API shape used by app code, including `hasAlpha()` and `getTransparentColor()`, even though decode still fails intentionally.
- Known simulator limits:
- No image rendering: `platformio.ini` ignores `hal`, `PNGdec`, and `JPEGDEC`, so image decoders are intentionally absent.
- JPEGDEC stub always fails; `JPEGDEC fallback: open failed (err=-1)` is expected in simulator.
Expand All @@ -23,6 +27,19 @@ Keep this file focused on repo-specific gotchas that are worth reusing in future
- Kindle EPUBs may contain paired high-res and old-Kindle fallback images. `ChapterHtmlSlimParser` should skip `<img>` nodes with `data-AmznRemoved-M8` to avoid duplicate stacked images.
- After image/layout pipeline changes that affect cached EPUB output, clear the affected `.crosspoint/epub_<hash>/` cache if behavior looks stale.

## UI Consistency

- Use FreeInkUI SDK components and input routing for list-style screens where possible. Row rendering, touch targets,
hit testing, and pagination should share the same FreeInkUI list configuration instead of custom touch scaling.

## Heap Baselines (X4 hardware, SD card font)

- A normal resume-into-partial reading session runs at ~85-90KB free / ~49KB maxAlloc by
the first watermark crossing (Epub metadata + x-locations + resident glyph caches).
Do not read mid-range heap numbers as session degradation without checking the scenario.
- SD-font section builds cost ~38-50KB at cold start; the 4-style advance-table prewarm
(~30KB incl. 16KB contiguous scratch) dominates and is skipped below 80KB free.

## Misc Repo Gotchas

- POSIX TZ signs are inverted from ISO 8601 in `TimeStore::applyTimezone()`: `"UTC-1"` means UTC+1.
Expand Down
20 changes: 18 additions & 2 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ body:
label: Device
description: Which device is this affecting?
options:
- "--- Select ---"
- X4
- X3
- Both
- Seeed Sticky
validations:
required: true

Expand All @@ -35,6 +36,7 @@ body:
label: EPUB Optimization
description: Is your EPUB optimized?
options:
- "--- Select ---"
- No / Not Applicable
- Yes, using the built-in web transfer EPUB optimizer
- Yes, using a different EPUB optimizer
Expand All @@ -48,6 +50,7 @@ body:
label: Cache State
description: Have you attempted to clear any cached data?
options:
- "--- Select ---"
- No / Not Applicable
- Yes, book cache (Reader menu > Delete Book Cache)
- Yes, reading cache (Settings > System > Clear Reading Cache)
Expand All @@ -61,7 +64,7 @@ body:
attributes:
label: Describe the Bug
description: A clear and concise description of what the bug is.
placeholder:
placeholder: |
validations:
required: true

Expand All @@ -85,6 +88,19 @@ body:
validations:
required: true

- type: dropdown
id: epub-attachment
attributes:
label: File Provided
description: If your issue is related to a specific file (EPUB, XTC, etc.), please make sure to attach the exact file in this ticket or email it to julia@uxj.io and reference your issue number. **_EPUBs and XTC files need to be zipped to be attached._**
options:
- "--- Select ---"
- Not Applicable
- I've attached it
- I've emailed it
validations:
required: true

- type: textarea
id: logs
attributes:
Expand Down
5 changes: 0 additions & 5 deletions .github/PULL_REQUEST_TEMPLATE.md

This file was deleted.

44 changes: 33 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,36 +65,58 @@ jobs:
run: pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high

build:
# Never run untrusted fork PR code on the self-hosted runner.
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: [self-hosted, linux, crossink-build]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
environment: [default, sticky]
steps:
- uses: actions/checkout@v6
with:
submodules: recursive

- name: Verify PlatformIO Core
run: pio --version
- uses: actions/setup-python@v6
with:
python-version: "3.14"

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "latest"
enable-cache: true

- name: Cache PlatformIO packages
uses: actions/cache@v4
with:
path: ~/.platformio
key: ${{ runner.os }}-platformio-${{ matrix.environment }}-${{ hashFiles('platformio.ini', 'platformio.local.example.ini') }}
restore-keys: |
${{ runner.os }}-platformio-${{ matrix.environment }}-
${{ runner.os }}-platformio-

- name: Install PlatformIO Core
run: uv pip install --system -U https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.19.zip

- name: Build CrossInk tiny
- name: Build ${{ matrix.environment }} firmware
run: |
set -euo pipefail
pio run -e tiny | tee pio.log
pio run -e ${{ matrix.environment }} | tee pio-${{ matrix.environment }}.log

- name: Extract firmware stats
run: |
set -euo pipefail
{
echo "## Firmware build stats"
grep -E "RAM:\s|Flash:\s" pio.log | while read -r line; do echo "- ${line}"; done
echo "## ${{ matrix.environment }} firmware build stats"
grep -E "RAM:\s|Flash:\s" pio-${{ matrix.environment }}.log | while read -r line; do echo "- ${line}"; done
} >> "$GITHUB_STEP_SUMMARY"

- name: Upload firmware artifacts
if: matrix.environment == 'default'
uses: actions/upload-artifact@v7
with:
name: firmware-tiny
name: firmware-x3-x4
path: |
.pio/build/tiny/firmware-tiny.bin
.pio/build/default/firmware-x3-x4.bin
if-no-files-found: error

# This job is used as the PR required actions check, allows for changes to other steps in the future without breaking
Expand Down
16 changes: 12 additions & 4 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches: [main]
paths:
- "docs/**"
- "site/**"
- ".github/workflows/pages.yml"
workflow_dispatch:

Expand All @@ -28,14 +29,21 @@ jobs:

- uses: actions/configure-pages@v6

- uses: actions/jekyll-build-pages@v1
- uses: actions/setup-node@v5
with:
source: ./docs
destination: ./_site
node-version: 22
cache: npm
cache-dependency-path: site/package-lock.json

- run: npm ci
working-directory: site

- run: npm run build
working-directory: site

- uses: actions/upload-pages-artifact@v4
with:
path: ./_site
path: ./site/dist

- name: Deploy to GitHub Pages
id: deployment
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,16 @@ jobs:

- name: Build CrossInk
env:
CROSSPOINT_RELEASE_VERSION: ${{ env.RELEASE_VERSION }}
run: pio run -e tiny -e xlarge
CROSSINK_RELEASE_VERSION: ${{ env.RELEASE_VERSION }}
run: pio run -j1 -e default -e sticky
Comment on lines +64 to +65

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Write the requested version into the active PlatformIO key

When workflow_dispatch supplies a version different from the checked-in value, the preceding sed still searches for the removed crossink_version key, so I verified that it leaves platformio.ini byte-for-byte unchanged. The newly added Sticky build then uses its hardcoded ${crossink.version}-sticky runtime version even though the artifact is named with ${RELEASE_VERSION}, causing OTA comparisons and diagnostics to report a different version from the released binary name. Update [crossink].version or make the Sticky environment consume the release variable before building. (sed --help confirms -i edits the input file in place; the exact substitution was tested against this file.)

AGENTS.md reference: AGENTS.md:L106-L106

Useful? React with 👍 / 👎.


- name: Generate release catalog
run: |
python3 scripts/generate_release_catalog.py \
--version "${{ env.RELEASE_VERSION }}" \
--repo "${{ github.repository }}" \
--firmware ".pio/build/tiny/firmware-tiny-v${{ env.RELEASE_VERSION }}.bin" \
--firmware ".pio/build/xlarge/firmware-xlarge-v${{ env.RELEASE_VERSION }}.bin" \
--firmware ".pio/build/default/firmware-x3-x4-v${{ env.RELEASE_VERSION }}.bin" \
--firmware ".pio/build/sticky/firmware-sticky-v${{ env.RELEASE_VERSION }}.bin" \
--output ".pio/build/catalog"

- name: Publish catalog to GitHub Pages source
Expand Down Expand Up @@ -113,5 +113,5 @@ jobs:
target_commitish: ${{ github.sha }}
draft: true
files: |
.pio/build/tiny/firmware-tiny-v${{ env.RELEASE_VERSION }}.bin
.pio/build/xlarge/firmware-xlarge-v${{ env.RELEASE_VERSION }}.bin
.pio/build/default/firmware-x3-x4-v${{ env.RELEASE_VERSION }}.bin
.pio/build/sticky/firmware-sticky-v${{ env.RELEASE_VERSION }}.bin
14 changes: 7 additions & 7 deletions .github/workflows/release_candidate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,18 @@ jobs:
escaped_version=$(printf '%s\n' "$VERSION" | sed 's/[&|]/\\&/g')
sed -i "s|^crossink_version = .*|crossink_version = ${escaped_version}|" platformio.ini

- name: Build CrossPoint
- name: Build CrossInk
shell: bash
env:
CROSSPOINT_RC_ARTIFACTS: "1"
CROSSPOINT_RC_BRANCH: ${{ env.RC_BRANCH_RAW }}
CROSSPOINT_RC_HASH: ${{ env.RC_HASH_SHORT }}
CROSSINK_RELEASE_VERSION: "1"
CROSSINK_RC_BRANCH: ${{ env.RC_BRANCH_RAW }}
CROSSINK_RC_HASH: ${{ env.RC_HASH_SHORT }}
run: |
build_args=()
for env_name in $RC_ENVS; do
build_args+=(-e "$env_name")
done
pio run "${build_args[@]}"
pio run -j1 "${build_args[@]}"

- name: Create GitHub RC Prerelease
uses: softprops/action-gh-release@v3
Expand All @@ -102,5 +102,5 @@ jobs:
draft: true
prerelease: true
files: |
.pio/build/tiny/firmware-tiny-${{ env.RC_BRANCH_SAFE }}-${{ env.RC_HASH_SHORT }}-RC.bin
.pio/build/xlarge/firmware-xlarge-${{ env.RC_BRANCH_SAFE }}-${{ env.RC_HASH_SHORT }}-RC.bin
.pio/build/default/firmware-x3-x4-${{ env.RC_BRANCH_SAFE }}-${{ env.RC_HASH_SHORT }}-RC.bin
.pio/build/sticky/firmware-sticky-${{ env.RC_BRANCH_SAFE }}-${{ env.RC_HASH_SHORT }}-RC.bin
15 changes: 14 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ build
/.venv
*.local*
fs_/
/site/node_modules/
/site/dist/
/site/.astro/
/site/public/images/
/site/public/catalog
/site/public/CNAME

# scratchpad used as release notes for next crossink version
release.md
Expand All @@ -35,4 +41,11 @@ lib/EpdFont/scripts/output/
/site/public/catalog
/site/public/CNAME

dist-publish/
dist-publish/

# Generated by pioarduino when custom_sdkconfig rebuilds the framework.
/managed_components/
/.dummy/
/CMakeLists.txt
/dependencies.lock
/sdkconfig.*
31 changes: 19 additions & 12 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
This is the canonical repo instruction file.
`CLAUDE.md` should point here so Codex and Claude read the same guidance.

Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
Project: Open-source e-reader firmware for ESP32-C3 and ESP32-S3 devices.

## Core Rules

- Role: Senior Embedded Systems Engineer for ESP-IDF / Arduino-ESP32 work.
- The ESP32-C3 has no PSRAM and about 380 KB usable RAM. Stability beats features.
- Support both constrained ESP32-C3 devices and PSRAM-equipped ESP32-S3 devices. Keep shared code safe for the C3 unless it is explicitly capability-gated; stability beats features.
- Cite file paths and line numbers before proposing non-trivial changes.
- Do not assume ESP-IDF or SDK API availability. Verify in `open-x4-sdk/` or the live code.
- Do not assume ESP-IDF or SDK API availability. Verify in `freeink-sdk/` or the live code.
- Do not claim performance or memory wins without explaining the mechanism, such as reduced heap churn, flash vs DRAM placement, or smaller stack use.
- Justify new heap allocations or explain why stack/static storage is not suitable.
- Explain fixes in plain language where possible, ideally in terms a Node / React developer would follow.
Expand All @@ -20,7 +20,6 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).

- Read `.claude/CONTEXT.md` at session start for durable repo-specific gotchas.
- Keep `.claude/CONTEXT.md` short. Add only reusable findings, not turn-by-turn history.
- If asked to summarize a session, create `.claude/CONTEXT-YYYY-MM-DD.md` with the relevant findings for that session.

## Repo Skills

Expand All @@ -37,10 +36,11 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).

## Hardware Constraints

- MCU: ESP32-C3, single-core RISC-V at 160 MHz.
- Display: 800x480 e-ink.
- Single framebuffer only: `800 * 480 / 8 = 48000` bytes.
- Storage is SD via SdFat. On real hardware, only one reader can hold a file open at a time.
- ESP32-C3 targets (Xteink X3/X4): single-core RISC-V at 160 MHz, no PSRAM, and about 380 KB usable internal RAM.
- ESP32-S3R8 targets (Seeed reTerminal Sticky/Xteink X4 Pro): dual-core Xtensa at up to 240 MHz with 8 MB PSRAM. PSRAM is slower than internal DRAM and is not suitable for every DMA, ISR, or latency-sensitive buffer.
- Current displays use an 800x480 1-bit e-ink framebuffer: `800 * 480 / 8 = 48000` bytes. Use runtime renderer dimensions because orientation and future device profiles may differ.
- Use one framebuffer only. C3 targets keep it in internal RAM; current S3 targets place it in PSRAM via `FREEINK_FB_PSRAM`.
- Storage is exposed through SdFat, but the transport is device-specific (SPI SD on X3/X4/Sticky and SDMMC on X4 Pro). On real hardware, only one reader can hold a file open at a time.

## Resource Rules

Expand All @@ -55,6 +55,7 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
9. `new` is not nothrow on ESP32. With exceptions disabled, bare `new` calls `abort()` on allocation failure instead of returning `nullptr`. Use `new (std::nothrow)` or `makeUniqueNoThrow<T>()` from `lib/Memory/Memory.h` for fallible allocations.
10. Prefer `makeUniqueNoThrow<T>()` / `makeUniqueNoThrow<T[]>()` for owned heap allocations so cleanup is automatic on early returns.
11. Use raw `malloc` or `new (std::nothrow)` only when a C or SDK API takes ownership; add a short comment explaining that ownership transfer.
12. Treat PSRAM as a device capability, not a universal assumption. Keep shared paths within C3 limits or gate S3-only allocations behind the relevant board/capability macro, and handle PSRAM allocation failure.

## HAL And Platform Rules

Expand Down Expand Up @@ -106,13 +107,15 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
- Host environment may be macOS, Linux, WSL, or Windows Git Bash. Check `uname -s` before recommending platform-specific shell commands.
- Logging uses `LOG_INF`, `LOG_DBG`, and `LOG_ERR`.
- The simulator env in this repo is `simulator`.
- For simulator work, build from this firmware repo unless the change belongs in `crosspoint-simulator` itself.
- For simulator work, build from this firmware repo unless the change belongs in `crossink-simulator` itself.
- Common validation commands:
- `pio run -e simulator` for simulator-facing UI/reader work.
- `pio run -e default` for firmware compile validation.
- `pio run -e default` for the ESP32-C3 X3/X4 firmware.
- `pio run -e sticky` for the ESP32-S3 Sticky firmware.
- `pio run -e x4-pro` for the ESP32-S3 X4 Pro firmware.
- `pio check -e default --fail-on-defect low --fail-on-defect medium --fail-on-defect high` for static analysis.
- `find src lib include test -name "*.cpp" -o -name "*.h" | xargs clang-format -i` for formatting touched C++ files.
- For crash debugging, check serial logs, heap with `ESP.getFreeHeap()`, task stack high-water marks, and whether cache files need clearing.
- For crash debugging, check serial logs, internal heap with `ESP.getFreeHeap()` and `ESP.getMaxAllocHeap()`, task stack high-water marks, and whether cache files need clearing. On S3 targets, also inspect PSRAM free space and largest allocatable block; abundant PSRAM does not prove that internal-RAM or DMA-capable allocations can succeed.
- Hardware verification should mention the concrete device path to test, expected UI/log behavior, and any cache reset needed.

## Generated Files
Expand All @@ -131,7 +134,10 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
## Git Workflow

- Check `git status --short` before edits and before reporting results. Preserve unrelated user changes.
- Do not commit unless the user explicitly asks.
- When resolving merge, rebase, or cherry-pick conflicts, inspect the relevant commit messages for upstream PR references such as `#2608`. Open the PR in its source repository and read its description and changed files before resolving the conflict so the intended behavior is understood.
- Do not resolve conflicts by automatically keeping CrossInk's current implementation or by discarding the upstream change wholesale. Preserve or adapt the upstream intent unless it is already fully implemented, would introduce a regression, or would substantially and unjustifiably change CrossInk's UX or behavior. When rejecting an upstream change, state the concrete reason.
- If a referenced PR cannot be accessed, inspect the source commit diff and nearby history, then report that the PR intent could not be verified instead of guessing.
- Do not commit unless the user explicitly asks or committing is part of the skill utilized.
- Before staging, ensure ignored/generated/local files such as `.pio/`, `*.generated.h`, `compile_commands.json`, and `platformio.local.ini` are not included.
- Branch names should use repo-style prefixes such as `feat/`, `fix/`, `docs/`, `refactor/`, `test/`, or `chore/`.
- Suggested commit messages should follow `<type>: <short summary>`, using types like `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, or `perf`.
Expand All @@ -150,6 +156,7 @@ When new features are added or issues are fixed, make sure to add an entry to `C
- The release date of each version is displayed.

### Types of Changelog Changes

- Added - for new features.
- Changed - for changes in existing functionality.
- Deprecated - for soon-to-be removed features.
Expand Down
Loading
Loading