feat(ui): change popup logic (#442)
## Summary
* refactors Indexing popups into ScreenComponents (they had different
implementations in different files)
* removes Indexing popup for small chapters
* only show Indexing popup (without progress bar) for large chapters
(using same minimum file size condition as for progress bar before)
## Additional Context
* Having to show even single popup message and redraw the screen slows
down the flow significantly
* Testing results:
* Opening large chapter with progress bar - 11 seconds
* Same chapter without progress bar, only single Indexing popup - 5
seconds
---
### AI Usage
Did you use AI tools to help write this code? _**< PARTIALLY>**_
This commit is contained in:
committed by
GitHub
parent
f935b59a41
commit
f4df513bf3
@@ -42,6 +42,38 @@ void ScreenComponents::drawBattery(const GfxRenderer& renderer, const int left,
|
||||
renderer.fillRect(x + 2, y + 2, filledWidth, batteryHeight - 4);
|
||||
}
|
||||
|
||||
ScreenComponents::PopupLayout ScreenComponents::drawPopup(const GfxRenderer& renderer, const char* message) {
|
||||
constexpr int margin = 15;
|
||||
constexpr int y = 60;
|
||||
const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, message, EpdFontFamily::BOLD);
|
||||
const int textHeight = renderer.getLineHeight(UI_12_FONT_ID);
|
||||
const int w = textWidth + margin * 2;
|
||||
const int h = textHeight + margin * 2;
|
||||
const int x = (renderer.getScreenWidth() - w) / 2;
|
||||
|
||||
renderer.fillRect(x - 2, y - 2, w + 4, h + 4, true); // frame thickness 2
|
||||
renderer.fillRect(x, y, w, h, false);
|
||||
|
||||
const int textX = x + (w - textWidth) / 2;
|
||||
const int textY = y + margin - 2;
|
||||
renderer.drawText(UI_12_FONT_ID, textX, textY, message, true, EpdFontFamily::BOLD);
|
||||
renderer.displayBuffer();
|
||||
return {x, y, w, h};
|
||||
}
|
||||
|
||||
void ScreenComponents::fillPopupProgress(const GfxRenderer& renderer, const PopupLayout& layout, const int progress) {
|
||||
constexpr int barHeight = 4;
|
||||
const int barWidth = layout.width - 30; // twice the margin in drawPopup to match text width
|
||||
const int barX = layout.x + (layout.width - barWidth) / 2;
|
||||
const int barY = layout.y + layout.height - 10;
|
||||
|
||||
int fillWidth = barWidth * progress / 100;
|
||||
|
||||
renderer.fillRect(barX, barY, fillWidth, barHeight, true);
|
||||
|
||||
renderer.displayBuffer(HalDisplay::FAST_REFRESH);
|
||||
}
|
||||
|
||||
void ScreenComponents::drawBookProgressBar(const GfxRenderer& renderer, const size_t bookProgress) {
|
||||
int vieweableMarginTop, vieweableMarginRight, vieweableMarginBottom, vieweableMarginLeft;
|
||||
renderer.getOrientedViewableTRBL(&vieweableMarginTop, &vieweableMarginRight, &vieweableMarginBottom,
|
||||
|
||||
@@ -15,9 +15,20 @@ class ScreenComponents {
|
||||
public:
|
||||
static const int BOOK_PROGRESS_BAR_HEIGHT = 4;
|
||||
|
||||
struct PopupLayout {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
static void drawBattery(const GfxRenderer& renderer, int left, int top, bool showPercentage = true);
|
||||
static void drawBookProgressBar(const GfxRenderer& renderer, size_t bookProgress);
|
||||
|
||||
static PopupLayout drawPopup(const GfxRenderer& renderer, const char* message);
|
||||
|
||||
static void fillPopupProgress(const GfxRenderer& renderer, const PopupLayout& layout, int progress);
|
||||
|
||||
// Draw a horizontal tab bar with underline indicator for selected tab
|
||||
// Returns the height of the tab bar (for positioning content below)
|
||||
static int drawTabBar(const GfxRenderer& renderer, int y, const std::vector<TabInfo>& tabs);
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
|
||||
#include "CrossPointSettings.h"
|
||||
#include "CrossPointState.h"
|
||||
#include "ScreenComponents.h"
|
||||
#include "fontIds.h"
|
||||
#include "images/CrossLarge.h"
|
||||
#include "util/StringUtils.h"
|
||||
|
||||
void SleepActivity::onEnter() {
|
||||
Activity::onEnter();
|
||||
renderPopup("Entering Sleep...");
|
||||
|
||||
ScreenComponents::drawPopup(renderer, "Entering Sleep...");
|
||||
|
||||
if (SETTINGS.sleepScreen == CrossPointSettings::SLEEP_SCREEN_MODE::BLANK) {
|
||||
return renderBlankSleepScreen();
|
||||
@@ -31,20 +33,6 @@ void SleepActivity::onEnter() {
|
||||
renderDefaultSleepScreen();
|
||||
}
|
||||
|
||||
void SleepActivity::renderPopup(const char* message) const {
|
||||
const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, message, EpdFontFamily::BOLD);
|
||||
constexpr int margin = 20;
|
||||
const int x = (renderer.getScreenWidth() - textWidth - margin * 2) / 2;
|
||||
constexpr int y = 117;
|
||||
const int w = textWidth + margin * 2;
|
||||
const int h = renderer.getLineHeight(UI_12_FONT_ID) + margin * 2;
|
||||
// renderer.clearScreen();
|
||||
renderer.fillRect(x - 5, y - 5, w + 10, h + 10, true);
|
||||
renderer.fillRect(x + 5, y + 5, w - 10, h - 10, false);
|
||||
renderer.drawText(UI_12_FONT_ID, x + margin, y + margin, message, true, EpdFontFamily::BOLD);
|
||||
renderer.displayBuffer();
|
||||
}
|
||||
|
||||
void SleepActivity::renderCustomSleepScreen() const {
|
||||
// Check if we have a /sleep directory
|
||||
auto dir = SdMan.open("/sleep");
|
||||
|
||||
@@ -10,7 +10,6 @@ class SleepActivity final : public Activity {
|
||||
void onEnter() override;
|
||||
|
||||
private:
|
||||
void renderPopup(const char* message) const;
|
||||
void renderDefaultSleepScreen() const;
|
||||
void renderCustomSleepScreen() const;
|
||||
void renderCoverSleepScreen() const;
|
||||
|
||||
@@ -369,49 +369,11 @@ void EpubReaderActivity::renderScreen() {
|
||||
viewportHeight, SETTINGS.hyphenationEnabled)) {
|
||||
Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
|
||||
|
||||
// Progress bar dimensions
|
||||
constexpr int barWidth = 200;
|
||||
constexpr int barHeight = 10;
|
||||
constexpr int boxMargin = 20;
|
||||
const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, "Indexing...");
|
||||
const int boxWidthWithBar = (barWidth > textWidth ? barWidth : textWidth) + boxMargin * 2;
|
||||
const int boxWidthNoBar = textWidth + boxMargin * 2;
|
||||
const int boxHeightWithBar = renderer.getLineHeight(UI_12_FONT_ID) + barHeight + boxMargin * 3;
|
||||
const int boxHeightNoBar = renderer.getLineHeight(UI_12_FONT_ID) + boxMargin * 2;
|
||||
const int boxXWithBar = (renderer.getScreenWidth() - boxWidthWithBar) / 2;
|
||||
const int boxXNoBar = (renderer.getScreenWidth() - boxWidthNoBar) / 2;
|
||||
constexpr int boxY = 50;
|
||||
const int barX = boxXWithBar + (boxWidthWithBar - barWidth) / 2;
|
||||
const int barY = boxY + renderer.getLineHeight(UI_12_FONT_ID) + boxMargin * 2;
|
||||
|
||||
// Always show "Indexing..." text first
|
||||
{
|
||||
renderer.fillRect(boxXNoBar, boxY, boxWidthNoBar, boxHeightNoBar, false);
|
||||
renderer.drawText(UI_12_FONT_ID, boxXNoBar + boxMargin, boxY + boxMargin, "Indexing...");
|
||||
renderer.drawRect(boxXNoBar + 5, boxY + 5, boxWidthNoBar - 10, boxHeightNoBar - 10);
|
||||
renderer.displayBuffer();
|
||||
pagesUntilFullRefresh = 0;
|
||||
}
|
||||
|
||||
// Setup callback - only called for chapters >= 50KB, redraws with progress bar
|
||||
auto progressSetup = [this, boxXWithBar, boxWidthWithBar, boxHeightWithBar, barX, barY] {
|
||||
renderer.fillRect(boxXWithBar, boxY, boxWidthWithBar, boxHeightWithBar, false);
|
||||
renderer.drawText(UI_12_FONT_ID, boxXWithBar + boxMargin, boxY + boxMargin, "Indexing...");
|
||||
renderer.drawRect(boxXWithBar + 5, boxY + 5, boxWidthWithBar - 10, boxHeightWithBar - 10);
|
||||
renderer.drawRect(barX, barY, barWidth, barHeight);
|
||||
renderer.displayBuffer();
|
||||
};
|
||||
|
||||
// Progress callback to update progress bar
|
||||
auto progressCallback = [this, barX, barY, barWidth, barHeight](int progress) {
|
||||
const int fillWidth = (barWidth - 2) * progress / 100;
|
||||
renderer.fillRect(barX + 1, barY + 1, fillWidth, barHeight - 2, true);
|
||||
renderer.displayBuffer(HalDisplay::FAST_REFRESH);
|
||||
};
|
||||
const auto popupFn = [this]() { ScreenComponents::drawPopup(renderer, "Indexing..."); };
|
||||
|
||||
if (!section->createSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled, progressSetup, progressCallback)) {
|
||||
viewportHeight, SETTINGS.hyphenationEnabled, popupFn)) {
|
||||
Serial.printf("[%lu] [ERS] Failed to persist page data to SD\n", millis());
|
||||
section.reset();
|
||||
return;
|
||||
|
||||
@@ -207,28 +207,10 @@ void TxtReaderActivity::buildPageIndex() {
|
||||
|
||||
size_t offset = 0;
|
||||
const size_t fileSize = txt->getFileSize();
|
||||
int lastProgressPercent = -1;
|
||||
|
||||
Serial.printf("[%lu] [TRS] Building page index for %zu bytes...\n", millis(), fileSize);
|
||||
|
||||
// Progress bar dimensions (matching EpubReaderActivity style)
|
||||
constexpr int barWidth = 200;
|
||||
constexpr int barHeight = 10;
|
||||
constexpr int boxMargin = 20;
|
||||
const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, "Indexing...");
|
||||
const int boxWidth = (barWidth > textWidth ? barWidth : textWidth) + boxMargin * 2;
|
||||
const int boxHeight = renderer.getLineHeight(UI_12_FONT_ID) + barHeight + boxMargin * 3;
|
||||
const int boxX = (renderer.getScreenWidth() - boxWidth) / 2;
|
||||
constexpr int boxY = 50;
|
||||
const int barX = boxX + (boxWidth - barWidth) / 2;
|
||||
const int barY = boxY + renderer.getLineHeight(UI_12_FONT_ID) + boxMargin * 2;
|
||||
|
||||
// Draw initial progress box
|
||||
renderer.fillRect(boxX, boxY, boxWidth, boxHeight, false);
|
||||
renderer.drawText(UI_12_FONT_ID, boxX + boxMargin, boxY + boxMargin, "Indexing...");
|
||||
renderer.drawRect(boxX + 5, boxY + 5, boxWidth - 10, boxHeight - 10);
|
||||
renderer.drawRect(barX, barY, barWidth, barHeight);
|
||||
renderer.displayBuffer();
|
||||
ScreenComponents::drawPopup(renderer, "Indexing...");
|
||||
|
||||
while (offset < fileSize) {
|
||||
std::vector<std::string> tempLines;
|
||||
@@ -248,17 +230,6 @@ void TxtReaderActivity::buildPageIndex() {
|
||||
pageOffsets.push_back(offset);
|
||||
}
|
||||
|
||||
// Update progress bar every 10% (matching EpubReaderActivity logic)
|
||||
int progressPercent = (offset * 100) / fileSize;
|
||||
if (lastProgressPercent / 10 != progressPercent / 10) {
|
||||
lastProgressPercent = progressPercent;
|
||||
|
||||
// Fill progress bar
|
||||
const int fillWidth = (barWidth - 2) * progressPercent / 100;
|
||||
renderer.fillRect(barX + 1, barY + 1, fillWidth, barHeight - 2, true);
|
||||
renderer.displayBuffer(HalDisplay::FAST_REFRESH);
|
||||
}
|
||||
|
||||
// Yield to other tasks periodically
|
||||
if (pageOffsets.size() % 20 == 0) {
|
||||
vTaskDelay(1);
|
||||
@@ -402,9 +373,6 @@ void TxtReaderActivity::renderScreen() {
|
||||
|
||||
// Initialize reader if not done
|
||||
if (!initialized) {
|
||||
renderer.clearScreen();
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Indexing...", true, EpdFontFamily::BOLD);
|
||||
renderer.displayBuffer();
|
||||
initializeReader();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user