Commit Graph

344 Commits

Author SHA1 Message Date
Brackyt
4b085e6e50
Merge 2cd569bb1f into 0d82b03981 2026-02-01 22:19:53 +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)
Some checks are pending
CI / build (push) Waiting to run
## 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
Brackyt
2cd569bb1f fix(cppcheck}: clang format 2026-01-29 13:59:19 +01:00
Brackyt
bb05b5ae6d perf: Clear ThemeEngine asset caches in HomeActivity to free memory for reader buffers. 2026-01-29 13:57:45 +01:00
Brackyt
1803cdc389 style: use std::find_if instead of raw loop
Address cppcheck useStlAlgorithm warning in HomeActivity.
2026-01-29 13:42:01 +01:00
Brackyt
fea92fd235 fix: post-rebase fixes for upstream compatibility
- Update HomeActivity to use RecentBook struct instead of string
- Remove leftover conflict marker from SettingsActivity
2026-01-29 13:24:07 +01:00
Brackyt
7254d46401 feat: optimize ThemeEngine render performance
- Add layout caching in UIElement to skip redundant layout passes
- Use binary search for text wrapping in Label (O(log n) vs O(n))
- Cache rendered bitmaps using captureRegion/restoreRegion
- Add RAM caching for BMP files to avoid SD card reads
- Cache book metadata in HomeActivity.onEnter() instead of every render
- Reuse recent books data to avoid duplicate ePub loads
2026-01-29 13:17:42 +01:00
Brackyt
93a94ea838 feat: bug fixes and optimizations
- fix double-free
- safe int/float parse
- grid division guard
- list string allocations
- label vector reserve
- skip second layout pass for hstack/vstack
2026-01-29 13:14:57 +01:00
Brackyt
999e60b75e feat: add valign and halign to stack elements 2026-01-29 13:14:57 +01:00
Brackyt
5e9e53cc13 fix(cppcheck): clang format 2026-01-29 13:14:57 +01:00
Brackyt
bd28d9d648 feat: Enhance ThemeEngine and apply new theming to SettingsActivity
- Improve ThemeManager with Children property support and safe integer parsing.
- Refactor SettingsActivity to use new theme elements.
- Update BasicElements and LayoutElements for better rendering.
2026-01-29 13:14:35 +01:00
Brackyt
f559f408bb fix(cppcheck): more clang format fix 2026-01-29 13:11:31 +01:00
Brackyt
fce43feea1 fix(cppcheck): clang format 2026-01-29 13:11:04 +01:00
Brackyt
092fcafd19 fix(cppcheck): resolve style and performance issues
- Remove unused HomeActivity::restoreCoverBuffer
- Use initialization lists in constructors
- Mark single-argument constructors as explicit
2026-01-29 13:11:04 +01:00
Brackyt
667e4d954c feat: expose detailed book metadata in HomeActivity 2026-01-29 13:11:04 +01:00
Brackyt
738f79c61c fix: support upscaling for bitmap render 2026-01-29 13:11:04 +01:00
Brackyt
e3c2b04cab feat: border radius on bitmap 2026-01-29 13:09:21 +01:00
Brackyt
49598aec3e feat: draw icons with transparent background 2026-01-29 13:08:16 +01:00
Brackyt
8162cf831e fix: covers not displaying when too large because of ram and transparency 2026-01-29 13:06:44 +01:00
Brackyt
9b7a6a4eed default theme closer to reality 2026-01-29 13:06:44 +01:00
Brackyt
968c65a695 feat: multiline support 2026-01-29 13:06:44 +01:00
Brackyt
73f47423e7 fix: rendering correctly + alpha channel 2026-01-29 13:06:44 +01:00
Brackyt
40b5420e11 feat: better icon loading for themes 2026-01-29 13:06:44 +01:00
Brackyt
dccd200b86 fix: reset clang correctly 2026-01-29 13:06:44 +01:00
Brackyt
1fab1f9ec5 fix: set default theme to original crosspoint ui + add small font + battery icon 2026-01-29 13:04:36 +01:00
Brackyt
ad2bea2122 fix: make home navigation work for all themes 2026-01-29 13:04:36 +01:00
Brackyt
84d08684a2 fix: theme switching works and restarts 2026-01-29 13:04:36 +01:00
Brackyt
7a5c1e8e0e - rounded rects
- background fill
- border radius
- container paddings
- fix navigation in home
2026-01-29 13:02:15 +01:00
Brackyt
d54f3c5143 fix:
- text no showing if clipping out of screen
- inner child dimensions setting 0 for height
- navigation to home menus was skipping transfer
2026-01-29 12:57:54 +01:00
Brackyt
374f1a1106 refactor: Enhance Bitmap handling and introduce ThemeEngine
- Refactored Bitmap class to improve memory management and streamline methods.
- Introduced ThemeEngine with foundational classes for UI elements, layout management, and theme parsing.
- Added support for dynamic themes and improved rendering capabilities in the HomeActivity and settings screens.

This update lays the groundwork for a more flexible theming system, allowing for easier customization and management of UI elements across the application.
2026-01-29 12:57:54 +01:00
Xuan-Son Nguyen
da4d3b5ea5
feat: add HalDisplay and HalGPIO (#522)
Some checks failed
CI / build (push) Has been cancelled
## 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)
Some checks are pending
CI / build (push) Waiting to run
## 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