Skip to content

feat: Lyra screens#732

Merged
daveallie merged 16 commits intocrosspoint-reader:masterfrom
CaptainFrito:feature/lyra-screens
Feb 19, 2026
Merged

feat: Lyra screens#732
daveallie merged 16 commits intocrosspoint-reader:masterfrom
CaptainFrito:feature/lyra-screens

Conversation

@CaptainFrito
Copy link
Contributor

@CaptainFrito CaptainFrito commented Feb 6, 2026

Summary

Implements Lyra theme for some more Crosspoint screens:

IMG_7960 Medium
IMG_7961 Medium
IMG_7962 Medium
IMG_7963 Medium
IMG_7964 Medium
IMG_7965 Medium

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

@lukestein
Copy link
Contributor

Looking good.

I notice that on the Wifi selection screen, the width of the black bar for the selected network varies between encrypted and unencrypted networks.

Also, the Exit button fails to exit the Create Hotspot or Network Transfer screens (it seems to have to be long-held), but I think that's our longstanding bug #579.

@CaptainFrito
Copy link
Contributor Author

I notice that on the Wifi selection screen, the width of the black bar for the selected network varies between encrypted and unencrypted networks.

Ah yes this is not great. The mockups don't actually have the black highlight for this screen, it looks better without it. I just didn't want to add another parameter to the drawList method which already has enough as it is, but it looks like we're gonna have to!

@CaptainFrito CaptainFrito changed the title feat: Lyra screens - File transfer feat: Lyra screens Feb 7, 2026
@CaptainFrito
Copy link
Contributor Author

More screens migrated (not all pictured)
IMG_7967 Medium
IMG_7969 Medium

@CaptainFrito
Copy link
Contributor Author

More screens migrated

IMG_7976 Medium

@CaptainFrito CaptainFrito force-pushed the feature/lyra-screens branch 4 times, most recently from cc42ec7 to 5003cee Compare February 9, 2026 08:16
@CaptainFrito
Copy link
Contributor Author

CaptainFrito commented Feb 9, 2026

IMG_8020 Medium

The home screen is updated with the 1-cover, 1-column layout that won the popular vote!

I moved the 3-cover layout to a separate theme file, Lyra3CoversTheme, to keep that as an additional theme option, but since it's not a very popular choice we can remove it if you'd like.

Edit: The extra theme with 3 covers is now called "Lyra Extended". Again we can keep it or not.

@CaptainFrito CaptainFrito force-pushed the feature/lyra-screens branch 2 times, most recently from 92a27a0 to 51151e1 Compare February 9, 2026 08:32
@CaptainFrito CaptainFrito mentioned this pull request Feb 9, 2026
@CaptainFrito CaptainFrito force-pushed the feature/lyra-screens branch 4 times, most recently from a2ffaa7 to ffec742 Compare February 9, 2026 13:43
@jpirnay
Copy link
Contributor

jpirnay commented Feb 9, 2026

I really like what you are doing, kudos.
There is one thing though, which needs addressing: you don't acknowledge the imposed margins when button indicators are present and the orientation is not portrait. In these cases the buttons overlay the content. EpubReaderMenuActivity is a working example, the WifiSelectionActivity is a non working one and where it is very obvious.

@CaptainFrito
Copy link
Contributor Author

I really like what you are doing, kudos. There is one thing though, which needs addressing: you don't acknowledge the imposed margins when button indicators are present and the orientation is not portrait. In these cases the buttons overlay the content. EpubReaderMenuActivity is a working example, the WifiSelectionActivity is a non working one and where it is very obvious.

Thanks! Good catch, I didn’t realize we could change the orientation in the menus now. Time to work on this.

@CaptainFrito
Copy link
Contributor Author

I really like what you are doing, kudos. There is one thing though, which needs addressing: you don't acknowledge the imposed margins when button indicators are present and the orientation is not portrait. In these cases the buttons overlay the content. EpubReaderMenuActivity is a working example, the WifiSelectionActivity is a non working one and where it is very obvious.

Thanks! Good catch, I didn’t realize we could change the orientation in the menus now. Time to work on this.

