fix: resolve end-of-book deadlock, long-press guards, archive UX, and home screen refresh
- Fix device freeze at end-of-book by deferring EndOfBookMenuActivity creation from render() to loop() (avoids RenderLock deadlock) in EpubReaderActivity and XtcReaderActivity - Add initialSkipRelease to BookManageMenuActivity to prevent stale Confirm release from triggering actions when opened via long-press - Add initialSkipRelease to MyLibraryActivity for long-press Browse Files -> archive navigation - Thread skip-release through HomeActivity callback and main.cpp - Fix HomeActivity stale cover buffer after archive/delete by fully resetting render state (freeCoverBuffer, firstRenderDone, etc.) - Swap short/long-press actions in .archive context: short-press opens manage menu, long-press unarchives and opens the book - Add deferred open pattern (pendingOpenPath) to wait for Confirm release before navigating to reader after unarchive - Add BookManager::cleanupEmptyArchiveDirs() to remove empty parent directories after unarchive/delete inside .archive - Add optional unarchivedPath output parameter to BookManager::unarchiveBook - Restyle EndOfBookMenuActivity to standard list layout with proper header, margins, and button hints matching other screens - Change EndOfBookMenuActivity back button hint to "« Back" - Add Table of Contents option to EndOfBookMenuActivity Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -222,6 +222,52 @@ void EpubReaderActivity::loop() {
|
||||
return; // Don't access 'this' after callback
|
||||
}
|
||||
|
||||
// Deferred end-of-book menu (set in render() to avoid deadlock)
|
||||
if (pendingEndOfBookMenu) {
|
||||
pendingEndOfBookMenu = false;
|
||||
endOfBookMenuOpened = true;
|
||||
const std::string path = epub->getPath();
|
||||
enterNewActivity(new EndOfBookMenuActivity(
|
||||
renderer, mappedInput, path, [this](EndOfBookMenuActivity::Action action) {
|
||||
exitActivity();
|
||||
switch (action) {
|
||||
case EndOfBookMenuActivity::Action::ARCHIVE:
|
||||
if (epub) BookManager::archiveBook(epub->getPath());
|
||||
pendingGoHome = true;
|
||||
break;
|
||||
case EndOfBookMenuActivity::Action::DELETE:
|
||||
if (epub) BookManager::deleteBook(epub->getPath());
|
||||
pendingGoHome = true;
|
||||
break;
|
||||
case EndOfBookMenuActivity::Action::TABLE_OF_CONTENTS:
|
||||
endOfBookMenuOpened = false;
|
||||
currentSpineIndex = epub->getSpineItemsCount() - 1;
|
||||
nextPageNumber = UINT16_MAX;
|
||||
section.reset();
|
||||
openChapterSelection();
|
||||
break;
|
||||
case EndOfBookMenuActivity::Action::BACK_TO_BEGINNING:
|
||||
currentSpineIndex = 0;
|
||||
nextPageNumber = 0;
|
||||
section.reset();
|
||||
endOfBookMenuOpened = false;
|
||||
requestUpdate();
|
||||
break;
|
||||
case EndOfBookMenuActivity::Action::CLOSE_BOOK:
|
||||
pendingGoHome = true;
|
||||
break;
|
||||
case EndOfBookMenuActivity::Action::CLOSE_MENU:
|
||||
currentSpineIndex = epub->getSpineItemsCount() - 1;
|
||||
nextPageNumber = UINT16_MAX;
|
||||
section.reset();
|
||||
endOfBookMenuOpened = false;
|
||||
requestUpdate();
|
||||
break;
|
||||
}
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip button processing after returning from subactivity
|
||||
// This prevents stale button release events from triggering actions
|
||||
// We wait until: (1) all relevant buttons are released, AND (2) wasReleased events have been cleared
|
||||
@@ -840,42 +886,10 @@ void EpubReaderActivity::render(Activity::RenderLock&& lock) {
|
||||
currentSpineIndex = epub->getSpineItemsCount();
|
||||
}
|
||||
|
||||
// Show end of book screen
|
||||
// End of book — defer menu creation to loop() to avoid deadlock (render holds the lock)
|
||||
if (currentSpineIndex == epub->getSpineItemsCount()) {
|
||||
if (!endOfBookMenuOpened) {
|
||||
endOfBookMenuOpened = true;
|
||||
const std::string path = epub->getPath();
|
||||
enterNewActivity(new EndOfBookMenuActivity(
|
||||
renderer, mappedInput, path, [this](EndOfBookMenuActivity::Action action) {
|
||||
exitActivity();
|
||||
switch (action) {
|
||||
case EndOfBookMenuActivity::Action::ARCHIVE:
|
||||
if (epub) BookManager::archiveBook(epub->getPath());
|
||||
pendingGoHome = true;
|
||||
break;
|
||||
case EndOfBookMenuActivity::Action::DELETE:
|
||||
if (epub) BookManager::deleteBook(epub->getPath());
|
||||
pendingGoHome = true;
|
||||
break;
|
||||
case EndOfBookMenuActivity::Action::BACK_TO_BEGINNING:
|
||||
currentSpineIndex = 0;
|
||||
nextPageNumber = 0;
|
||||
section.reset();
|
||||
endOfBookMenuOpened = false;
|
||||
requestUpdate();
|
||||
break;
|
||||
case EndOfBookMenuActivity::Action::CLOSE_BOOK:
|
||||
pendingGoHome = true;
|
||||
break;
|
||||
case EndOfBookMenuActivity::Action::CLOSE_MENU:
|
||||
currentSpineIndex = epub->getSpineItemsCount() - 1;
|
||||
nextPageNumber = UINT16_MAX;
|
||||
section.reset();
|
||||
endOfBookMenuOpened = false;
|
||||
requestUpdate();
|
||||
break;
|
||||
}
|
||||
}));
|
||||
pendingEndOfBookMenu = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user