diff --git a/src/activities/home/MyLibraryActivity.cpp b/src/activities/home/MyLibraryActivity.cpp index a299a8fe..319b3b6b 100644 --- a/src/activities/home/MyLibraryActivity.cpp +++ b/src/activities/home/MyLibraryActivity.cpp @@ -6,9 +6,11 @@ #include +#include "BookManageMenuActivity.h" #include "MappedInputManager.h" #include "components/UITheme.h" #include "fontIds.h" +#include "util/BookManager.h" #include "util/StringUtils.h" namespace { @@ -133,7 +135,22 @@ void MyLibraryActivity::loop() { const int pageItems = UITheme::getInstance().getNumberOfItemsPerPage(renderer, true, false, true, false); + // Long-press Confirm: open manage menu for book files + if (mappedInput.isPressed(MappedInputManager::Button::Confirm) && mappedInput.getHeldTime() >= LONG_PRESS_MS && + !ignoreNextConfirmRelease) { + if (!files.empty() && selectorIndex < files.size() && files[selectorIndex].back() != '/') { + ignoreNextConfirmRelease = true; + const std::string fullPath = (basepath.back() == '/' ? basepath : basepath + "/") + files[selectorIndex]; + openManageMenu(fullPath); + return; + } + } + if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { + if (ignoreNextConfirmRelease) { + ignoreNextConfirmRelease = false; + return; + } if (files.empty()) { return; } @@ -240,6 +257,51 @@ void MyLibraryActivity::render(Activity::RenderLock&&) { renderer.displayBuffer(); } +void MyLibraryActivity::openManageMenu(const std::string& bookPath) { + const bool isArchived = BookManager::isArchived(bookPath); + const std::string capturedPath = bookPath; + enterNewActivity(new BookManageMenuActivity( + renderer, mappedInput, capturedPath, isArchived, + [this, capturedPath](BookManageMenuActivity::Action action) { + exitActivity(); + bool success = false; + switch (action) { + case BookManageMenuActivity::Action::ARCHIVE: + success = BookManager::archiveBook(capturedPath); + break; + case BookManageMenuActivity::Action::UNARCHIVE: + success = BookManager::unarchiveBook(capturedPath); + break; + case BookManageMenuActivity::Action::DELETE: + success = BookManager::deleteBook(capturedPath); + break; + case BookManageMenuActivity::Action::DELETE_CACHE: + success = BookManager::deleteBookCache(capturedPath); + break; + case BookManageMenuActivity::Action::REINDEX: + success = BookManager::reindexBook(capturedPath, false); + break; + case BookManageMenuActivity::Action::REINDEX_FULL: + success = BookManager::reindexBook(capturedPath, true); + break; + } + { + RenderLock lock(*this); + GUI.drawPopup(renderer, success ? tr(STR_DONE) : tr(STR_ACTION_FAILED)); + } + requestUpdateAndWait(); + loadFiles(); + if (selectorIndex >= files.size() && !files.empty()) { + selectorIndex = files.size() - 1; + } + requestUpdate(); + }, + [this] { + exitActivity(); + requestUpdate(); + })); +} + size_t MyLibraryActivity::findEntry(const std::string& name) const { for (size_t i = 0; i < files.size(); i++) if (files[i] == name) return i; diff --git a/src/activities/home/MyLibraryActivity.h b/src/activities/home/MyLibraryActivity.h index 96f5c185..b0df420f 100644 --- a/src/activities/home/MyLibraryActivity.h +++ b/src/activities/home/MyLibraryActivity.h @@ -17,6 +17,10 @@ class MyLibraryActivity final : public ActivityWithSubactivity { std::string basepath = "/"; std::vector files; + // Long-press state + bool ignoreNextConfirmRelease = false; + static constexpr unsigned long LONG_PRESS_MS = 700; + // Callbacks const std::function onSelectBook; const std::function onGoHome; @@ -25,6 +29,8 @@ class MyLibraryActivity final : public ActivityWithSubactivity { void loadFiles(); size_t findEntry(const std::string& name) const; + void openManageMenu(const std::string& bookPath); + public: explicit MyLibraryActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::function& onGoHome, diff --git a/src/activities/home/RecentBooksActivity.cpp b/src/activities/home/RecentBooksActivity.cpp index e2d54b4a..ae72321e 100644 --- a/src/activities/home/RecentBooksActivity.cpp +++ b/src/activities/home/RecentBooksActivity.cpp @@ -6,10 +6,12 @@ #include +#include "BookManageMenuActivity.h" #include "MappedInputManager.h" #include "RecentBooksStore.h" #include "components/UITheme.h" #include "fontIds.h" +#include "util/BookManager.h" #include "util/StringUtils.h" namespace { @@ -53,7 +55,21 @@ void RecentBooksActivity::loop() { const int pageItems = UITheme::getInstance().getNumberOfItemsPerPage(renderer, true, false, true, true); + // Long-press Confirm: open manage menu + if (mappedInput.isPressed(MappedInputManager::Button::Confirm) && mappedInput.getHeldTime() >= LONG_PRESS_MS && + !ignoreNextConfirmRelease) { + if (!recentBooks.empty() && selectorIndex < static_cast(recentBooks.size())) { + ignoreNextConfirmRelease = true; + openManageMenu(recentBooks[selectorIndex].path); + return; + } + } + if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { + if (ignoreNextConfirmRelease) { + ignoreNextConfirmRelease = false; + return; + } if (!recentBooks.empty() && selectorIndex < static_cast(recentBooks.size())) { LOG_DBG("RBA", "Selected recent book: %s", recentBooks[selectorIndex].path.c_str()); onSelectBook(recentBooks[selectorIndex].path); @@ -116,3 +132,48 @@ void RecentBooksActivity::render(Activity::RenderLock&&) { renderer.displayBuffer(); } + +void RecentBooksActivity::openManageMenu(const std::string& bookPath) { + const bool isArchived = BookManager::isArchived(bookPath); + const std::string capturedPath = bookPath; + enterNewActivity(new BookManageMenuActivity( + renderer, mappedInput, capturedPath, isArchived, + [this, capturedPath](BookManageMenuActivity::Action action) { + exitActivity(); + bool success = false; + switch (action) { + case BookManageMenuActivity::Action::ARCHIVE: + success = BookManager::archiveBook(capturedPath); + break; + case BookManageMenuActivity::Action::UNARCHIVE: + success = BookManager::unarchiveBook(capturedPath); + break; + case BookManageMenuActivity::Action::DELETE: + success = BookManager::deleteBook(capturedPath); + break; + case BookManageMenuActivity::Action::DELETE_CACHE: + success = BookManager::deleteBookCache(capturedPath); + break; + case BookManageMenuActivity::Action::REINDEX: + success = BookManager::reindexBook(capturedPath, false); + break; + case BookManageMenuActivity::Action::REINDEX_FULL: + success = BookManager::reindexBook(capturedPath, true); + break; + } + { + RenderLock lock(*this); + GUI.drawPopup(renderer, success ? tr(STR_DONE) : tr(STR_ACTION_FAILED)); + } + requestUpdateAndWait(); + loadRecentBooks(); + if (selectorIndex >= static_cast(recentBooks.size()) && !recentBooks.empty()) { + selectorIndex = recentBooks.size() - 1; + } + requestUpdate(); + }, + [this] { + exitActivity(); + requestUpdate(); + })); +} diff --git a/src/activities/home/RecentBooksActivity.h b/src/activities/home/RecentBooksActivity.h index 381aa9fb..f7d7116d 100644 --- a/src/activities/home/RecentBooksActivity.h +++ b/src/activities/home/RecentBooksActivity.h @@ -18,12 +18,17 @@ class RecentBooksActivity final : public ActivityWithSubactivity { // Recent tab state std::vector recentBooks; + // Long-press state + bool ignoreNextConfirmRelease = false; + static constexpr unsigned long LONG_PRESS_MS = 700; + // Callbacks const std::function onSelectBook; const std::function onGoHome; // Data loading void loadRecentBooks(); + void openManageMenu(const std::string& bookPath); public: explicit RecentBooksActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,