## Summary
Closes#743.
**What is the goal of this PR?**
- Add back handling for HTML entities in expat. This was originally part
of the code that got removed
[here](https://github.com/crosspoint-reader/crosspoint-reader/pull/274)
- Handle ` ` characters to resolve issue #743
**What changes are included?**
- Brought back HTML entity table from previous commit and refactored it
to use a static const char * table with linear lookup to reduce heap
allocations.
- Used `XML_SetDefaultHandlerExpand` in expat to parse out the entities
correctly, without needing them defined in DOCTYPE
- Added handling for ` ` so that the text stays together and
doesn't break onto a new line with text separated by an ` `
## Additional Context
- This supersedes [this
PR](https://github.com/crosspoint-reader/crosspoint-reader/pull/751)
that simply handled `nbsp;` as whitespace. Instead, we want that
character to serve its true purpose and affect the line-breaking
algorithm.
- Updated my test EPUB [here](https://github.com/jdk2pq/css-test-epub)
with ` ` characters examples at the end of the book
---
### 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? _**YES**_, Claude Code
## Summary
* Definition and use of a central LOG function, that can later be
extended or completely be removed (for public use where debugging
information may not be required) to save flash by suppressing the
-DENABLE_SERIAL_LOG like in the slim branch
* **What changes are included?**
## Additional Context
* By using the central logger the usual:
```
#include <HardwareSerial.h>
...
Serial.printf("[%lu] [WCS] Obfuscating/deobfuscating %zu bytes\n", millis(), data.size());
```
would then become
```
#include <Logging.h>
...
LOG_DBG("WCS", "Obfuscating/deobfuscating %zu bytes", data.size());
```
You do have ``LOG_DBG`` for debug messages, ``LOG_ERR`` for error
messages and ``LOG_INF`` for informational messages. Depending on the
verbosity level defined (see below) soe of these message types will be
suppressed/not-compiled.
* The normal compilation (default) will create a firmware.elf file of
42.194.356 bytes, the same code via slim will create 42.024.048 bytes -
170.308 bytes less
* Firmware.bin : 6.469.984 bytes for default, 6.418.672 bytes for slim -
51.312 bytes less
### 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? _NO_
---------
Co-authored-by: Xuan Son Nguyen <son@huggingface.co>
## Summary
* Add a small loop in main to be able to receive external commands,
currently being sent via the debugging_monitor
* Implemented command: cmd:SCREENSHOT sends the currently displayed
screen to the monitor, which will then store it to screenshot.bmp
## Additional Context
I was getting annoyed with taking tilted/unsharp photos of the device
screen, so I added the ability to press Enter during the monitor
execution and type SCREENSHOT to send a command. Could be extended in
the future
[screenshot.bmp](https://github.com/user-attachments/files/25213230/screenshot.bmp)
---
### 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? No
## Summary
This PR extends the delay in main loop from 10ms to 50ms after the
device is idle for a while. This translates to extended battery life in
a longer period (see testing section above), while not hurting too much
the user experience.
With the help from [this
patch](https://github.com/ngxson/crosspoint-reader/tree/xsn/measure_cpu_usage),
I was able to measure the CPU usage on idle:
```
PR:
[20017] [MEM] Free: 150188 bytes, Total: 232092 bytes, Min Free: 150092 bytes
[20017] [IDLE] Idle time: 99.62% (CPU load: 0.38%)
[30042] [MEM] Free: 150188 bytes, Total: 232092 bytes, Min Free: 150092 bytes
[30042] [IDLE] Idle time: 99.63% (CPU load: 0.37%)
[40067] [MEM] Free: 150188 bytes, Total: 232092 bytes, Min Free: 150092 bytes
[40067] [IDLE] Idle time: 99.62% (CPU load: 0.38%)
master:
[20012] [MEM] Free: 195016 bytes, Total: 231532 bytes, Min Free: 132460 bytes
[20012] [IDLE] Idle time: 98.53% (CPU load: 1.47%)
[30017] [MEM] Free: 195016 bytes, Total: 231532 bytes, Min Free: 132460 bytes
[30017] [IDLE] Idle time: 98.53% (CPU load: 1.47%)
[40022] [MEM] Free: 195016 bytes, Total: 231532 bytes, Min Free: 132460 bytes
[40022] [IDLE] Idle time: 98.53% (CPU load: 1.47%)
```
While this is a x3.8 reduce in CPU usage, it doesn't translate to the
same amount of battery life extension in real life. The reasons are:
1. The CPU is not shut down completely
2. freeRTOS tick is still running (however, I planned to experiment with
tickless functionality)
3. Current leakage to other components, for example: voltage dividers,
eink screen, SD card, etc
A note on
[light-sleep](https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/api-reference/system/sleep_modes.html)
functionality: it is not possible in our use case because:
- Light-sleep for 50ms introduce too much overhead on wake up, it has
negative effect on battery life
- Light-sleep for longer period doesn't work because the ADC GPIO
buttons cannot be used as wake up source
## Testing (duration = 6 hrs)
To test this, I patched the `CrossPointSettings::getSleepTimeoutMs()` to
always returns a timeout of 6 hrs. This allow me to leave the device
idle for 6 hrs straight.
- On master branch, 6 hrs costs 26% battery life (100% --> 74%), meaning
battery life is ~23 hrs
- With this PR, 6 hrs costs 20% battery life (100% --> 80%), meaning
battery life is ~30 hrs
So in theory, this extends the battery by about 7 hrs. Even with some
error margin added, I think 3 hrs increase is possible with a normal
usage setup (i.e. only read ebooks, no wifi)
## Additional Context
Would appreciate if someone can test this with an oscilloscope.
---
### 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? **NO**
## Summary
* Unify all serial port debug messages
## Additional Context
* All messages sent to the serial port now follow the "[timestamp]
[origin] payload" format (notable exception framework messages)
---
### 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? No
## Summary
Show "Back" in file browser if not in root, "Home" otherwise.
---
### 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? YES
## Summary
* Manually trigger GPIO update in File Browser mode
* Previously just assumed that the GPIO data would update automatically
(presumably via yield), the data is currently updated in the main loop
(and now here as well during the middle of the processing loop).
* This allows the back button to be correctly detected instead of only
being checked once every 100ms or so for the button state.
## Additional Context
* Fixes
https://github.com/crosspoint-reader/crosspoint-reader/issues/579
---
### 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? No
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Enhanced input state detection in the web server interface for more
responsive and accurate user command recognition during high-frequency
operations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Noticed that the Indexing... popup went missing despite 3-5 seconds
delay. Reducing to 10KB, so we get a popup for delays > ~2s.
### 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? no
Added explanation how to recover from broken config/cache.
### 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? no
## Summary
* Prevent sleeping when in OPDS browser / downloading books
## Additional Context
* Raised in
https://github.com/crosspoint-reader/crosspoint-reader/discussions/673
---
### 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? No
## Summary
* I needed the ability to filter and or suppress debug messages
containig certain keywords (eg [GFX] for render related stuff)
* Update of debugging_monitor.py script for development work
## Additional Context
```
usage: debugging_monitor.py [-h] [--baud BAUD] [--filter FILTER] [--suppress SUPPRESS] [port]
ESP32 Monitor with Graph
positional arguments:
port Serial port
options:
-h, --help show this help message and exit
--baud BAUD Baud rate
--filter FILTER Only display lines containing this keyword (case-insensitive)
--suppress SUPPRESS Suppress lines containing this keyword (case-insensitive)
```
* plus a couple of platform specific defaults (port, pip style)
---
### 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? NO
Added info about optimizing EPUB.
### 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? no
## Summary
* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
Implement natural sort (e.g. "file1.txt, file2.txt, file10.txt" instead
of "file1.txt, file10.txt, file2.txt") for files in the
MyLibraryActivity menu
* **What changes are included?**
Modifies the `sortFileList` function under
`src/activities/home/MyLibraryActivity.cpp` to use natural sort as
opposed to lexicographical sort
## Additional Context
I wasn't entirely sure whether or not i should make this a configurable
option, but most file browsers and directory listing tools have this set
as an immutable default, so I opted against it.
* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
specific areas to focus on).
---
### 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? _**NO**_
## Summary
fixing issue if book href are absolute url and not relative to the
server
## Additional Context
* Fixes
https://github.com/crosspoint-reader/crosspoint-reader/issues/632
* https://github.com/harshit181/RSSPub/issues/43
---
### 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>**_
This PR unifies navigation handling & adds system-wide support for
continuous navigation.
## Summary
Holding down a navigation button now continuously advances through items
until the button is released. This removes the need for repeated
press-and-release actions and makes navigation faster and smoother,
especially in long menus or documents.
When page-based navigation is available, it will navigate through pages.
If not, it will progress through menu items or similar list-based UI
elements.
Additionally, this PR fixes inconsistencies in wrap-around behavior and
navigation index calculations.
Places where the navigation system was updated:
- Home Page
- Settings Pages
- My Library Page
- WiFi Selection Page
- OPDS Browser Page
- Keyboard
- File Transfer Page
- XTC Chapter Selector Page
- EPUB Chapter Selector Page
I’ve tested this on the device as much as possible and tried to match
the existing behavior. Please let me know if I missed anything. Thanks 🙏

---
Following the request from @osteotek and @daveallie for system-wide
support, the old PR (#379) has been closed in favor of this
consolidated, system-wide implementation.
---
### AI Usage
Did you use AI tools to help write this code? _**PARTIALLY**_
---------
Co-authored-by: Dave Allie <dave@daveallie.com>
## Summary
* **What is the goal of this PR?** Add Italian language hyphenation
support to improve text rendering for Italian books.
* **What changes are included?**
* Added Italian hyphenation trie (hyph-it.trie.h) generated from Typst's
hypher patterns
* Registered italianHyphenator in LanguageRegistry.cpp for language tag
it
* Added Italian to the hyphenation evaluation test suite
* Added Italian test data file with 5000 test cases
## Additional Context
* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
specific areas to focus on).
---
### 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? _**NO**_
---------
Co-authored-by: drbourbon <fabio@MacBook-Air-di-Fabio.local>
## Summary
- Closes#730
**What is the goal of this PR?**
- Adds percentage-based value support to CSS properties that accept
percentages (padding, margin, text-indent)
**What changes are included?**
- Adds `Percent` as another CSS unit
- Passes the viewport width to `fromCssStyle` so that we can resolve
percentage-based values
- Adds a fallback of using an emspace for text-indent if we have an
unresolvable value for whatever reason
## Additional Context
- This was missed in my CSS support feature, and the fallback when we
encounter a percentage value is to use px instead. This means 5% (which
would be ~30px on the screen) turns into 5px. When percentages are used
in `text-indent`, this fallback behavior makes the indent look like a
single space character. Whoops! 😬
My test EPUB has been updated
[here](https://github.com/jdk2pq/css-test-epub) with percentage based
CSS values at the end of the book.
---
### 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? _**YES**_, Claude Code
## Summary
- Closes#730
**What is the goal of this PR?**
- Adds percentage-based value support to CSS properties that accept
percentages (padding, margin, text-indent)
**What changes are included?**
- Adds `Percent` as another CSS unit
- Passes the viewport width to `fromCssStyle` so that we can resolve
percentage-based values
- Adds a fallback of using an emspace for text-indent if we have an
unresolvable value for whatever reason
## Additional Context
- This was missed in my CSS support feature, and the fallback when we
encounter a percentage value is to use px instead. This means 5% (which
would be ~30px on the screen) turns into 5px. When percentages are used
in `text-indent`, this fallback behavior makes the indent look like a
single space character. Whoops! 😬
My test EPUB has been updated
[here](https://github.com/jdk2pq/css-test-epub) with percentage based
CSS values at the end of the book.
---
### 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? _**YES**_, Claude Code
## Summary
* Allow OTA update from RC build to full release
* If all the segments match, then also check if the current version
contains "-rc"
---
### 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? No
## Summary
* Allow OTA update from RC build to full release
* If all the segments match, then also check if the current version
contains "-rc"
---
### 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? No
I had an epub that just showed a blank cover and wouldnt work for the
sleep screen either, turns out it was an epub3 and I guess we didn't
support that. Super simple fix here
## Summary
This is an updated version of @itsthisjustin's #346 that builds on
current master and also deduplicates the settings list so we don't have
two copies of the settings. In the Web UI, it should organize the
settings a little closer to what you see on device.
## Additional Context
I tested this live on device and it seems to play nicely for me. It's
re-based on master since master's settings stuff has moved somewhat
since the original PR and addresses the sole review comment #346 - it
also means that I don't need to manually key in the URL for my OPDS
server. :)
---
### AI Usage
My changes were implemented with Claude Opus 4.5 and Claude Code 2.1.25.
I don't know if @itsthisjustin's original work used AI assistance.
Co-authored-by: Dave Allie <dave@daveallie.com>
## Summary
Continue my changes to introduce the HAL infrastructure from
https://github.com/crosspoint-reader/crosspoint-reader/pull/522
This PR touches quite a lot of files, but most of them are just name
changing. It should not have any impacts to the end behavior.
## Additional Context
My plan is to firstly add this small shim layer, which sounds useless at
first, but then I'll implement an emulated driver which can be helpful
for testing and for development.
Currently, on my fork, I'm using a FS driver that allow "mounting" a
local directory from my computer to the device, much like the `-v` mount
option on docker. This allows me to quickly reset `.crosspoint`
directory if anything goes wrong. I plan to upstream this feature when
this PR get merged.
---
### 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? NO
## Summary
**What is the goal of this PR?**
- Just a simple rename after feedback in #738
**What changes are included?**
- Renamed "Embedded Style" to "Book's Embedded Style" to more clearly
associate it with "Book's Style" option in "Paragraph Alignment"
settings
---
### 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? _**NO**_
## Summary
Ref https://github.com/crosspoint-reader/crosspoint-reader/pull/737
This PR further reduce ~25ms from rendering time, testing inside the
Setting screen:
```
master:
[68440] [GFX] Time = 73 ms from clearScreen to displayBuffer
PR:
[97806] [GFX] Time = 47 ms from clearScreen to displayBuffer
```
And in extreme case (fill the entire screen with black or gray color):
```
master:
[1125] [ ] Test fillRectDither drawn in 327 ms
[1347] [ ] Test fillRect drawn in 222 ms
PR:
[1334] [ ] Test fillRectDither drawn in 225 ms
[1455] [ ] Test fillRect drawn in 121 ms
```
Note that
https://github.com/crosspoint-reader/crosspoint-reader/pull/737 is NOT
applied on top of this PR. But with 2 of them combined, it should reduce
from 47ms --> 42ms
## Details
This PR based on the fact that function calls are costly if the function
is small enough. For example, this simple call:
```
int rotatedX = 0;
int rotatedY = 0;
rotateCoordinates(x, y, &rotatedX, &rotatedY);
```
Generated assembly code:
<img width="771" height="215" alt="image"
src="https://github.com/user-attachments/assets/37991659-3304-41c3-a3b2-fb967da53f82"
/>
This adds ~10 instructions just to prepare the registers prior to the
function call, plus some more instructions for the function's
epilogue/prologue. Inlining it removing all of these:
<img width="1471" height="832" alt="image"
src="https://github.com/user-attachments/assets/b67a22ee-93ba-4017-88ed-c973e28ec914"
/>
Of course, this optimization is not magic. It's only beneficial under 3
conditions:
- The function is small, not in size, but in terms of effective
instructions. For example, the `rotateCoordinates` is simply a jump
table, where each branch is just 3-4 inst
- The function has multiple input arguments, which requires some move to
put it onto the correct place
- The function is called very frequently (i.e. critical path)
---
### 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? **NO**
## Summary
Fix for the page skip issue detected
https://github.com/crosspoint-reader/crosspoint-reader/pull/700#issuecomment-3856374323
by user @whyte-j
Skipping down on the last page now skips to the last item, and up on the
first page to the first item, rather than wrapping around the list in a
weird way.
## Additional Context
The calculation was outdated after several changes were added afterwards
---
### 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? _**NO**_
## Summary
This PR optimizes the `fillRectDither` function, making it as fast as a
normal `fillRect`
Testing code:
```cpp
{
auto start_t = millis();
renderer.fillRectDither(0, 0, renderer.getScreenWidth(), renderer.getScreenHeight(), Color::LightGray);
auto elapsed = millis() - start_t;
Serial.printf("[%lu] [ ] Test fillRectDither drawn in %lu ms\n", millis(), elapsed);
}
{
auto start_t = millis();
renderer.fillRect(0, 0, renderer.getScreenWidth(), renderer.getScreenHeight(), true);
auto elapsed = millis() - start_t;
Serial.printf("[%lu] [ ] Test fillRect drawn in %lu ms\n", millis(), elapsed);
}
```
Before:
```
[1125] [ ] Test fillRectDither drawn in 327 ms
[1347] [ ] Test fillRect drawn in 222 ms
```
After:
```
[1065] [ ] Test fillRectDither drawn in 238 ms
[1287] [ ] Test fillRect drawn in 222 ms
```
## Visual validation
Before:
<img width="415" height="216" alt="Screenshot 2026-02-07 at 01 04 19"
src="https://github.com/user-attachments/assets/5802dbba-187b-4d2b-a359-1318d3932d38"
/>
After:
<img width="420" height="191" alt="Screenshot 2026-02-07 at 01 36 30"
src="https://github.com/user-attachments/assets/3c3c8e14-3f3a-4205-be78-6ed771dcddf4"
/>
## Details
The original version is quite slow because it does quite a lot of
computations. A single pixel needs around 20 instructions just to know
if it's black or white:
<img width="1170" height="693" alt="Screenshot 2026-02-07 at 00 15 54"
src="https://github.com/user-attachments/assets/7c5a55e7-0598-4340-8b7b-17307d7921cb"
/>
With the new, templated and more light-weight approach, each pixel takes
only 3-4 instructions, the modulo operator is translated into bitwise
ops:
<img width="1175" height="682" alt="Screenshot 2026-02-07 at 01 47 51"
src="https://github.com/user-attachments/assets/4ec2cf74-6cc0-4b5b-87d5-831563ef164f"
/>
---
### 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? **NO**
## Summary
Ref https://github.com/crosspoint-reader/crosspoint-reader/pull/737
This PR further reduce ~25ms from rendering time, testing inside the
Setting screen:
```
master:
[68440] [GFX] Time = 73 ms from clearScreen to displayBuffer
PR:
[97806] [GFX] Time = 47 ms from clearScreen to displayBuffer
```
And in extreme case (fill the entire screen with black or gray color):
```
master:
[1125] [ ] Test fillRectDither drawn in 327 ms
[1347] [ ] Test fillRect drawn in 222 ms
PR:
[1334] [ ] Test fillRectDither drawn in 225 ms
[1455] [ ] Test fillRect drawn in 121 ms
```
Note that
https://github.com/crosspoint-reader/crosspoint-reader/pull/737 is NOT
applied on top of this PR. But with 2 of them combined, it should reduce
from 47ms --> 42ms
## Details
This PR based on the fact that function calls are costly if the function
is small enough. For example, this simple call:
```
int rotatedX = 0;
int rotatedY = 0;
rotateCoordinates(x, y, &rotatedX, &rotatedY);
```
Generated assembly code:
<img width="771" height="215" alt="image"
src="https://github.com/user-attachments/assets/37991659-3304-41c3-a3b2-fb967da53f82"
/>
This adds ~10 instructions just to prepare the registers prior to the
function call, plus some more instructions for the function's
epilogue/prologue. Inlining it removing all of these:
<img width="1471" height="832" alt="image"
src="https://github.com/user-attachments/assets/b67a22ee-93ba-4017-88ed-c973e28ec914"
/>
Of course, this optimization is not magic. It's only beneficial under 3
conditions:
- The function is small, not in size, but in terms of effective
instructions. For example, the `rotateCoordinates` is simply a jump
table, where each branch is just 3-4 inst
- The function has multiple input arguments, which requires some move to
put it onto the correct place
- The function is called very frequently (i.e. critical path)
---
### 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? **NO**
## Summary
Fix for the page skip issue detected
https://github.com/crosspoint-reader/crosspoint-reader/pull/700#issuecomment-3856374323
by user @whyte-j
Skipping down on the last page now skips to the last item, and up on the
first page to the first item, rather than wrapping around the list in a
weird way.
## Additional Context
The calculation was outdated after several changes were added afterwards
---
### 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? _**NO**_
## Summary
**What is the goal of this PR?**
- Just a simple rename after feedback in #738
**What changes are included?**
- Renamed "Embedded Style" to "Book's Embedded Style" to more clearly
associate it with "Book's Style" option in "Paragraph Alignment"
settings
---
### 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? _**NO**_
## Summary
This PR optimizes the `fillRectDither` function, making it as fast as a
normal `fillRect`
Testing code:
```cpp
{
auto start_t = millis();
renderer.fillRectDither(0, 0, renderer.getScreenWidth(), renderer.getScreenHeight(), Color::LightGray);
auto elapsed = millis() - start_t;
Serial.printf("[%lu] [ ] Test fillRectDither drawn in %lu ms\n", millis(), elapsed);
}
{
auto start_t = millis();
renderer.fillRect(0, 0, renderer.getScreenWidth(), renderer.getScreenHeight(), true);
auto elapsed = millis() - start_t;
Serial.printf("[%lu] [ ] Test fillRect drawn in %lu ms\n", millis(), elapsed);
}
```
Before:
```
[1125] [ ] Test fillRectDither drawn in 327 ms
[1347] [ ] Test fillRect drawn in 222 ms
```
After:
```
[1065] [ ] Test fillRectDither drawn in 238 ms
[1287] [ ] Test fillRect drawn in 222 ms
```
## Visual validation
Before:
<img width="415" height="216" alt="Screenshot 2026-02-07 at 01 04 19"
src="https://github.com/user-attachments/assets/5802dbba-187b-4d2b-a359-1318d3932d38"
/>
After:
<img width="420" height="191" alt="Screenshot 2026-02-07 at 01 36 30"
src="https://github.com/user-attachments/assets/3c3c8e14-3f3a-4205-be78-6ed771dcddf4"
/>
## Details
The original version is quite slow because it does quite a lot of
computations. A single pixel needs around 20 instructions just to know
if it's black or white:
<img width="1170" height="693" alt="Screenshot 2026-02-07 at 00 15 54"
src="https://github.com/user-attachments/assets/7c5a55e7-0598-4340-8b7b-17307d7921cb"
/>
With the new, templated and more light-weight approach, each pixel takes
only 3-4 instructions, the modulo operator is translated into bitwise
ops:
<img width="1175" height="682" alt="Screenshot 2026-02-07 at 01 47 51"
src="https://github.com/user-attachments/assets/4ec2cf74-6cc0-4b5b-87d5-831563ef164f"
/>
---
### 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? **NO**
## Summary
* Inverts back button behaviour while reading - short press to go home,
long press to open file browser
## Additional Context
* It seems counterintuitive that going into a book from home screen and
pressing back doesn’t take you back to the home screen. With the recent
books now displayed in the home view and a separate recents view, going
directly to the file browser is less necessary.
Closes#182. Closes#710. Closes#711.
## Summary
**What is the goal of this PR?**
- A longer-term, more robust fix for the issue with spurious spaces
appearing after style changes. Replaces solution from #694.
**What changes are included?**
- Add continuation flags to determine if to add a space after a word or
if the word connects to the previous word. Replaces simple solution that
only considered ending punctuation.
- Fixed an issue with greedy line-breaking algorithm where punctuation
could appear on the next line, separated from the word, if there was a
style change between the word and punctuation
---
### 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? _**YES**_, Claude Code
## Summary
Reduce/fix the lag on the home screen before recent book covers are
rendered
## Additional Context
We were previously rendering the screen in two steps, delaying the
recent book covers render to avoid a lag before the screen loads.
In this PR, we are now doing that only if at least one book doesn't have
the cover thumbnail generated yet. If all thumbs are already generated,
we load and display them right away, with no lag.
---
### 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? _**NO **_
Closes#182. Closes#710. Closes#711.
## Summary
**What is the goal of this PR?**
- A longer-term, more robust fix for the issue with spurious spaces
appearing after style changes. Replaces solution from #694.
**What changes are included?**
- Add continuation flags to determine if to add a space after a word or
if the word connects to the previous word. Replaces simple solution that
only considered ending punctuation.
- Fixed an issue with greedy line-breaking algorithm where punctuation
could appear on the next line, separated from the word, if there was a
style change between the word and punctuation
---
### 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? _**YES**_, Claude Code
## Summary
Reduce/fix the lag on the home screen before recent book covers are
rendered
## Additional Context
We were previously rendering the screen in two steps, delaying the
recent book covers render to avoid a lag before the screen loads.
In this PR, we are now doing that only if at least one book doesn't have
the cover thumbnail generated yet. If all thumbs are already generated,
we load and display them right away, with no lag.
---
### 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? _**NO **_
Closes#712
## Summary
**What is the goal of this PR?**
- To add new settings for toggling on/off embedded CSS styles in the
reader. This gives more control and customization to the user over how
the ereader experience looks.
**What changes are included?**
- Added new "Embedded Style" option to the Reader settings
- Added new "Book's Style" option for "Paragraph Alignment"
- User's selected "Paragraph Alignment" will take precedence and
override the embedded CSS `text-align` property, _unless_ the user has
"Book's Style" set as their "Paragraph Alignment"
## Additional Context

https://github.com/user-attachments/assets/9e404b13-c7e0-41c7-9406-4715f389166a
Addresses feedback from the community about the new CSS feature:
https://github.com/crosspoint-reader/crosspoint-reader/pull/700
---
### 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? _**YES**_, Claude Code
Closes#712
## Summary
**What is the goal of this PR?**
- To add new settings for toggling on/off embedded CSS styles in the
reader. This gives more control and customization to the user over how
the ereader experience looks.
**What changes are included?**
- Added new "Embedded Style" option to the Reader settings
- Added new "Book's Style" option for "Paragraph Alignment"
- User's selected "Paragraph Alignment" will take precedence and
override the embedded CSS `text-align` property, _unless_ the user has
"Book's Style" set as their "Paragraph Alignment"
## Additional Context

https://github.com/user-attachments/assets/9e404b13-c7e0-41c7-9406-4715f389166a
Addresses feedback from the community about the new CSS feature:
https://github.com/crosspoint-reader/crosspoint-reader/pull/700
---
### 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? _**YES**_, Claude Code
## Summary
* Direct swap of X with new logo for boot and sleep screens
* More to be done here in the future to make these screens look a little
nicer
## Additional Context
* The design comes straight from @lepislepis -
https://github.com/crosspoint-reader/crosspoint-reader/discussions/396#discussioncomment-15590508
---
### 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? _**No
## Summary
This pull request introduces a new "Chapter Progress Bar" mode to the
status bar, allowing users to track their progress within the current
chapter in addition to the existing book-level progress options. It also
unifies and increases the progress bar height for better visibility, and
updates the settings UI to support the new mode.
Closes#636
**Status Bar/Progress Bar Enhancements:**
* Added a new `CHAPTER_PROGRESS_BAR` mode to
`CrossPointSettings::STATUS_BAR_MODE`, and updated the settings UI to
allow users to select this mode.
[[1]](diffhunk://#diff-3af36372bb6233a83387a68091b5e0651c23585c7c0a95669ed893268ca709a8R34)
[[2]](diffhunk://#diff-c55df9ec3ade843be000ba463cb75aa3df27dc34620a56c248fc4cc4e917b34bL22-R23)
* Implemented `drawChapterProgressBar` in `ScreenComponents` and
integrated it into both EPUB and TXT reader activities, so the chapter
progress bar is displayed when the new mode is selected.
[[1]](diffhunk://#diff-be271778a942f7fab0d920acd73442512346ff811a4625c011275a7ca6be3a3eL51-R64)
[[2]](diffhunk://#diff-dd410cab3a363d78172706d2ad6591f327e9b5b05f314db405db31a667af03faL16-R20)
[[3]](diffhunk://#diff-82798dedbe135495e619d4aa27a4bef560c70c7663cf43148b67a26ddde45682R518-R525)
[[4]](diffhunk://#diff-471ba9d9eb65b1a8451d41246db2aa695a42ea4ae4762163adfda4c20fec0950R563-R567)
* Updated logic in EPUB and TXT reader activities to show the correct
progress bar, progress text, and battery indicator based on the selected
status bar mode, including the new chapter progress bar mode.
[[1]](diffhunk://#diff-82798dedbe135495e619d4aa27a4bef560c70c7663cf43148b67a26ddde45682R470-R481)
[[2]](diffhunk://#diff-82798dedbe135495e619d4aa27a4bef560c70c7663cf43148b67a26ddde45682L490-R503)
[[3]](diffhunk://#diff-471ba9d9eb65b1a8451d41246db2aa695a42ea4ae4762163adfda4c20fec0950R522-R533)
[[4]](diffhunk://#diff-471ba9d9eb65b1a8451d41246db2aa695a42ea4ae4762163adfda4c20fec0950L539-R548)
**UI/Visual Tweaks:**
* Increased the progress bar height from 4 to 6 pixels for improved
visibility, and refactored code to use the new constant.
[[1]](diffhunk://#diff-dd410cab3a363d78172706d2ad6591f327e9b5b05f314db405db31a667af03faL16-R20)
[[2]](diffhunk://#diff-82798dedbe135495e619d4aa27a4bef560c70c7663cf43148b67a26ddde45682L295-R295)
[[3]](diffhunk://#diff-471ba9d9eb65b1a8451d41246db2aa695a42ea4ae4762163adfda4c20fec0950L177-R177)
These changes collectively provide users with more granular progress
tracking options and a clearer visual indicator for reading progress.
## Additional Context
---
### AI Usage
Did you use AI tools to help write this code? _**YES**_
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
## Summary
* **What is the goal of this PR?**
Move the "Sync Progress" option from TOC (Chapter Selection) screen to
the Reader Menu, and fix use-after-free crashes related to callback
handling in activity lifecycle.
* **What changes are included?**
- Added "Sync Progress" as a menu item in `EpubReaderMenuActivity` (now
4 items: Go to Chapter, Sync Progress, Go Home, Delete Book Cache)
- Removed sync-related logic from `EpubReaderChapterSelectionActivity` -
TOC now only displays chapters
- Implemented `pendingGoHome` and `pendingSubactivityExit` flags in
`EpubReaderActivity` to safely handle activity destruction
- Fixed GO_HOME, DELETE_CACHE, and SYNC menu actions to use deferred
callbacks avoiding use-after-free
## Additional Context
* Root cause of crashes: callbacks like `onGoHome()` or `onCancel()`
invoked from activity handlers could destroy the current activity while
code was still executing, causing use-after-free and race conditions
with FreeRTOS display task.
* Solution: Deferred execution pattern - set flags and process them in
`loop()` after all nested activity loops have safely returned.
* Files changed: `EpubReaderMenuActivity.h`,
`EpubReaderActivity.h/.cpp`, `EpubReaderChapterSelectionActivity.h/.cpp`
---
### 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? _**YES**_
Co-authored-by: danoooob <danoooob@example.com>
Co-authored-by: Dave Allie <dave@daveallie.com>
Fixes issue #182
## Summary
**What is the goal of this PR?**
When inline styles change mid-paragraph, words like periods, commas, and
quotes could end up as separate tokens. The justified text algorithm was
treating these as regular words, adding space before them.
**What changes are included?**
Now tracks which words are "attaching punctuation" (., , ! ? ; : " ' and
smart quotes) and excludes them from gap counting. These punctuation
marks attach directly to the preceding word without spacing.
## Additional Context
This is split out from code in #411 to address this comment
https://github.com/crosspoint-reader/crosspoint-reader/pull/411#discussion_r2751166631
---
### 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? _**YES**_, Claude Code
## Summary
Minor fix
### 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? no
## Summary
* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
Add shift lock to KeyboardEntryActivity
https://github.com/user-attachments/assets/00973866-6b87-4d5b-a3bf-6f4f85a5e0a6
(Apologies for the graininess of the video - I was struggling to get it
below 10mb)
* **What changes are included?**
* Relax shift disable criteria to include any character
* Add third shift option `LOCK` which is not disabled on character
entry.
## Additional Context
* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
specific areas to focus on).
---
### 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? _**NO**_
## Summary
* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
This adds renaming and moving files to the File Manager
* **What changes are included?**
New `/move` and `/rename` endpoints, and corresponding modals and icons
added. Uses the `file.rename()` function, after sanity checking.
## Additional Context
* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
specific areas to focus on).
Fixes#559, #661, #663. Only touches the File Manager, so low risk of
affecting other systems.
Simpler than #619, at the cost of not migrating the cache of renamed
books.
<img width="870" height="437" alt="image"
src="https://github.com/user-attachments/assets/73e0e750-dfc8-48e0-a7a6-9694470b7ded"
/>
<img width="575" height="318" alt="image"
src="https://github.com/user-attachments/assets/38c5fb19-c38a-436b-b3ad-75c1be7375ab"
/>
<img width="574" height="293" alt="image"
src="https://github.com/user-attachments/assets/1d2a2403-765d-473f-8c4f-c6968e9bbfeb"
/>
---
### 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? _**YES**_
I used Codex for the implementation itself, and then carefully reviewed
the code myself. As this is a simple change and only to the webserver,
it is low risk.
## Summary
* **What is the goal of this PR?**
The goal of this PR is to deliver a fix for or at least mitigate the
impact of the issue described in #561
* **What changes are included?**
This PR includes a new option "Sunlight Fading Fix" under "Settings ->
Display".
When set to ON, we will disable the displays analog supply voltage after
every update and turn it back on before the next update.
## Additional Context
* Until now, I was only able to do limited testing because of limited
sunlight at my location, but the fix seems to be working. I'll also
attach a pre-built binary based on 0.16.0 (current master) with the fix
applied to the linked ticket, as building this fix is a bit annoying
because the submodule open-x4-sdk also needs an update.
* [PR in
open-x4-sdk](https://github.com/open-x4-epaper/community-sdk/pull/15)
needs to be merged first, we also need to add another commit to this
here PR, updating this dependency.
* I decided to hide this behind a default-OFF option. While I'm not
really concerned that this fix might potentially damage the display,
someone more knowledgeable on E-Ink technology could maybe have a look
at this.
* There's a binary attached in the linked issue, if someone has the
required sunlight to test this in-depth.
---
### 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? _**NO**_
---------
Co-authored-by: Dave Allie <dave@daveallie.com>
## Summary
* Add PR title check on sync
## Additional Context
---
### 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? No
## Summary
* Adds Go To % action in Epub Reader menu with slider style percent
selector
<img width="860" height="1147" alt="image"
src="https://github.com/user-attachments/assets/a38ecc71-429e-40e8-94ac-37fb1509dbd9"
/>
---
### 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 >**_
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
## Summary
* **What is the goal of this PR?** Provide support to koreader sync
server embedded in the popular *Calibre Web Automated* self-hosted
digital library solution.
* **What changes are included?**
* Trivial addition of **HTTP Basic Auth (RFC 7617) header** to
`lib/KOReaderSync/KOReaderSyncClient.cpp`
## Additional Context
None
---
### 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? _**NO**_
---------
Co-authored-by: drbourbon <fabio@MacBook-Air-di-Fabio.local>
## Summary
* Add CI check job to consolidate status
## Additional Context
* As in the inline comment:
> This job is used as the PR required actions check, allows for changes
to other steps in the future without breaking PR requirements.
---
### 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? No
## Summary
* adds rotation setting in epub reader menu, actual rotation happens on
going back
* improves button hint drawing to draw correctly in all orientations
<img width="860" height="1147" alt="image"
src="https://github.com/user-attachments/assets/91ceeca6-729f-4304-b68a-e412f6e2c9a7"
/>
---
### 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
Allows to fallback to custom sleep screens if the book does not have a
cover.
---
### 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 >**_
---------
Co-authored-by: mrtnvgr <root@unixis.fun>
## Summary
Use non-crop mode as expected for home thumb generation. I likely broke
this when I fixed the artifacts on the sleep screen.
---
### 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? NO
## Summary
* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
- Allows back button to be held to escape boot loops when reader
activity crashes and device attempts to boot to previous state
- Reduces the need of removing SD card and access to another device to
delete the `/.crosspoint/state.bin`
* **What changes are included?**
- Back button can be held while booting to boot to home screen
- Update of User Guide section to include this feature
## Additional Context
* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
specific areas to focus on).
---
### 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? _**NO**_
---------
Co-authored-by: Arthur Tazhitdinov <lisnake@gmail.com>
## Summary
* Additional documentation for CrossPoint in the way of a SCOPE.md and
GOVERNANCE.md document.
* These are intentionally pretty lightweight for now
---
### 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?
- Visual UI overhaul
- UI theme selection
### What changes are included?
- Added a setting "UI Theme": Classic, Lyra
- The classic theme is the current Crosspoint theme
- The Lyra theme implements these mockups:
https://www.figma.com/design/UhxoV4DgUnfrDQgMPPTXog/Lyra-Theme?node-id=2003-7596&t=4CSOZqf0n9uQMxDt-0
by Discord users yagofarias, ruby and gan_shu
- New functions in GFXRenderer to render rounded rectangles, greyscale
fills (using dithering) and thick lines
- Basic UI components are factored into BaseTheme methods which can be
overridden by each additional theme. Methods that are not overridden
will fallback to BaseTheme behavior. This means any new
features/components in CrossPoint only need to be developed for the
"Classic" BaseTheme.
- Additional themes can easily be developed by the community using this
foundation



## Additional Context
- Only the Home, Library and main Settings screens have been implemented
so far, this will be extended to the transfer screens and chapter
selection screen later on, but we need to get the ball rolling somehow
:)
- Loading extra covers on the home screen in the Lyra theme takes a
little more time (about 2 seconds), I added a loading bar popup (reusing
the Indexing progress bar from the reader view, factored into a neat UI
component) but the popup adds ~400ms to the loading time.
- ~~Home screen thumbnails will need to be generated separately for each
theme, because they are displayed in different sizes. Because we're
using dithering, displaying a thumb with the wrong size causes the
picture to look janky or dark as it does on the screenshots above. No
worries this will be fixed in a future PR.~~ Thumbs are now generated
with a size parameter
- UI Icons will need to be implemented in a future PR.
---
### 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**_
This is not a vibe coded PR. Copilot was used for autocompletion to save
time but I reviewed, understood and edited all generated code.
---------
Co-authored-by: Dave Allie <dave@daveallie.com>
## Summary
* **What is the goal of this PR?**
- Adds basic CSS parsing to EPUBs and determine the CSS rules when
rendering to the screen so that text is styled correctly. Currently
supports bold, underline, italics, margin, padding, and text alignment
## Additional Context
- My main reason for wanting this is that the book I'm currently
reading, Carl's Doomsday Scenario (2nd in the Dungeon Crawler Carl
series), relies _a lot_ on styled text for telling parts of the story.
When text is bolded, it's supposed to be a message that's rendered
"on-screen" in the story. When characters are "chatting" with each
other, the text is bolded and their names are underlined. Plus, normal
emphasis is provided with italicizing words here and there. So, this
greatly improves my experience reading this book on the Xteink, and I
figured it was useful enough for others too.
- For transparency: I'm a software engineer, but I'm mostly frontend and
TypeScript/JavaScript. It's been _years_ since I did any C/C++, so I
would not be surprised if I'm doing something dumb along the way in this
code. Please don't hesitate to ask for changes if something looks off. I
heavily relied on Claude Code for help, and I had a lot of inspiration
from how [microreader](https://github.com/CidVonHighwind/microreader)
achieves their CSS parsing and styling. I did give this as good of a
code review as I could and went through everything, and _it works on my
machine_ 😄
### Before


### After


---
### AI Usage
Did you use AI tools to help write this code? **YES**, Claude Code
## Summary
The main motivation behind this PR was because `uploadBuffer` is
statically allocated, but only used when web server is enabled. This
results in 4KB of memory sitting idle most of the time.
As expected, 4KB of initial RAM is freed with this PR:
```
master:
RAM: [=== ] 32.5% (used 106508 bytes from 327680 bytes)
PR:
RAM: [=== ] 31.2% (used 102276 bytes from 327680 bytes)
```
## Additional Context
This also highlights the importance of only using statically-allocated
buffer when absolutely needed (for example, if the component is active
most of the time). Otherwise, it makes more sense to tie the buffer's
life cycle to its activity.
---
### 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? NO
## Summary
**What is the goal of this PR?**
- Minor correction to the `debugging_monitor.py` script instructions
**What changes are included?**
- `pyserial` should be installed, NOT `serial`, which is a [different
lib](https://pypi.org/project/serial/)
- Added macOS serial port
## Additional Context
- Just a minor docs update. I can confirm the debugging script is
working great on macOS
---
### 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? _**< NO >**_
## Summary
* Instruction text says "Press OK to scan again" but button label is
actually "Connect" (not OK)
* Corrects instruction text
---
### AI Usage
Did you use AI tools to help write this code? **No**
## Rationale
I have 2 wifi access points with almost identical names, just one has
`_EXT` at the end of it. With the current display limit of 13 characters
before adding ellipsis, I can't tell which is which.
Before device screenshot with masked SSIDs:
<img
src="https://github.com/user-attachments/assets/3c5cbbaa-b2f6-412f-b5a8-6278963bd0f2"
width="300">
## Summary
Adjusted displayed length from 13 characters to 30 in the Wifi selection
screen - I've left some space for potential proportional font changes in
the future
After image with masked SSIDs:
<img
src="https://github.com/user-attachments/assets/c5f0712b-bbd3-4eec-9820-4693fae90c9f"
width="300">
---
### 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? _**< NO >**_
## Summary
Resolves#562
Implements regex change to support valid characters discussed by
@daveallie in issue
[here](https://github.com/crosspoint-reader/crosspoint-reader/issues/562#issuecomment-3830809156).
Also rejects `.` and `..` as folder names which are invalid in FAT32 and
exFAT filesystems
## Additional Context
- Unsure on the wording for the alert, it feels overly explicit, but
that might be a good thing. Happy to change.
---
### 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?**
Add a debugging script to help developers monitor the ESP32 serial port
directly from a PC.
* **What changes are included?**
Added a new script: scripts/debugging_monitor.py
## Additional Context
While working on a new Crosspoint-Reader feature, it quickly became
clear that watching the ESP32 serial output without any visual cues was
inconvenient and easy to mess up.
This script improves the debugging experience by reading data from the
serial port and providing:
1. A timestamp prefix for every log line (instead of milliseconds since
power-up)
2. Color-coded output for different message types
3. A secondary window displaying a live graph of RAM usage, which is
especially useful for tracking the memory impact of new features
<img width="1916" height="1049" alt="Screenshot_20260126_183811"
src="https://github.com/user-attachments/assets/6291887f-ac17-43ac-9e43-f5dec8a7097e"
/>
---
### AI Usage
Did you use AI tools to help write this code? _**< PARTIALLY >**_
I wrote the initial version of the script. Gemini was used to help add
the Matplotlib-based graphing and threading logic.
## Summary
* Truncating chapter titles using utf8 safe functions (Cyrillic titles
were split mid codepoint)
* refactoring of lib/Utf8
---
### 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
* Fixing custom sleep behaviour where the first image in the /sleep
directory is not shown
* image at index 0 is not being rendered when more than 1 image is
stored in /sleep directory, because `APP_STATE.lastSleepImage` is always
0.
## Additional Context
* `APP_STATE.lastSleepImage` is reset to 0 when a epub is open, this
value is only used to compare it to the randomly selected one in
`renderCustomSleepScreen()` that should always be a valid index, since
the list of valid bmp images is colected from scratch. -> no need to
reset it and block image @ index 0 from being rendered
---
### 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? _**NO**_
Co-authored-by: Oyster <Oyster@home>
## Summary
* This change hides the button hints from overlapping chapter titles
when in landscape CW mode.
Before

After

## Additional Context
* I initially considered implementing an offset fix, but with potential
UI changes on the horizon, hiding the button hints appears to be the
simplest solution for now.
---
### 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
* Clarify strings on Wifi connection error screens
* I have confirmed on device that these are short enough not to overflow
screen margins
## Additional Context
* Several screens give duplicative text (e.g., header "Connection
Failed" with contents text "Connection failed") or slightly confusing
text (header "Forget Network?" with text "Remove saved password?")
---
### AI Usage
Did you use AI tools to help write this code? **No**
## Summary
* refactors Indexing popups into ScreenComponents (they had different
implementations in different files)
* removes Indexing popup for small chapters
* only show Indexing popup (without progress bar) for large chapters
(using same minimum file size condition as for progress bar before)
## Additional Context
* Having to show even single popup message and redraw the screen slows
down the flow significantly
* Testing results:
* Opening large chapter with progress bar - 11 seconds
* Same chapter without progress bar, only single Indexing popup - 5
seconds
---
### AI Usage
Did you use AI tools to help write this code? _**< PARTIALLY>**_
## Summary
* Adds a menu in the Epub reader
* The Chapter selection is moved there to pos 1 (so it can be reached by
double tapping the confirm button)
* A Go Home is there, too
* Most significantly, a function "Delete Book Cache" is added. This
returns to main (to avoid directly rebuilding cached items, eg. if this
is used to debug/develop other areas - and it's also easier ;))
Probably, the Sync function could now be moved from the Chapter
selection to this menu, too.
---
### 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
Extracted some changes from
https://github.com/crosspoint-reader/crosspoint-reader/pull/500 to make
reviewing easier
This PR adds HAL (Hardware Abstraction Layer) for display and GPIO
components, making it easier to write a stub or an emulated
implementation of the hardware.
SD card HAL will be added via another PR, because it's a bit more
tricky.
---
### 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? **NO**
* **What is the goal of this PR?** Implement a metadata viewer for the
Recents screen
* **What changes are included?**
| Recents | Files |
| --- | --- |
| <img alt="image"
src="https://github.com/user-attachments/assets/e0f2d816-ddce-4a2e-bd4a-cd431d0e6532"
/> | <img alt="image"
src="https://github.com/user-attachments/assets/3225cdce-d501-4175-bc92-73cb8bfe7a41"
/> |
For the Files screen, I have not made any changes on purpose. For the
Recents screen, we now display the Book title and author. If it is a
file with no epub metadata like txt or md, we display the file name
without the file extension.
---
Did you use AI tools to help write this code? _**< YES >**_
Although I went trough all the code manually and made changes as well,
please be aware the majority of the code is AI generated.
---------
Co-authored-by: Eliz Kilic <elizk@google.com>
## Summary
* Correctly render italics on image alt placeholders
* Parser incorrectly handled depth of self-closing tags
* Self-closing tags immediately call start and end tag
## Additional Context
* Previously, it would incorrectly make the whole chapter bold/italics,
or not italicised the image alt
---
### 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? No
## Summary
* **What is the goal of this PR?**
Quality of Life
* **What changes are included?**
Add compile_commands.json & .cache to .gitignore .
Both are use by clangd that can help IDE support.
Run `pio run --target compiledb` to generate `compile_commands.json`.
---
### 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? _**NO**_
## Summary
Finally, I have received my device and got to chance to work on OTA.
https://github.com/crosspoint-reader/crosspoint-reader/issues/176
* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
Existing OTA functionality is very buggy, many of times (I would say 8
out of 10) are end up with fail for me. When the time that it works it
is very slow and take ages. For others looks like end up with crash or
different issues.
* **What changes are included?**
To be honest, I'm not familiar with Arduino APIs of OTA process, but
looks like not good as much esp-idf itself. I always found Arduino APIs
very bulky for esp32. Wrappers and wrappers.
## Additional Context
Right now, OTA takes ~ 3min 10sec (of course depends on size of .bin
file). Can be tested with playing version info inside from
`platform.ini` file.
```
[crosspoint]
version = 0.14.0
```
---
### 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? _**< NO >**_
## Summary
Optimizes EPUB metadata indexing for large books (2000+ chapters) from
~30 minutes to ~50 seconds by replacing O(n²) algorithms with O(n log n)
hash-indexed lookups.
Fixes#134
## Problem
Three phases had O(n²) complexity due to nested loops:
| Phase | Operation | Before (2768 chapters) |
|-------|-----------|------------------------|
| OPF Pass | For each spine ref, scan all manifest items | ~25 min |
| TOC Pass | For each TOC entry, scan all spine items | ~5 min |
| buildBookBin | For each spine item, scan ZIP central directory | ~8.4
min |
Total: **~30+ minutes** for first-time indexing of large EPUBs.
## Solution
Replace linear scans with sorted hash indexes + binary search:
- **OPF Pass**: Build `{hash(id), len, offset}` index from manifest,
binary search for each spine ref
- **TOC Pass**: Build `{hash(href), len, spineIndex}` index from spine,
binary search for each TOC entry
- **buildBookBin**: New `ZipFile::fillUncompressedSizes()` API - single
ZIP central directory scan with batch hash matching
All indexes use FNV-1a hashing with length as secondary key to minimize
collisions. Indexes are freed immediately after each phase.
## Results
**Shadow Slave EPUB (2768 chapters):**
| Phase | Before | After | Speedup |
|-------|--------|-------|---------|
| OPF pass | ~25 min | 10.8 sec | ~140x |
| TOC pass | ~5 min | 4.7 sec | ~60x |
| buildBookBin | 506 sec | 34.6 sec | ~15x |
| **Total** | **~30+ min** | **~50 sec** | **~36x** |
**Normal EPUB (87 chapters):** 1.7 sec - no regression.
## Memory
Peak temporary memory during indexing:
- OPF index: ~33KB (2770 items × 12 bytes)
- TOC index: ~33KB (2768 items × 12 bytes)
- ZIP batch: ~44KB (targets + sizes arrays)
All indexes cleared immediately after each phase. No OOM risk on
ESP32-C3.
## Note on Threshold
All optimizations are gated by `LARGE_SPINE_THRESHOLD = 400` to preserve
existing behavior for small books. However, the algorithms work
correctly for any book size and are faster even for small books:
| Book Size | Old O(n²) | New O(n log n) | Improvement |
|-----------|-----------|----------------|-------------|
| 10 ch | 100 ops | 50 ops | 2x |
| 100 ch | 10K ops | 800 ops | 12x |
| 400 ch | 160K ops | 4K ops | 40x |
If preferred, the threshold could be removed to use the optimized path
universally.
## Testing
- [x] Shadow Slave (2768 chapters): 50s first-time indexing, loads and
navigates correctly
- [x] Normal book (87 chapters): 1.7s indexing, no regression
- [x] Build passes
- [x] clang-format passes
## Files Changed
- `lib/Epub/Epub/parsers/ContentOpfParser.h/.cpp` - OPF manifest index
- `lib/Epub/Epub/BookMetadataCache.h/.cpp` - TOC index + batch size
lookup
- `lib/ZipFile/ZipFile.h/.cpp` - New `fillUncompressedSizes()` API
- `lib/Epub/Epub.cpp` - Timing logs
<details>
<summary><b>Algorithm Details</b> (click to expand)</summary>
### Phase 1: OPF Pass - Manifest to Spine Lookup
**Problem**: Each `<itemref idref="ch001">` in spine must find matching
`<item id="ch001" href="...">` in manifest.
```
OLD: For each of 2768 spine refs, scan all 2770 manifest items
= 7.6M string comparisons
NEW: While parsing manifest, build index:
{ hash("ch001"), len=5, file_offset=120 }
Sort index, then binary search for each spine ref:
2768 × log₂(2770) ≈ 2768 × 11 = 30K comparisons
```
### Phase 2: TOC Pass - TOC Entry to Spine Index Lookup
**Problem**: Each TOC entry with `href="chapter0001.xhtml"` must find
its spine index.
```
OLD: For each of 2768 TOC entries, scan all 2768 spine entries
= 7.6M string comparisons
NEW: At beginTocPass(), read spine once and build index:
{ hash("OEBPS/chapter0001.xhtml"), len=25, spineIndex=0 }
Sort index, binary search for each TOC entry:
2768 × log₂(2768) ≈ 30K comparisons
Clear index at endTocPass() to free memory.
```
### Phase 3: buildBookBin - ZIP Size Lookup
**Problem**: Need uncompressed file size for each spine item (for
reading progress). Sizes are in ZIP central directory.
```
OLD: For each of 2768 spine items, scan ZIP central directory (2773 entries)
= 7.6M filename reads + string comparisons
Time: 506 seconds
NEW:
Step 1: Build targets from spine
{ hash("OEBPS/chapter0001.xhtml"), len=25, index=0 }
Sort by (hash, len)
Step 2: Single pass through ZIP central directory
For each entry:
- Compute hash ON THE FLY (no string allocation)
- Binary search targets
- If match: sizes[target.index] = uncompressedSize
Step 3: Use sizes array directly (O(1) per spine item)
Total: 2773 entries × log₂(2768) ≈ 33K comparisons
Time: 35 seconds
```
### Why Hash + Length?
Using 64-bit FNV-1a hash + string length as a composite key:
- Collision probability: ~1 in 2⁶⁴ × typical_path_lengths
- No string storage needed in index (just 12-16 bytes per entry)
- Integer comparisons are faster than string comparisons
- Verification on match handles the rare collision case
</details>
---
_AI-assisted development. All changes tested on hardware._
## Summary
* **What is the goal of this PR?** Add Spanish language hyphenation
support to improve text rendering for Spanish books.
* **What changes are included?**
- Added Spanish hyphenation trie (`hyph-es.trie.h`) generated from
Typst's hypher patterns
- Registered `spanishHyphenator` in `LanguageRegistry.cpp` for language
tag `es`
- Added Spanish to the hyphenation evaluation test suite
- Added Spanish test data file with 5000 test cases
## Additional Context
* **Test Results:** Spanish hyphenation achieves 99.02% F1 Score (97.72%
perfect matches out of 5000 test cases)
* **Compatibility:** Works automatically for EPUBs with
`<dc:language>es</dc:language>` (or es-ES, es-MX, etc.)
<img width="115" height="189" alt="imagen"
src="https://github.com/user-attachments/assets/9b92e7fc-b98d-48af-8d53-dfdc2e68abee"
/>
| Metric | Value |
|--------|-------|
| Perfect matches | 97.72% |
| Overall Precision | 99.33% |
| Overall Recall | 99.42% |
| Overall F1 Score | 99.38% |
---
### AI Usage
Did you use AI tools to help write this code? _**PARTIALLY**_
AI assisted with:
- Guiding and compile
- Preparing the PR description
## Summary
* If long-press chapter skip is disabled, turn pages on button pressed,
not released
* Makes page turning snappier
* Refactors MappedInputManager for readability
---
### AI Usage
Did you use AI tools to help write this code? _**< PARTIALLY>**_
---------
Co-authored-by: Dave Allie <dave@daveallie.com>
## Summary
* **What is the goal of this PR?** This PR introduces a new "Status Bar"
mode that displays a visual progress bar at the bottom of the screen,
providing readers with a graphical indication of their position within
the book.
* **What changes are included?**
* **Settings**: Updated SettingsActivity to expand the "Status Bar"
configuration with a new option: Full w/ Progress Bar.
* **EPUB Reader**: Modified EpubReaderActivity to calculate the global
book progress and render a progress bar at the bottom of the viewable
area when the new setting is active.
* **TXT Reader**: Modified TxtReaderActivity to implement similar
progress bar rendering logic based on the current page and total page
count.
## Additional Context
* The progress bar is rendered with a height of 4 pixels at the very
bottom of the screen (adjusted for margins).
* The feature reuses the existing renderStatusBar logic but
conditionally draws the bar instead of (or in addition to) other
elements depending on the specific implementation details in each
reader.
* Renamed existing 'Full' mode to 'Full w/ Percentage'
* Added new 'Full w/ Progress Bar' option
<img
src="https://github.com/user-attachments/assets/08c0dd49-c64c-4d4d-9fbb-f576c02d05d9"
width="500">
---
### 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? _**NO**_
## Summary
Fixes#487
---
### 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? _** YES **_
Co-authored-by: Dave Allie <dave@daveallie.com>
## Summary
This was originally a comment in #499, but I'm making it its own PR,
because it doesn't depend on anything there and then I can base that PR
on this one.
Currently, `drawBitmap` is used for covers and sleep wallpaper, and
`drawImage` is used for the boot logo. `drawBitmap` goes row by row and
pixel by pixel, so it respects the renderer orientation. `drawImage`
just calls the `EInkDisplay`'s `drawImage`, which works in the eink
panel's native display orientation.
`drawImage` rotates the x,y coordinates where it's going to draw the
image, but doesn't account for the fact that the northwest corner in
portrait orientation becomes, the southwest corner of the image
rectangle in the native orientation. The boot and sleep activities
currently work around this by calculating the north*east* corner of
where the image should go, which becomes the northwest corner after
`rotateCoordinates`.
I think this wasn't really apparent because the CrossPoint logo is
rotationally symmetrical. The `EInkDisplay` `drawImage` always draws the
image in native orientation, but that looks the same for the "X" image.
If we rotate the origin coordinate in `GfxRenderer`'s `drawImage`, we
can use a much clearer northwest corner coordinate in the boot and sleep
activities. (And then, in #499, we can actually rotate the boot screen
to the user's preferred orientation).
This does *not* yet rotate the actual bits in the image; it's still
displayed in native orientation. This doesn't affect the
rotationally-symmetric logo, but if it's ever changed, we will probably
want to allocate a new `u8int[]` and transpose rows and columns if
necessary.
## Additional Context
I've created an additional branch on top of this to demonstrate by
replacing the logo with a non-rotationally-symmetrical image:
<img width="128" height="128" alt="Cat-in-a-pan-128-bw"
src="https://github.com/user-attachments/assets/d0b239bc-fe75-4ec8-bc02-9cf9436ca65f"
/>
https://github.com/crosspoint-reader/crosspoint-reader/compare/master...maeveynot:rotated-cat
(many thanks to https://notisrac.github.io/FileToCArray/)
As you can see, it is always drawn in native orientation, which makes it
sideways (turned clockwise) in portrait.
---
### AI Usage
No
Co-authored-by: Maeve Andrews <maeve@git.mail.maeveandrews.com>
## Summary
* Extract author from XTC/XTCH files
## Additional Context
* Based on updated details in
https://gist.github.com/CrazyCoder/b125f26d6987c0620058249f59f1327d
---
### 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? No
## Summary
* **What is the goal of this PR?** Simple quality of life, ease
maintenance
* **What changes are included?**
Update fontconvert.py to include the command used to generate each font
file in the header comment, making it easier to regenerate fonts when
needed.
I plan on adding options to this scripts (kerning, and maybe ligatures),
thus knowing which command was used, even with already existing options
like `--additional-intervals`, is important.
---
### 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? _**NO**_
## Summary
- Update README with the list of supported languages for EPUB files.
- Update USER_GUIDE with an extended list of supported and unsupported
languages.
## Additional Context
For weeks, I thought this firmware only supported English, because I
remember you saying that full language support would only be possible
after implementing proper font rendering. I also remember mentioning a
separate Korean fork, Vietnamese issues and so on.
All of this made it clear that this system doesn't support my languages.
I was surprised when I saw a Reddit post with a photo of a book in my
native language. Only then I did learn that such languages are
supported. Therefore, mentioning the supported languages would help
future buyers and new users.
---
### AI Usage
Did you use AI tools to help write this code? _**NO**_
## Summary
* **What is the goal of this PR?**
Resolve [KoSync progress does not sync between Crosspoint-reader and
KOReader
(Kindle)](https://github.com/crosspoint-reader/crosspoint-reader/issues/502)
* **What changes are included?**
KOReaderDocumentId::getOffset() - Update the value for the md5 offset
calculation to match KOReader.
## Additional Context
I've tested this with a couple of my ebooks and binary matching with
KOReader sync seems to be working fine now for both pushing and pulling
progress.
---
### 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? _**NO**_
## Summary
Should address issues discussed in #168 and potentially fix#478.
---
### 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?** (e.g., Implements the new feature for
file uploading.)
* Aims to fix Issue #220
* **What changes are included?**
- Increased size of `progress.bin` such that total page count of current
section can be stored
- Comparison of total page count is done to determine if reader settings
were changed
- New position/page number is calculated using percentage calculated
from read progress
## Additional Context
* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
specific areas to focus on).
---
### 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? _**NO**_
## Summary
Fix https://github.com/crosspoint-reader/crosspoint-reader/issues/288
Based on my observation, it seems like the problem was that
`inputManager.isPressed(InputManager::BTN_POWER)` takes a bit of time
after waking up to report the correct value. I haven't tested this
behavior with a standalone ESP32C3, but if you know more about this,
feel free to comment.
However, if we just want short press, I think it's enough to check for
wake up source. If we plan to allow multiple buttons to wake up in the
future, may consider using ext1 / `esp_sleep_get_ext1_wakeup_status()`
to allow identify which pin triggered wake up.
Note that I'm not particularly experienced in esp32 developments, just
happen to have prior knowledge hacking esphome.
## Additional Context
N/A
---
### 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? NO
---------
Co-authored-by: Dave Allie <dave@daveallie.com>
## Summary
* Fixes#519
* Refactors repeated code into new function:
`ChapterHtmlSlimParser::flushPartWordBuffer()`
## Additional Context
* The `<br/>` tag is self closing and _in-line_, so the existing logic
for closing block tags does not get applied to `<br/>` tags.
* This PR adds the _in-line_ logic to:
* Flush the word preceding the `<br/>` tag from `partWordBuffer` to
`currentTextBlock` before calling `startNewTextBlock`
* **New function**: `ChapterHtmlSlimParser::flushPartWordBuffer()`
* **Purpose**: Consolidates the logic for flushing `partWordBuffer` to
`currentTextBlock`
* **Impact**: Simplifies `ChapterHtmlSlimParser::characterData(…)`,
`ChapterHtmlSlimParser::startElement(…)`, and
`ChapterHtmlSlimParser::endElement(…)` by integrating reused code into
single function
---
### 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? _**NO**_
Our esp32 consistently dropped the last few packets of the TCP transfer
in the old implementation. Only about 1/5 transfers would complete. I've
refactored that entire system into an actual Calibre Device Plugin that
basically uses the exact same system as the web server's file transfer
protocol. I kept them separate so that we don't muddy up the existing
file transfer stuff even if it's basically the same at the end of the
day I didn't want to limit our ability to change it later.
I've also added basic auth to OPDS and renamed that feature to OPDS
Browser to just disassociate it from Calibre.
---------
Co-authored-by: Arthur Tazhitdinov <lisnake@gmail.com>
Co-authored-by: Dave Allie <dave@daveallie.com>
## Summary
On the Forget Network page
* Update the default option to be DON'T forget the network
* Make the options clearer ("Cancel" and "Forget network")
* Unify the button hints to match the rest of the UI
## Additional Context
Closes#427
---
### 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
* Fixes#475
* Fixes#477
* Closes#428
## Additional Context
* Updates to
`src/activities/reader/EpubReaderChapterSelectionActivity.cpp` are
copied verbatim from #433 (thanks to @jonasdiemer)
* Update to `src/activities/settings/KOReaderSettingsActivity.cpp` per
discussion with @itsthisjustin at #428
Tested on my device with several books and koreader sync turned on and
off.
---
### AI Usage
Did you use AI tools to help write this code? _NO_
## Summary
Addresses
https://github.com/crosspoint-reader/crosspoint-reader/issues/504
- Reverts book progress % to showing as an integer instead of with a
decimal place
- This was changed to 1 decimal point of precision in
https://github.com/crosspoint-reader/crosspoint-reader/pull/232 from
what I can tell
- As this wasn't the primary intention of that PR, I'm assuming it was
left in accidentally
IMO having a decimal place of precision is too much for something as
vague as book completion percent. This de-clutters the status bar and
prevents extra updates as you change pages.
---
### AI Usage
YES
When reading on Landscape Counter ClockWise mode, the left/right button
appear inverted: the upper button (left) goes down and the lower button
(right) goes up.
Discussion: #449
## Summary
* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
Add a new configuration for the front buttons: Back, Confirm, Right,
Left
---
### 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? _**NO**_
## Summary
* Add additional punctuation marks to the list of characters that can be
immediately followed by a line break even where there is no explicit
space
## Additional Context
* Huge appreciation to @osteotek for his amazing work on hyphenation.
Reading on the device is so much better now.
* I am getting bad line breaks when ellipses (…) are between words and
book file does not explicitly include some kind of breaking space.
* Per
[discussion](https://github.com/crosspoint-reader/crosspoint-reader/pull/305#issuecomment-3765411406),
several new characters are added in this PR to the `isExplicitHyphen`
list to allow line breaks immediately after them:
Character | Unicode | Usage | Why include it?
-- | -- | -- | --
Solidus (Slash) | U+002F | / | Essential for breaking URLs and "and/or"
constructs.
Backslash | U+005C | \ | Critical for technical text, file paths, and
coding documentation.
Underscore | U+005F | _ | Prevents "runaway" line lengths in usernames
or code snippets.
Middle Dot | U+00B7 | · | Acts as a semantic separator in dictionaries
or stylistic lists.
Ellipsis | U+2026 | … | Prevents justification failure when dialogue
lacks following spaces.
Midline Horizontal Ellipsis | U+22EF | ⋯ | Useful for mathematical
sequences and technical notation.
### Example:
This shows an example of what line breaking looks like *with* this PR.
Note the line break after "matter…" (which would not previously have
been allowed). It's particularly important here because the book
includes non-breaking spaces in "Mr. Aldrich" and "Mr. Rockefeller."

---
### 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**
2026-01-27 20:18:09 +11:00
224 changed files with 22784 additions and 4651 deletions
@@ -41,7 +41,11 @@ This project is **not affiliated with Xteink**; it's built as a community projec
- [ ] Full UTF support
- [x] Screen rotation
See [the user guide](./USER_GUIDE.md) for instructions on operating CrossPoint.
Multi-language support: Read EPUBs in various languages, including English, Spanish, French, German, Italian, Portuguese, Russian, Ukrainian, Polish, Swedish, Norwegian, [and more](./USER_GUIDE.md#supported-languages).
See [the user guide](./USER_GUIDE.md) for instructions on operating CrossPoint.
For more details about the scope of the project, see the [SCOPE.md](SCOPE.md) document.
## Installing
@@ -56,7 +60,7 @@ back to the other partition using the "Swap boot partition" button here https://
### Web (specific firmware version)
1. Connect your Xteink X4 to your computer via USB-C
2. Download the `firmware.bin` file from the release of your choice via the [releases page](https://github.com/daveallie/crosspoint-reader/releases)
2. Download the `firmware.bin` file from the release of your choice via the [releases page](https://github.com/crosspoint-reader/crosspoint-reader/releases)
3. Go to https://xteink.dve.al/ and flash the firmware file using the "OTA fast flash controls" section
To revert back to the official firmware, you can flash the latest official firmware from https://xteink.dve.al/, or swap
@@ -80,7 +84,7 @@ See [Development](#development) below.
CrossPoint uses PlatformIO for building and flashing the firmware. To get started, clone the repository:
@@ -131,9 +154,12 @@ For more details on the internal file structures, see the [file formats document
Contributions are very welcome!
If you're looking for a way to help out, take a look at the [ideas discussion board](https://github.com/daveallie/crosspoint-reader/discussions/categories/ideas).
If you're looking for a way to help out, take a look at the [ideas discussion board](https://github.com/crosspoint-reader/crosspoint-reader/discussions/categories/ideas).
If there's something there you'd like to work on, leave a comment so that we can avoid duplicated effort.
Everyone here is a volunteer, so please be respectful and patient. For more details on our goverance and community
principles, please see [GOVERNANCE.md](GOVERNANCE.md).
@@ -81,6 +84,18 @@ See the [webserver docs](./docs/webserver.md) for more information on how to con
> [!TIP]
> Advanced users can also manage files programmatically or via the command line using `curl`. See the [webserver docs](./docs/webserver.md) for details.
### 3.4.1 Calibre Wireless Transfers
CrossPoint supports sending books from Calibre using the CrossPoint Reader device plugin.
1. Install the plugin in Calibre:
- Head to https://github.com/crosspoint-reader/calibre-plugins/releases to download the latest version of the crosspoint_reader plugin.
- Download the zip file.
- Open Calibre → Preferences → Plugins → Load plugin from file → Select the zip file.
2. On the device: File Transfer → Connect to Calibre → Join a network.
3. Make sure your computer is on the same WiFi network.
4. In Calibre, click "Send to device" to transfer books.
### 3.5 Settings
The Settings screen allows you to configure the device's behavior. There are a few settings you can adjust:
@@ -90,13 +105,21 @@ The Settings screen allows you to configure the device's behavior. There are a f
- "Custom" - Custom images from the SD card; see [Sleep Screen](#36-sleep-screen) below for more information
- "Cover" - The book cover image (Note: this is experimental and may not work as expected)
- "None" - A blank screen
- "Cover + Custom" - The book cover image, fallbacks to "Custom" behavior
- **Sleep Screen Cover Mode**: How to display the book cover when "Cover" sleep screen is selected:
- "Fit" (default) - Scale the image down to fit centered on the screen, padding with white borders as necessary
- "Crop" - Scale the image down and crop as necessary to try to to fill the screen (Note: this is experimental and may not work as expected)
- **Sleep Screen Cover Filter**: What filter will be applied to the book cover when "Cover" sleep screen is selected
- "None" (default) - The cover image will be converted to a grayscale image and displayed as it is
- "Contrast" - The image will be displayed as a black & white image without grayscale conversion
- "Inverted" - The image will be inverted as in white&black and will be displayed without grayscale conversion
- **Status Bar**: Configure the status bar displayed while reading:
- "None" - No status bar
- "No Progress" - Show status bar without reading progress
- "Full" - Show status bar with reading progress
- "Full w/ Percentage" - Show status bar with book progress (as percentage)
- "Full w/ Book Bar" - Show status bar with book progress (as bar)
- "Book Bar Only" - Show book progress (as bar)
- "Full w/ Chapter Bar" - Show status bar with chapter progress (as bar)
- **Hide Battery %**: Configure where to suppress the battery pecentage display in the status bar; the battery icon will still be shown:
- "Never" - Always show battery percentage (default)
- "In Reader" - Show battery percentage everywhere except in reading mode
@@ -116,6 +139,7 @@ The Settings screen allows you to configure the device's behavior. There are a f
- Back, Confirm, Left, Right (default)
- Left, Right, Back, Confirm
- Left, Back, Confirm, Right
- Back, Confirm, Right, Left
- **Side Button Layout (reader)**: Swap the order of the up and down volume buttons from Previous/Next to Next/Previous. This change is only in effect when reading.
- **Long-press Chapter Skip**: Set whether long-pressing page turn buttons skip to the next/previous chapter.
- "Chapter Skip" (default) - Long-pressing skips to next/previous chapter
@@ -131,7 +155,10 @@ The Settings screen allows you to configure the device's behavior. There are a f
- **Reader Paragraph Alignment**: Set the alignment of paragraphs; options are "Justified" (default), "Left", "Center", or "Right".
- **Time to Sleep**: Set the duration of inactivity before the device automatically goes to sleep.
- **Refresh Frequency**: Set how often the screen does a full refresh while reading to reduce ghosting.
- **Calibre Settings**: Set up integration for accessing a Calibre web library or connecting to Calibre as a wireless device.
- **Sunlight Fading Fix**: Configure whether to enable a software-fix for the issue where white X4 models may fade when used in direct sunlight
- "OFF" (default) - Disable the fix
- "ON" - Enable the fix
- **OPDS Browser**: Configure OPDS server settings for browsing and downloading books. Set the server URL (for Calibre Content Server, add `/opds` to the end), and optionally configure username and password for servers requiring authentication. Note: Only HTTP Basic authentication is supported. If using Calibre Content Server with authentication enabled, you must set it to use Basic authentication instead of the default Digest authentication.
- **Check for updates**: Check for firmware updates over WiFi.
### 3.6 Sleep Screen
@@ -177,6 +204,15 @@ This feature can be disabled in **[Settings](#35-settings)** to help avoid chang
* **Return to Home:** Press and **hold** the **Back** button to close the book and return to the **[Home](#31-home-screen)** screen.
* **Chapter Menu:** Press **Confirm** to open the **[Table of Contents/Chapter Selection](#5-chapter-selection-screen)**.
### Supported Languages
CrossPoint renders text using the following Unicode character blocks, enabling support for a wide range of languages:
***Cyrillic Script (Standard and Extended):** Covers Russian, Ukrainian, Belarusian, Bulgarian, Serbian, Macedonian, Kazakh, Kyrgyz, Mongolian, and others.
What is not supported: Chinese, Japanese, Korean, Vietnamese, Hebrew, Arabic, Greek and Farsi.
---
## 5. Chapter Selection Screen
@@ -194,3 +230,18 @@ Accessible by pressing **Confirm** while inside a book.
Please note that this firmware is currently in active development. The following features are **not yet supported** but are planned for future updates:
* **Images:** Embedded images in e-books will not render.
* **Cover Images:** Large cover images embedded into EPUB require several seconds (~10s for ~2000 pixel tall image) to convert for sleep screen and home screen thumbnail. Consider optimizing the EPUB with e.g. https://github.com/bigbag/epub-to-xtc-converter to speed this up.
---
## 7. Troubleshooting Issues & Escaping Bootloop
If an issue or crash is encountered while using Crosspoint, feel free to raise an issue ticket and attach the serial monitor logs. The logs can be obtained by connecting the device to a computer and starting a serial monitor. Either [Serial Monitor](https://www.serialmonitor.org/) or the following command can be used:
```
pio device monitor
```
If the device is stuck in a bootloop, press and release the Reset button. Then, press and hold on to the configured Back button and the Power Button to boot to the Home Screen.
There can be issues with broken cache or config. In this case, delete the `.crosspoint` directory on your SD card (or consider deleting only `settings.bin`, `state.bin`, or `epub_*` cache directories in the `.crosspoint/` folder).
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.