## Summary
* **What is the goal of this PR?**
Improve reliability and user experience during chapter indexing by
adding retry logic for SD card operations and a visual progress bar.
* **What changes are included?**
- **Retry logic**: Add 3 retry attempts with 50ms delay for ZIP to SD
card streaming to handle timing issues after display refresh
- **Progress bar**: Display a visual progress bar (0-100%) during
chapter indexing based on file read progress, updating every 10% to
balance responsiveness with e-ink display limitations
## Additional Context
* **Problem observed**: When navigating quickly through books with many
chapters (before chapter titles finish rendering), the "Indexing..."
screen would appear frozen. Checking the serial log revealed the
operation had silently failed, but the UI showed no indication of this.
Users would likely assume the device had crashed. Pressing the next
button again would resume operation, but this behavior was confusing and
unexpected.
* **Solution**:
- Retry logic handles transient SD card timing failures automatically,
so users don't need to manually retry
- Progress bar provides visual feedback so users know indexing is
actively working (not frozen)
* **Why timing issues occur**: After display refresh operations, there
can be timing conflicts when immediately starting SD card write
operations. This is more likely to happen when rapidly navigating
through chapters.
* **Progress bar design**: Updates every 10% to avoid excessive e-ink
refreshes while still providing meaningful feedback during long indexing
operations (especially for large chapters with CJK characters).
* **Performance**: Minimal overhead - progress calculation is simple
byte counting, and display updates use `FAST_REFRESH` mode.
Add setting toggle that allows status bar display options in EpubReader.
Supported options would be as follows:
- FULL: display as is today
- PROGRESS: display progress bar only
- BATTERY: display battery only
- NONE: hide status bar
---------
Co-authored-by: Dave Allie <dave@daveallie.com>
## Summary
* **What is the goal of this PR?**
Add a "Continue Reading" feature to improve user experience when
returning to a previously opened book.
* **What changes are included?**
- Add dynamic "Continue: <book name>" menu item in Home screen when a
book was previously opened
- File browser now starts from the folder of the last opened book
instead of always starting from root directory
- Menu dynamically shows 3 or 4 items based on reading history:
- Without history: `Browse`, `File transfer`, `Settings`
- With history: `Continue: <book>`, `Browse`, `File transfer`,
`Settings`
## Additional Context
* This feature leverages the existing `APP_STATE.openEpubPath` which
already persists the last opened book path
* The Continue Reading menu only appears if the book file still exists
on the SD card
* Book name in the menu is truncated to 25 characters with "..." suffix
if too long
* If the last book's folder was deleted, the file browser gracefully
falls back to root directory
* No new dependencies or significant memory overhead - reuses existing
state management
## Summary
* Use single unified cache file for book spine, table of contents, and
core metadata (title, author, cover image)
* Use new temp item store file in OPF parsing to store items to be
rescaned when parsing spine
* This avoids us holding these items in memory
* Use new toc.bin.tmp and spine.bin.tmp to build out partial toc / spine
data as part of parsing content.opf and the NCX file
* These files are re-read multiple times to ultimately build book.bin
## Additional Context
* Spec for file format included below as an image
* This should help with:
* #10
* #60
* #99
## Summary
* Give activities name and log when entering and exiting them
* Clearer logs when attempting to debug, knowing where users are coming
from/going to helps
## Summary
* Unset openEpubPath on boot and set once epub fully loaded
## Additional Context
* If an epub was crashing when loading, it was possible to get the
device stuck into a loop. There was no way to get back to the home
screen as we'd always load you back into old epub
* Break this loop by clearing the stored value when we boot, still
jumping to the last open epub, but only resetting that value once the
epub has been fully loaded
## Problem
Reading progress.bin used `SD.exists()` then `SD.open()` without
checking if open succeeded. Race conditions or SD errors could cause
file handle to be invalid.
## Fix
- Removed redundant `SD.exists()` check
- Check if file opened successfully before reading
- Verify correct number of bytes were read
## Testing
- Builds successfully with `pio run`
- Affects: `src/activities/reader/EpubReaderActivity.cpp`
## Problem
The status bar title truncation loop crashes when the chapter title is
shorter than 8 characters.
```cpp
// title.length() - 8 underflows when length < 8 (size_t is unsigned)
title = title.substr(0, title.length() - 8) + "...";
```
## Fix
Added a length guard to skip truncation for titles that are too short to
truncate safely.
## Testing
- Builds successfully with `pio run`
- Affects: `src/activities/reader/EpubReaderActivity.cpp`
## Summary
* This PR drastically reshapes the structure of the codebase, moving
from the concept of "Screens" to "Activities", restructing the files and
setting up the concept of subactivities.
* This should help with keep the main file clean and containing all
functional logic in the relevant activity.
* CrossPointState is now also a global singleton which should help with
accessing it from within activities.
## Additional Context
* This is probably going to be a bit disruptive for people with open
PRs, sorry 😞