Compare commits

...

175 Commits

Author SHA1 Message Date
Xuan Son Nguyen c0a7088fcc passes = 1 2026-02-16 21:48:09 +01:00
Xuan Son Nguyen e79f86fa24 more resync 2026-02-16 11:13:34 +01:00
Xuan Son Nguyen fd933ba368 move requestResync to HAL 2026-02-16 10:56:40 +01:00
Justin Mitchell c14dc4c109 Fix scanning text in calibre and customize buttons for x3 2026-02-15 21:14:52 -05:00
Justin Mitchell cd4303a8fb Updates to X3-specific display and power button handling
Centralize display initialization and power button verification for X3 devices
2026-02-15 19:58:37 -05:00
Justin Mitchell 961a704aaa Revert platformio.ini to use open-x4-sdk submodule
Accidentally committed local community-sdk path.
2026-02-15 18:32:46 -05:00
Justin Mitchell 7061d054ef improves wake from sleep on x3 2026-02-13 19:30:15 -05:00
Justin Mitchell 39bf8a5609 clang formatting 2026-02-13 19:28:47 -05:00
Justin Mitchell a78897478f Fixes maintainer requests 2026-02-13 19:04:58 -05:00
Justin Mitchell 4f0a39ab03 Merge upstream/master into x3-support 2026-02-13 15:56:38 -05:00
Justin Mitchell d97a436a48 fixes wake from sleep being randomly not reliable 2026-02-13 15:53:42 -05:00
Justin Mitchell 6114b80e5d adds x3 commands for refresh types 2026-02-13 15:27:13 -05:00
Jake Kenneally 6e51afb977 fix: Account for nbsp; character as non-breaking space (#757)
## 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
2026-02-13 15:46:46 +01:00
jpirnay cb24947477 feat: Add central logging pragma (#843)
## 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>
2026-02-13 12:16:39 +01:00
jpirnay 7a385d78a4 feat: Allow screenshot retrieval from device (#820)
## 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
2026-02-13 02:31:15 +03:00
Justin Mitchell d4eb089e49 cleanup 2026-02-12 18:28:47 -05:00
Justin Mitchell 9a1548189c fixes battery reading on x3 2026-02-12 16:55:27 -05:00
Justin Mitchell cbea838f91 Initial support for the x3 2026-02-12 16:16:54 -05:00
Xuan-Son Nguyen 0991782fb4 feat: more power saving on idle (#801)
## 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**
2026-02-12 09:49:05 +01:00
jpirnay 3ae1007cbe fix: chore: make all debug messages uniform (#825)
## 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
2026-02-11 16:25:17 +01:00
Jonas Diemer efb9b72e64 fix: Show "Back" in file browser if not in root, "Home" otherwise. (#822)
## 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
2026-02-11 16:44:10 +03:00
Dave Allie 4a210823a8 fix: Manually trigger GPIO update in File Browser mode (#819)
## 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 -->
2026-02-11 13:42:37 +03:00
Jonas Diemer f5b85f5ca1 fix: Reduce MIN_SIZE_FOR_POPUP to 10KB (#809)
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
2026-02-10 16:15:23 +01:00
Jonas Diemer 7e93411f46 docs: Update USER_GUIDE.md (#817)
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
2026-02-10 23:23:14 +11:00
Dave Allie 44452a42e9 fix: Prevent sleeping when in OPDS browser / downloading books (#818)
## 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
2026-02-10 22:56:22 +11:00
jpirnay 0c2df24f5c feat: Extend python debugging monitor functionality (keyword filter / suppress) (#810)
## 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
2026-02-10 22:07:56 +11:00
Jonas Diemer 3a12ca2725 docs: Update USER_GUIDE.md (#808)
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
2026-02-10 22:04:32 +11:00
Eliz 98e6789626 feat: Connect to last wifi by default (#752)
## Summary

* **What is the goal of this PR?** 

Use last connected network as default

* **What changes are included?**

- Refactor how an action type of Settings are handled
- Add a new System Settings option → Network
- Add the ability to forget a network in the Network Selection Screen
- Add the ability to Refresh network list
- Save the last connected network SSID
- Use the last connection whenever network is needed (OPDS, Koreader
sync, update etc)

## Additional Context

* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
  specific areas to focus on).


![IMG_6504](https://github.com/user-attachments/assets/e48fb013-b5c3-45c0-b284-e183e6fd5a68)

![IMG_6503](https://github.com/user-attachments/assets/78c4b6b6-4e7b-4656-b356-19d65ff6aa12)




https://github.com/user-attachments/assets/95bf34a8-44ce-4279-8cd8-f78524ce745b





---

### AI Usage

Did you use AI tools to help write this code? _** PARTIALLY: I wrote
most of it but I also used Gemini as assist.

---------

Co-authored-by: Eliz Kilic <elizk@google.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-10 20:41:44 +11:00
ThatCrispyToast b5d28a3a9c feat: use natural sort in file browser (#722)
## 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**_
2026-02-10 01:09:24 +03:00
harshit181 14ef625679 fix: issue if book href are absolute url and not relative to server (#741)
## 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>**_
2026-02-09 22:12:21 +11:00
Istiak Tridip 64d161e88b feat: unify navigation handling with system-wide continuous navigation (#600)
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 🙏


![crosspoint](https://github.com/user-attachments/assets/6a3c7482-f45e-4a77-b156-721bb3b679e6)

---

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>
2026-02-09 20:19:34 +11:00
Fabio Barbon e73bb3213f feat: Add Italian hyphenation support (#584)
## 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>
2026-02-09 19:55:58 +11:00
Dave Allie 6202bfd651 Merge branch 'release/1.0.0' 2026-02-09 17:18:24 +11:00
Jake Kenneally 9e04eec072 feat: Add percentage support to CSS properties (#738)
## 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
2026-02-09 08:32:45 +11:00
Jake Kenneally 9b04c2ec76 feat: Add percentage support to CSS properties (#738)
## 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
2026-02-09 08:31:52 +11:00
Dave Allie def1094411 Use GITHUB_REF_NAME over GITHUB_HEAD_REF in release candidate workflow 2026-02-09 08:24:10 +11:00
Dave Allie ffddc2472b Use GITHUB_REF_NAME over GITHUB_HEAD_REF in release candidate workflow 2026-02-09 08:22:20 +11:00
Dave Allie 5765bbe821 Add release candidate workflow 2026-02-09 08:16:36 +11:00
Dave Allie 7538e55795 Move release candidate workflow to manual dispatch 2026-02-09 08:15:13 +11:00
Dave Allie 21e7d29286 fix: Allow OTA update from RC build to full release (#778)
## 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
2026-02-09 08:08:40 +11:00
Dave Allie b4b028be3a fix: Allow OTA update from RC build to full release (#778)
## 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
2026-02-09 08:08:19 +11:00
Yaroslav f34d7d2aac fix(ui): Add Back label in KOReader Sync screen (#770)
## Summary

- Remove duplicate Cancel option 
- Add Back label

<img width="435" height="613" alt="image"
src="https://github.com/user-attachments/assets/a3af4133-46fa-46e6-8360-a15dd7c4fe2a"
/>


## Result

<img width="575" height="431" alt="image"
src="https://github.com/user-attachments/assets/6ccdac89-43df-45bf-bcfa-3a7cc4bd88e4"
/>


---

### AI Usage

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

Closes #754
2026-02-09 07:51:51 +11:00
Justin Mitchell 71769490fb fix: Add EPUB 3 cover image detection (#760)
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
2026-02-09 07:49:49 +11:00
Jesse Vincent cda0a3f898 feat: A web editor for settings (#667)
## 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>
2026-02-09 07:46:14 +11:00
Xuan-Son Nguyen 7f40c3f477 feat: add HalStorage (#656)
## 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
2026-02-09 07:29:14 +11:00
Jake Kenneally 5e52a46837 refactor: Rename "Embedded Style" to "Book's Embedded Style" (#746)
## 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**_
2026-02-09 05:12:33 +11:00
Xuan-Son Nguyen 6909f127b4 perf: optimize drawPixel() (#748)
## 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**
2026-02-09 05:07:35 +11:00
Arthur Tazhitdinov 4f0a3aa4dd feat: wakeup target detection (#731)
## Summary

* If going to sleep was from the Reader view, wake up to the same book.
Otherwise, wakeup to the Home view
2026-02-09 05:07:32 +11:00
CaptainFrito bb983d0ef4 fix: Scrolling page items calculation (#716)
## 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**_
2026-02-09 05:07:23 +11:00
Xuan-Son Nguyen b45eaf7ded feat: optimize fillRectDither (#737)
## 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**
2026-02-09 05:07:13 +11:00
Xuan-Son Nguyen a87eacc6ab perf: optimize drawPixel() (#748)
## 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**
2026-02-09 05:05:42 +11:00
Arthur Tazhitdinov 1caad578fc feat: wakeup target detection (#731)
## Summary

* If going to sleep was from the Reader view, wake up to the same book.
Otherwise, wakeup to the Home view
2026-02-09 05:01:30 +11:00
James Whyte 75b0ed7781 fix: increase lyra sideButtonHintsWidth to 30 (#727)
## Summary

Increase the width of Lyra's side button hints. It has been set to 30,
the same width as the classic theme.


Before:
<img width="457" height="742" alt="image"
src="https://github.com/user-attachments/assets/316e4679-fbf0-4f6e-b117-413075da1be2"
/>

After:
<img width="512" height="849" alt="image"
src="https://github.com/user-attachments/assets/3b0cf069-55ad-4d5a-a93c-4aeca3ff67f8"
/>



## Additional Context

Resolves
https://github.com/crosspoint-reader/crosspoint-reader/pull/700#issuecomment-3856983832

---

### 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
2026-02-09 05:00:09 +11:00
CaptainFrito 5b90b68e99 fix: Scrolling page items calculation (#716)
## 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**_
2026-02-09 04:58:46 +11:00
Jake Kenneally 67ddd60fce refactor: Rename "Embedded Style" to "Book's Embedded Style" (#746)
## 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**_
2026-02-08 20:34:06 +03:00
Xuan-Son Nguyen 76908d38e1 feat: optimize fillRectDither (#737)
## 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**
2026-02-08 14:59:13 +03:00
Arthur Tazhitdinov e6f5fa43e6 feat(ux): invert BACK button behavior in reader activities (#726)
## 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.
2026-02-07 10:17:00 -05:00
James Whyte e7e31ac487 fix: increase lyra sideButtonHintsWidth to 30 (#727)
## Summary

Increase the width of Lyra's side button hints. It has been set to 30,
the same width as the classic theme.


Before:
<img width="457" height="742" alt="image"
src="https://github.com/user-attachments/assets/316e4679-fbf0-4f6e-b117-413075da1be2"
/>

After:
<img width="512" height="849" alt="image"
src="https://github.com/user-attachments/assets/3b0cf069-55ad-4d5a-a93c-4aeca3ff67f8"
/>



## Additional Context

Resolves
https://github.com/crosspoint-reader/crosspoint-reader/pull/700#issuecomment-3856983832

---

### 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
2026-02-07 10:15:41 -05:00
Jake Kenneally 47f3137dee fix: Remove separations after style changes (#720)
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
2026-02-06 19:19:31 +11:00
CaptainFrito d8632eae08 fix: Lag before displaying covers on home screen (#721)
## 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 **_
2026-02-06 19:19:27 +11:00
Jake Kenneally 9f78fd33e8 fix: Remove separations after style changes (#720)
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
2026-02-06 19:10:37 +11:00
CaptainFrito bd8132a260 fix: Lag before displaying covers on home screen (#721)
## 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 **_
2026-02-06 18:58:32 +11:00
Jake Kenneally 3223e85ea5 feat: Add Settings for toggling CSS on or off (#717)
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

![IMG_6336](https://github.com/user-attachments/assets/dff619ef-986d-465e-b352-73a76baae334)


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
2026-02-06 18:50:24 +11:00
Jake Kenneally f89ce514c8 feat: Add Settings for toggling CSS on or off (#717)
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

![IMG_6336](https://github.com/user-attachments/assets/dff619ef-986d-465e-b352-73a76baae334)


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
2026-02-06 18:49:04 +11:00
Dave Allie 211153fcd5 Use GITHUB_HEAD_REF 2026-02-06 03:49:00 +11:00
Dave Allie 91777a9023 release: 1.0.0 2026-02-06 03:18:47 +11:00
Dave Allie d8e813a78d chore: Swap logo (#699)
## 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
2026-02-06 02:50:01 +11:00
Luke Stein c3b9bc38b9 feat: Add Chapter Progress Bar status bar option (#636)
## 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>
2026-02-06 02:49:38 +11:00
danoob fb0af32ec0 feat: Move Sync feature to menu (#680)
## 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>
2026-02-06 02:04:38 +11:00
Jake Kenneally cb4d86fec6 fix: prevent spurious spaces before attaching punctuation (#694)
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
2026-02-06 01:55:15 +11:00
Jonas Diemer e94f056e8a fix: debug printf of cover name (#690)
## 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
2026-02-06 00:48:07 +11:00
James Whyte 20c5d8ccf8 feat: add shift lock to KeyboardEntryActivity (#513)
## 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**_
2026-02-06 00:02:43 +11:00
Matthías Páll Gissurarson d35bda8023 feat: rename and move in file manager (#630)
## 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.
2026-02-05 23:56:00 +11:00
Maik Allgöwer d762325035 feat: Implement fix for sunlight fading issue (#603)
## 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>
2026-02-05 23:32:05 +11:00
Dave Allie 7f2b1a818e chore: Add PR title check on sync (#698)
## 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
2026-02-05 23:29:53 +11:00
Arthur Tazhitdinov ddbe49f536 feat: Go To Position for epubs (#666)
## 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>
2026-02-05 23:17:51 +11:00
Fabio Barbon 17fedd2a69 feat: Calibre Web Automated (CWA) koreader sync server support (#594)
## 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>
2026-02-05 23:10:08 +11:00
Dave Allie 768c2f8eed chore: Add CI check job to consolidate status (#696)
## 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
2026-02-05 23:08:16 +11:00
Arthur Tazhitdinov 216dbc8ee3 chore: CI Build Summary - firmware stats, firmware artifact (#601)
## Summary

* adds to the Action Summary firmware RAM and Flash usage
* splits cppcheck, clang-format and build into separate jobs, more
apparent what had failed.
* attaches the built artifact (firmware.bin) to the Action Summary for
easier testing.


<img width="853" height="456" alt="image"
src="https://github.com/user-attachments/assets/61d21c3c-58c2-42f3-8d8e-4cbedcf193e9"
/>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-05 23:00:18 +11:00
Arthur Tazhitdinov ee987f07ff feat: quick rotate option in epub reader menu (#685)
## 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  >**_
2026-02-05 22:53:35 +11:00
Егор Мартынов 23ecc52261 feat(settings): add "Cover + Custom" sleep screen mode (#582)
## 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>
2026-02-05 22:46:14 +11:00
Jonas Diemer edaf8fff9d fix: Artifacts on Thumb on Home Screen (#662)
## 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
2026-02-05 22:45:56 +11:00
GenesiaW c8683340ab feat: holding back button while booting, boots to home screen as a mean of escaping boot loop (#587)
## 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>
2026-02-05 22:45:09 +11:00
Dave Allie 5a9ee19eb8 docs: Add small SCOPE.md and GOVERNANCE.md documents (#640)
## 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
2026-02-05 22:38:42 +11:00
Arthur Tazhitdinov c49a819939 feat: front button remapper (#664)
## Summary

* Custom remapper to create any variant of front button layout.

## Additional Context

* Included migration from previous frontlayout setting
* This will solve:
    *  https://github.com/crosspoint-reader/crosspoint-reader/issues/654
    * https://github.com/crosspoint-reader/crosspoint-reader/issues/652
    * https://github.com/crosspoint-reader/crosspoint-reader/issues/620
    * https://github.com/crosspoint-reader/crosspoint-reader/issues/468

<img width="860" height="1147" alt="image"
src="https://github.com/user-attachments/assets/457356ed-7a7d-4e1c-8683-e187a1df47c0"
/>



---

### 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-02-05 22:37:17 +11:00
CaptainFrito bf87a7dc60 feat: UI themes, Lyra (#528)
## 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

![IMG_7649
Medium](https://github.com/user-attachments/assets/b516f5a9-2636-4565-acff-91a25b93b39b)
![IMG_7746
Medium](https://github.com/user-attachments/assets/def41810-ab6e-4952-b40f-b9ce7d62bea8)
![IMG_7651
Medium](https://github.com/user-attachments/assets/518a9a6d-107a-4be3-9533-43a2b64b944b)



## 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>
2026-02-05 21:50:11 +11:00
Jake Kenneally 2cf799f45b feat: Add CSS parsing and CSS support in EPUBs (#411)
## 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

![IMG_6271](https://github.com/user-attachments/assets/dba7554d-efb6-4d13-88bc-8b83cd1fc615)

![IMG_6272](https://github.com/user-attachments/assets/61ba2de0-87c9-4f39-956f-013da4fe20a4)

### After

![IMG_6268](https://github.com/user-attachments/assets/ebe11796-cca9-4a46-b9c7-0709c7932818)

![IMG_6269](https://github.com/user-attachments/assets/e89c33dc-ff47-4bb7-855e-863fe44b3202)

---

### AI Usage

Did you use AI tools to help write this code? **YES**, Claude Code
2026-02-05 21:28:10 +11:00
Xuan-Son Nguyen db659f3ea2 fix: move http upload state to heap (#657)
## 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
2026-02-05 21:03:19 +11:00
Jake Kenneally 78d6e5931c fix: Correct debugging_monitor.py script instructions (#676)
## 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 >**_
2026-02-04 00:33:20 +03:00
Luke Stein dac11c3fdd fix: Correct instruction text to match actual button text (#672)
## 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**
2026-02-04 00:32:52 +03:00
Aaron Cunliffe d403044f76 fix: Increase network SSID display length (#670)
## 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 >**_
2026-02-03 18:24:23 +03:00
Aaron Cunliffe f67c544e16 fix: webserver folder creation regex change (#653)
## 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 >**_
2026-02-02 21:27:02 +11:00
Uri Tauber e5c0ddc9fa feat: Debugging monitor script (#555)
## 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.
2026-02-01 22:53:20 +11:00
Arthur Tazhitdinov b1dcb7733b fix: truncating chapter titles using UTF-8 safe function (#599)
## 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 >**_
2026-02-01 22:23:48 +11:00
Arthur Tazhitdinov 0d82b03981 fix: don't wake up after USB connect (#644)
## Summary

* fixes problem that if short power button press is enabled, connecting
device to usb leads to waking up
2026-02-01 22:19:33 +11:00
Dave Allie 5a97334ace Revert "fix: don't wake up after USB connect" (#643)
Reverts crosspoint-reader/crosspoint-reader#576

Causing a boot loop on master
2026-02-01 21:35:25 +11:00
Gaspar Fabrega Ragni 4dd73a211a fix: custom sleep not showing image at index 0 (#639)
## 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>
2026-02-01 19:22:52 +11:00
Thomas Foskolos 634f6279cb docs: Update USER_GUIDE.md (#625)
Add Greek as not supported language atm on the use guide
2026-02-01 19:21:36 +11:00
nscheung 11b2a59233 fix: Hide button hints in landscape CW mode (#637)
## Summary

* This change hides the button hints from overlapping chapter titles
when in landscape CW mode.

Before

![Before](https://github.com/user-attachments/assets/3015a9b3-3fa5-443b-a641-3e65841a6fbc)
After

![After](https://github.com/user-attachments/assets/011de15d-5ae6-429c-8f91-d8f37abe52d9)

## 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 >
2026-02-01 19:21:28 +11:00
Luke Stein 12c20bb09e fix: WiFi error screen text clarifications (#612)
## 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**
2026-02-01 19:19:23 +11:00
Arthur Tazhitdinov 6b7065b986 fix: don't wake up after USB connect (#576)
## Summary

* fixes problem that if short power button press is enabled, connecting
device to usb leads to waking up
2026-02-01 18:51:31 +11:00
Arthur Tazhitdinov f4df513bf3 feat(ui): change popup logic (#442)
## 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>**_
2026-02-01 18:41:24 +11:00
Jonas Diemer f935b59a41 feat: Add reading menu and delete cache function (#433)
## 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**_
2026-02-01 18:34:30 +11:00
Xuan-Son Nguyen da4d3b5ea5 feat: add HalDisplay and HalGPIO (#522)
## 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**
2026-01-28 04:50:15 +11:00
Eliz 172916afd4 feat: Display epub metadata on Recents (#511)
* **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>
2026-01-28 04:25:42 +11:00
Dave Allie ebcd813ff6 chore: Cut release 0.16.0 2026-01-28 04:08:04 +11:00
Dave Allie 712c566664 fix: Correctly render italics on image alt placeholders (#569)
## 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
2026-01-28 03:33:36 +11:00
Boris Faure 5894ae5afe chore: .gitignore: add compile_commands.json & .cache (#568)
## 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**_
2026-01-28 03:32:33 +11:00
Dave Allie 8c1c80787a fix: Render keyboard entry over multiple lines (#567)
## Summary

* Render keyboard entry over multiple lines
  * Grows display areas based on input text
  * Shown on OPDS entry, but applies everywhere

## Additional Context

* Fixes
https://github.com/crosspoint-reader/crosspoint-reader/issues/554

| One line | Multi-line |
| --- | --- |
|
![IMG_5925](https://github.com/user-attachments/assets/28be00a8-7b90-4bf6-9ebf-4d4ad6642bc9)
|
![IMG_5926](https://github.com/user-attachments/assets/1c69a96f-d868-49a1-866c-546ca7b784ab)
|

---

### 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
2026-01-28 02:43:04 +11:00
Arthur Tazhitdinov 140fcb9db5 fix: missing front layout in mapLabels() (#564)
## Summary

* adds missing front layout to mapLabels function
2026-01-28 02:09:05 +11:00
V e0b6b9b28a refactor: Re-work for OTA feature (#509)
## 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 >**_
2026-01-28 01:30:27 +11:00
Daniel Chelling 83315b6179 perf: optimize large EPUB indexing from O(n^2) to O(n) (#458)
## 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._
2026-01-28 01:29:15 +11:00
Lalo 8e0d2bece2 feat: Add Spanish hyphenation support (#558)
## 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
2026-01-28 01:17:48 +11:00
Eliz 4848a77e1b feat: Add support to B&W filters to image covers (#476)
## Summary

* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
Implementation of a new feature in Display options as Image Filter
* **What changes are included?**
Black & White and Inverted Black & White options are added.

## Additional Context

Here are some examples:

| None | Contrast | Inverted |
| --- | --- | --- |
| <img alt="image"
src="https://github.com/user-attachments/assets/fe02dd9b-f647-41bd-8495-c262f73177c4"
/> | <img alt="image"
src="https://github.com/user-attachments/assets/2d17747d-3ff6-48a9-b9b9-eb17cccf19cf"
/> | <img alt="image"
src="https://github.com/user-attachments/assets/792dea50-f003-4634-83fe-77849ca49095"
/> |
| <img alt="image"
src="https://github.com/user-attachments/assets/28395b63-14f8-41e2-886b-8ddf3faeafc4"
/> | <img alt="image"
src="https://github.com/user-attachments/assets/71a569c8-fc54-4647-ad4c-ec96e220cddb"
/> | <img alt="image"
src="https://github.com/user-attachments/assets/9139e32c-9175-433e-8372-45fa042d3dc9"
/> |



* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
  specific areas to focus on).

I have also tried adding Color inversion, but could not see much
difference with that. It might be because my implementation was wrong.

---

### 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: Dave Allie <dave@daveallie.com>
2026-01-28 00:21:59 +11:00
Arthur Tazhitdinov 49190cca6d feat(ux): page turning on button pressed if long-press chapter skip is disabled (#451)
## 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>
2026-01-27 23:53:13 +11:00
Alex Faria e9c2fe1c87 feat: Add status bar option "Full w/ Progress Bar" (#438)
## 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**_
2026-01-27 23:25:44 +11:00
Jonas Diemer dd1741bf0b fix: Validate settings on read. (#492)
## 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>
2026-01-27 23:08:58 +11:00
Maeve Andrews 51c5c3c0aa fix: rotate origin in drawImage (#557)
## 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>
2026-01-27 22:59:41 +11:00
Dave Allie 5e24895f6d feat: Extract author from XTC/XTCH files (#563)
## 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
2026-01-27 22:56:51 +11:00
Егор Мартынов e2ca0e94ca fix: add txt books to recent tab (#526)
Fixes #512

---

### AI Usage

 _**NO**_
2026-01-27 22:53:31 +11:00
Boris Faure a4b9a43ca1 docs: add font generation commands to builtin font headers (#547)
## 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**_
2026-01-27 22:19:19 +11:00
Yaroslav c73fca26f5 docs: Update README with supported languages for EPUB (#530)
## 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**_
2026-01-27 22:14:32 +11:00
Carson Hicks dfd7b615dc fix: Fix KOReader document md5 calculation for binary matching progress sync (#529)
## 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**_
2026-01-27 22:14:07 +11:00
Jonas Diemer aca6dceaa8 fix: Make sure img alt text is treated as separate text block (#497)
## 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**_
2026-01-27 22:12:40 +11:00
GenesiaW 6ca75c4653 fix: goes to relative position when reader settings are changed (#486)
## 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**_
2026-01-27 22:11:11 +11:00
Xuan-Son Nguyen 1b9c8ab545 fix: short-press power button to wakeup (#482)
## 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>
2026-01-27 22:07:37 +11:00
Vincent Politzer bf6cf83577 fix: line break (#525)
## 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**_
2026-01-27 22:07:02 +11:00
Justin Mitchell 3a761b18af Refactors Calibre Wireless Device & Calibre Library (#404)
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>
2026-01-27 22:02:38 +11:00
Brendan O'Leary 13f0ebed96 UX improvment to Forget Network page (#484)
## 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
2026-01-27 21:26:17 +11:00
Arthur Tazhitdinov 0bc0baa966 feat: treat .md files as .txt (#498)
## Summary

* Quick fix for markdown reading - open them as txt files
2026-01-27 21:25:48 +11:00
Luke Stein 5d369df6be fix: Chapter Selection UI bugs when koreader sync is enabled, and clarify default kosync URL (#501)
## 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_
2026-01-27 21:25:25 +11:00
Sam Davis b8ebcf5867 fix: remove decimal places from progress % (#507)
## 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
2026-01-27 21:24:39 +11:00
Boris Faure e858ebbe88 feat: add new configuration for front buttons, more usable on landscape ccw (#460)
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**_
2026-01-27 21:15:42 +11:00
Jonas Diemer 9224bc3f8c fix: #348 fit cover artifacts 2 (#465)
Supersedes #358 and includes the bugfix from #351
2026-01-27 20:21:15 +11:00
Yaroslav 67a679ab41 fix: Add .vs folder to .gitignore (#466)
## Summary

* Adds Visual Studio project files folder to .gitignore

Otherwise:

<img width="425" height="193" alt="image"
src="https://github.com/user-attachments/assets/522d6eec-40c2-45d1-92af-01b0ec8f0dc1"
/>
2026-01-27 20:20:48 +11:00
Luke Stein 7a53342f9d fix: Allow line break after ellipsis and underscore (#425)
## 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."


![IMG_2917](https://github.com/user-attachments/assets/8fa610a9-91dd-407f-8526-0019a8a7195f)

---

### 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
Dave Allie 3ce11f14ce chore: Cut release 0.15.0 2026-01-22 02:20:22 +11:00
KasyanDiGris 47ef92e8fd fix: OPDS browser OOM (#403)
## Summary

- Rewrite OpdsParser to stream parsing instead of full content
- Fix OOM due to big http xml response

Closes #385 

---

### 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**_
2026-01-22 01:43:51 +11:00
Juan Biondi e3d6e32609 docs: Add detailed webserver documentation (#446)
## More detailed documentation

* **What is the goal of this PR?** 
Add more information about the exposed webserver.
* **What changes are included?**
Detailed documentation for the webserver endpoints
(`./docs/webserver-endpoints.md`)
Adding a table of content so it is easier to navigate directly to the
section you're interested on (Almost all `.md` files or at least all
those relevant)

## Additional Context

Not sure if this would get accepted but I thought it might be useful for
those trying to create separate apps that would sync files to the
device. It was at least to me trying to upload files using python as
stated
[here](https://github.com/crosspoint-reader/crosspoint-reader/discussions/434#discussioncomment-15545349)

---

### 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-22 00:29:39 +11:00
Logan Garbarini d399afb53d feat: invalidate cache on web uploads and opds downloads and add Clear Cache action (#393)
## Summary

When uploading or downloading an updated ebook from SD/WebUI/OPDS with
same the filename the `.crosspoint` cache is not cleared. This can lead
to issues with the Table of Contents and hangs when switching between
chapters.

I encountered this issue in two places:
- When I need to do further ePub cleaning using Calibre after I load an
ePub and find that some of its formatting should be cleaned up. When I
reprocess the same book and want to place it back in the same location I
need a way to invalidate the cache.
- When syncing RSS feed generated epubs. I generate news ePubs with
filenames like `news-outlet.epub` and so every day when I fetch new news
the crosspoint cache needs to be cleared to load that file.

This change offers the following features:
- On web uploads, if the file already exists, the cache for that file is
cleared
- On OPDS downloads, if the file already exists, the cache for that file
is cleared
- There's now an action for `Clear Cache` in the Settings page which can
clear the cache for all books


Addresses
https://github.com/crosspoint-reader/crosspoint-reader/issues/281

---

### 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: Dave Allie <dave@daveallie.com>
2026-01-22 00:06:07 +11:00
Arthur Tazhitdinov 838993259d fix: hard reset via RTS pin after flashing firmware (#437)
## Summary

* Disables going to sleep after uploading new firmware
* Makes developer experience easier

---

### 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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-21 23:35:23 +11:00
Jonas Diemer cc74039cab fix: Skip negative screen coordinates only after we read the bitmap row. (#431)
Otherwise, we don't crop properly.

Fixes #430 

### AI Usage

Did you use AI tools to help write this code? _**< NO >**_
2026-01-21 23:27:41 +11:00
Jonas Diemer 87d6c032a5 Reclaim space if we don't show battery Percentage (#352)
## Summary

Give space to the chapter title if we don't show battery percentage.

---

### 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>
2026-01-21 12:09:48 +00:00
Dave Allie c9b5462370 feat: Include superscripts and subscripts in fonts (#463)
## Summary

* Include superscripts and subscripts in fonts

## Additional Context

* Original change came from
https://github.com/crosspoint-reader/crosspoint-reader/pull/248

---

### 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: cor <cor@pruijs.dev>
2026-01-21 22:42:41 +11:00
Kenneth e548bfc0e1 My Library: Tab bar w/ Recent Books + File Browser (#250)
# Summary

This PR introduces a reusable Tab Bar component and combines the Recent
Books and File Browser into a unified tabbed page called "My Library"
accessible from the Home screen.

## Features
### New Tab Bar Component
A flexible, reusable tab bar component added to `ScreenComponents` that
can be used throughout the application.

### New Scroll Indicator Component
A page position indicator for lists that span multiple pages.
**Features:**
- Up/down arrow indicators
- Current page fraction display (e.g., "1/3")
- Only renders when content spans multiple pages

### My Library Activity
A new unified view combining Recent Books and File Browser into a single
tabbed page.

**Tabs:**
- **Recent** - Shows recently opened books
- **Files** - Browse SD card directory structure

**Navigation:**
- Up/Down or Left/Right: Navigate through list items
- Left/Right (when first item selected): Switch between tabs
- Confirm: Open selected book or enter directory
- Back: Go up directory (Files tab) or return home
- Long press Back: Jump to root directory (Files tab)

**UI Elements:**
- Tab bar with selection indicator
- Scroll/page indicator on right side
- Side button hints (up/down arrows)
- Dynamic bottom button labels ("BACK" in subdirectories, "HOME" at
root)

## Tab Bar Usage
The tab bar component is designed to be reusable across different
activities. Here's how to use it:

### Basic Example
```cpp
#include "ScreenComponents.h"
void MyActivity::render() const {
  renderer.clearScreen();
  
  // Define tabs with labels and selection state
  std::vector<TabInfo> tabs = {
    {"Tab One", currentTab == 0},   // Selected when currentTab is 0
    {"Tab Two", currentTab == 1},   // Selected when currentTab is 1
    {"Tab Three", currentTab == 2}  // Selected when currentTab is 2
  };
  
  // Draw tab bar at Y position 15, returns height of the tab bar
  int tabBarHeight = ScreenComponents::drawTabBar(renderer, 15, tabs);
  
  // Position your content below the tab bar
  int contentStartY = 15 + tabBarHeight + 10; // Add some padding
  
  // Draw content based on selected tab
  if (currentTab == 0) {
    renderTabOneContent(contentStartY);
  } else if (currentTab == 1) {
    renderTabTwoContent(contentStartY);
  } else {
    renderTabThreeContent(contentStartY);
  }
  
  renderer.displayBuffer();
}
```
Video Demo: https://share.cleanshot.com/P6NBncFS

<img width="250"
src="https://github.com/user-attachments/assets/07de4418-968e-4a88-9b42-ac5f53d8a832"
/>
<img width="250"
src="https://github.com/user-attachments/assets/e40201ed-dcc8-4568-b008-cd2bf13ebb2a"
/>
<img width="250"
src="https://github.com/user-attachments/assets/73db269f-e629-4696-b8ca-0b8443451a05"
/>

---------

Co-authored-by: Dave Allie <dave@daveallie.com>
2026-01-21 11:38:38 +00:00
Daniel Poulter 73c30748d8 feat: adding categories to settings screen (#331)
## Summary

* **What is the goal of this PR?** (e.g., Fixes a bug in the user
authentication module, Implements the new feature for
  file uploading.)

As we get more settings, I think it makes sense to do categories for
them. This just allows users to find the settings easier and navigate to
them.

* **What changes are included?**

## Additional Context

* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks, specific areas to
focus on).

Co-authored-by: dpoulter <daniel@yoco.com>
Co-authored-by: Dave Allie <dave@daveallie.com>
2026-01-21 11:13:51 +00:00
GenesiaW 6d68466891 fix: truncate chapter names that are too long (#422)
## Summary

* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
- Implements a fix to truncate chapter names that exceeds display width
 
* **What changes are included?**
- Implements a fix to truncate chapter names that exceeds display width
## Additional Context

* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
  specific areas to focus on).
- Prior to the fix, if the book contains multiple chapters with names
longer than the display width, there is a noticeable delay when
scrolling through the list of chapters.

Serial output of the issue:
```
[25673] [ACT] Entering activity: EpubReaderChapterSelection
[25693] [GFX] !! Outside range (485, 65) -> (65, -6)
[25693] [GFX] !! Outside range (486, 65) -> (65, -7)
[25693] [GFX] !! Outside range (487, 65) -> (65, -8)
[25693] [GFX] !! Outside range (488, 65) -> (65, -9)
[25693] [GFX] !! Outside range (485, 66) -> (66, -6)
[25693] [GFX] !! Outside range (486, 66) -> (66, -7)
[25694] [GFX] !! Outside range (487, 66) -> (66, -8)
[25694] [GFX] !! Outside range (484, 67) -> (67, -5)
[25694] [GFX] !! Outside range (485, 67) -> (67, -6)
[25694] [GFX] !! Outside range (486, 67) -> (67, -7)
[25694] [GFX] !! Outside range (483, 68) -> (68, -4)
[25694] [GFX] !! Outside range (484, 68) -> (68, -5)
[25694] [GFX] !! Outside range (485, 68) -> (68, -6)
``` 


---

### 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>
2026-01-19 13:01:51 +00:00
Arthur Tazhitdinov 8824c87490 feat: dict based Hyphenation (#305)
## Summary

* Adds (optional) Hyphenation for English, French, German, Russian
languages

## Additional Context

* Included hyphenation dictionaries add approximately 280kb to the flash
usage (German alone takes 200kb)
* Trie encoded dictionaries are adopted from hypher project
(https://github.com/typst/hypher)
* Soft hyphens (and other explicit hyphens) take precedence over
dict-based hyphenation. Overall, the hyphenation rules are quite
aggressive, as I believe it makes more sense on our smaller screen.

---------

Co-authored-by: Dave Allie <dave@daveallie.com>
2026-01-19 12:56:26 +00:00
Maeve Andrews 5fef99c641 fix: render U+FFFD replacement character instead of ? (#366)
The current behavior of rendering `?` for an unknown Unicode character
can be hard to distinguish from a typo. Use the standard Unicode
"replacement character" instead, that's what it's designed for:

https://en.wikipedia.org/wiki/Specials_(Unicode_block)

I'm making this PR as a draft because I'm not sure I did everything that
was needed to change the character set covered by the fonts. Running
that script is in its own commit. If this is proper, I'll rebase/squash
into one commit and un-draft.

Co-authored-by: Maeve Andrews <maeve@git.mail.maeveandrews.com>
2026-01-19 22:58:43 +11:00
Luke Stein 7a792a5384 fix: Invert colors on home screen cover overlay when recent book is selected (#390)
## Summary

* Fixes #388 

## Additional Context

* Tested on my own device
  * See images at #388 for what home screen looked like before.
* With this PR the home screen shows the following (selected and
unselected recent book × cover image rendered or not)


![Picsew_20260115153419](https://github.com/user-attachments/assets/44193f9d-76b7-4c77-b890-72b0dbae01c4)


---

### 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: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-01-19 22:57:39 +11:00
Justin Mitchell f69cddf2cc Adds KOReader Sync support (#232)
## Summary

- Adds KOReader progress sync integration, allowing CrossPoint to sync
reading positions with other
KOReader-compatible devices
- Stores credentials securely with XOR obfuscation
- Uses KOReader's partial MD5 document hashing for cross-device book
matching
  - Syncs position via percentage with estimated XPath for compatibility

# Features
- Settings: KOReader Username, Password, and Authenticate options
- Sync from chapters menu: "Sync Progress" option appears when
credentials are configured
- Bidirectional sync: Can apply remote progress or upload local progress

---------

Co-authored-by: Dave Allie <dave@daveallie.com>
2026-01-19 11:55:35 +00:00
Nathan James 7185e5d287 feat: Change keyboard "caps" to "shift" & Wrap Keyboard (#377)
## Summary

* This PR solves issue
https://github.com/crosspoint-reader/crosspoint-reader/issues/357 in the
first commit
* I then added an additional commit which means when you reach the end
of the keyboard, if you go 'beyond', you wrap back to the other side.
* This replaces existing behaviour, so if you would rather this be
removed, let me know and I'll just do the `caps` -> `shift` change

## Additional Context

### Screenshots for the new shift display

I thought it might not fit and need column size changes, but ended up
fitting fine, see screenshots showing this below:

<img width="573" height="366" alt="image"
src="https://github.com/user-attachments/assets/b8f6a4ec-94f5-4f5e-b9a6-06cc5f250ddb"
/>

<img width="570" height="308" alt="image"
src="https://github.com/user-attachments/assets/7d775518-4784-4120-a20a-a9dc67af8565"
/>


### Gif showing the wrap-around of the text



![IMG_7648](https://github.com/user-attachments/assets/7eec9066-e1cc-49a1-8b6b-a61556038d31)

---

### AI Usage

Did you use AI tools to help write this code? **PARTIALLY** - used to
double check the text wrapping had no edge-cases. (It did also suggest
rewriting the function, but I decided that was too big of a change for a
working part of the codebase, for now!)
2026-01-19 22:50:34 +11:00
Eunchurn Park 12940cc546 fix: XTC 1-bit thumb BMP polarity inversion (#373)
## Summary

* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
* **What changes are included?**

- Fix inverted colors in Continue Reading cover image for 1-bit XTC
files

## Additional Context

* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
  specific areas to focus on).

- Fix `grayValue = pixelBit ? 0 : 255` → `grayValue = pixelBit ? 255 :
0` in `lib/Xtc/Xtc.cpp`
- The thumb BMP generation had inverted polarity compared to cover BMP
generation
- bit=0 should be black, bit=1 should be white (matching the BMP palette
order)
- Update misleading comment about XTC polarity

---

### 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-19 22:41:48 +11:00
Luke Stein 21277e03eb docs: Update User Guide to reflect release 0.14.0 (#376) 2026-01-15 23:27:17 +11:00
Luke Stein 4eef2b5793 feat: Add MAC address display to WiFi Networks screen (#381)
## Summary

* Implements #380, allowing the user to see the device's MAC address in
order to register on wifi networks

## Additional Context

* Although @markatlnk suggested showing on the settings screen, I
implemented display at the bottom of the WiFi Networks selection screen
(accessed via "File Transfer" > "Join a Network") since I think it makes
more sense there.
* Tested on my own device


![IMG_2873](https://github.com/user-attachments/assets/b82a20dc-41a0-4b21-81f1-20876aa2c6b0)


---

### 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: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-01-15 23:26:39 +11:00
Nathan James 5a55fa1c6e fix: also apply longPressChapterSkip setting to xtc reader (#378)
## Summary

* This builds upon the helpful PR
https://github.com/crosspoint-reader/crosspoint-reader/pull/341, and
adds support for the setting to also apply to the XTC reader, which I
believed has just been missed and was not intentionally left out.
* XTC does not have chapter support yet, but it does skip 10 pages when
long-pressed, and so I think this is useful.

---

### AI Usage

Did you use AI tools to help write this code? No
2026-01-15 23:25:18 +11:00
Maeve Andrews c98ba142e8 fix: draw button hints correctly if orientation is not portrait (#363)
~~Quick~~ fix for
https://github.com/daveallie/crosspoint-reader/issues/362

(this just applies to the chapter selection menu:)

~~If the orientation is portrait, hints as we know them make sense to
draw. If the orientation is inverted, we'd have to change the order of
the labels (along with everything's position), and if it's one of the
landscape choices, we'd have to render the text and buttons vertically.
All those other cases will be more complicated.~~

~~Punt on this for now by only rendering if portrait.~~

Update: this now draws the hints at the physical button position no
matter what the orientation is, by temporarily changing orientation to
portrait.

---------

Co-authored-by: Maeve Andrews <maeve@git.mail.maeveandrews.com>
2026-01-15 23:23:36 +11:00
Jonas Diemer c1c94c0112 Feature: Show img alt text (#168)
Let's start small by showing the ALT text of IMG. This is rudimentary,
but avoids those otherwise completely blank chapters.

I feel we will need this even when we can render images if that
rendering takes >1s - I would then prefer rendering optional and showing
the ALT text first.
2026-01-15 23:21:46 +11:00
Dave Allie eb84bcee7c chore: Pin links2004/WebSockets version 2026-01-15 23:15:30 +11:00
efenner d45f355e87 feat: Add EPUB table omitted placeholder (#372)
## Summary

* **What is the goal of this PR?**: Fix the bug I reported in
https://github.com/daveallie/crosspoint-reader/issues/292
* **What changes are included?**: Instead of silently dropping table
content in EPUBs., replace with an italicized '[Table omitted]' message
where tables appear.

## 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? _**PARTIALLY **_

---------

Co-authored-by: Evan Fenner <evan@evanfenner.com>
Co-authored-by: Warp <agent@warp.dev>
2026-01-15 23:14:59 +11:00
Dave Allie 56ec3dfb6d chore: Cut release 0.14.0 2026-01-15 01:01:47 +11:00
Maeve Andrews e517945aaa Add a bullet to the beginning of any <li> (#368)
Currently there is no visual indication whatsoever if something is in a
list. An `<li>` is essentially just another paragraph.

As a partial remedy for this, add a bullet character to the beginning of
`<li>` text blocks so that the user can see that they're list items.
This is incomplete in that an `<ol>` should also have a counter so that
its list items can get numbers instead of bullets (right now I don't
think we track if we're in a `<ul>` or an `<ol>` at all), but it's
strictly better than the current situation.

Co-authored-by: Maeve Andrews <maeve@git.mail.maeveandrews.com>
2026-01-14 23:23:03 +11:00
Maeve Andrews 489220832f Only indent paragraphs for justify/left-align (#367)
Currently, when Extra Paragraph Spacing is off, an em-space is added to
the beginning of each ParsedText even for blocks like headers that are
centered. This whitespace makes the centering slightly off. Change the
calculation here to only add the em-space for left/justified text.

Co-authored-by: Maeve Andrews <maeve@git.mail.maeveandrews.com>
2026-01-14 23:21:48 +11:00
Dave Allie 3ee10b31ab Update OTA updater URL 2026-01-14 23:14:00 +11:00
swwilshub a946c83a07 Turbocharge WiFi uploads with WebSocket + watchdog stability (#364)
## Summary

* **What is the goal of this PR?** Fix WiFi file transfer stability
issues (especially crashes during uploads) and improve upload speed via
WebSocket binary protocol. File transfers now don't really crash as
much, if they do it recovers and speed has gone form 50KB/s to 300+KB/s.

* **What changes are included?**
- **WebSocket upload support** - Adds WebSocket binary protocol for file
uploads, achieving faster speeds 335 KB/s vs HTTP multipart)
- **Watchdog stability fixes** - Adds `esp_task_wdt_reset()` calls
throughout upload path to prevent watchdog timeouts during:
    - File creation (FAT allocation can be slow)
    - SD card write operations
    - HTTP header parsing
    - WebSocket chunk processing
- **4KB write buffering** - Batches SD card writes to reduce I/O
overhead
- **WiFi health monitoring** - Detects WiFi disconnection in STA mode
and exits gracefully
- **Improved handleClient loop** - 500 iterations with periodic watchdog
resets and button checks for responsiveness
- **Progress bar improvements** - Fixed jumping/inaccurate progress by
capping local progress at 95% until server confirms completion
- **Exit button responsiveness** - Button now checked inside the
handleClient loop every 64 iterations
- **Reduced exit delays** - Decreased shutdown delays from ~850ms to
~140ms

**Files changed:**
- `platformio.ini` - Added WebSockets library dependency
- `CrossPointWebServer.cpp/h` - WebSocket server, upload buffering,
watchdog resets
- `CrossPointWebServerActivity.cpp` - WiFi monitoring, improved loop,
button handling
- `FilesPage.html` - WebSocket upload JavaScript with HTTP fallback

## Additional Context

- WebSocket uses 4KB chunks with backpressure management to prevent
ESP32 buffer overflow
- Falls back to HTTP automatically if WebSocket connection fails
- The main bottleneck now is SD card write speed (~44% of transfer
time), not WiFi
- STA mode was more prone to crashes than AP mode due to external
network factors; WiFi health monitoring helps detect and handle
disconnections gracefully

---

### AI Usage

Did you use AI tools to help write this code? _**YES**_ Claude did it
ALL, I have no idea what I am doing, but my books transfer fast now.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-14 23:11:28 +11:00
Justin Mitchell 847786e342 Fixes issue with Calibre web expecting SSL (#347)
http urls now work with Calibre web

---------

Co-authored-by: Dave Allie <dave@daveallie.com>
2026-01-14 11:54:14 +00:00
Luke Stein c2fb8ce55d Update User Guide to reflect release 0.13.1 (#337)
Please note I have not tested the Calibre features and am not yet in a
position to offer detailed documentation of how they work.
2026-01-14 22:48:43 +11:00
Armando Cerna ed05554d74 feat: Add setting to toggle long-press chapter skip (#341)
## Summary

Adds a new "Long-press Chapter Skip" toggle in Settings to control
whether holding the side buttons skips chapters.

I kept accidentally triggering chapter skips while reading, which caused
me to lose my place in the middle of long chapters.

## 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? _**PARTIALLY **_
2026-01-14 22:47:24 +11:00
Jonas Diemer 9a9dc044ce ifdef around optional fonts to reduce flash size/time. (#339)
## Summary

Adds define to omit optional fonts from the build. This reduces time to
flash from >31s to <13s. Useful for development that doesn't require
fonts. Addresses #193

Invoke it like this during development:
`PLATFORMIO_BUILD_FLAGS="-D OMIT_FONTS" pio run --target upload && pio
device monitor`

Changing the define causes `pio` to do a full rebuild (but it will be
quick if you keep the define).

---

### 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
2026-01-14 22:40:40 +11:00
Jonas Diemer 1c027ce2cd Skip BOM character (sometimes used in front of em-dashes) (#340)
## Summary

Skip BOM character (sometimes used in front of em-dashes) - they are not
part of the glyph set and would render `?` otherwise.

---

### AI Usage

Did you use AI tools to help write this code? _**YES**_
2026-01-14 22:38:30 +11:00
Eunchurn Park 49f97b69ca Add TXT file reader support (#240)
## Summary

* **What is the goal of this PR?** 

Add support for reading plain text (.txt) files, enabling users to
browse, read, and track progress in TXT documents alongside existing
EPUB and XTC formats.

* **What changes are included?**

- New Txt library for loading and parsing plain text files
- New TxtReaderActivity with streaming page rendering using 8KB chunks
to handle large files without memory issues on ESP32-C3
- Page index caching system (index.bin) for instant re-open after sleep
or app restart
- Progress bar UI during initial file indexing (matching EPUB style)
- Word wrapping with proper UTF-8 support
- Cover image support for TXT files:
- Primary: image with same filename as TXT (e.g., book.jpg for book.txt)
  - Fallback: cover.bmp/jpg/jpeg in the same folder
  - JPG to BMP conversion using existing converter
  - Sleep screen cover mode now works with TXT files
- File browser now shows .txt files

## Additional Context

* Add any other information that might be helpful for the reviewer

* Memory constraints: The streaming approach was necessary because
ESP32-C3 only has 320KB RAM. A 700KB TXT file cannot be loaded entirely
into memory, so we read 8KB chunks and build a page offset index
instead.

* Cache invalidation: The page index cache automatically invalidates
when file size, viewport width, or lines per page changes (e.g., font
size or orientation change).

* Performance: First open requires indexing (with progress bar),
subsequent opens load from cache instantly.

* Cover image format: PNG is detected but not supported for conversion
(no PNG decoder available). Only BMP and JPG/JPEG work.
2026-01-14 21:36:40 +11:00
Dave Allie 14643d0225 Move string helpers out of HomeActivity into StringUtils 2026-01-14 21:24:45 +11:00
Eunchurn Park fecd1849b9 Add cover image display in *Continue Reading* card with framebuffer caching (#200)
## Summary

* **What is the goal of this PR?** (e.g., Fixes a bug in the user
authentication module,

Display the book cover image in the **"Continue Reading"** card on the
home screen, with fast navigation using framebuffer caching.

* **What changes are included?**

- Display book cover image in the "Continue Reading" card on home screen
- Load cover from cached BMP (same as sleep screen cover)
- Add framebuffer store/restore functions (`copyStoredBwBuffer`,
`freeStoredBwBuffer`) for fast navigation after initial render
- Fix `drawBitmap` scaling bug: apply scale to offset only, not to base
coordinates
- Add white text boxes behind title/author/continue reading label for
readability on cover
- Support both EPUB and XTC file cover images
- Increase HomeActivity task stack size from 2048 to 4096 for cover
image rendering

## Additional Context

* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks, specific areas to
focus on).

- Performance: First render loads cover from SD card (~800ms),
subsequent navigation uses cached framebuffer (~instant)
- Memory: Framebuffer cache uses ~48KB (6 chunks × 8KB) while on home
screen, freed on exit
- Fallback: If cover image is not available, falls back to standard
text-only display
- The `drawBitmap` fix corrects a bug where screenY = (y + offset) scale
was incorrectly scaling the base coordinates. Now correctly uses screenY
= y + (offset scale)
2026-01-14 21:24:02 +11:00
Will Morrow 2040e088e7 Ensure new custom sleep image every time (#300)
When picking a random sleep image from a set of custom images, compare
the randomly chosen index against a cached value in settings. If the
value matches, use the next image (rolling over if it's the last image).
Cache the chosen image index to settings in either case.

## Summary

Implements a tweak on the custom sleep image feature that ensures that
the user gets a new image every time the device goes to sleep.
This change adds a new setting (perhaps there's a better place to cache
this?) that stores the most recently used file index. During picking the
random image index, we compare this against the random index and choose
the next one (modulo the number of image files) if it matches, ensuring
we get a new image.

## Additional Context

As mentioned, I used settings to cache this value since it is a
persisted store, perhaps that's overkill. Open to suggestions on if
there's a better way.
2026-01-14 21:05:08 +11:00
Andrew Brandt 65d23910a3 ci: add PR format check workflow (#328)
**Description**:

Add a new workflow to check the PR formatting to ensure consistency on
PR titles. We can also use this for semantic release versioning later,
if we so desire.

**Related Issue(s)**:

Implements first portion of #327

---------

Signed-off-by: Andrew Brandt <brandt.andrew89@gmail.com>
2026-01-14 21:04:02 +11:00
261 changed files with 87400 additions and 22085 deletions
+89 -17
View File
@@ -1,10 +1,55 @@
name: CI
'on':
name: CI (build)
on:
push:
branches: [master]
pull_request:
permissions:
contents: read
jobs:
clang-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: Install clang-format-21
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 21
sudo apt-get update
sudo apt-get install -y clang-format-21
- name: Run clang-format
run: |
PATH="/usr/lib/llvm-21/bin:$PATH" ./bin/clang-format-fix
git diff --exit-code || (echo "Please run 'bin/clang-format-fix' to fix formatting issues" && exit 1)
cppcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Run cppcheck
run: pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high
build:
runs-on: ubuntu-latest
steps:
@@ -19,19 +64,46 @@ jobs:
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Install clang-format-21
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 21
sudo apt-get update
sudo apt-get install -y clang-format-21
- name: Run cppcheck
run: pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high
- name: Run clang-format
run: PATH="/usr/lib/llvm-21/bin:$PATH" ./bin/clang-format-fix && git diff --exit-code || (echo "Please run 'bin/clang-format-fix' to fix formatting issues" && exit 1)
- name: Build CrossPoint
run: pio run
run: |
set -euo pipefail
pio run | tee pio.log
- name: Extract firmware stats
run: |
set -euo pipefail
ram_line="$(grep -E "RAM:\\s" -m1 pio.log || true)"
flash_line="$(grep -E "Flash:\\s" -m1 pio.log || true)"
echo "ram_line=${ram_line}" >> "$GITHUB_OUTPUT"
echo "flash_line=${flash_line}" >> "$GITHUB_OUTPUT"
{
echo "## Firmware build stats"
if [ -n "$ram_line" ]; then echo "- ${ram_line}"; else echo "- RAM: not found"; fi
if [ -n "$flash_line" ]; then echo "- ${flash_line}"; else echo "- Flash: not found"; fi
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload firmware.bin artifact
uses: actions/upload-artifact@v6
with:
name: firmware.bin
path: .pio/build/default/firmware.bin
if-no-files-found: error
# This job is used as the PR required actions check, allows for changes to other steps in the future without breaking
# PR requirements.
test-status:
name: Test Status
needs:
- build
- clang-format
- cppcheck
if: always()
runs-on: ubuntu-latest
steps:
- name: Fail because needed jobs failed
# Fail if any job failed or was cancelled (skipped jobs are ok)
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
run: exit 1
- name: Success
run: exit 0
+27
View File
@@ -0,0 +1,27 @@
name: "PR Formatting"
on:
pull_request:
pull_request_target:
types:
- opened
- reopened
- edited
permissions:
statuses: write
jobs:
title-check:
name: Title Check
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
- name: Check PR Title
uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+48
View File
@@ -0,0 +1,48 @@
name: Compile Release Candidate
on:
workflow_dispatch:
jobs:
build-release-candidate:
if: startsWith(github.ref_name, 'release/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- uses: actions/cache@v5
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Extract env
run: |
echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV
echo "BRANCH_SUFFIX=${GITHUB_REF_NAME#release/}" >> $GITHUB_ENV
- name: Build CrossPoint Release Candidate
env:
CROSSPOINT_RC_HASH: ${{ env.SHORT_SHA }}
run: pio run -e gh_release_rc
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: CrossPoint-RC-${{ env.BRANCH_SUFFIX }}
path: |
.pio/build/gh_release_rc/bootloader.bin
.pio/build/gh_release_rc/firmware.bin
.pio/build/gh_release_rc/firmware.elf
.pio/build/gh_release_rc/firmware.map
.pio/build/gh_release_rc/partitions.bin
+6
View File
@@ -4,3 +4,9 @@
.vscode
lib/EpdFont/fontsrc
*.generated.h
.vs
build
**/__pycache__/
/compile_commands.json
/.cache
/notes.md
+38
View File
@@ -0,0 +1,38 @@
# Project Governance & Community Principles
CrossPoint Reader is a community-driven, open-source project. Our goal is to provide a high-quality, open-source
firmware alternative for the Xteink X4 hardware. To keep this project productive and welcoming as we grow, we ask all
contributors to follow these principles.
### 1. The "Human First" Rule
Technical discussions can get heated, but they should never be personal.
- **Assume good intent:** We are all volunteers working on this in our free time. If a comment seems abrasive, assume
its a language barrier or a misunderstanding before taking offense.
- **Focus on the code, not the person:** Critique the implementation, the performance, or the UX. Never the intelligence
or character of the contributor.
- **Inflammatory language:** Personal attacks, trolling, or exclusionary language (based on race, gender, background,
etc.) are not welcome here and will be moderated.
### 2. A "Do-ocracy" with Guidance
CrossPoint thrives because people step up to build what they want to see.
- If you want a feature, the best way to get it is to start an
[Idea Discussion](https://github.com/crosspoint-reader/crosspoint-reader/discussions/categories/ideas) or open a PR.
- If you want to report a bug, check for duplicates and create an
[Issue](https://github.com/crosspoint-reader/crosspoint-reader/issues).
- While we encourage experimentation, the maintainers reserve the right to guide the projects technical direction to
ensure stability on the ESP32-C3s constrained hardware.
- For more guidance on the scope of the project, see the [SCOPE.md](SCOPE.md) document.
### 3. Transparent Communication
To keep the project healthy, we keep our "work" in the open.
- **Public by Default:** All technical decisions and project management discussions happen in GitHub Issues, Pull
Requests, or the public Discussions tab.
- **Clarity in Writing:** Because we have a global community with different levels of English proficiency, please be as
explicit and clear as possible in your PR descriptions and bug reports.
### 4. Moderation & Safety
The maintainers are responsible for keeping the community a safe place to contribute.
- We reserve the right to hide comments, lock threads, or block users who repeatedly violate these principles or engage
in harassment.
- **Reporting:** If you feel you are being harassed or see behavior that is damaging the community, please reach out
privately to @daveallie.
+30 -4
View File
@@ -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:
```
git clone --recursive https://github.com/daveallie/crosspoint-reader
git clone --recursive https://github.com/crosspoint-reader/crosspoint-reader
# Or, if you've already cloned without --recursive:
git submodule update --init --recursive
@@ -93,6 +97,25 @@ Connect your Xteink X4 to your computer via USB-C and run the following command.
```sh
pio run --target upload
```
### Debugging
After flashing the new features, its recommended to capture detailed logs from the serial port.
First, make sure all required Python packages are installed:
```python
python3 -m pip install pyserial colorama matplotlib
```
after that run the script:
```sh
# For Linux
# This was tested on Debian and should work on most Linux systems.
python3 scripts/debugging_monitor.py
# For macOS
python3 scripts/debugging_monitor.py /dev/cu.usbmodem2101
```
Minor adjustments may be required for Windows.
## Internals
@@ -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).
### To submit a contribution:
1. Fork the repo
+48
View File
@@ -0,0 +1,48 @@
# Project Vision & Scope: CrossPoint Reader
The goal of CrossPoint Reader is to create an efficient, open-source reading experience for the Xteink X4. We believe a
dedicated e-reader should do one thing exceptionally well: **facilitate focused reading.**
## 1. Core Mission
To provide a lightweight, high-performance firmware that maximizes the potential of the X4, prioritizing legibility and
usability over "swiss-army-knife" functionality.
## 2. Scope
### In-Scope
*These are features that directly improve the primary purpose of the device.*
* **User Experience:** E.g. User-friendly interfaces, and interactions, both inside the reader and navigating the
firmware. This includes things like button mapping, book loading, and book navigation like bookmarks.
* **Document Rendering:** E.g. Support for rendering documents (primarily EPUB) and improvements to the rendering
engine.
* **Format Optimization:** E.g. Efficiently parsing EPUB (CSS/Images) and other documents within the device's
capabilities.
* **Typography & Legibility:** E.g. Custom font support, hyphenation engines, and adjustable line spacing.
* **E-Ink Driver Refinement:** E.g. Reducing full-screen flashes (ghosting management) and improving general rendering.
* **Library Management:** E.g. Simple, intuitive ways to organize and navigate a collection of books.
* **Local Transfer:** E.g. Simple, "pull" based book loading via a basic web-server or public and widely-used standards.
* **Language Support:** E.g. Support for multiple languages both in the reader and in the interfaces.
### Out-of-Scope
*These items are rejected because they compromise the device's stability or mission.*
* **Interactive Apps:** No Notepads, Calculators, or Games. This is a reader, not a PDA.
* **Active Connectivity:** No RSS readers, News aggregators, or Web browsers. Background Wi-Fi tasks drain the battery
and complicate the single-core CPU's execution.
* **Media Playback:** No Audio players or Audio-books.
* **Complex Reader Features:** No highlighting, notes, or dictionary lookup. These features are better suited for
devices with better input capabilities and more powerful chips.
## 3. Idea Evaluation
While I appreciate the desire to add new and exciting features to CrossPoint Reader, CrossPoint Reader is designed to be
a lightweight, reliable, and performant e-reader. Things which distract or compromise the device's core mission will not
be accepted. As a guiding question, consider if your idea improve the "core reading experience" for the average user,
and, critically, not distract from that reading experience.
> **Note to Contributors:** If you are unsure if your idea fits the scope, please open a **Discussion** before you start
> coding!
+104 -9
View File
@@ -2,6 +2,30 @@
Welcome to the **CrossPoint** firmware. This guide outlines the hardware controls, navigation, and reading features of the device.
- [CrossPoint User Guide](#crosspoint-user-guide)
- [1. Hardware Overview](#1-hardware-overview)
- [Button Layout](#button-layout)
- [2. Power \& Startup](#2-power--startup)
- [Power On / Off](#power-on--off)
- [First Launch](#first-launch)
- [3. Screens](#3-screens)
- [3.1 Home Screen](#31-home-screen)
- [3.2 Book Selection](#32-book-selection)
- [3.3 Reading Mode](#33-reading-mode)
- [3.4 File Upload Screen](#34-file-upload-screen)
- [3.4.1 Calibre Wireless Transfers](#341-calibre-wireless-transfers)
- [3.5 Settings](#35-settings)
- [3.6 Sleep Screen](#36-sleep-screen)
- [4. Reading Mode](#4-reading-mode)
- [Page Turning](#page-turning)
- [Chapter Navigation](#chapter-navigation)
- [System Navigation](#system-navigation)
- [Supported Languages](#supported-languages)
- [5. Chapter Selection Screen](#5-chapter-selection-screen)
- [6. Current Limitations \& Roadmap](#6-current-limitations--roadmap)
- [7. Troubleshooting Issues \& Escaping Bootloop](#7-troubleshooting-issues--escaping-bootloop)
## 1. Hardware Overview
The device utilises the standard buttons on the Xtink X4 (in the same layout as the manufacturer firmware, by default):
@@ -20,9 +44,10 @@ Button layout can be customized in **[Settings](#35-settings)**.
### Power On / Off
To turn the device on or off, **press and hold the Power button for half a second**. In **[Settings](#35-settings)** you can configure the power button to trigger on a short press instead of a long one.
To turn the device on or off, **press and hold the Power button for approximately half a second**.
In **[Settings](#35-settings)** you can configure the power button to turn the device off with a short press instead of a long one.
To reboot the device (for example if it's frozen, or after a firmware update), press and release the Reset button, and then hold the Power button for a few seconds.
To reboot the device (for example if it's frozen, or after a firmware update), press and release the Reset button, and then quickly press and hold the Power button for a few seconds.
### First Launch
@@ -59,22 +84,53 @@ 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:
- **Sleep Screen**: Which sleep screen to display when the device sleeps:
- "Dark" (default) - The default dark sleep screen
- "Dark" (default) - The default dark Crosspoint logo sleep screen
- "Light" - The same default sleep screen, on a white background
- "Custom" - Custom images from the SD card, see [Sleep Screen](#36-sleep-screen) below for more information
- "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)
- "Blank" - A blank screen
- "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
- "Always" - Always hide battery percentage
- **Extra Paragraph Spacing**: If enabled, vertical space will be added between paragraphs in the book. If disabled, paragraphs will not have vertical space between them, but will have first-line indentation.
- **Short Power Button Click**: Whether to trigger the power button on a short press or a long press.
- **Reading Orientation**: Set the screen orientation for reading:
- **Text Anti-Aliasing**: Whether to show smooth grey edges (anti-aliasing) on text in reading mode. Note this slows down page turns slightly.
- **Short Power Button Click**: Controls the effect of a short click of the power button:
- "Ignore" - Require a long press to turn off the device
- "Sleep" - A short press powers the device off
- "Page Turn" - A short press in reading mode turns to the next page; a long press turns the device off
- **Reading Orientation**: Set the screen orientation for reading EPUB files:
- "Portrait" (default) - Standard portrait orientation
- "Landscape CW" - Landscape, rotated clockwise
- "Inverted" - Portrait, upside down
@@ -83,16 +139,26 @@ 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
- **Side Button Layout**: Swap the order of the up and down volume buttons from Previous/Next to Next/Previous. This change is only in effect when reading.
- 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
- "Page Scroll" - Long-pressing scrolls a page up/down
- Swap the order of the up and down volume buttons from Previous/Next to Next/Previous. This change is only in effect when reading.
- **Reader Font Family**: Choose the font used for reading:
- "Bookerly" (default) - Amazon's reading font
- "Noto Sans" - Google's sans-serif font
- "Open Dyslexic" - Font designed for readers with dyslexia
- **Reader Font Size**: Adjust the text size for reading; options are "Small", "Medium", "Large", or "X Large".
- **Reader Line Spacing**: Adjust the spacing between lines; options are "Tight", "Normal", or "Wide".
- **Reader Screen Margin**: Controls the screen margins in reader mode between 5 and 40 pixels in 5 pixel increments.
- **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.
- **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
@@ -124,15 +190,29 @@ Once you have opened a book, the button layout changes to facilitate reading.
The role of the volume (side) buttons can be swapped in **[Settings](#35-settings)**.
If the **Short Power Button Click** setting is set to "Page Turn", you can also turn to the next page by briefly pressing the Power button.
### Chapter Navigation
* **Next Chapter:** Press and **hold** the **Right** (or **Volume Down**) button briefly, then release.
* **Previous Chapter:** Press and **hold** the **Left** (or **Volume Up**) button briefly, then release.
This feature can be disabled in **[Settings](#35-settings)** to help avoid changing chapters by mistake.
### System Navigation
* **Return to Book Selection:** Press **Back** to close the book and return to the **[Book Selection](#32-book-selection)** screen.
* **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:
* **Latin Script (Basic, Supplement, Extended-A):** Covers English, German, French, Spanish, Portuguese, Italian, Dutch, Swedish, Norwegian, Danish, Finnish, Polish, Czech, Hungarian, Romanian, Slovak, Slovenian, Turkish, and others.
* **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
@@ -150,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).
+2
View File
@@ -13,7 +13,9 @@ fi
# --modified: files tracked by git that have been modified (staged or unstaged)
# --exclude-standard: ignores files in .gitignore
# Additionally exclude files in 'lib/EpdFont/builtinFonts/' as they are script-generated.
# Also exclude files in 'lib/Epub/Epub/hyphenation/generated/' as they are script-generated.
git ls-files --exclude-standard ${GIT_LS_FILES_FLAGS} \
| grep -E '\.(c|cpp|h|hpp)$' \
| grep -v -E '^lib/EpdFont/builtinFonts/' \
| grep -v -E '^lib/Epub/Epub/hyphenation/generated/' \
| xargs -r clang-format -style=file -i
+66
View File
@@ -0,0 +1,66 @@
# Hypher Binary Tries
CrossPoint embeds the exact binary automata produced by
[Typst's `hypher`](https://github.com/typst/hypher).
## File layout
Each `.bin` blob is a single self-contained automaton:
```
uint32_t root_addr_be; // big-endian offset of the root node
uint8_t levels[]; // shared "levels" tape (dist/score pairs)
uint8_t nodes[]; // node records packed back-to-back
```
The size of the `levels` tape is implicit. Individual nodes reference slices
inside that tape via 12-bit offsets, so no additional pointers are required.
### Node encoding
Every node starts with a single control byte:
- Bit 7 set when the node stores scores (`levels`).
- Bits 5-6 stride of the target deltas (1, 2, or 3 bytes, big-endian).
- Bits 0-4 transition count (values ≥ 31 spill into an extra byte).
If the `levels` flag is set, two more bytes follow. Together they encode a
12-bit offset into the global `levels` tape and a 4-bit length. Each byte in the
levels tape packs a distance/score pair as `dist * 10 + score`, where `dist`
counts how many UTF-8 bytes we advanced since the previous digit.
After the optional levels header come the transition labels (one byte per edge)
followed by the signed target deltas. Targets are stored as relative offsets
from the current node address. Deltas up to ±128 fit in a single byte, larger
distances grow to 2 or 3 bytes. The runtime walks the transitions with a simple
linear scan and materializes the absolute address by adding the decoded delta
to the current nodes base.
## Embedding blobs into the firmware
The helper script `scripts/generate_hyphenation_trie.py` acts as a thin
wrapper: it reads the hypher-generated `.bin` files, formats them as `constexpr`
byte arrays, and emits headers under
`lib/Epub/Epub/hyphenation/generated/`. Each header defines the raw data plus a
`SerializedHyphenationPatterns` descriptor so the reader can keep the automaton
in flash.
To refresh the firmware assets after updating the `.bin` files, run:
```
./scripts/generate_hyphenation_trie.py \
--input lib/Epub/Epub/hyphenation/tries/en.bin \
--output lib/Epub/Epub/hyphenation/generated/hyph-en.trie.h
./scripts/generate_hyphenation_trie.py \
--input lib/Epub/Epub/hyphenation/tries/fr.bin \
--output lib/Epub/Epub/hyphenation/generated/hyph-fr.trie.h
./scripts/generate_hyphenation_trie.py \
--input lib/Epub/Epub/hyphenation/tries/de.bin \
--output lib/Epub/Epub/hyphenation/generated/hyph-de.trie.h
./scripts/generate_hyphenation_trie.py \
--input lib/Epub/Epub/hyphenation/tries/ru.bin \
--output lib/Epub/Epub/hyphenation/generated/hyph-ru.trie.h
```
+57
View File
@@ -0,0 +1,57 @@
# Troubleshooting
This document show most common issues and possible solutions while using the device features.
- [Troubleshooting](#troubleshooting)
- [Cannot See the Device on the Network](#cannot-see-the-device-on-the-network)
- [Connection Drops or Times Out](#connection-drops-or-times-out)
- [Upload Fails](#upload-fails)
- [Saved Password Not Working](#saved-password-not-working)
### Cannot See the Device on the Network
**Problem:** Browser shows "Cannot connect" or "Site can't be reached"
**Solutions:**
1. Verify both devices are on the **same WiFi network**
- Check your computer/phone WiFi settings
- Confirm the CrossPoint Reader shows "Connected" status
2. Double-check the IP address
- Make sure you typed it correctly
- Include `http://` at the beginning
3. Try disabling VPN if you're using one
4. Some networks have "client isolation" enabled - check with your network administrator
### Connection Drops or Times Out
**Problem:** WiFi connection is unstable
**Solutions:**
1. Move closer to the WiFi router
2. Check signal strength on the device (should be at least `||` or better)
3. Avoid interference from other devices
4. Try a different WiFi network if available
### Upload Fails
**Problem:** File upload doesn't complete or shows an error
**Solutions:**
1. Ensure the file is a valid `.epub` file
2. Check that the SD card has enough free space
3. Try uploading a smaller file first to test
4. Refresh the browser page and try again
### Saved Password Not Working
**Problem:** Device fails to connect with saved credentials
**Solutions:**
1. When connection fails, you'll be prompted to "Forget Network"
2. Select **Yes** to remove the saved password
3. Reconnect and enter the password again
4. Choose to save the new password
+331
View File
@@ -0,0 +1,331 @@
# Webserver Endpoints
This document describes all HTTP and WebSocket endpoints available on the CrossPoint Reader webserver.
- [Webserver Endpoints](#webserver-endpoints)
- [Overview](#overview)
- [HTTP Endpoints](#http-endpoints)
- [GET `/` - Home Page](#get----home-page)
- [GET `/files` - File Browser Page](#get-files---file-browser-page)
- [GET `/api/status` - Device Status](#get-apistatus---device-status)
- [GET `/api/files` - List Files](#get-apifiles---list-files)
- [POST `/upload` - Upload File](#post-upload---upload-file)
- [POST `/mkdir` - Create Folder](#post-mkdir---create-folder)
- [POST `/delete` - Delete File or Folder](#post-delete---delete-file-or-folder)
- [WebSocket Endpoint](#websocket-endpoint)
- [Port 81 - Fast Binary Upload](#port-81---fast-binary-upload)
- [Network Modes](#network-modes)
- [Station Mode (STA)](#station-mode-sta)
- [Access Point Mode (AP)](#access-point-mode-ap)
- [Notes](#notes)
## Overview
The CrossPoint Reader exposes a webserver for file management and device monitoring:
- **HTTP Server**: Port 80
- **WebSocket Server**: Port 81 (for fast binary uploads)
---
## HTTP Endpoints
### GET `/` - Home Page
Serves the home page HTML interface.
**Request:**
```bash
curl http://crosspoint.local/
```
**Response:** HTML page (200 OK)
---
### GET `/files` - File Browser Page
Serves the file browser HTML interface.
**Request:**
```bash
curl http://crosspoint.local/files
```
**Response:** HTML page (200 OK)
---
### GET `/api/status` - Device Status
Returns JSON with device status information.
**Request:**
```bash
curl http://crosspoint.local/api/status
```
**Response (200 OK):**
```json
{
"version": "1.0.0",
"ip": "192.168.1.100",
"mode": "STA",
"rssi": -45,
"freeHeap": 123456,
"uptime": 3600
}
```
| Field | Type | Description |
| ---------- | ------ | --------------------------------------------------------- |
| `version` | string | CrossPoint firmware version |
| `ip` | string | Device IP address |
| `mode` | string | `"STA"` (connected to WiFi) or `"AP"` (access point mode) |
| `rssi` | number | WiFi signal strength in dBm (0 in AP mode) |
| `freeHeap` | number | Free heap memory in bytes |
| `uptime` | number | Seconds since device boot |
---
### GET `/api/files` - List Files
Returns a JSON array of files and folders in the specified directory.
**Request:**
```bash
# List root directory
curl http://crosspoint.local/api/files
# List specific directory
curl "http://crosspoint.local/api/files?path=/Books"
```
**Query Parameters:**
| Parameter | Required | Default | Description |
| --------- | -------- | ------- | ---------------------- |
| `path` | No | `/` | Directory path to list |
**Response (200 OK):**
```json
[
{"name": "MyBook.epub", "size": 1234567, "isDirectory": false, "isEpub": true},
{"name": "Notes", "size": 0, "isDirectory": true, "isEpub": false},
{"name": "document.pdf", "size": 54321, "isDirectory": false, "isEpub": false}
]
```
| Field | Type | Description |
| ------------- | ------- | ---------------------------------------- |
| `name` | string | File or folder name |
| `size` | number | Size in bytes (0 for directories) |
| `isDirectory` | boolean | `true` if the item is a folder |
| `isEpub` | boolean | `true` if the file has `.epub` extension |
**Notes:**
- Hidden files (starting with `.`) are automatically filtered out
- System folders (`System Volume Information`, `XTCache`) are hidden
---
### POST `/upload` - Upload File
Uploads a file to the SD card via multipart form data.
**Request:**
```bash
# Upload to root directory
curl -X POST -F "file=@mybook.epub" http://crosspoint.local/upload
# Upload to specific directory
curl -X POST -F "file=@mybook.epub" "http://crosspoint.local/upload?path=/Books"
```
**Query Parameters:**
| Parameter | Required | Default | Description |
| --------- | -------- | ------- | ------------------------------- |
| `path` | No | `/` | Target directory for the upload |
**Response (200 OK):**
```
File uploaded successfully: mybook.epub
```
**Error Responses:**
| Status | Body | Cause |
| ------ | ----------------------------------------------- | --------------------------- |
| 400 | `Failed to create file on SD card` | Cannot create file |
| 400 | `Failed to write to SD card - disk may be full` | Write error during upload |
| 400 | `Failed to write final data to SD card` | Error flushing final buffer |
| 400 | `Upload aborted` | Client aborted the upload |
| 400 | `Unknown error during upload` | Unspecified error |
**Notes:**
- Existing files with the same name will be overwritten
- Uses a 4KB buffer for efficient SD card writes
---
### POST `/mkdir` - Create Folder
Creates a new folder on the SD card.
**Request:**
```bash
curl -X POST -d "name=NewFolder&path=/" http://crosspoint.local/mkdir
```
**Form Parameters:**
| Parameter | Required | Default | Description |
| --------- | -------- | ------- | ---------------------------- |
| `name` | Yes | - | Name of the folder to create |
| `path` | No | `/` | Parent directory path |
**Response (200 OK):**
```
Folder created: NewFolder
```
**Error Responses:**
| Status | Body | Cause |
| ------ | ----------------------------- | ----------------------------- |
| 400 | `Missing folder name` | `name` parameter not provided |
| 400 | `Folder name cannot be empty` | Empty folder name |
| 400 | `Folder already exists` | Folder with same name exists |
| 500 | `Failed to create folder` | SD card error |
---
### POST `/delete` - Delete File or Folder
Deletes a file or folder from the SD card.
**Request:**
```bash
# Delete a file
curl -X POST -d "path=/Books/mybook.epub&type=file" http://crosspoint.local/delete
# Delete an empty folder
curl -X POST -d "path=/OldFolder&type=folder" http://crosspoint.local/delete
```
**Form Parameters:**
| Parameter | Required | Default | Description |
| --------- | -------- | ------- | -------------------------------- |
| `path` | Yes | - | Path to the item to delete |
| `type` | No | `file` | Type of item: `file` or `folder` |
**Response (200 OK):**
```
Deleted successfully
```
**Error Responses:**
| Status | Body | Cause |
| ------ | --------------------------------------------- | ----------------------------- |
| 400 | `Missing path` | `path` parameter not provided |
| 400 | `Cannot delete root directory` | Attempted to delete `/` |
| 400 | `Folder is not empty. Delete contents first.` | Non-empty folder |
| 403 | `Cannot delete system files` | Hidden file (starts with `.`) |
| 403 | `Cannot delete protected items` | Protected system folder |
| 404 | `Item not found` | Path does not exist |
| 500 | `Failed to delete item` | SD card error |
**Protected Items:**
- Files/folders starting with `.`
- `System Volume Information`
- `XTCache`
---
## WebSocket Endpoint
### Port 81 - Fast Binary Upload
A WebSocket endpoint for high-speed binary file uploads. More efficient than HTTP multipart for large files.
**Connection:**
```
ws://crosspoint.local:81/
```
**Protocol:**
1. **Client** sends TEXT message: `START:<filename>:<size>:<path>`
2. **Server** responds with TEXT: `READY`
3. **Client** sends BINARY messages with file data chunks
4. **Server** sends TEXT progress updates: `PROGRESS:<received>:<total>`
5. **Server** sends TEXT when complete: `DONE` or `ERROR:<message>`
**Example Session:**
```
Client -> "START:mybook.epub:1234567:/Books"
Server -> "READY"
Client -> [binary chunk 1]
Client -> [binary chunk 2]
Server -> "PROGRESS:65536:1234567"
Client -> [binary chunk 3]
...
Server -> "PROGRESS:1234567:1234567"
Server -> "DONE"
```
**Error Messages:**
| Message | Cause |
| --------------------------------- | ---------------------------------- |
| `ERROR:Failed to create file` | Cannot create file on SD card |
| `ERROR:Invalid START format` | Malformed START message |
| `ERROR:No upload in progress` | Binary data received without START |
| `ERROR:Write failed - disk full?` | SD card write error |
**Example with `websocat`:**
```bash
# Interactive session
websocat ws://crosspoint.local:81
# Then type:
START:mybook.epub:1234567:/Books
# Wait for READY, then send binary data
```
**Notes:**
- Progress updates are sent every 64KB or at completion
- Disconnection during upload will delete the incomplete file
- Existing files with the same name will be overwritten
---
## Network Modes
The device can operate in two network modes:
### Station Mode (STA)
- Device connects to an existing WiFi network
- IP address assigned by router/DHCP
- `mode` field in `/api/status` returns `"STA"`
- `rssi` field shows signal strength
### Access Point Mode (AP)
- Device creates its own WiFi hotspot
- Default IP is typically `192.168.4.1`
- `mode` field in `/api/status` returns `"AP"`
- `rssi` field returns `0`
---
## Notes
- These examples use `crosspoint.local`. If your network does not support mDNS or the address does not resolve, replace it with the specific **IP Address** displayed on your device screen (e.g., `http://192.168.1.102/`).
- All paths on the SD card start with `/`
- Trailing slashes are automatically stripped (except for root `/`)
- The webserver uses chunked transfer encoding for file listings
+3 -84
View File
@@ -153,7 +153,7 @@ Click **File Manager** to access file management features.
1. Click the **+ Add** button in the top-right corner
2. Select **New Folder** from the dropdown menu
3. Enter a folder name (letters, numbers, underscores, and hyphens only)
3. Enter a folder name (must not contain characters \" * : < > ? / \\ | and must not be . or ..)
4. Click **Create Folder**
This is useful for organizing your ebooks by genre, author, or series.
@@ -172,89 +172,7 @@ This is useful for organizing your ebooks by genre, author, or series.
## Command Line File Management
For power users, you can manage files directly from your terminal using `curl` while the device is in File Upload mode.
### Uploading a File
To upload a file to the root directory, use the following command:
```bash
curl -F "file=@book.epub" "http://crosspoint.local/upload?path=/"
```
* **`-F "file=@filename"`**: Points to the local file on your computer.
* **`path=/`**: The destination folder on the device SD card.
### Deleting a File
To delete a specific file, provide the full path on the SD card:
```bash
curl -F "path=/folder/file.epub" "http://crosspoint.local/delete"
```
### Advanced Flags
For more reliable transfers of large EPUB files, consider adding these flags:
* `-#`: Shows a simple progress bar.
* `--connect-timeout 30`: Limits how long curl waits to establish a connection (in seconds).
* `--max-time 300`: Sets a maximum duration for the entire transfer (5 minutes).
> [!NOTE]
> These examples use `crosspoint.local`. If your network does not support mDNS or the address does not resolve, replace it with the specific **IP Address** displayed on your device screen (e.g., `http://192.168.1.102/`).
---
## Troubleshooting
### Cannot See the Device on the Network
**Problem:** Browser shows "Cannot connect" or "Site can't be reached"
**Solutions:**
1. Verify both devices are on the **same WiFi network**
- Check your computer/phone WiFi settings
- Confirm the CrossPoint Reader shows "Connected" status
2. Double-check the IP address
- Make sure you typed it correctly
- Include `http://` at the beginning
3. Try disabling VPN if you're using one
4. Some networks have "client isolation" enabled - check with your network administrator
### Connection Drops or Times Out
**Problem:** WiFi connection is unstable
**Solutions:**
1. Move closer to the WiFi router
2. Check signal strength on the device (should be at least `||` or better)
3. Avoid interference from other devices
4. Try a different WiFi network if available
### Upload Fails
**Problem:** File upload doesn't complete or shows an error
**Solutions:**
1. Ensure the file is a valid `.epub` file
2. Check that the SD card has enough free space
3. Try uploading a smaller file first to test
4. Refresh the browser page and try again
### Saved Password Not Working
**Problem:** Device fails to connect with saved credentials
**Solutions:**
1. When connection fails, you'll be prompted to "Forget Network"
2. Select **Yes** to remove the saved password
3. Reconnect and enter the password again
4. Choose to save the new password
---
For power users, you can manage files directly from your terminal using `curl` while the device is in File Upload mode a detailed documentation can be found [here](./webserver-endpoints.md).
## Security Notes
@@ -303,4 +221,5 @@ Your uploaded files will be immediately available in the file browser!
## Related Documentation
- [User Guide](../USER_GUIDE.md) - General device operation
- [Troubleshooting](./troubleshooting.md) - Troubleshooting
- [README](../README.md) - Project overview and features
+1 -2
View File
@@ -22,8 +22,7 @@ void EpdFont::getTextBounds(const char* string, const int startX, const int star
const EpdGlyph* glyph = getGlyph(cp);
if (!glyph) {
// TODO: Replace with fallback glyph property?
glyph = getGlyph('?');
glyph = getGlyph(REPLACEMENT_GLYPH);
}
if (!glyph) {
+10 -14
View File
@@ -1,23 +1,19 @@
#include "EpdFontFamily.h"
const EpdFont* EpdFontFamily::getFont(const Style style) const {
if (style == BOLD && bold) {
// Extract font style bits (ignore UNDERLINE bit for font selection)
const bool hasBold = (style & BOLD) != 0;
const bool hasItalic = (style & ITALIC) != 0;
if (hasBold && hasItalic) {
if (boldItalic) return boldItalic;
if (bold) return bold;
if (italic) return italic;
} else if (hasBold && bold) {
return bold;
}
if (style == ITALIC && italic) {
} else if (hasItalic && italic) {
return italic;
}
if (style == BOLD_ITALIC) {
if (boldItalic) {
return boldItalic;
}
if (bold) {
return bold;
}
if (italic) {
return italic;
}
}
return regular;
}
+1 -1
View File
@@ -3,7 +3,7 @@
class EpdFontFamily {
public:
enum Style : uint8_t { REGULAR = 0, BOLD = 1, ITALIC = 2, BOLD_ITALIC = 3 };
enum Style : uint8_t { REGULAR = 0, BOLD = 1, ITALIC = 2, BOLD_ITALIC = 3, UNDERLINE = 4 };
explicit EpdFontFamily(const EpdFont* regular, const EpdFont* bold = nullptr, const EpdFont* italic = nullptr,
const EpdFont* boldItalic = nullptr)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More