1db14423194acfeb707f2514256fe910de68bf01
39
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1db1442319 |
fix: several bookmarks UX improvments (#2372)
## Summary This PR enhances the EPUB reader's bookmark system with two complementary improvements: a per-page bookmark indicator icon and toggle behavior on the existing long-press action. --- ### What Changed **Bookmark Toggle (was: add-only)** The long-press Confirm action now toggles bookmarks rather than always adding. `addBookmark()` checks whether a bookmark with the same xpath already exists in the in-memory cache: - If found → removes it and shows "Bookmark removed." - If not found → adds it and shows "Bookmark added." A new `STR_BOOKMARK_REMOVED` translation string was added to support the removal message. **Bookmark Icon Indicator** A `BookmarkIcon` is now drawn at the top-right corner of the page whenever the current page has a bookmark. `updateBookmarkFlag()` is called at render time to determine whether the current page is bookmarked. **In-Memory Bookmark Cache** Bookmarks are now loaded into `cachedBookmarks` on `onEnter()` rather than being re-read from disk on every toggle. All subsequent add/remove operations work against this cache and flush to disk, avoiding redundant file reads on each bookmark action. **Faster bookmarks list** Previously, calculating "page X/Y" for each entry required decompressing the entire spine item. We now persist `si`/`pc`/`pp` (spine index, page count, and page progress) in the bookmark JSON when saving, and restore them when loading. This avoids the expensive `toCrossPoint()` loop in `onEnter()`, significantly reducing the cost of initializing the bookmarks list. --- ### Files Changed - `EpubReaderActivity.cpp` — `addBookmark()` toggle logic, `updateBookmarkFlag()` (new), icon rendering in `renderContents()`, cache initialization in `onEnter()` - `EpubReaderActivity.h` — new fields: `currentPageBookmarked`, `bookmarkRemoved`, `cachedBookmarks`; new method declaration `updateBookmarkFlag()` --- ### 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: Julia Nguyen <julia@uxj.io> |
||
|
|
55a56914d7 | fix(i18n): localize home empty-state strings (#2342) | ||
|
|
f04b8aa9a9 | fix: apply progress bar offset from top instead of bottom edge (#2250) | ||
|
|
36a3a0cc3a |
feat: epub bookmarks (#1337)
Co-authored-by: vedi0boy <nate@origin8publishing.com> Co-authored-by: Uri Tauber <uritaube@gmail.com> |
||
|
|
e9120888fa | refactor: Drop FsFile alias, use HalFile in downstream code (#2141) | ||
|
|
d7797baff2 | fix: Fill the gap under the screen for the progress bar (#2138) | ||
|
|
b53ac3d52c |
chore: Minor cleanup flagged by newer gcc (#2140)
## Summary Minor cleanup flagged by newer gcc: - Removed unused variables - Removed unimplemented function declaration - `static` -> `inline` to avoid per-TU duplication --- ### AI Usage Did you use AI tools to help write this code? _**NO**_ |
||
|
|
b69111bea5 | refactor: Consolidate theme rendering into ThemeMetrics (#1868) | ||
|
|
cfd3a381ed | feat: X3 clock display with DS3231 RTC and NTP sync (#1612) | ||
|
|
8a11f44571 | feat: Themed reader menus (#1072) | ||
|
|
bf30964982 |
fix: overlap in download font list layout (#1900)
## Summary
Fix font download list layout overlap in Classic and RoundedRaff themes.
The font description was shown as a right-aligned value, causing text to
overlap with the font name on narrow screens.
### Changes
- Move font description from `rowValue` to `rowSubtitle` (second line)
- Show only status ("Installed"/"Update Available") as `rowValue`
- Fix Classic and RoundedRaff themes `rowValue` truncation (was fixed
60px, now dynamic)
## Screenshots
### Classic
| RC 1.3.0 | #1900 |
|-|-|
|<img width="480" height="800" alt="image"
src="https://github.com/user-attachments/assets/534434d6-d7a6-4f73-9d80-8fe5d060907c"
/>|<img width="480" height="800" alt="image"
src="https://github.com/user-attachments/assets/e616c4b7-43b9-49a8-8aa6-ab19f29865f1"
/>|
### Lyra
| RC 1.3.0 | #1900 |
|-|-|
|<img width="480" height="800" alt="image"
src="https://github.com/user-attachments/assets/5b42bad4-2860-4863-a025-5292aa391c1a"
/>|<img width="480" height="800" alt="image"
src="https://github.com/user-attachments/assets/4c27dcbb-8e8e-4ef0-8771-f92975210f11"
/>|
### RoundedRaff
| RC 1.3.0 | #1900 |
|-|-|
|<img width="480" height="800" alt="image"
src="https://github.com/user-attachments/assets/f0510c6f-7712-4cec-8fc8-4386951b1795"
/>|<img width="480" height="800" alt="image"
src="https://github.com/user-attachments/assets/017596b8-fe95-4541-884b-5de034c24193"
/>|
---
### 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>**_
|
||
|
|
7993b2bb97 |
feat: add SD card font support with on-device download and web management
Add a complete SD card font subsystem that enables users to install and use custom fonts beyond the three built-in families. This combines the back-end firmware support (#1327) with the font configuration, build pipeline, CI distribution, and user-facing management UI (#1392). Core font system: - Custom .cpfont binary format (v4) with multi-style support (regular, bold, italic, bold-italic) packed into a single file per size - On-demand glyph loading from SD card with two-pass prewarm rendering to bulk-read glyphs per page, achieving near-flash performance for Latin text (~697ms vs ~681ms) and viable CJK rendering (~32% slower) - Persistent advance cache for layout measurement without SD I/O - Overflow ring buffer for glyph cache misses during rendering - Memory-conscious design: only advance tables kept in RAM; glyph bitmaps, kern tables, and ligatures loaded on demand from SD Font management: - On-device WiFi download from GitHub Releases with manifest-based discovery, install/update detection, and progress UI - Web interface font upload, listing, and deletion via /fonts page - Manual SD card copy to /fonts/ or /.fonts/ directories - Font selection integrated into Settings > Reader > Font Family Build pipeline: - Declarative YAML config (sd-fonts.yaml) as single source of truth for the 17-family font library (serif, sans, mono, accessibility) - Python converter (fontconvert_sdcard.py) for TTF/OTF to .cpfont with FreeType rasterization, class-based kerning, and ligature extraction - Parallel build orchestrator with variable font instance extraction - CI workflow publishing versioned + stable releases to a dedicated crosspoint-fonts repository with auto-incrementing revision tags - Centralized version constants (cpfont_version.py) shared across build tooling and CI, with firmware headers as manual sync points Additional fixes: - CJK characters no longer get hyphens inserted at line breaks - Advance table eliminates 30+ second stalls during CJK section indexing for paragraphs with >512 unique codepoints Closes #930 Co-authored-by: Zach Nelson <zach@zdnelson.com> Co-authored-by: Justin <itsthisjustin@users.noreply.github.com> Co-authored-by: jpirnay <jens@pirnay.com> Co-authored-by: mcrosson <kemonine@kemonine.info> |
||
|
|
e841c84194 |
refactor: Deduplicate Roundraff battery drawing (#1847)
## Summary Deduplicated battery drawing code for Roundraff theme with other themes. Now `BaseTheme` provides non-virtual `drawBatteryLeft` and `drawBatteryRight` methods, which use a shared static `drawBatteryOutline` implementation, and defer to a virtual `fillBatteryIcon` implementation. In Classic and Roundraff `fillBatteryIcon` uses a solid fill, while Lyra and Lyra Extended use a segmented fill. The charging indicator inside the battery was missing for Roundraff, but is now consistent with other themes because of the shared drawing implementation. --- ### 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**_ |
||
|
|
1a145fe085 |
fix: keyboard feedback #1644 (#1697)
Addresses reviewer feedback from #1644: - **Localize keyboard hint strings** — 13 hardcoded English strings replaced with \`tr()\` macro (\`STR_KB_HINT_*\`), making them translatable across all 22 languages (fallback to English when not yet translated) - **Deduplicate \`Lyra3CoversMetrics\`** — now derives from \`LyraMetrics\` via lambda copy, overriding only \`homeCoverTileHeight\` and \`homeRecentBooksCount\` (eliminates ~30 duplicated metric fields) - **Unify keyboard drawing in \`BaseTheme\`** — \`drawTextField\` and \`drawKeyboardKey\` overrides removed from \`LyraTheme\`; variability controlled via \`keyboardKeyCornerRadius\` metric (0=Base, 6=Lyra). Unified text field padding to 6, adopted Lyra's secondary label draw order (main first, then secondary) - **Add URL-optimized keyboard layout** — \`urlLayout\` with \`:\` and \`/\` replacing \`=\` and \`,\` for easier URL input without switching to SYM mode --- ### 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 **_ |
||
|
|
77b2c31635 |
refactor: redesign on-screen keyboard (#1644)
# Refactor: Redesign On-Screen Keyboard ## Summary Complete redesign of the on-screen keyboard (used for WiFi password, KOReader, Calibre URLs) with improved layout, navigation, visual style, and new input features: **cursor mode** for text navigation, **password mode** with visibility toggle, and **URL mode** with pre-defined snippets. ## Screenshots ### Base Theme |**master** | **PR #1644** | |----------|-------------| | <img width="480" height="800" alt="image" src="https://github.com/user-attachments/assets/49125857-12d0-4020-b872-05d0ddbf1d94" /> | <img width="480" height="800" alt="image" src="https://github.com/user-attachments/assets/ad16656b-d66e-43dd-8697-2b85f709d7f8" /> | ### Lyra Theme | **master** | **PR #1644** | |----------|-------------| | <img width="480" height="800" alt="image" src="https://github.com/user-attachments/assets/d9901251-9154-48d2-83b4-376d3223d132" /> | <img width="480" height="800" alt="image" src="https://github.com/user-attachments/assets/84b45949-ed61-4924-af1b-d570c4c61e13" /> | ### Keyboard States | ABC Mode | Symbol Mode | URL Mode | |----------|-------------|----------| | <img width="480" height="280" alt="image" src="https://github.com/user-attachments/assets/6397a82e-50b8-4d03-92e0-f707ed7c9054" /> | <img width="480" height="280" alt="image" src="https://github.com/user-attachments/assets/205d34fe-0413-49e9-9db2-30569c297ba0" /> | <img width="480" height="280" alt="image" src="https://github.com/user-attachments/assets/801ddeab-e082-4a22-a9df-c66adb1afc16" /> | | Cursor Mode | Password Toggle | |-------------|-----------------| | <img width="480" height="800" alt="image" src="https://github.com/user-attachments/assets/841773e1-7a3c-45e5-aa89-e5787255608c" /> | <img width="480" height="800" alt="image" src="https://github.com/user-attachments/assets/9487a0b3-3f47-41ed-9cd3-b24e56e342a8" /> | ## Changes ### Layout (10-column uniform grid) - Reduced from 13/11/10 columns per row to **10 uniform columns** across all rows - Keyboard now uses **90% of screen width** (was ~66%) - Row 0: Numbers `1-9, 0` with secondary symbols (`!@#$%^&*()`) - Rows 1-3: Standard QWERTY letters - Bottom row: `shift` | `#@!` | `___` | `←` | `OK` ### New Symbol Mode (#@!) - New mode toggle key `#@!` / `abc` switches between letter and symbol layouts - Symbol layout: 4 rows (numbers, inverted symbols, paired symbols, loose symbols) - Covers all 95 printable ASCII characters - **No secondary hints, no long-press** in symbol mode (simple and direct) - SHIFT key remains visible but **disabled** in symbol mode ### URL Mode - In `InputType::Url`, the Space key becomes a **URL toggle** button - Activating URL mode replaces the 4 content rows with a **3×3 grid of URL snippets**: - Col 0 (protocols): `https://`, `http://`, `/opds` - Col 1 (hosts/ports): `www.`, `192.168.`, `:8080` - Col 2 (domains): `.com`, `.org`, `.net` - Snippets are inserted as full strings at the cursor position - URL mode **persists** after inserting a snippet (does not auto-deactivate) - Column alignment: col 0 over ABC, col 1 over URL, col 2 over Del - Up/Down navigation maps `bottomCol - 1` / `urlCol + 1` - SHIFT disabled in URL mode - SpecMode (`abc`) exits URL mode back to ABC - SpecSpace (`URL`) toggles URL mode on/off; selection always stays on the URL button - Button styled with `KeyboardKeyType::Mode` for consistent outline ### Cursor Mode - **Enter**: Long-press Up (500ms) while in keyboard mode - **Exit**: Short-press Down while in cursor mode (resets `passwordVisible`, clears toggle position) - **Navigate**: Left/Right move cursor position within text (one position per press, no continuous repeat) - **Visual**: - Keyboard mode: underline cursor (2px line + serifs) - Cursor mode: inverted block cursor (black fill + white character) - Block width adapts to the actual character width under cursor (minimum 6px for narrow chars like space) - Block position includes inter-character kerning offset for correct alignment (calculated via string-difference: `getTextWidth(before+char) - getTextWidth(before) - getTextWidth(char)`) - End-of-text: thin 6px block - Password hidden: 3-part drawing (Part 1 + block + Part 3) to prevent block overflow onto `*` characters - Toggle position: caret ("I") cursor at saved position, `[abc]`/`[***]` label with inverted selection - **Inactive key styling**: - BaseTheme: 2px outline rectangle - LyraTheme: gray filled rounded rectangle (`Color::LightGray`) - **Password toggle position**: in cursor mode (Password only), Hold Right (500ms) enters toggle — caret cursor shows saved position, `[abc]`/`[***]` label becomes selected. Press Confirm to toggle `passwordVisible`. Press Left to restore cursor to saved position. Right from toggle is a no-op. Down from toggle exits to keyboard. - `cursorPos` persists between keyboard and cursor modes ### Password Mode - `InputType::Password` enum replaces `bool isPassword` parameter - Text is masked with `*` except for one revealed character: - Keyboard mode: reveals character at `cursorPos - 1` - Cursor mode: no reveal in display text (block cursor draws actual char directly) - **Toggle `[abc]`/`[***]`**: accessible via cursor mode — Hold Right (500ms) enters toggle position, Confirm toggles visibility, Left exits back to cursor. Caret ("I") shown at saved position while in toggle. - `passwordVisible` resets to `false` when exiting cursor mode - **Long-press Del (1.5s)**: clears all text and resets cursor to 0 ### InputType Enum - Replaced `bool isPassword` constructor parameter with `enum class InputType { Text, Password, Url }` - Callers updated: `WifiSelectionActivity`, `KOReaderSettingsActivity`, `CalibreSettingsActivity` ### Contextual Tips - `"Tips:"` header followed by context-sensitive hints, centered between text field underline and keyboard as a block - ABC mode: `"Hold SELECT for UPPERCASE or secondary char"` (shift ON: `"lowercase"` variant) + `"Hold DEL to clear all text"` (only if text not empty) - ABC + `InputType::Url`: same + `"Press URL for snippets"` - Symbol mode: `"Hold DEL to clear all text"` (only if text not empty) - URL mode: `"Press ABC to exit URL mode"` + `"Hold DEL to clear all text"` (only if text not empty) - Cursor mode: `"Press DOWN to return to keyboard"` ### Hint Phases (cursor mode, Password only) - **Phase 1**: `"Hold UP to edit entry"` — shown after 2× DEL press, auto-hides after 4s, positioned below underline - **Phase 2**: `"Press < or > to move cursor"` + dynamic password toggle hint — shown when entering cursor mode, positioned below underline, visible until exit - When `!passwordVisible`: `"Hold > then press [abc] to show password"` - When `passwordVisible`: `"Hold > then press [***] to hide password"` - When in toggle position: `"Press < to return to cursor position"` ### Long-Press Alternative Character - Holding Confirm (>500ms) inserts the **alternative character** instead of the primary - Letters: long-press inserts opposite case (e.g., `a`→`A`, `A`→`a`) - Numbers/symbols (row 0): long-press inserts secondary (e.g., `0`→`)`, `)`→`0`) - Only active in ABC mode; disabled in Symbol mode and URL mode - **`InputType::Url`**: Hold SELECT on ABC rows 1+ (letters) returns primary character only (same as short press). Row 0 (symbols) still returns secondary character on Hold SELECT. ### Shift (2 sticky states) - Reduced from 3 states (shift/SHIFT/LOCK) to **2 sticky states** (shift/SHIFT) - Shift stays active after typing until manually toggled off - Label: `shift` (off) / `SHIFT` (on) ### SpecialKeyType Enum - `enum class SpecialKeyType { Shift, Mode, Space, Del, Ok }` replaces plain `enum` (`SpecShift`, `SpecMode`, etc.) for type safety - All switch cases updated to `SpecialKeyType::*` with `static_cast<int>()` for array indexing - `onExit()` reverted to simple `Activity::onExit()` call (half-refresh removed) - **Bottom row column mapping**: navigating up/down between content rows and bottom row uses `col/2` and `col*2` formulas for consistent positioning (10 cols ↔ 5 cols) - **URL mode column mapping**: `bottomCol - 1` / `urlCol + 1` (3 cols ↔ 5 cols) - **Wrap-around**: row 0 → up → bottom row and bottom row → down → row 0 both apply correct column mapping ### Visual Improvements (both Base and Lyra themes) - **Space key**: underscore-style horizontal line (60% of key width, 3px thick) - **Delete key**: arrow `←` drawn with lines (3px thick) instead of "DEL" text - **Secondary label** (ABC row 0): small hint in top-right corner with separation from primary number - **BaseTheme**: selection uses **inverted fill** (black rect + white text) instead of `[bracket]` markers - **BaseTheme**: text field brackets drawn as **stretchable lines** that adapt to multi-line input (1px normal, 3px cursor mode) - **LyraTheme**: text field uses **fixed-width underline** (16px margins, 8px each side) instead of stretchable line (2px normal, 3px cursor mode) - **Both themes**: special keys (shift, mode, space, del, OK) have bordered/bordered-rounded rectangles - **Font size**: keyboard uses `UI_12_FONT_ID` in both themes (was `UI_10` in Base) - **Key height**: 40px in all themes for better proportions - **Layout unification**: text and password toggle are left-aligned in all themes (`keyboardCenteredText = false` for Lyra/Lyra3Covers) - **`primaryOffset` removed**: dead code eliminated from BaseTheme and LyraTheme `drawKeyboardKey` ### New Theme Metrics - `keyboardVerticalOffset`: per-theme vertical adjustment of keyboard position - Base: `-13`, Lyra: `-7` - `keyboardBottomKeySpacing`: independent spacing for bottom row keys - Base: `5`, Lyra: `5` - Bottom-aligned keyboard in both themes for consistent vertical positioning - Bottom row total width calculated to match content rows width (10-col based, consistent across modes) - 4px extra gap between content rows and bottom row when `bkSpacing > 0` - `keyboardCenteredText`: `false` for all themes (unified left-aligned text) ### Defensive Improvements - **State reset on re-entry**: `onEnter()` resets all mutable state (`symMode`, `urlMode`, `cursorMode`, `togglePos`, `passwordVisible`, `shiftState`, `selectedRow`, `selectedCol`, `rightHeld`, `rightLongHandled`, `savedCursorPos`, `rightStartCursorPos`, `delPressCount`, `hintVisible`, `hintShowTime`) — prevents stale state when re-entering the keyboard - **Bounds checking**: `insertChar`/`insertString` clamp `cursorPos` to `text.length()` before inserting - **Empty string guard**: `insertString` returns early on empty string - **`std::string::npos`**: used instead of `SIZE_MAX` for size_t sentinel (proper C++ idiom) - **`<algorithm>` header**: included for `std::max` ## Files Modified | File | Changes | |------|---------| | `src/activities/util/KeyboardEntryActivity.h` | `InputType` enum, `KeyDef` struct, 10-col layouts, cursor/password/URL/toggle state, hints (`delPressCount`, `hintVisible`, `hintShowTime`), held vars (`rightHeld`, `rightLongHandled`, `savedCursorPos`, `rightStartCursorPos`), `mapColContentBottom` helper | | `src/activities/util/KeyboardEntryActivity.cpp` | Complete rewrite: layout rendering, symbol/cursor/password/URL modes, toggle position, long-press, contextual tips, hint phases, block cursor kerning alignment, defensive bounds checks, state reset | | `src/components/themes/BaseTheme.h` | `KeyboardKeyType` enum, new `drawTextField`/`drawKeyboardKey` signatures, `keyboardVerticalOffset`, `keyboardBottomKeySpacing` metrics | | `src/components/themes/BaseTheme.cpp` | Redesigned `drawTextField` (stretchable brackets), `drawKeyboardKey` (inverted selection, space/delete graphics, secondary label, inactive selection), removed `primaryOffset` dead code | | `src/components/themes/lyra/LyraTheme.h` | Override signatures, `keyboardVerticalOffset`, `keyboardBottomKeySpacing`, `keyboardKeyHeight` adjustments | | `src/components/themes/lyra/LyraTheme.cpp` | `drawTextField` (fixed underline), `drawKeyboardKey` (rounded rects for special keys, space/delete graphics, secondary label, inactive selection), removed `primaryOffset` dead code | | `src/components/themes/lyra/Lyra3CoversTheme.h` | `keyboardCenteredText = false`, `keyboardVerticalOffset = -7`, inherits Lyra overrides | | `src/activities/network/WifiSelectionActivity.cpp` | `bool isPassword` → `InputType::Password` | | `src/activities/settings/KOReaderSettingsActivity.cpp` | `bool isPassword` → `InputType::Text`/`InputType::Password`/`InputType::Url` | | `src/activities/settings/CalibreSettingsActivity.cpp` | `bool isPassword` → `InputType::Text`/`InputType::Password`/`InputType::Url` | ## Backward Compatibility - **API change**: Constructor parameter changed from `bool isPassword` to `InputType inputType` (default `InputType::Text`) - **All callers updated**: WiFi, KOReader, and Calibre integrations migrated to new `InputType` enum ## Testing ### Input & Text Handling - [x] Empty input → press OK (submit empty string) - [x] Back button → cancel (no text returned) - [x] Pre-filled initial text (e.g., editing existing WiFi password) - [x] Password mode: text masked with `*` characters, one character revealed - [x] Delete on empty text (no crash) - [x] Very long text near maxLength limit - [x] URL with path and port (~60 chars) - [x] Multi-line text wrapping in input field - [x] Space insert in middle of text (cursor mode) - [x] Delete last character repeatedly - [ ] Type all 95 printable ASCII characters ### Mode Switching - [x] ABC → #@! preserves typed text and cursor position - [x] #@! → ABC preserves typed text and cursor position - [x] Shift state preserved when switching modes - [x] Switch modes multiple times rapidly ### Shift Behavior - [x] Shift OFF → type letter → inserts lowercase, shift stays OFF - [x] Shift ON → type letter → inserts uppercase, shift stays ON - [x] Shift ON → type number → inserts symbol, shift stays ON - [x] Shift ON → navigate rows → shift stays ON - [x] Shift ON → switch to #@! → shift shows "shift" (disabled) - [x] Shift ON → switch to ABC → shift state preserved - [x] Shift ON → switch to URL → shift shows "shift" (disabled) - [x] Shift disabled in URL mode: pressing shift does nothing ### Long-Press - [x] Long-press letter with shift OFF → inserts uppercase - [x] Long-press letter with shift ON → inserts lowercase - [x] Long-press number → inserts secondary symbol - [x] Long-press symbol (row 0) → inserts opposite (number) - [x] Long-press key without secondary (e.g., `-`, `=` in rows 2-3) → inserts primary character on release - [x] Long-press on special keys (shift, mode, space, del, ok) → no alternative inserted - [x] Long-press in #@! mode → no effect (disabled) - [x] Long-press in URL mode → no effect (disabled) - [x] Long-press number in row 0 with InputType::Url → inserts secondary symbol (same as non-URL) - [x] Short press after cancelled long-press → normal behavior - [x] Long-press at maxLength → no character inserted - [x] Long-press Del (1.5s) → clears all text ### Cursor Mode - [x] Long-press Up → enters cursor mode - [x] Short-press Down → exits cursor mode (resets passwordVisible) - [x] Left/Right navigate within text - [x] Left at position 0 → no movement - [x] Right at end of text → no movement in Text mode, enters toggle in Password mode (Hold Right) - [x] Block cursor visual: correct width for character, thin block at end - [x] Underline cursor visual (keyboard mode): correct position with serifs - [x] Inactive key styling: outline (Base) or gray fill (Lyra) on selected key - [x] Typing with cursor mid-text → inserts at cursor position - [x] Deleting with cursor mid-text → deletes character before cursor - [x] Exit cursor mode → type at cursor position (inserts mid-text, not at end) - [x] Exit cursor mode from toggle → cursor at saved position (not end of text) ### Password Mode - [x] Masked text with one revealed character at `cursorPos - 1` - [x] Cursor mode: block shows actual character, display text all `*` - [x] Toggle `[abc]`/`[***]`: Hold Right (500ms) in cursor mode enters toggle, Confirm toggles visibility, Left exits back to cursor - [x] Exiting cursor mode resets `passwordVisible` to false - [x] Long-press Del clears all text ### URL Mode - [x] URL toggle activates/deactivates URL mode - [x] URL button stays selected after toggle (both on and off) - [x] Deactivating URL mode returns to ABC (not SYM) - [x] 3×3 snippet grid displays correctly - [x] Column alignment: col 0 over ABC, col 1 over URL, col 2 over Del - [x] Snippet insertion: inserts full string at cursor position - [x] URL mode persists after snippet insertion - [x] Shift disabled in InputType::Url - [x] SpecMode (`abc`) exits URL mode to ABC - [x] Up/Down navigation between URL grid and bottom row ### Re-entry State Reset - [x] Enter keyboard → activate URL mode → exit → re-enter → URL mode OFF - [x] Enter keyboard → switch to SYM → exit → re-enter → ABC mode - [x] Enter keyboard → enter cursor mode → exit → re-enter → keyboard mode - [x] Enter keyboard → enter toggle pos → exit → re-enter → togglePos OFF - [x] Enter keyboard → activate shift → exit → re-enter → shift OFF - [x] Enter password keyboard → toggle password visible → exit → re-enter → password hidden ### Navigation - [x] Left/right wrap-around within content rows - [x] Left/right wrap-around within bottom row - [x] Up from row 0 → bottom row (correct column mapping) - [x] Down from bottom row → row 0 (correct column mapping) - [x] Up from bottom row → last content row (correct column) - [x] Down from last content row → bottom row (correct column) - [x] Navigate horizontally in bottom row, then up → correct content column - [x] Navigate horizontally in bottom row, then down (wrap) → correct content column ### Visual (both themes) - [x] Secondary hints only on ABC row 0 - [x] No secondary hints in #@! mode or URL mode - [x] No secondary hints on letter rows (1-3) - [x] Space bar: horizontal line centered, not touching edges - [x] Delete: arrow `←` drawn correctly - [x] Selected key: inverted colors (black fill, white text) - [x] All special keys have border rectangles - [x] Fixed underline in text field (Both themes) - [x] Mode key label: `#@!` in ABC mode, `abc` in symbol mode, `abc` in URL mode - [x] URL key label: `URL` (only in InputType::Url), styled same as other bottom keys - [x] Shift label: `shift` when OFF, `SHIFT` when ON, `shift` when disabled (SYM/URL) - [x] Both themes: bottom row total width matches content rows width - [x] URL snippet grid centered over ABC/URL/Del buttons ### Device & Theme Coverage - [ ] Base Theme on X3 - [x] Base Theme on X4 - [ ] Lyra Theme on X3 - [x] Lyra Theme on X4 - [ ] Lyra Extended Theme on X3 - [x] Lyra Extended Theme on X4 ### Toggle Position - [x] Hold Right > 500ms in cursor mode (Password) → enters toggle, caret visible at saved position - [x] Short-press Right in cursor mode (Password) → advances cursor 1 position, does not jump to toggle - [x] Short-press Left in cursor mode (Password) → moves cursor left 1 position, from toggle returns to saved position - [x] Confirm in toggle → toggles `passwordVisible` - [x] Left from toggle → returns to saved position, caret disappears, block cursor appears - [x] Right from toggle → no-op - [x] Down from toggle → exits to keyboard, cursor at saved position - [x] Hold Right in cursor mode (InputType::Text) → no effect - [x] Hold Right in cursor mode (InputType::Url) → no effect - [x] Hold Right < 500ms released in cursor mode (Password) → short press, advances cursor 1 - [x] No continuous repeat when holding Left or Right in cursor mode ### Caret Visual in Toggle - [x] In toggle: caret "I" visible at saved cursor position - [x] Character under cursor visible (no gap) in password not-visible mode - [x] Character under cursor visible in password visible mode - [x] `[abc]`/`[***]` label with inverted selection in toggle ### Contextual Tips - [x] `"Tips:"` header centered above contextual hints - [x] Single tip → `"Tips:"` + one line - [x] Multiple tips → `"Tips:"` + multiple lines, all centered as block - [x] No tips shown when not applicable (e.g., ABC with empty text and non-URL) - [x] `"UPPERCASE"` shown when shift OFF - [x] `"lowercase"` shown when shift ON - [x] `"secondary char"` shown for InputType::Url ### Hint Phases - [x] 2× DEL → Phase 1 appears ("Hold UP to edit entry") - [x] Phase 1 auto-hides after 4s - [x] Phase 2 appears when entering cursor mode ("Press < or > to move cursor") - [x] Phase 2 shows "Hold > then press [abc] to show password" when `!passwordVisible` - [x] Phase 2 shows "Hold > then press [***] to hide password" when `passwordVisible` - [x] Phase 2 shows "Press < to return to cursor position" when in toggle - [x] Phase 2 disappears when exiting cursor mode ### Long-Press `InputType::Url` Behavior - [x] Hold SELECT on letter rows (rows 1+) with InputType::Url → same character as short press - [x] Hold SELECT on row 0 with InputType::Url → secondary character works normally ### Number Row Reorder - [x] Number row order: 1-9, 0 left to right - [x] `(` and `)` are adjacent (positions 8 and 9) via secondary labels - [x] Long-press on row 0 returns correct secondary symbols in new order - [x] SYM row 1: `(` and `)` also adjacent (positions 8 and 9) ### Block Cursor Alignment - [x] Block cursor correctly positioned for consecutive spaces (kerning offset applied) - [x] Block cursor correctly positioned for mixed characters (letters, numbers, symbols) - [x] Block width minimum 6px for narrow characters (space) — visible as block, not thin line - [x] Password hidden: 3-part drawing prevents block overflow onto `*` characters - [x] Password visible: block post-loop draws correctly on continuous text (no 3-part needed) - [x] End-of-text block: thin 6px block at correct position ### Integration - [x] WiFi password entry (connect to network) - [ ] KOReader username, password, and sync server URL - [ ] Calibre OPDS URL, username, and password - [ ] Calibre OPDS URL: empty → opens with "https://" prefilled - [ ] Calibre OPDS URL: type "http://" or "https://" only → saved as empty - [ ] Calibre OPDS URL: type full URL → saved correctly - [ ] Calibre OPDS URL: existing URL → opens with existing URL (not "https://" prefill) |
||
|
|
cced77783f |
feat: add orientation-aware popups for reader activities (#1428)
## Summary Make popups (like "Going to sleep") respect the current screen orientation when shown from reader activities. **What changes are included?** - Apply reader orientation in SleepActivity before showing popup when `lastSleepFromReader` is true - Make popup Y-position proportional to screen height (7.5% for BaseTheme, 16.5% for LyraTheme) instead of hardcoded pixel values, ensuring correct positioning in both portrait and landscape modes. - Add `isReaderActivity()` override to all reader sub-screens (menu, chapter selection, percent selection, footnotes, QR display, KOReader sync), so sleep popups rotate correctly when entering sleep from any reader context. ## Additional Context <img src="https://github.com/user-attachments/assets/47d88c2c-ffc5-41a7-b3f2-af272ea0150e" width="400" height="240"> --- ### 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 Opus 4.5) |
||
|
|
1bd7a1de67 |
refactor: Deduplicate battery drawing code and fix Lyra charging indicator (#1437)
## Summary **What is the goal of this PR?** Following up on #1427: - Extracted shared battery drawing logic, including lightning bolt, to reduce duplication. - In Lyra with segmented battery the lightning bolt was hard to see, so when charging Lyra now uses a solid battery fill. --- ### 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**_ |
||
|
|
23aad213fc |
refactor: Removed redundant FsFile close() calls (#1434)
## Summary **What is the goal of this PR?** (e.g., Implements the new feature for file uploading.) `DESTRUCTOR_CLOSES_FILE=1` is set in platformio.ini, which makes SdFat's FsBaseFile destructor call close() automatically when a file goes out of scope. Three categories of file close calls remain untouched: 1. Close before Storage.remove() on the same path: ScreenshotUtil.cpp closes the file before deleting it on write error. The remove might fail if the file is still open. 2. Close before reopening the same variable: Epub.cpp writes a temp NCX/nav file, closes it, then reopens it for reading. The RecentBooksStore.cpp close before saveToFile() is the same pattern, it rewrites the same file. 3. Close on member variables: BookMetadataCache.cpp (bookFile, spineFile, tocFile), Section.cpp (file), XtcParser.cpp (m_file), ZipFile.cpp (file). These persist beyond any single function scope, so the destructor timing doesn't match the intended close point. --- ### 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**_ |
||
|
|
9b3885135f |
feat: Initial support for the x3 (#875)
## Summary Adds Xteink X3 hardware support to CrossPoint Reader. The X3 uses the same SSD1677 e-ink controller as the X4 but with a different panel (792x528 vs 800x480), different button layout, and an I2C fuel gauge (BQ27220) instead of ADC-based battery reading. All X3-specific behavior is gated by runtime device detection — X4 behavior is unchanged. Depends on community-sdk X3 support: open-x4-epaper/community-sdk#19 (merged). ## Changes ### HAL Layer **HalGPIO** (`lib/hal/HalGPIO.cpp/.h`) - I2C-based device fingerprinting at boot: probes for BQ27220 fuel gauge, DS3231 RTC, and QMI8658 IMU to distinguish X3 from X4 - Detection result cached in NVS for fast subsequent boots - Exposes `deviceIsX3()` / `deviceIsX4()` helpers used throughout the codebase - X3 button mapping (7 GPIOs vs X4's layout) - USB connection detection and wake classification for X3 **HalDisplay** (`lib/hal/HalDisplay.cpp/.h`) - Calls `einkDisplay.setDisplayX3()` before init when X3 is detected - Requests display resync after power button / flash wake events - Runtime display dimension accessors (`getDisplayWidth()`, `getDisplayHeight()`, `getBufferSize()`) - Exposed as global `display` instance for use by image converters **HalPowerManager** (`lib/hal/HalPowerManager.cpp/.h`) - X3 battery reading via I2C fuel gauge (BQ27220 at 0x55, SOC register) - X3 power button uses GPIO hold for deep sleep ### Display & Rendering **GfxRenderer** (`lib/GfxRenderer/GfxRenderer.cpp/.h`) - Buffer size and display dimensions are now runtime values (not compile-time constants) to support both panel sizes - X3 anti-aliasing tuning: only the darker grayscale level is applied to avoid washed-out text on the X3 panel. X4 retains both levels via `deviceIsX4()` gate **Image Converters** (`lib/JpegToBmpConverter`, `lib/PngToBmpConverter`) - Cover image prescale target uses runtime display dimensions from HAL instead of hardcoded 800x480 ### UI Themes **BaseTheme / LyraTheme** (`src/components/themes/`) - X3 button position mapping for the different physical layout - Adjusted UI element positioning for 792x528 viewport ### Boot & Init **main.cpp** - X3 hardware detection logging - Adjusted init sequence for X3 (no `HalSystem::begin()` dependency on X3 path) **HomeActivity** - Uses runtime `renderer.getBufferSize()` instead of static `GfxRenderer::getBufferSize()` FYI I did not add support for the gyro page turner. That can be it's own PR. |
||
|
|
71719e1d94 |
feat: battery charging indicator (mirroring PR #537) (#1427)
## Summary * **What is the goal of this PR?** All praise goes to @didacta for his PR #537. Just picked up the reviewer comments to contain the changes as suggested (there was no response for more than 6 weeks, so I wanted to reanimate this feature). Just one addition: should recognize usb cable plug ins / retractions and update the icon immediately * **What changes are included?** ## Additional Context see #537 --- ### 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 >**_ |
||
|
|
3b4f2a1129 |
feat: Auto Page Turn for Epub Reader (#1219)
## Summary * **What is the goal of this PR?** (e.g., Implements the new feature for file uploading.) - Implements auto page turn feature for epub reader in the reader submenu * **What changes are included?** - added auto page turn feature in epub reader in the submenu - currently there are 5 settings, `OFF, 1, 3, 6, 12` pages per minute ## Additional Context * Add any other information that might be helpful for the reviewer (e.g., performance implications, potential risks, specific areas to focus on). - Replacement PR for #723 - when auto turn is enabled, space reserved for chapter title will be used to indicate auto page turn being active - Back and Confirm button is used to disable it --- ### 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 (mainly code reviews)**_ |
||
|
|
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> |
||
|
|
35988ada55 |
feat: wrapped text in GfxRender, implemented in themes so far (#1141)
## Summary * **What is the goal of this PR?** (e.g., Implements the new feature for file uploading.) * **What changes are included?** Conrgegate the changes of #1074 , #1013 , and extended upon #911 by @lkristensen New function implemented in GfxRenderer.cpp ```C++ std::vector<std::string> GfxRenderer::wrappedText(const int fontId, const char* text, const int maxWidth, const int maxLines, const EpdFontFamily::Style style) const ``` Applied logic to all uses in Lyra, Lyra Extended, and base theme (continue reading card as pointed out by @znelson ## 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? _**< YES >**_ --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
f2fbdccd53 |
fix: Fix coverRendered flag (#1154)
## Summary * **What is the goal of this PR?** During low memory situations (which I encounterde a lot during my recent bugfixing activities) a cover was considered rendered even if the buffer could not be stored. * **What changes are included?** Proper assignment of flag logic ## 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**_ |
||
|
|
0eb8a9346b |
feat: Support for kerning and ligatures (#873)
## Summary **What is the goal of this PR?** Improved typesetting, including [kerning](https://en.wikipedia.org/wiki/Kerning) and [ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet). **What changes are included?** - The script to convert built-in fonts now adds kerning and ligature information to the generated font headers. - Epub page layout calculates proper kerning spaces and makes ligature substitutions according to the selected font.    ## Additional Context - I am not a typography expert. - The implementation has been reworked from the earlier version, so it is no longer necessary to omit Open Dyslexic, and kerning data now covers all fonts, styles, and codepoints for which we include bitmap data. - Claude Opus 4.6 helped with a lot of this. - There's an included test epub document with lots of kerning and ligature examples, shown in the photos. **_After some time to mature, I think this change is in decent shape to merge and get people testing._** After opening this PR I came across #660, which overlaps in adding ligature support. --- ### 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 Opus 4.6**_ --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
410c70ab89 |
perf: UITheme::getMetrics const and const-ref usage (#1094)
## Summary **What is the goal of this PR?** Small cleanup to make getTheme and getMetrics methods on UITheme const. They return const refs, so updated call sites to use `const auto&`. Realistically this won't make much performance difference, but it better conveys the nature of theme metrics being shared const state. --- ### 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**_ |
||
|
|
10a2678584 |
fix: Fixed book title in home screen (#1013)
## Summary * **What is the goal of this PR?** (e.g., Implements the new feature for file uploading.) * The goal is to fix the title of books in the Home Screen. Before  After:  * **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). --- ### 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, Cursor |
||
|
|
c9faf2a8c0 |
fix: continue reading card classic theme (#990)
## Summary * **What is the goal of this PR?** * **What changes are included?** - Adapt card width to cover image aspect ratio in Classic theme - Increase homeTopPadding from 20px to 40px to avoid overlap with battery icon - Card width now calculated from BMP dimensions instead of fixed 240px - Maximum card width limited to 90% of screen width - Falls back to original behavior (half screen width) when no cover available ## Additional Context * Solve conflicts in PR #683 Before: <img width="1052" height="1014" alt="image" src="https://github.com/user-attachments/assets/6c857913-d697-4e9e-9695-443c0a4c0804" /> 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? _**< YES >**_ |
||
|
|
cabbfcfd7e |
fix: Use HalPowerManager for battery percentage (#1005)
## Summary The introduction of `HalGPIO` moved the `BatteryMonitor battery` object into the member function `HalGPIO::getBatteryPercentage()`. Then, with the introduction of `HalPowerManager`, this function was moved to `HalPowerManager::getBatteryPercentage()`. However, the original `BatteryMonitor battery` object is still utilized by themes for displaying the battery percentage. This PR replaces these deprecated uses of `BatteryMonitor battery` with the new `HalPowerManager::getBatteryPercentage()` 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 **_ |
||
|
|
fdcd71e94d |
feat: Lyra Icons (#725)
/!\ This PR depends on https://github.com/crosspoint-reader/crosspoint-reader/pull/732 being merged first Also requires the https://github.com/open-x4-epaper/community-sdk/pull/18 PR ## Summary Lyra theme icons on the home menu, in the file browser and on empty book covers     ## Additional Context - Added a function to the open-x4-sdk renderer to draw transparent images - Added a scripts/convert_icon.py script to convert svg/png icons into a C array that can be directly imported into the project. Usage: ```bash python ./scripts/convert_icon.py 'path/to/icon.png' cover 32 32 ``` This will create a components/icons/cover.h file with a C array called CoverIcon, of size 32x32px. Lyra uses icons from https://lucide.dev/icons with a stroke width of 2px, that can be downloaded with any desired size on the site. > The file browser is noticeably slower with the addition of icons, and using an image buffer like on the home page doesn't help very much. Any suggestions to optimize this are welcome. --- ### 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**_ The icon conversion python script was generated by Copilot as I am not a python dev. --------- Co-authored-by: Dave Allie <dave@daveallie.com> |
||
|
|
e7ee6ff05e |
feat: Lyra screens (#732)
## Summary Implements Lyra theme for some more Crosspoint screens:       ## Additional Context - A bit of refactoring for list scrolling logic --- ### 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> |
||
|
|
d6f38d4441 |
fix: align battery icon based on context (UI / Reader) (#796)
Issues solved: #729 and #739 ## Summary * **What is the goal of this PR?** Currently, the battery icon and charge percentage were aligned to the left even for the UI, where they were positioned on the right side of the screen. This meant that when changing values of different numbers of digits, the battery would shift, creating a block of icons and text that was illegible. * **What changes are included?** - Add drawBatteryUi() method for right-aligned battery display in UI headers - Keep drawBattery() for left-aligned display in reader mode - Extract drawBatteryIcon() helper to reduce code duplication - Battery icon now stays fixed at right edge regardless of percentage digits - Text adjusts to left of icon in UI mode, to right of icon in reader mode ## Additional Context * Add any other information that might be helpful for the reviewer * This fix applies to both themes (Base and Lyra). --- ### 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 >**_ |
||
|
|
7ba5978848 |
feat: User-Interface I18n System (#728)
## Summary **What is the goal of this PR?** This PR introduces Internationalization (i18n) support, enabling users to switch the UI language dynamically. **What changes are included?** - Core Logic: Added I18n class (`lib/I18n/I18n.h/cpp`) to manage language state and string retrieval. - Data Structures: - `lib/I18n/I18nStrings.h/cpp`: Static string arrays for each supported language. - `lib/I18n/I18nKeys.h`: Enum definitions for type-safe string access. - `lib/I18n/translations.csv`: single source of truth. - Documentation: Added `docs/i18n.md` detailing the workflow for developers and translators. - New Settings activity: `src/activities/settings/LanguageSelectActivity.h/cpp` ## Additional Context This implementation (building on concepts from #505) prioritizes performance and memory efficiency. The core approach is to store all localized strings for each language in dedicated arrays and access them via enums. This provides O(1) access with zero runtime overhead, and avoids the heap allocations, hashing, and collision handling required by `std::map` or `std::unordered_map`. The main trade-off is that enums and string arrays must remain perfectly synchronized—any mismatch would result in incorrect strings being displayed in the UI. To eliminate this risk, I added a Python script that automatically generates `I18nStrings.h/.cpp` and `I18nKeys.h` from a CSV file, which will serve as the single source of truth for all translations. The full design and workflow are documented in `docs/i18n.md`. ### Next Steps - [x] Python script `generate_i18n.py` to auto-generate C++ files from CSV - [x] Populate translations.csv with initial translations. Currently available translations: English, Español, Français, Deutsch, Čeština, Português (Brasil), Русский, Svenska. Thanks, community! **Status:** EDIT: ready to be merged. As a proof of concept, the SPANISH strings currently mirror the English ones, but are fully uppercased. --- ### AI Usage Did you use AI tools to help write this code? _**< PARTIALLY >**_ I used AI for the black work of replacing strings with I18n references across the project, and for generating the documentation. EDIT: also some help with merging changes from master. --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: yeyeto2788 <juanernestobiondi@gmail.com> |
||
|
|
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>
|
||
|
|
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 |
||
|
|
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**_ |
||
|
|
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 **_ |
||
|
|
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> |
||
|
|
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    ## 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> |