Wait no we still can’t rotate the menus, other than the in reader menu. What did you mean by the WifiSelectionActivity is a non working one?

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new UI theme option LYRA_3_COVERS with full theme implementation and wiring; extends BaseTheme/LyraTheme drawing APIs and UI metrics; refactors many activities to use metric-driven GUI helpers; updates translations and I18n keys; small API/field type adjustments (int → size_t) and renderer geometry fixes.

Changes

Cohort / File(s) Summary
Theme enum & settings
src/CrossPointSettings.h, src/SettingsList.h
Added LYRA_3_COVERS theme and added STR_THEME_LYRA_EXTENDED option in settings list.
I18n translations
lib/I18n/I18nKeys.h, lib/I18n/translations/*.yaml
Added STR_THEME_LYRA_EXTENDED across locales; minor French/Spanish text tweaks.
Theme wiring & UITheme
src/components/UITheme.h, src/components/UITheme.cpp
Wired Lyra3CoversTheme into theme selection and set metrics; forward-declared MappedInputManager.
Base theme API & metrics
src/components/themes/BaseTheme.h, src/components/themes/BaseTheme.cpp
Extended header/list APIs (subtitle), added drawSubHeader/drawHelpText/drawTextField/drawKeyboardKey, added progressBarHeight and keyboard metrics, added highlightValue flag to drawList.
Lyra theme core
src/components/themes/lyra/LyraTheme.h, src/components/themes/lyra/LyraTheme.cpp
Adjusted Lyra metrics, extended drawHeader/drawList signatures, added drawSubHeader/drawEmptyRecents/drawTextField/drawKeyboardKey, refactored recent cover rendering.
New Lyra3Covers theme
src/components/themes/lyra/Lyra3CoversTheme.h, src/components/themes/lyra/Lyra3CoversTheme.cpp
Added Lyra3CoversTheme class and metrics; implemented drawRecentBookCover (3-column grid, cover loading/caching, placeholders, selection highlight, buffer-store callback).
Activity render refactors
src/activities/network/..., src/activities/settings/..., src/activities/util/KeyboardEntryActivity.*, src/activities/home/MyLibraryActivity.cpp
Rewrote many renders to use UITheme/GUI metrics and new draw helpers; removed hard-coded coordinates and early returns; updated selection index types in several headers.
Keyboard entry API
src/activities/util/KeyboardEntryActivity.h, src/activities/util/KeyboardEntryActivity.cpp
Removed startY constructor parameter/member; replaced per-key selector rendering with GUI.drawKeyboardKey and metrics-driven keyboard layout.
Selection index type changes
src/activities/network/WifiSelectionActivity.h, src/activities/settings/CalibreSettingsActivity.h, src/activities/settings/KOReaderSettingsActivity.h
Changed selectedIndex/selectedNetworkIndex from int to size_t.
Calibre/Web server UI
src/activities/network/CalibreConnectActivity.cpp, src/activities/network/CrossPointWebServerActivity.cpp
Reworked SERVER_RUNNING/AP_STARTING and progress/QR rendering to metrics-driven layouts; inlined/removed legacy helper functions.
Renderer geometry fix
lib/GfxRenderer/GfxRenderer.cpp
Improved fillRoundedRect to respect per-corner rounding and avoid unnecessary fills.
Open-X4 SDK
open-x4-sdk
Submodule pointer update only.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Activity
participant UITheme
participant Storage
participant GfxRenderer
participant PersistCB as StoreCallback

Activity->>UITheme: drawRecentBookCover(rect, recentBooks, selectorIndex, storeCB)
UITheme->>Storage: load cover bitmaps if not cached
Storage-->>UITheme: cover data / not found
UITheme->>GfxRenderer: render grid (covers, placeholders, titles, selection highlight)
UITheme->>PersistCB: invoke storeCoverBuffer()
PersistCB-->>UITheme: success/failure
UITheme-->>Activity: drawing complete

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • daveallie
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Lyra screens' is concise and directly related to the main change: implementing the Lyra theme for additional CrossPoint screens.
Description check ✅ Passed The description is related to the changeset, providing context about Lyra theme implementation, refactoring of list scrolling logic, and including screenshots demonstrating the UI changes.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into master

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Comment @coderabbitai help to get the list of available commands and usage tips.

@jpirnay
Copy link
Contributor

jpirnay commented Feb 10, 2026

I really like what you are doing, kudos. There is one thing though, which needs addressing: you don't acknowledge the imposed margins when button indicators are present and the orientation is not portrait. In these cases the buttons overlay the content. EpubReaderMenuActivity is a working example, the WifiSelectionActivity is a non working one and where it is very obvious.

Thanks! Good catch, I didn’t realize we could change the orientation in the menus now. Time to work on this.

Wait no we still can’t rotate the menus, other than the in reader menu. What did you mean by the WifiSelectionActivity is a non working one?

Open the ReaderMenu (orientation aware) choose KoSync (another faulty layout), that will cause the wifi selector to appear

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/UITheme.cpp (1)

28-46: ⚠️ Potential issue | 🟡 Minor

Potential memory leak in setTheme.

When setTheme is called multiple times (e.g., via reload()), the previous currentTheme pointer is overwritten without being deleted, causing a memory leak. Consider deleting the old theme before allocating a new one.

🛠️ Proposed fix
 void UITheme::setTheme(CrossPointSettings::UI_THEME type) {
+  delete currentTheme;
+  currentTheme = nullptr;
+
   switch (type) {
     case CrossPointSettings::UI_THEME::CLASSIC:
src/components/themes/lyra/LyraTheme.cpp (1)

384-390: ⚠️ Potential issue | 🔴 Critical

Critical: Dangling pointer causes undefined behavior.

buttonLabel(i) returns a std::string by value. Calling .c_str() on this temporary and storing the result in label creates a dangling pointer because the temporary string is destroyed at the semicolon. When label is used in drawText at line 390, it reads freed memory.

This is inconsistent with the safe pattern used elsewhere in this file (e.g., lines 196-198 in drawList), where the string is stored in a variable first.

🐛 Proposed fix
-    const char* label = buttonLabel(i).c_str();
     const int textX = tileRect.x + 16;
     const int lineHeight = renderer.getLineHeight(UI_12_FONT_ID);
     const int textY = tileRect.y + (LyraMetrics::values.menuRowHeight - lineHeight) / 2;

     // Invert text when the tile is selected, to contrast with the filled background
-    renderer.drawText(UI_12_FONT_ID, textX, textY, label, true);
+    renderer.drawText(UI_12_FONT_ID, textX, textY, buttonLabel(i).c_str(), true);

Or store the string in a variable to keep it alive:

-    const char* label = buttonLabel(i).c_str();
+    const std::string label = buttonLabel(i);
     const int textX = tileRect.x + 16;
     const int lineHeight = renderer.getLineHeight(UI_12_FONT_ID);
     const int textY = tileRect.y + (LyraMetrics::values.menuRowHeight - lineHeight) / 2;

     // Invert text when the tile is selected, to contrast with the filled background
-    renderer.drawText(UI_12_FONT_ID, textX, textY, label, true);
+    renderer.drawText(UI_12_FONT_ID, textX, textY, label.c_str(), true);
🤖 Fix all issues with AI agents
In `@src/activities/network/CrossPointWebServerActivity.cpp`:
- Around line 446-448: The SSID is concatenated directly into the Wi‑Fi QR
payload (wifiConfig) without escaping reserved ZXing characters; update
CrossPointWebServerActivity.cpp to sanitize connectedSSID before building
wifiConfig by replacing/escaping any occurrences of backslash, semicolon, comma,
or colon (e.g. convert '\' to '\\', ';' to '\;', ',' to '\,', ':' to '\:');
implement a small helper (e.g. escapeWifiSSID or sanitizeSSID) and use that
escaped string when constructing wifiConfig and passing to drawQRCode to ensure
the QR payload remains valid for arbitrary SSIDs.

In `@src/components/themes/BaseTheme.cpp`:
- Line 20: The hardcoded constant subtitleY (constexpr int subtitleY = 738)
assumes a fixed screen size; remove or stop using this global constant and
compute subtitleY dynamically inside drawHeader (or wherever header rendering
occurs) using the current header rectangle and font metrics — e.g., calculate
subtitleY = rect.y + rect.height - renderer.getLineHeight(SMALL_FONT_ID) - 5 (or
similar) so the subtitle is always positioned relative to rect and the
renderer’s line height; update any references to subtitleY to use this computed
local value and delete the hardcoded constexpr to avoid conflicting layout on
different screen sizes.
🧹 Nitpick comments (16)
src/components/UITheme.h (1)

9-10: Unused forward declaration.

MappedInputManager is forward-declared but not referenced anywhere in this header. If it's not needed, consider removing it.

🧹 Proposed removal
-class MappedInputManager;
-
 class UITheme {
src/CrossPointSettings.h (1)

120-120: Consider adding a count sentinel for consistency.

Other enums in this file include a _COUNT sentinel value (e.g., SLEEP_SCREEN_MODE_COUNT, ORIENTATION_COUNT). Adding UI_THEME_COUNT would maintain consistency and simplify bounds checking.

♻️ Proposed change
-  enum UI_THEME { CLASSIC = 0, LYRA = 1, LYRA_3_COVERS = 2 };
+  enum UI_THEME { CLASSIC = 0, LYRA = 1, LYRA_3_COVERS = 2, UI_THEME_COUNT };
src/activities/settings/ClearCacheActivity.cpp (1)

78-82: Minor: "Clearing cache..." no longer bold.

The removal of the bold styling and the true parameter for text wrapping from the "Clearing cache..." message appears intentional but is a subtle UX change. Confirm this is the desired behavior, as other status messages in this file (e.g., "Cache Cleared" at line 85) retain bold styling.

src/components/UITheme.cpp (2)

7-7: Unused include.

MappedInputManager.h appears to be included but not used in this file. Consider removing it if not needed.


12-14: Remove unused constant SKIP_PAGE_MS.

The constant is defined but never used anywhere in the codebase. Remove it to reduce code clutter.

src/activities/network/WifiSelectionActivity.cpp (1)

593-595: Magic number in help text positioning.

The -15 offset in the Y coordinate calculation (pageHeight - metrics.buttonHintsHeight - metrics.contentSidePadding - 15) appears to be a hardcoded adjustment. Consider extracting this as a named constant or using a metric value for consistency with the theme system.

src/activities/settings/OtaUpdateActivity.cpp (1)

166-174: Missing button hints for terminal states.

The NO_UPDATE, FAILED, and FINISHED states render status text but don't display button hints to inform the user how to navigate back. The loop() method handles Back button presses for NO_UPDATE and FAILED, but users won't see visual guidance.

Consider adding button hints similar to WAITING_CONFIRMATION:

   } else if (state == NO_UPDATE) {
     renderer.drawCenteredText(UI_10_FONT_ID, top, "No update available", true, EpdFontFamily::BOLD);
+    const auto labels = mappedInput.mapLabels("« Back", "", "", "");
+    GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
   } else if (state == FAILED) {
     renderer.drawCenteredText(UI_10_FONT_ID, top, "Update failed", true, EpdFontFamily::BOLD);
+    const auto labels = mappedInput.mapLabels("« Back", "", "", "");
+    GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
   } else if (state == FINISHED) {
src/components/themes/lyra/Lyra3CoversTheme.cpp (1)

16-20: Remove unused coverWidth variable.

The coverWidth variable is declared in the anonymous namespace but never used in this file. This appears to be leftover from copying the structure from LyraTheme.cpp.

 namespace {
 constexpr int hPaddingInSelection = 8;
 constexpr int cornerRadius = 6;
-int coverWidth = 0;
 }  // namespace
src/components/themes/lyra/Lyra3CoversTheme.h (1)

1-3: Remove extraneous blank lines at file start.

Minor style issue: the file starts with two blank lines before #pragma once.

-
-
 `#pragma` once
src/components/themes/BaseTheme.cpp (2)

67-67: Remove or gate debug logging in production code.

The Serial.printf in drawProgressBar will output to serial on every progress update. Consider removing this debug statement or guarding it with a debug flag:

-  Serial.printf("Drawing progress bar: current=%u, total=%u, percent=%d\n", current, total, percent);

262-281: Remove unused local constants in drawSubHeader.

The constants underlineHeight and underlineGap are declared but never used in the function body:

 void BaseTheme::drawSubHeader(const GfxRenderer& renderer, Rect rect, const char* label, const char* rightLabel) const {
-  constexpr int underlineHeight = 2;  // Height of selection underline
-  constexpr int underlineGap = 4;     // Gap between text and underline
   constexpr int maxListValueWidth = 200;
src/components/themes/lyra/LyraTheme.cpp (2)

23-23: Mutable namespace-scope variable can cause persistent state issues.

coverWidth is modified at runtime (lines 300, 322) and never reset. Once a bitmap sets this width, subsequent calls will use that width even for different books or after the cover fails to load. Consider making this a class member variable or passing it as an output parameter to avoid shared mutable state.


307-307: Consider using const reference to avoid copy.

RecentBook book = recentBooks[0]; creates a full copy of the struct. Since the book is only read, using a const reference would be more efficient.

♻️ Suggested change
-    RecentBook book = recentBooks[0];
+    const RecentBook& book = recentBooks[0];
src/activities/settings/KOReaderAuthActivity.cpp (1)

126-148: Center the multi-line status block within the available content.

top is computed from a single-line height across the full page, but SUCCESS/FAILED render two lines. This makes the block sit low and can crowd header/button hints on smaller or landscape screens. Consider computing a block height and centering that (and, if available, within the content area below the header).

Proposed adjustment
-  const auto height = renderer.getLineHeight(UI_10_FONT_ID);
-  const auto top = (pageHeight - height) / 2;
+  const auto height = renderer.getLineHeight(UI_10_FONT_ID);
+  const auto lineCount = (state == SUCCESS || state == FAILED) ? 2 : 1;
+  const auto blockHeight = lineCount * height + (lineCount - 1) * 10;
+  const auto top = (pageHeight - blockHeight) / 2;
src/activities/network/CrossPointWebServerActivity.cpp (2)

26-27: Align QR code height with the rendered size.

The QR code is rendered as 33 modules × 6 px (= 198), but QR_CODE_HEIGHT is set to 200. This small mismatch can accumulate into layout drift. Consider deriving height from width to keep the geometry consistent.

🛠️ Suggested tweak
-constexpr int QR_CODE_HEIGHT = 200;
+constexpr int QR_CODE_HEIGHT = QR_CODE_WIDTH;

386-399: Avoid double‑drawing the header/subheader in SERVER_RUNNING.

render() draws the header/subheader and then renderServerRunning() draws them again, duplicating work each render. Let one path own the header/subheader to keep responsibilities clear and reduce buffer work.

♻️ Suggested refactor
-    GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight},
-                   isApMode ? "Hotspot Mode" : "Network Transfer", nullptr);
-
-    if (state == WebServerActivityState::SERVER_RUNNING) {
-      GUI.drawSubHeader(renderer, Rect{0, metrics.topPadding + metrics.headerHeight, pageWidth, metrics.tabBarHeight},
-                        connectedSSID.c_str());
-      renderServerRunning();
-    } else {
+    if (state == WebServerActivityState::SERVER_RUNNING) {
+      renderServerRunning();
+    } else {
+      GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight},
+                     isApMode ? "Hotspot Mode" : "Network Transfer", nullptr);
       const auto height = renderer.getLineHeight(UI_10_FONT_ID);
       const auto top = (pageHeight - height) / 2;
       renderer.drawCenteredText(UI_10_FONT_ID, top, "Starting Hotspot...");
     }

@lkristensen
Copy link

By the way if someone is interested in working on a multiline drawText function that wraps, so we can avoid truncating the title, that would be awesome!

Sounds like a good first issue. Would it make sense to create a multilinedText() function that works similar to truncatedText but instead of returning a single truncated string, returns a vector of strings that will fit the screen? That way you can still control the layout and know exactly where each string is.
I will be happy to do this, if the solution makes sense.

That's a great idea! If you look at the drawRecentBookCover in BaseTheme.cpp, there's an attempt at doing something like that, but it's very convoluted IMO. A centralized function in GFXRenderer that does what you're saying for a specified width would be a massive improvement.

I have created a pull request against your branch. I hope that is an appropriate way of contributing this, as it can be used directly. If you prefer the contribution be made in some other way, let me know.

I have added it directly to crosspoint, it can be found here: #911
@CaptainFrito will you be one of the reviewers?

@daveallie daveallie dismissed coderabbitai[bot]’s stale review February 19, 2026 10:15

Misconfigured coderabbit to block PRs

@daveallie daveallie merged commit e7ee6ff into crosspoint-reader:master Feb 19, 2026
6 checks passed
daveallie added a commit that referenced this pull request Feb 19, 2026
/!\ This PR depends on
#732 being
merged first

Also requires the
open-x4-epaper/community-sdk#18 PR

## Summary

Lyra theme icons on the home menu, in the file browser and on empty book
covers

![IMG_8023
Medium](https://github.com/user-attachments/assets/ba7c1407-94d2-4353-80ff-d5b800c6ac5b)
![IMG_8024
Medium](https://github.com/user-attachments/assets/edb59e13-b1c9-4c86-bef3-c61cc8134e64)
![IMG_7958
Medium](https://github.com/user-attachments/assets/d3079ce1-95f0-43f4-bbc7-1f747cc70203)
![IMG_8033
Medium](https://github.com/user-attachments/assets/f3e2e03b-0fa8-47b7-8717-c0b71361b7a8)


## 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 <[email protected]>
@pablohc
Copy link
Contributor

pablohc commented Feb 19, 2026

I just tried it and the navigation has improved incredibly, it feels super smooth!!! Thank you @CaptainFrito

saslv pushed a commit to saslv/crosspoint-reader that referenced this pull request Feb 19, 2026
saslv pushed a commit to saslv/crosspoint-reader that referenced this pull request Feb 19, 2026
/!\ This PR depends on
crosspoint-reader#732 being
merged first

Also requires the
open-x4-epaper/community-sdk#18 PR

## Summary

Lyra theme icons on the home menu, in the file browser and on empty book
covers

![IMG_8023
Medium](https://github.com/user-attachments/assets/ba7c1407-94d2-4353-80ff-d5b800c6ac5b)
![IMG_8024
Medium](https://github.com/user-attachments/assets/edb59e13-b1c9-4c86-bef3-c61cc8134e64)
![IMG_7958
Medium](https://github.com/user-attachments/assets/d3079ce1-95f0-43f4-bbc7-1f747cc70203)
![IMG_8033
Medium](https://github.com/user-attachments/assets/f3e2e03b-0fa8-47b7-8717-c0b71361b7a8)


## 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 <[email protected]>
el pushed a commit to el/crosspoint-reader that referenced this pull request Feb 19, 2026
el pushed a commit to el/crosspoint-reader that referenced this pull request Feb 19, 2026
/!\ This PR depends on
crosspoint-reader#732 being
merged first

Also requires the
open-x4-epaper/community-sdk#18 PR

## Summary

Lyra theme icons on the home menu, in the file browser and on empty book
covers

![IMG_8023
Medium](https://github.com/user-attachments/assets/ba7c1407-94d2-4353-80ff-d5b800c6ac5b)
![IMG_8024
Medium](https://github.com/user-attachments/assets/edb59e13-b1c9-4c86-bef3-c61cc8134e64)
![IMG_7958
Medium](https://github.com/user-attachments/assets/d3079ce1-95f0-43f4-bbc7-1f747cc70203)
![IMG_8033
Medium](https://github.com/user-attachments/assets/f3e2e03b-0fa8-47b7-8717-c0b71361b7a8)


## 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 <[email protected]>
lukestein pushed a commit to lukestein/crosspoint-reader that referenced this pull request Feb 20, 2026
lukestein pushed a commit to lukestein/crosspoint-reader that referenced this pull request Feb 20, 2026
/!\ This PR depends on
crosspoint-reader#732 being
merged first

Also requires the
open-x4-epaper/community-sdk#18 PR

## Summary

Lyra theme icons on the home menu, in the file browser and on empty book
covers

![IMG_8023
Medium](https://github.com/user-attachments/assets/ba7c1407-94d2-4353-80ff-d5b800c6ac5b)
![IMG_8024
Medium](https://github.com/user-attachments/assets/edb59e13-b1c9-4c86-bef3-c61cc8134e64)
![IMG_7958
Medium](https://github.com/user-attachments/assets/d3079ce1-95f0-43f4-bbc7-1f747cc70203)
![IMG_8033
Medium](https://github.com/user-attachments/assets/f3e2e03b-0fa8-47b7-8717-c0b71361b7a8)


## 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 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants