fix: placeholder cover text, indexing timing, TOC long-press, cache deletion UI

- Fix fp4 fixed-point misuse in PlaceholderCoverGenerator (advanceX is 12.4
  fixed-point, not pixels) causing only first letter of each word to render
- Remove duplicate silentIndexNextChapterIfNeeded() call from loop() that
  blocked UI before render, preventing the indexing indicator from showing
- Fix indexing icon Y position to align within the status bar
- Add ignoreNextConfirmRelease to EpubReaderChapterSelectionActivity so
  long-press confirm release doesn't immediately select the first TOC item
- Reload recent books after cache deletion in HomeActivity and clear stale
  ignoreNextConfirmRelease flag to fix "no open books" and double-press bugs

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-07 22:58:13 -05:00
parent a5ca15df4f
commit 022f5197d7
5 changed files with 17 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
#include "PlaceholderCoverGenerator.h" #include "PlaceholderCoverGenerator.h"
#include <EpdFont.h> #include <EpdFont.h>
#include <EpdFontData.h>
#include <HalStorage.h> #include <HalStorage.h>
#include <Logging.h> #include <Logging.h>
#include <Utf8.h> #include <Utf8.h>
@@ -170,7 +171,7 @@ class PixelBuffer {
} }
} }
return glyph->advanceX * scale; return fp4::toPixel(glyph->advanceX) * scale;
} }
/// Render a UTF-8 string at (x, y) where y is the top of the text line, with integer scaling. /// Render a UTF-8 string at (x, y) where y is the top of the text line, with integer scaling.
@@ -232,7 +233,7 @@ int getCharAdvance(const EpdFontData* font, uint32_t cp) {
const EpdFont fontObj(font); const EpdFont fontObj(font);
const EpdGlyph* glyph = fontObj.getGlyph(cp); const EpdGlyph* glyph = fontObj.getGlyph(cp);
if (!glyph) return 0; if (!glyph) return 0;
return glyph->advanceX; return fp4::toPixel(glyph->advanceX);
} }
/// Split a string into words (splitting on whitespace: space, newline, tab, CR). /// Split a string into words (splitting on whitespace: space, newline, tab, CR).

View File

@@ -307,6 +307,7 @@ void HomeActivity::openManageMenu(const std::string& bookPath) {
startActivityForResult( startActivityForResult(
std::make_unique<BookManageMenuActivity>(renderer, mappedInput, capturedPath, isArchived, true), std::make_unique<BookManageMenuActivity>(renderer, mappedInput, capturedPath, isArchived, true),
[this, capturedPath](const ActivityResult& result) { [this, capturedPath](const ActivityResult& result) {
ignoreNextConfirmRelease = false;
if (result.isCancelled) { if (result.isCancelled) {
requestUpdate(); requestUpdate();
return; return;
@@ -339,13 +340,13 @@ void HomeActivity::openManageMenu(const std::string& bookPath) {
GUI.drawPopup(renderer, success ? tr(STR_DONE) : tr(STR_ACTION_FAILED)); GUI.drawPopup(renderer, success ? tr(STR_DONE) : tr(STR_ACTION_FAILED));
} }
requestUpdateAndWait(); requestUpdateAndWait();
recentBooks.clear();
recentsLoaded = false; recentsLoaded = false;
recentsLoading = false; recentsLoading = false;
coverRendered = false; coverRendered = false;
freeCoverBuffer(); freeCoverBuffer();
selectorIndex = 0; selectorIndex = 0;
firstRenderDone = false; firstRenderDone = false;
loadRecentBooks(UITheme::getInstance().getMetrics().homeRecentBooksCount);
requestUpdate(); requestUpdate();
}); });
} }

View File

@@ -381,8 +381,6 @@ void EpubReaderActivity::loop() {
} else { } else {
pageTurn(true); pageTurn(true);
} }
silentIndexNextChapterIfNeeded();
} }
// Translate an absolute percent into a spine index plus a normalized position // Translate an absolute percent into a spine index plus a normalized position
@@ -454,8 +452,10 @@ void EpubReaderActivity::onReaderMenuConfirm(EpubReaderMenuActivity::MenuAction
case EpubReaderMenuActivity::MenuAction::SELECT_CHAPTER: { case EpubReaderMenuActivity::MenuAction::SELECT_CHAPTER: {
const int spineIdx = currentSpineIndex; const int spineIdx = currentSpineIndex;
const std::string path = epub->getPath(); const std::string path = epub->getPath();
const bool consumeRelease = ignoreNextConfirmRelease;
startActivityForResult( startActivityForResult(
std::make_unique<EpubReaderChapterSelectionActivity>(renderer, mappedInput, epub, path, spineIdx), std::make_unique<EpubReaderChapterSelectionActivity>(renderer, mappedInput, epub, path, spineIdx,
consumeRelease),
[this](const ActivityResult& result) { [this](const ActivityResult& result) {
if (!result.isCancelled && currentSpineIndex != std::get<ChapterResult>(result.data).spineIndex) { if (!result.isCancelled && currentSpineIndex != std::get<ChapterResult>(result.data).spineIndex) {
RenderLock lock(*this); RenderLock lock(*this);
@@ -1203,7 +1203,7 @@ void EpubReaderActivity::renderStatusBar() const {
if (SETTINGS.indexingDisplay == CrossPointSettings::INDEXING_DISPLAY::INDEXING_STATUS_TEXT) { if (SETTINGS.indexingDisplay == CrossPointSettings::INDEXING_DISPLAY::INDEXING_STATUS_TEXT) {
renderer.drawText(SMALL_FONT_ID, indicatorX, textY, tr(STR_INDEXING)); renderer.drawText(SMALL_FONT_ID, indicatorX, textY, tr(STR_INDEXING));
} else if (SETTINGS.indexingDisplay == CrossPointSettings::INDEXING_DISPLAY::INDEXING_STATUS_ICON) { } else if (SETTINGS.indexingDisplay == CrossPointSettings::INDEXING_DISPLAY::INDEXING_STATUS_ICON) {
renderer.drawIcon(kIndexingIcon, indicatorX, textY - kIndexingIconSize + 2, kIndexingIconSize, kIndexingIconSize); renderer.drawIcon(kIndexingIcon, indicatorX, textY + 2, kIndexingIconSize, kIndexingIconSize);
} }
} }
} }

View File

@@ -48,6 +48,10 @@ void EpubReaderChapterSelectionActivity::loop() {
const int totalItems = getTotalItems(); const int totalItems = getTotalItems();
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
if (ignoreNextConfirmRelease) {
ignoreNextConfirmRelease = false;
return;
}
const auto newSpineIndex = epub->getSpineIndexForTocIndex(selectorIndex); const auto newSpineIndex = epub->getSpineIndexForTocIndex(selectorIndex);
if (newSpineIndex == -1) { if (newSpineIndex == -1) {
ActivityResult result; ActivityResult result;

View File

@@ -12,6 +12,7 @@ class EpubReaderChapterSelectionActivity final : public Activity {
ButtonNavigator buttonNavigator; ButtonNavigator buttonNavigator;
int currentSpineIndex = 0; int currentSpineIndex = 0;
int selectorIndex = 0; int selectorIndex = 0;
bool ignoreNextConfirmRelease = false;
// Number of items that fit on a page, derived from logical screen height. // Number of items that fit on a page, derived from logical screen height.
// This adapts automatically when switching between portrait and landscape. // This adapts automatically when switching between portrait and landscape.
@@ -23,11 +24,12 @@ class EpubReaderChapterSelectionActivity final : public Activity {
public: public:
explicit EpubReaderChapterSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, explicit EpubReaderChapterSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
const std::shared_ptr<Epub>& epub, const std::string& epubPath, const std::shared_ptr<Epub>& epub, const std::string& epubPath,
const int currentSpineIndex) const int currentSpineIndex, bool consumeFirstRelease = false)
: Activity("EpubReaderChapterSelection", renderer, mappedInput), : Activity("EpubReaderChapterSelection", renderer, mappedInput),
epub(epub), epub(epub),
epubPath(epubPath), epubPath(epubPath),
currentSpineIndex(currentSpineIndex) {} currentSpineIndex(currentSpineIndex),
ignoreNextConfirmRelease(consumeFirstRelease) {}
void onEnter() override; void onEnter() override;
void onExit() override; void onExit() override;
void loop() override; void loop() override;