feat: BookInfo button mapping, ManageBook integration, cover regen fix
- Fix BookInfo buttons: Left/Right front = scroll down/up, Confirm = no-op, side buttons retained. Separate Up/Down hints on btn3/btn4. - Fallback load: try epub.load(true, true) when cache-only load fails, so Book Info works for unopened books. - Add "Book Info" to ManageBook menu (BOOK_INFO action) with handlers in all 4 result sites (Home, Recent, FileBrowser, Reader). - Fix HomeActivity cover regen: call generateCoverBmp(false) + validate with isValidThumbnailBmp before falling to placeholder, matching the reader's multi-tier fallback pipeline. Same for XTC branch. Made-with: Cursor
This commit is contained in:
@@ -63,7 +63,10 @@ void BookInfoActivity::onEnter() {
|
||||
|
||||
if (FsHelpers::hasEpubExtension(fileName)) {
|
||||
Epub epub(filePath, "/.crosspoint");
|
||||
if (epub.load(false, true)) {
|
||||
if (!epub.load(false, true)) {
|
||||
epub.load(true, true);
|
||||
}
|
||||
{
|
||||
title = epub.getTitle();
|
||||
author = epub.getAuthor();
|
||||
series = epub.getSeries();
|
||||
@@ -177,8 +180,7 @@ void BookInfoActivity::buildLayout(const std::string& title, const std::string&
|
||||
}
|
||||
|
||||
void BookInfoActivity::loop() {
|
||||
if (mappedInput.wasReleased(MappedInputManager::Button::Back) ||
|
||||
mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
|
||||
if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
|
||||
ActivityResult r;
|
||||
r.isCancelled = true;
|
||||
setResult(std::move(r));
|
||||
@@ -189,14 +191,18 @@ void BookInfoActivity::loop() {
|
||||
const int pageH = renderer.getScreenHeight();
|
||||
const int scrollStep = pageH / 3;
|
||||
|
||||
if (mappedInput.wasReleased(MappedInputManager::Button::Down)) {
|
||||
if (mappedInput.wasReleased(MappedInputManager::Button::Down) ||
|
||||
mappedInput.wasReleased(MappedInputManager::Button::PageForward) ||
|
||||
mappedInput.wasReleased(MappedInputManager::Button::Left)) {
|
||||
if (scrollOffset + pageH < contentHeight) {
|
||||
scrollOffset += scrollStep;
|
||||
requestUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
if (mappedInput.wasReleased(MappedInputManager::Button::Up)) {
|
||||
if (mappedInput.wasReleased(MappedInputManager::Button::Up) ||
|
||||
mappedInput.wasReleased(MappedInputManager::Button::PageBack) ||
|
||||
mappedInput.wasReleased(MappedInputManager::Button::Right)) {
|
||||
if (scrollOffset > 0) {
|
||||
scrollOffset -= scrollStep;
|
||||
if (scrollOffset < 0) scrollOffset = 0;
|
||||
@@ -252,8 +258,9 @@ void BookInfoActivity::render(RenderLock&&) {
|
||||
|
||||
const bool canScrollDown = scrollOffset + pageH < contentHeight;
|
||||
const bool canScrollUp = scrollOffset > 0;
|
||||
const char* scrollHint = canScrollDown ? tr(STR_DIR_DOWN) : (canScrollUp ? tr(STR_DIR_UP) : "");
|
||||
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", scrollHint, "");
|
||||
const char* downHint = canScrollDown ? tr(STR_DIR_DOWN) : "";
|
||||
const char* upHint = canScrollUp ? tr(STR_DIR_UP) : "";
|
||||
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", downHint, upHint);
|
||||
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
|
||||
renderer.displayBuffer();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
void BookManageMenuActivity::buildMenuItems() {
|
||||
menuItems.clear();
|
||||
menuItems.push_back({Action::BOOK_INFO, StrId::STR_BOOK_INFO});
|
||||
if (archived) {
|
||||
menuItems.push_back({Action::UNARCHIVE, StrId::STR_UNARCHIVE_BOOK});
|
||||
} else {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
class BookManageMenuActivity final : public Activity {
|
||||
public:
|
||||
enum class Action {
|
||||
BOOK_INFO,
|
||||
ARCHIVE,
|
||||
UNARCHIVE,
|
||||
DELETE,
|
||||
|
||||
@@ -137,9 +137,17 @@ void FileBrowserActivity::handleManageResult(const std::string& fullPath, const
|
||||
const auto& menuResult = std::get<MenuResult>(result.data);
|
||||
auto action = static_cast<BookManageMenuActivity::Action>(menuResult.action);
|
||||
|
||||
if (action == BookManageMenuActivity::Action::BOOK_INFO) {
|
||||
startActivityForResult(std::make_unique<BookInfoActivity>(renderer, mappedInput, fullPath),
|
||||
[this](const ActivityResult&) { requestUpdate(); });
|
||||
return;
|
||||
}
|
||||
|
||||
auto executeAction = [this, action, fullPath]() {
|
||||
bool success = false;
|
||||
switch (action) {
|
||||
case BookManageMenuActivity::Action::BOOK_INFO:
|
||||
return;
|
||||
case BookManageMenuActivity::Action::ARCHIVE:
|
||||
success = BookManager::archiveBook(fullPath);
|
||||
break;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "../util/ConfirmationActivity.h"
|
||||
#include "BookInfoActivity.h"
|
||||
#include "BookManageMenuActivity.h"
|
||||
#include "CrossPointSettings.h"
|
||||
#include "CrossPointState.h"
|
||||
@@ -81,7 +82,11 @@ void HomeActivity::loadRecentCovers(int coverHeight) {
|
||||
epub.load(true, true);
|
||||
}
|
||||
success = epub.generateThumbBmp(coverHeight);
|
||||
if (success) {
|
||||
if (!success || !Epub::isValidThumbnailBmp(epub.getThumbBmpPath(coverHeight))) {
|
||||
epub.generateCoverBmp(false);
|
||||
success = epub.generateThumbBmp(coverHeight);
|
||||
}
|
||||
if (success && Epub::isValidThumbnailBmp(epub.getThumbBmpPath(coverHeight))) {
|
||||
const std::string thumbPath = epub.getThumbBmpPath(coverHeight);
|
||||
RECENT_BOOKS.updateBook(book.path, book.title, book.author, book.series, thumbPath);
|
||||
book.coverBmpPath = thumbPath;
|
||||
@@ -93,10 +98,16 @@ void HomeActivity::loadRecentCovers(int coverHeight) {
|
||||
Xtc xtc(book.path, "/.crosspoint");
|
||||
if (xtc.load()) {
|
||||
success = xtc.generateThumbBmp(coverHeight);
|
||||
if (success) {
|
||||
if (!success || !Epub::isValidThumbnailBmp(xtc.getThumbBmpPath(coverHeight))) {
|
||||
xtc.generateCoverBmp();
|
||||
success = xtc.generateThumbBmp(coverHeight);
|
||||
}
|
||||
if (success && Epub::isValidThumbnailBmp(xtc.getThumbBmpPath(coverHeight))) {
|
||||
const std::string thumbPath = xtc.getThumbBmpPath(coverHeight);
|
||||
RECENT_BOOKS.updateBook(book.path, book.title, book.author, book.series, thumbPath);
|
||||
book.coverBmpPath = thumbPath;
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
@@ -304,6 +315,8 @@ void HomeActivity::onOpdsBrowserOpen() { activityManager.goToBrowser(); }
|
||||
void HomeActivity::executeManageAction(BookManageMenuActivity::Action action, const std::string& capturedPath) {
|
||||
bool success = false;
|
||||
switch (action) {
|
||||
case BookManageMenuActivity::Action::BOOK_INFO:
|
||||
return;
|
||||
case BookManageMenuActivity::Action::ARCHIVE:
|
||||
success = BookManager::archiveBook(capturedPath);
|
||||
break;
|
||||
@@ -352,7 +365,11 @@ void HomeActivity::openManageMenu(const std::string& bookPath) {
|
||||
const auto& menuResult = std::get<MenuResult>(result.data);
|
||||
auto action = static_cast<BookManageMenuActivity::Action>(menuResult.action);
|
||||
|
||||
if (action == BookManageMenuActivity::Action::DELETE || action == BookManageMenuActivity::Action::ARCHIVE) {
|
||||
if (action == BookManageMenuActivity::Action::BOOK_INFO) {
|
||||
startActivityForResult(std::make_unique<BookInfoActivity>(renderer, mappedInput, capturedPath),
|
||||
[this](const ActivityResult&) { requestUpdate(); });
|
||||
} else if (action == BookManageMenuActivity::Action::DELETE ||
|
||||
action == BookManageMenuActivity::Action::ARCHIVE) {
|
||||
const char* promptKey =
|
||||
(action == BookManageMenuActivity::Action::DELETE) ? tr(STR_DELETE_BOOK) : tr(STR_ARCHIVE_BOOK);
|
||||
std::string heading = std::string(promptKey) + "?";
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "../util/ConfirmationActivity.h"
|
||||
#include "BookInfoActivity.h"
|
||||
#include "BookManageMenuActivity.h"
|
||||
#include "MappedInputManager.h"
|
||||
#include "RecentBooksStore.h"
|
||||
@@ -51,6 +52,8 @@ void RecentBooksActivity::onExit() {
|
||||
void RecentBooksActivity::executeManageAction(BookManageMenuActivity::Action action, const std::string& capturedPath) {
|
||||
bool success = false;
|
||||
switch (action) {
|
||||
case BookManageMenuActivity::Action::BOOK_INFO:
|
||||
return;
|
||||
case BookManageMenuActivity::Action::ARCHIVE:
|
||||
success = BookManager::archiveBook(capturedPath);
|
||||
break;
|
||||
@@ -92,7 +95,11 @@ void RecentBooksActivity::openManageMenu(const std::string& bookPath) {
|
||||
const auto& menuResult = std::get<MenuResult>(result.data);
|
||||
auto action = static_cast<BookManageMenuActivity::Action>(menuResult.action);
|
||||
|
||||
if (action == BookManageMenuActivity::Action::DELETE || action == BookManageMenuActivity::Action::ARCHIVE) {
|
||||
if (action == BookManageMenuActivity::Action::BOOK_INFO) {
|
||||
startActivityForResult(std::make_unique<BookInfoActivity>(renderer, mappedInput, capturedPath),
|
||||
[this](const ActivityResult&) { requestUpdate(); });
|
||||
} else if (action == BookManageMenuActivity::Action::DELETE ||
|
||||
action == BookManageMenuActivity::Action::ARCHIVE) {
|
||||
const char* promptKey =
|
||||
(action == BookManageMenuActivity::Action::DELETE) ? tr(STR_DELETE_BOOK) : tr(STR_ARCHIVE_BOOK);
|
||||
std::string heading = std::string(promptKey) + "?";
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ReaderUtils.h"
|
||||
#include "RecentBooksStore.h"
|
||||
#include "activities/ActivityManager.h"
|
||||
#include "activities/home/BookInfoActivity.h"
|
||||
#include "activities/home/BookManageMenuActivity.h"
|
||||
#include "activities/util/ConfirmationActivity.h"
|
||||
#include "components/UITheme.h"
|
||||
@@ -722,6 +723,12 @@ void EpubReaderActivity::onReaderMenuConfirm(EpubReaderMenuActivity::MenuAction
|
||||
const auto& menu = std::get<MenuResult>(result.data);
|
||||
const auto bookAction = static_cast<BookManageMenuActivity::Action>(menu.action);
|
||||
switch (bookAction) {
|
||||
case BookManageMenuActivity::Action::BOOK_INFO: {
|
||||
const std::string path = epub ? epub->getPath() : "";
|
||||
startActivityForResult(std::make_unique<BookInfoActivity>(renderer, mappedInput, path),
|
||||
[this](const ActivityResult&) { requestUpdate(); });
|
||||
return;
|
||||
}
|
||||
case BookManageMenuActivity::Action::ARCHIVE: {
|
||||
std::string heading = std::string(tr(STR_ARCHIVE_BOOK)) + "?";
|
||||
std::string bookName = epub ? epub->getTitle() : "";
|
||||
|
||||
Reference in New Issue
Block a user