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:
cottongin
2026-02-21 07:37:36 -05:00
parent 39ef1e6d78
commit 0e2440aea8
16 changed files with 255 additions and 119 deletions

View File

@@ -100,7 +100,7 @@ bool archiveBook(const std::string& bookPath) {
return true;
}
bool unarchiveBook(const std::string& archivePath) {
bool unarchiveBook(const std::string& archivePath, std::string* unarchivedPath) {
if (!isArchived(archivePath)) {
LOG_ERR("BKMGR", "Book is not in archive: %s", archivePath.c_str());
return false;
@@ -139,6 +139,7 @@ bool unarchiveBook(const std::string& archivePath) {
RECENT_BOOKS.removeBook(archivePath);
LOG_DBG("BKMGR", "Unarchived: %s -> %s", archivePath.c_str(), destPath.c_str());
if (unarchivedPath) *unarchivedPath = destPath;
return true;
}
@@ -222,4 +223,33 @@ bool reindexBook(const std::string& bookPath, bool alsoRegenerateCovers) {
return true;
}
void cleanupEmptyArchiveDirs(const std::string& bookPath) {
if (!isArchived(bookPath)) return;
// Walk up from the book's parent directory, removing empty dirs
std::string dir = bookPath.substr(0, bookPath.find_last_of('/'));
const std::string archiveRoot(ARCHIVE_ROOT);
while (dir.length() > archiveRoot.length()) {
auto d = Storage.open(dir.c_str());
if (!d || !d.isDirectory()) {
if (d) d.close();
break;
}
auto child = d.openNextFile();
const bool empty = !child;
if (child) child.close();
d.close();
if (!empty) break;
Storage.rmdir(dir.c_str());
LOG_DBG("BKMGR", "Removed empty archive dir: %s", dir.c_str());
auto slash = dir.find_last_of('/');
if (slash == std::string::npos || slash == 0) break;
dir = dir.substr(0, slash);
}
}
} // namespace BookManager

View File

@@ -15,7 +15,8 @@ bool archiveBook(const std::string& bookPath);
// Move a book from /.archive/ back to its original location.
// Falls back to "/" if the original directory no longer exists.
// Renames the cache dir to match the restored path hash. Returns true on success.
bool unarchiveBook(const std::string& archivePath);
// If unarchivedPath is non-null, stores the destination path on success.
bool unarchiveBook(const std::string& archivePath, std::string* unarchivedPath = nullptr);
// Delete a book file, its cache directory, and remove from recents.
bool deleteBook(const std::string& bookPath);
@@ -31,4 +32,8 @@ bool reindexBook(const std::string& bookPath, bool alsoRegenerateCovers);
// Returns true if the book path is inside the /.archive/ folder.
bool isArchived(const std::string& bookPath);
// Remove empty directories under /.archive/ walking up from the book's parent.
// Stops at /.archive itself (never removes it).
void cleanupEmptyArchiveDirs(const std::string& bookPath);
} // namespace BookManager