Re-applies changes that were accidentally discarded during a prior dry-run cherry-pick reset (git checkout -- .). - PR #1005: Use HalPowerManager for battery percentage (uint16_t return type, remove Battery.h, update theme files) - PR #1010: Fix dangling pointer in onGoToReader() - PR #1003: Render image placeholders while waiting for decode (adds isCached, renderPlaceholder, renderTextOnly, countUncachedImages, renderImagePlaceholders) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -61,6 +61,49 @@ std::unique_ptr<PageImage> PageImage::deserialize(FsFile& file) {
|
|||||||
return std::unique_ptr<PageImage>(new PageImage(std::move(ib), xPos, yPos));
|
return std::unique_ptr<PageImage>(new PageImage(std::move(ib), xPos, yPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PageImage::isCached() const { return imageBlock->isCached(); }
|
||||||
|
|
||||||
|
void PageImage::renderPlaceholder(GfxRenderer& renderer, const int xOffset, const int yOffset) const {
|
||||||
|
int x = xPos + xOffset;
|
||||||
|
int y = yPos + yOffset;
|
||||||
|
int w = imageBlock->getWidth();
|
||||||
|
int h = imageBlock->getHeight();
|
||||||
|
renderer.fillRect(x, y, w, h, true);
|
||||||
|
if (w > 2 && h > 2) {
|
||||||
|
renderer.fillRect(x + 1, y + 1, w - 2, h - 2, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Page::renderTextOnly(GfxRenderer& renderer, const int fontId, const int xOffset, const int yOffset) const {
|
||||||
|
for (auto& element : elements) {
|
||||||
|
if (element->getTag() == TAG_PageLine) {
|
||||||
|
element->render(renderer, fontId, xOffset, yOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Page::countUncachedImages() const {
|
||||||
|
int count = 0;
|
||||||
|
for (auto& element : elements) {
|
||||||
|
if (element->getTag() == TAG_PageImage) {
|
||||||
|
auto* img = static_cast<PageImage*>(element.get());
|
||||||
|
if (!img->isCached()) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Page::renderImagePlaceholders(GfxRenderer& renderer, const int xOffset, const int yOffset) const {
|
||||||
|
for (auto& element : elements) {
|
||||||
|
if (element->getTag() == TAG_PageImage) {
|
||||||
|
auto* img = static_cast<PageImage*>(element.get());
|
||||||
|
img->renderPlaceholder(renderer, xOffset, yOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// PageTableRow
|
// PageTableRow
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ class PageImage final : public PageElement {
|
|||||||
void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override;
|
void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override;
|
||||||
bool serialize(FsFile& file) override;
|
bool serialize(FsFile& file) override;
|
||||||
PageElementTag getTag() const override { return TAG_PageImage; }
|
PageElementTag getTag() const override { return TAG_PageImage; }
|
||||||
|
bool isCached() const;
|
||||||
|
void renderPlaceholder(GfxRenderer& renderer, int xOffset, int yOffset) const;
|
||||||
static std::unique_ptr<PageImage> deserialize(FsFile& file);
|
static std::unique_ptr<PageImage> deserialize(FsFile& file);
|
||||||
|
|
||||||
// Helper to get image block dimensions (needed for bounding box calculation)
|
// Helper to get image block dimensions (needed for bounding box calculation)
|
||||||
@@ -104,4 +106,8 @@ class Page {
|
|||||||
// Returns true if page has images and fills out the bounding box coordinates.
|
// Returns true if page has images and fills out the bounding box coordinates.
|
||||||
// If no images, returns false.
|
// If no images, returns false.
|
||||||
bool getImageBoundingBox(int& outX, int& outY, int& outWidth, int& outHeight) const;
|
bool getImageBoundingBox(int& outX, int& outY, int& outWidth, int& outHeight) const;
|
||||||
|
|
||||||
|
void renderTextOnly(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) const;
|
||||||
|
int countUncachedImages() const;
|
||||||
|
void renderImagePlaceholders(GfxRenderer& renderer, int xOffset, int yOffset) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -93,6 +93,11 @@ bool renderFromCache(GfxRenderer& renderer, const std::string& cachePath, int x,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
bool ImageBlock::isCached() const {
|
||||||
|
std::string cachePath = getCachePath(imagePath);
|
||||||
|
return Storage.exists(cachePath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
void ImageBlock::render(GfxRenderer& renderer, const int x, const int y) {
|
void ImageBlock::render(GfxRenderer& renderer, const int x, const int y) {
|
||||||
LOG_DBG("IMG", "Rendering image at %d,%d: %s (%dx%d)", x, y, imagePath.c_str(), width, height);
|
LOG_DBG("IMG", "Rendering image at %d,%d: %s (%dx%d)", x, y, imagePath.c_str(), width, height);
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class ImageBlock final : public Block {
|
|||||||
int16_t getHeight() const { return height; }
|
int16_t getHeight() const { return height; }
|
||||||
|
|
||||||
bool imageExists() const;
|
bool imageExists() const;
|
||||||
|
bool isCached() const;
|
||||||
|
|
||||||
BlockType getType() override { return IMAGE_BLOCK; }
|
BlockType getType() override { return IMAGE_BLOCK; }
|
||||||
bool isEmpty() override { return false; }
|
bool isEmpty() override { return false; }
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ void HalPowerManager::startDeepSleep(HalGPIO& gpio) const {
|
|||||||
esp_deep_sleep_start();
|
esp_deep_sleep_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
int HalPowerManager::getBatteryPercentage() const {
|
uint16_t HalPowerManager::getBatteryPercentage() const {
|
||||||
static const BatteryMonitor battery = BatteryMonitor(BAT_GPIO0);
|
static const BatteryMonitor battery = BatteryMonitor(BAT_GPIO0);
|
||||||
return battery.readPercentage();
|
return battery.readPercentage();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class HalPowerManager {
|
|||||||
void startDeepSleep(HalGPIO& gpio) const;
|
void startDeepSleep(HalGPIO& gpio) const;
|
||||||
|
|
||||||
// Get battery percentage (range 0-100)
|
// Get battery percentage (range 0-100)
|
||||||
int getBatteryPercentage() const;
|
uint16_t getBatteryPercentage() const;
|
||||||
|
|
||||||
// RAII lock to prevent low-power mode during critical work (e.g. rendering)
|
// RAII lock to prevent low-power mode during critical work (e.g. rendering)
|
||||||
class Lock {
|
class Lock {
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <BatteryMonitor.h>
|
|
||||||
|
|
||||||
#define BAT_GPIO0 0 // Battery voltage
|
|
||||||
|
|
||||||
static BatteryMonitor battery(BAT_GPIO0);
|
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Battery.h"
|
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "CrossPointState.h"
|
#include "CrossPointState.h"
|
||||||
#include "MappedInputManager.h"
|
#include "MappedInputManager.h"
|
||||||
|
|||||||
@@ -1020,6 +1020,14 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
|
|||||||
// Force special handling for pages with images when anti-aliasing is on
|
// Force special handling for pages with images when anti-aliasing is on
|
||||||
bool imagePageWithAA = page->hasImages() && SETTINGS.textAntiAliasing;
|
bool imagePageWithAA = page->hasImages() && SETTINGS.textAntiAliasing;
|
||||||
|
|
||||||
|
if (page->countUncachedImages() > 0) {
|
||||||
|
page->renderTextOnly(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop);
|
||||||
|
page->renderImagePlaceholders(renderer, orientedMarginLeft, orientedMarginTop);
|
||||||
|
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||||
|
renderer.displayBuffer();
|
||||||
|
renderer.clearScreen();
|
||||||
|
}
|
||||||
|
|
||||||
page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop);
|
page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop);
|
||||||
|
|
||||||
// Draw bookmark ribbon indicator in top-right corner if current page is bookmarked
|
// Draw bookmark ribbon indicator in top-right corner if current page is bookmarked
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "BaseTheme.h"
|
#include "BaseTheme.h"
|
||||||
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
|
#include <HalPowerManager.h>
|
||||||
#include <HalStorage.h>
|
#include <HalStorage.h>
|
||||||
#include <Logging.h>
|
#include <Logging.h>
|
||||||
#include <Utf8.h>
|
#include <Utf8.h>
|
||||||
@@ -9,7 +10,6 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Battery.h"
|
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "I18n.h"
|
#include "I18n.h"
|
||||||
#include "RecentBooksStore.h"
|
#include "RecentBooksStore.h"
|
||||||
@@ -49,7 +49,7 @@ void drawBatteryIcon(const GfxRenderer& renderer, int x, int y, int battWidth, i
|
|||||||
|
|
||||||
void BaseTheme::drawBatteryLeft(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
void BaseTheme::drawBatteryLeft(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
||||||
// Left aligned: icon on left, percentage on right (reader mode)
|
// Left aligned: icon on left, percentage on right (reader mode)
|
||||||
const uint16_t percentage = battery.readPercentage();
|
const uint16_t percentage = powerManager.getBatteryPercentage();
|
||||||
const int y = rect.y + 6;
|
const int y = rect.y + 6;
|
||||||
|
|
||||||
if (showPercentage) {
|
if (showPercentage) {
|
||||||
@@ -64,7 +64,7 @@ void BaseTheme::drawBatteryLeft(const GfxRenderer& renderer, Rect rect, const bo
|
|||||||
void BaseTheme::drawBatteryRight(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
void BaseTheme::drawBatteryRight(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
||||||
// Right aligned: percentage on left, icon on right (UI headers)
|
// Right aligned: percentage on left, icon on right (UI headers)
|
||||||
// rect.x is already positioned for the icon (drawHeader calculated it)
|
// rect.x is already positioned for the icon (drawHeader calculated it)
|
||||||
const uint16_t percentage = battery.readPercentage();
|
const uint16_t percentage = powerManager.getBatteryPercentage();
|
||||||
const int y = rect.y + 6;
|
const int y = rect.y + 6;
|
||||||
|
|
||||||
if (showPercentage) {
|
if (showPercentage) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "LyraTheme.h"
|
#include "LyraTheme.h"
|
||||||
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
|
#include <HalPowerManager.h>
|
||||||
#include <HalStorage.h>
|
#include <HalStorage.h>
|
||||||
#include <I18n.h>
|
#include <I18n.h>
|
||||||
#include <Utf8.h>
|
#include <Utf8.h>
|
||||||
@@ -10,7 +11,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Battery.h"
|
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "RecentBooksStore.h"
|
#include "RecentBooksStore.h"
|
||||||
#include "components/UITheme.h"
|
#include "components/UITheme.h"
|
||||||
@@ -88,7 +88,7 @@ const uint8_t* iconForName(UIIcon icon, int size) {
|
|||||||
|
|
||||||
void LyraTheme::drawBatteryLeft(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
void LyraTheme::drawBatteryLeft(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
||||||
// Left aligned: icon on left, percentage on right (reader mode)
|
// Left aligned: icon on left, percentage on right (reader mode)
|
||||||
const uint16_t percentage = battery.readPercentage();
|
const uint16_t percentage = powerManager.getBatteryPercentage();
|
||||||
const int y = rect.y + 6;
|
const int y = rect.y + 6;
|
||||||
const int battWidth = LyraMetrics::values.batteryWidth;
|
const int battWidth = LyraMetrics::values.batteryWidth;
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ void LyraTheme::drawBatteryLeft(const GfxRenderer& renderer, Rect rect, const bo
|
|||||||
|
|
||||||
void LyraTheme::drawBatteryRight(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
void LyraTheme::drawBatteryRight(const GfxRenderer& renderer, Rect rect, const bool showPercentage) const {
|
||||||
// Right aligned: percentage on left, icon on right (UI headers)
|
// Right aligned: percentage on left, icon on right (UI headers)
|
||||||
const uint16_t percentage = battery.readPercentage();
|
const uint16_t percentage = powerManager.getBatteryPercentage();
|
||||||
const int y = rect.y + 6;
|
const int y = rect.y + 6;
|
||||||
const int battWidth = LyraMetrics::values.batteryWidth;
|
const int battWidth = LyraMetrics::values.batteryWidth;
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include "Battery.h"
|
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "CrossPointState.h"
|
#include "CrossPointState.h"
|
||||||
#include "KOReaderCredentialStore.h"
|
#include "KOReaderCredentialStore.h"
|
||||||
@@ -227,9 +226,9 @@ void onGoHome();
|
|||||||
void onGoToMyLibraryWithPath(const std::string& path);
|
void onGoToMyLibraryWithPath(const std::string& path);
|
||||||
void onGoToRecentBooks();
|
void onGoToRecentBooks();
|
||||||
void onGoToReader(const std::string& initialEpubPath) {
|
void onGoToReader(const std::string& initialEpubPath) {
|
||||||
|
const std::string bookPath = initialEpubPath; // Copy before exitActivity() invalidates the reference
|
||||||
exitActivity();
|
exitActivity();
|
||||||
enterNewActivity(
|
enterNewActivity(new ReaderActivity(renderer, mappedInputManager, bookPath, onGoHome, onGoToMyLibraryWithPath));
|
||||||
new ReaderActivity(renderer, mappedInputManager, initialEpubPath, onGoHome, onGoToMyLibraryWithPath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onGoToFileTransfer() {
|
void onGoToFileTransfer() {
|
||||||
|
|||||||
Reference in New Issue
Block a user