2f969a93b4ca85ccdd96eb38516675e6762ee7fe
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2f969a93b4 |
feat: context-aware screenshot filenames with book title (#1589)
## Summary I love the new screenshot feature but I can tell that soon I'm gonna have a folder full of screenshots and not know what's what. It would be great if the folder could self organize. When a screenshot is taken while reading, the filename would now include the book title, chapter (EPUB), page number, and progress percentage. Example: My-Great-Book_ch3_p5_42pct_12345.bmp * **What is the goal of this PR?** (e.g., Implements the new feature for file uploading.) * **What changes are included?** ## Additional Context * Non-reader screens keep the existing screenshot-<millis>.bmp naming. --- ### 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 reviewed all the changes but I don't have any experience with this project so this is my best guess |
||
|
|
c4fc4effbd |
refactor: implement ActivityManager (#1016)
## Summary Ref comment: https://github.com/crosspoint-reader/crosspoint-reader/pull/1010#pullrequestreview-3828854640 This PR introduces `ActivityManager`, which mirrors the same concept of Activity in Android, where an activity represents a single screen of the UI. The manager is responsible for launching activities, and ensuring that only one activity is active at a time. Main differences from Android's ActivityManager: - No concept of Bundle or Intent extras - No onPause/onResume, since we don't have a concept of background activities - onActivityResult is implemented via a callback instead of a separate method, for simplicity ## Key changes - Single `renderTask` shared across all activities - No more sub-activity, we manage them using a stack; Results can be passed via `startActivityForResult` and `setResult` - Activity can call `finish()` to destroy themself, but the actual deletion will be handled by `ActivityManager` to avoid `delete this` pattern As a bonus: the manager will automatically call `requestUpdate()` when returning from another activity ## Example usage **BEFORE**: ```cpp // caller enterNewActivity(new WifiSelectionActivity(renderer, mappedInput, [this](const bool connected) { onWifiSelectionComplete(connected); })); // subactivity onComplete(true); // will eventually call exitActivity(), which deletes the caller instance (dangerous behavior) ``` **AFTER**: (mirrors the `startActivityForResult` and `setResult` from android) ```cpp // caller startActivityForResult(new NetworkModeSelectionActivity(renderer, mappedInput), [this](const ActivityResult& result) { onNetworkModeSelected(result.selectedNetworkMode); }); // subactivity ActivityResult result; result.isCancelled = false; result.selectedNetworkMode = mode; setResult(result); finish(); // signals to ActivityManager to go back to last activity AFTER this function returns ``` TODO: - [x] Reconsider if the `Intent` is really necessary or it should be removed (note: it's inspired by [Intent](https://developer.android.com/guide/components/intents-common) from Android API) ==> I decided to keep this pattern fr clarity - [x] Verify if behavior is still correct (i.e. back from sub-activity) - [x] Refactor the `ActivityWithSubactivity` to just simple `Activity` --> We are using a stack for keeping track of sub-activity now - [x] Use single task for rendering --> avoid allocating 8KB stack per activity - [x] Implement the idea of [Activity result](https://developer.android.com/training/basics/intents/result) --> Allow sub-activity like Wifi to report back the status (connected, failed, etc) --- ### 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**, some repetitive migrations are done by Claude, but I'm the one how ultimately approve it --------- Co-authored-by: Zach Nelson <zach@zdnelson.com> |
||
|
|
2d49c7b7b4 |
feat: split status bar setting (#733)
## Summary This PR aims to reduce the complexity of the status bar by splitting the setting into 5: - Chapter Page Count - Book Progress % - Progress Bar - Chapter Title - Battery Indicator These are located within the new StausBarSettings activity, which also shows a preview of the bar the user has created <img width="513" height="806" alt="image" src="https://github.com/user-attachments/assets/cdf852fb-15d8-4da2-a74f-fd69294d7b05" /> <img width="483" height="797" alt="image" src="https://github.com/user-attachments/assets/66fc0c0d-ee51-4d31-b70d-e2bc043205d1" /> When updating from a previous version, the user's past settings are honoured. ## Additional Context The PR aims to remove any duplication of status bar code where possible, and extracts the status bar rendering into a new component - StatusBar It also adds a new (optional) padding option to the progress bar to allow the status bar to be shifted upwards - this is only intended for use in the 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 - although did help to decode some C++ errors --------- Co-authored-by: Arthur Tazhitdinov <lisnake@gmail.com> |
||
|
|
a616f42cb4 |
refactor: move render() to Activity super class, use freeRTOS notification (#774)
## Summary Currently, each activity has to manage their own `displayTaskLoop` which adds redundant boilerplate code. The loop is a wait loop which is also not the best practice, as the `updateRequested` boolean is not protected by a mutex. In this PR: - Move `displayTaskLoop` to the super `Activity` class - Replace `updateRequested` with freeRTOS's [direct to task notification](https://www.freertos.org/Documentation/02-Kernel/02-Kernel-features/03-Direct-to-task-notifications/01-Task-notifications) - For `ActivityWithSubactivity`, whenever a sub-activity is present, the parent's `render()` automatically goes inactive With this change, activities now only need to expose `render()` function, and anywhere in the code base can call `requestUpdate()` to request a new rendering pass. ## Additional Context In theory, this change may also make the battery life a bit better, since one wait loop is removed. Although the equipment in my home lab wasn't been able to verify it (the electric current is too noisy and small). Would appreciate if anyone has any insights on this subject. Update: I managed to hack [a small piece of code](https://github.com/ngxson/crosspoint-reader/tree/xsn/measure_cpu_usage) that allow tracking CPU idle time. The CPU load does decrease a bit (1.47% down to 1.39%), which make sense, because the display task is now sleeping most of the time unless notified. This should translate to a slightly increase in battery life in the long run. ``` PR: [40012] [MEM] Free: 185856 bytes, Total: 231004 bytes, Min Free: 123316 bytes [40012] [IDLE] Idle time: 98.61% (CPU load: 1.39%) [50017] [MEM] Free: 185856 bytes, Total: 231004 bytes, Min Free: 123316 bytes [50017] [IDLE] Idle time: 98.61% (CPU load: 1.39%) [60022] [MEM] Free: 185856 bytes, Total: 231004 bytes, Min Free: 123316 bytes [60022] [IDLE] Idle time: 98.61% (CPU load: 1.39%) 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%) ``` --- ### 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 * **Refactor** * Streamlined rendering architecture by consolidating update mechanisms across all activities, improving efficiency and consistency. * Modernized synchronization patterns for display updates to ensure reliable, conflict-free rendering. * **Bug Fixes** * Enhanced rendering stability through improved locking mechanisms and explicit update requests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: znelson <znelson@users.noreply.github.com> |
||
|
|
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. |