diff --git a/lib/I18n/translations/english.yaml b/lib/I18n/translations/english.yaml index 78ef161e..f256cd85 100644 --- a/lib/I18n/translations/english.yaml +++ b/lib/I18n/translations/english.yaml @@ -20,6 +20,7 @@ STR_EMPTY_CHAPTER: "Empty chapter" STR_FINISHED_BOOK_HEADER: "Book finished!" STR_FINISHED_BOOK_HEADER_LINE1: "Congratulations, you finished this book." STR_FINISHED_BOOK_HEADER_LINE2: "What do you want to do now?" +STR_NEXT_BOOK_HEADER: "Next book to read:" STR_GO_BACK_TO_HOME: "Go back to Home" STR_GO_BACK_TO_HOME_DESC: "Return to the home screen" STR_OPEN_NEXT_BOOK: "Open the next book:" diff --git a/lib/I18n/translations/polish.yaml b/lib/I18n/translations/polish.yaml index a7e99f31..ca297cc2 100644 --- a/lib/I18n/translations/polish.yaml +++ b/lib/I18n/translations/polish.yaml @@ -324,6 +324,7 @@ STR_CHAPTER: "Rozdział" STR_EXAMPLE_CHAPTER: "Rozdział 21" STR_EXAMPLE_BOOK: "Tytuł książki" STR_PREVIEW: "Podgląd" +STR_NEXT_BOOK_HEADER: "Następna książka do przeczytania:" STR_TITLE: "Tytuł" STR_BATTERY: "Bateria" STR_XTC_STATUS_BAR: "Pasek statusu XTC" diff --git a/src/JsonSettingsIO.cpp b/src/JsonSettingsIO.cpp index 97a4e43f..0860ea51 100644 --- a/src/JsonSettingsIO.cpp +++ b/src/JsonSettingsIO.cpp @@ -212,6 +212,7 @@ bool JsonSettingsIO::saveSettings(const CrossPointSettings& s, const char* path) doc["sdFontFamilyName"] = s.sdFontFamilyName; } doc["moveFinishedBooksToCompleted"] = s.moveFinishedBooksToCompleted; + doc["removeFinishedBooksFromRecents"] = s.removeFinishedBooksFromRecents; String json; serializeJson(doc, json); diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index fb8a7d85..a1acffc7 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -472,8 +472,7 @@ void EpubReaderActivity::loop() { const std::string nextBookPath = BookFinished::findNextBookInDirectory(epub->getPath(), epub->getSeries(), epub->getSeriesIndex()); startActivityForResult( - std::make_unique(renderer, mappedInput, epub->getPath(), nextBookPath, - SETTINGS.moveFinishedBooksToCompleted), + std::make_unique(renderer, mappedInput, epub->getPath(), nextBookPath), [this, nextBookPath](const ActivityResult& result) { if (result.isCancelled) { requestUpdate(); @@ -722,8 +721,7 @@ void EpubReaderActivity::onReaderMenuConfirm(EpubReaderMenuActivity::MenuAction const std::string nextBookPath = BookFinished::findNextBookInDirectory(epub->getPath(), epub->getSeries(), epub->getSeriesIndex()); startActivityForResult( - std::make_unique(renderer, mappedInput, epub->getPath(), nextBookPath, - SETTINGS.moveFinishedBooksToCompleted), + std::make_unique(renderer, mappedInput, epub->getPath(), nextBookPath), [this, nextBookPath](const ActivityResult& result) { if (result.isCancelled) { requestUpdate(); @@ -1481,8 +1479,7 @@ void EpubReaderActivity::render(RenderLock&& lock) { BookFinished::findNextBookInDirectory(epub->getPath(), epub->getSeries(), epub->getSeriesIndex()); lock.unlock(); startActivityForResult( - std::make_unique(renderer, mappedInput, epub->getPath(), nextBookPath, - SETTINGS.moveFinishedBooksToCompleted), + std::make_unique(renderer, mappedInput, epub->getPath(), nextBookPath), [this, nextBookPath](const ActivityResult& result) { finishedBookActivityStarted_ = false; if (result.isCancelled) { diff --git a/src/activities/reader/FinishedBookActivity.cpp b/src/activities/reader/FinishedBookActivity.cpp index f18b345a..a7856886 100644 --- a/src/activities/reader/FinishedBookActivity.cpp +++ b/src/activities/reader/FinishedBookActivity.cpp @@ -46,7 +46,7 @@ std::string getFilename(const std::string& filePath) { static constexpr int kFinishedBookCoverHeight = 240; static constexpr int kFinishedBookCoverMaxWidth = 220; -std::string findUniqueCompletedSidecarPath(const std::string& basePath) { +std::string findUniquePathWithSuffix(const std::string& basePath) { if (!Storage.exists(basePath.c_str())) { return basePath; } @@ -63,6 +63,8 @@ std::string findUniqueCompletedSidecarPath(const std::string& basePath) { return {}; } +std::string findUniqueCompletedSidecarPath(const std::string& basePath) { return findUniquePathWithSuffix(basePath); } + std::string convertSidecarToBmp(const std::string& bookPath, const std::string& sidecarPath, int width, int height, const std::string& fileName) { const std::string cacheDir = "/.crosspoint/sidecar_" + std::to_string(std::hash{}(bookPath)); @@ -391,22 +393,7 @@ std::string buildCompletedTargetPath(const std::string& currentBookPath) { return std::string("/COMPLETED/") + fileName; } -std::string findUniqueCompletedPath(const std::string& basePath) { - if (!Storage.exists(basePath.c_str())) { - return basePath; - } - - const auto dotPos = basePath.find_last_of('.'); - const std::string base = (dotPos == std::string::npos) ? basePath : basePath.substr(0, dotPos); - const std::string ext = (dotPos == std::string::npos) ? std::string() : basePath.substr(dotPos); - for (int suffix = 1; suffix < 1000; ++suffix) { - const std::string candidate = base + " (" + std::to_string(suffix) + ")" + ext; - if (!Storage.exists(candidate.c_str())) { - return candidate; - } - } - return {}; -} +std::string findUniqueCompletedPath(const std::string& basePath) { return findUniquePathWithSuffix(basePath); } } // namespace namespace BookFinished { @@ -463,13 +450,11 @@ bool moveFinishedBookToCompleted(const std::string& currentBookPath, std::string } // namespace BookFinished FinishedBookActivity::FinishedBookActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, - std::string currentBookPath, std::string nextBookPath, - bool moveFinishedBooksToCompleted) + std::string currentBookPath, std::string nextBookPath) : Activity("FinishedBook", renderer, mappedInput), currentBookPath_(std::move(currentBookPath)), nextBookPath_(std::move(nextBookPath)), - nextBookAvailable_(!nextBookPath_.empty()), - moveFinishedBooksToCompleted_(moveFinishedBooksToCompleted) { + nextBookAvailable_(!nextBookPath_.empty()) { nextBookName_ = nextBookAvailable_ ? getFilename(nextBookPath_) : tr(STR_NOT_SET); } @@ -477,12 +462,7 @@ void FinishedBookActivity::onEnter() { Activity::onEnter(); const bool canMoveToCompleted = !pathIsInCompleted(currentBookPath_); const int optionCount = 1 + (nextBookAvailable_ ? 1 : 0) + (canMoveToCompleted ? 1 : 0) + 1; - if (selectedIndex_ < 0 || selectedIndex_ >= optionCount) { - selectedIndex_ = 0; - } - if (selectedIndex_ >= optionCount) { - selectedIndex_ = optionCount - 1; - } + selectedIndex_ = std::clamp(selectedIndex_, 0, optionCount - 1); moveFinishedBooksToCompleted_ = SETTINGS.moveFinishedBooksToCompleted; removeFinishedBooksFromRecents_ = SETTINGS.removeFinishedBooksFromRecents; @@ -607,7 +587,7 @@ void FinishedBookActivity::render(RenderLock&&) { y += yGap + 4; if (nextBookAvailable_) { - renderer.drawText(UI_12_FONT_ID, contentRect.x + metrics.contentSidePadding, y, "Next book to read:", true, + renderer.drawText(UI_12_FONT_ID, contentRect.x + metrics.contentSidePadding, y, tr(STR_NEXT_BOOK_HEADER), true, EpdFontFamily::BOLD); y += yGap + metrics.verticalSpacing; } diff --git a/src/activities/reader/FinishedBookActivity.h b/src/activities/reader/FinishedBookActivity.h index ce79bd48..9a91c2c6 100644 --- a/src/activities/reader/FinishedBookActivity.h +++ b/src/activities/reader/FinishedBookActivity.h @@ -21,7 +21,7 @@ enum class FinishedBookAction { class FinishedBookActivity : public Activity { public: FinishedBookActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::string currentBookPath, - std::string nextBookPath, bool moveFinishedBooksToCompleted); + std::string nextBookPath); void onEnter() override; void loop() override; diff --git a/src/activities/reader/MdReaderActivity.cpp b/src/activities/reader/MdReaderActivity.cpp index 938dda57..4be66cd7 100644 --- a/src/activities/reader/MdReaderActivity.cpp +++ b/src/activities/reader/MdReaderActivity.cpp @@ -282,8 +282,7 @@ void MdReaderActivity::loop() { const std::string nextBookPath = BookFinished::findNextBookInDirectory(currentBookPath, std::string(), std::string()); startActivityForResult( - std::make_unique(renderer, mappedInput, currentBookPath, nextBookPath, - SETTINGS.moveFinishedBooksToCompleted), + std::make_unique(renderer, mappedInput, currentBookPath, nextBookPath), [this, currentBookPath, nextBookPath](const ActivityResult& result) { if (result.isCancelled) { requestUpdate(); diff --git a/src/activities/reader/TxtReaderActivity.cpp b/src/activities/reader/TxtReaderActivity.cpp index ffec3821..5a7c6718 100644 --- a/src/activities/reader/TxtReaderActivity.cpp +++ b/src/activities/reader/TxtReaderActivity.cpp @@ -198,43 +198,7 @@ void TxtReaderActivity::loop() { currentPage++; requestUpdate(); } else { - saveProgress(); - const std::string nextBookPath = - BookFinished::findNextBookInDirectory(txt->getPath(), std::string(), std::string()); - startActivityForResult( - std::make_unique(renderer, mappedInput, txt->getPath(), nextBookPath, - SETTINGS.moveFinishedBooksToCompleted), - [this, nextBookPath](const ActivityResult& result) { - if (result.isCancelled) { - requestUpdate(); - return; - } - const auto& menuResult = std::get(result.data); - if (menuResult.action == static_cast(BookFinished::FinishedBookAction::GoHome)) { - if (SETTINGS.moveFinishedBooksToCompleted) { - std::string movedPath; - BookFinished::moveFinishedBookToCompleted(txt->getPath(), movedPath); - } - if (SETTINGS.removeFinishedBooksFromRecents) { - RECENT_BOOKS.removeBook(txt->getPath()); - } - activityManager.goHome(); - return; - } - if (menuResult.action == static_cast(BookFinished::FinishedBookAction::OpenNextBook) && - !nextBookPath.empty()) { - if (SETTINGS.moveFinishedBooksToCompleted) { - std::string movedPath; - BookFinished::moveFinishedBookToCompleted(txt->getPath(), movedPath); - } - if (SETTINGS.removeFinishedBooksFromRecents) { - RECENT_BOOKS.removeBook(txt->getPath()); - } - activityManager.goToReader(nextBookPath); - return; - } - requestUpdate(); - }); + launchFinishedBookFlow(); } return; } @@ -255,36 +219,50 @@ void TxtReaderActivity::loop() { currentPage++; requestUpdate(); } else { - const std::string nextBookPath = - BookFinished::findNextBookInDirectory(txt->getPath(), std::string(), std::string()); - startActivityForResult( - std::make_unique(renderer, mappedInput, txt->getPath(), nextBookPath, - SETTINGS.moveFinishedBooksToCompleted), - [this, nextBookPath](const ActivityResult& result) { - if (result.isCancelled) { - requestUpdate(); - return; - } - const auto& menuResult = std::get(result.data); - if (menuResult.action == static_cast(BookFinished::FinishedBookAction::GoHome)) { - activityManager.goHome(); - return; - } - if (menuResult.action == static_cast(BookFinished::FinishedBookAction::OpenNextBook) && - !nextBookPath.empty()) { - if (SETTINGS.moveFinishedBooksToCompleted) { - std::string movedPath; - BookFinished::moveFinishedBookToCompleted(txt->getPath(), movedPath); - } - activityManager.goToReader(nextBookPath); - return; - } - requestUpdate(); - }); + launchFinishedBookFlow(); } } } +void TxtReaderActivity::launchFinishedBookFlow() { + saveProgress(); + const std::string currentBookPath = txt->getPath(); + const std::string nextBookPath = BookFinished::findNextBookInDirectory(currentBookPath, std::string(), std::string()); + + startActivityForResult(std::make_unique(renderer, mappedInput, currentBookPath, nextBookPath), + [this, currentBookPath, nextBookPath](const ActivityResult& result) { + if (result.isCancelled) { + requestUpdate(); + return; + } + const auto& menuResult = std::get(result.data); + if (menuResult.action == static_cast(BookFinished::FinishedBookAction::GoHome)) { + if (SETTINGS.moveFinishedBooksToCompleted) { + std::string movedPath; + BookFinished::moveFinishedBookToCompleted(currentBookPath, movedPath); + } + if (SETTINGS.removeFinishedBooksFromRecents) { + RECENT_BOOKS.removeBook(currentBookPath); + } + activityManager.goHome(); + return; + } + if (menuResult.action == static_cast(BookFinished::FinishedBookAction::OpenNextBook) && + !nextBookPath.empty()) { + if (SETTINGS.moveFinishedBooksToCompleted) { + std::string movedPath; + BookFinished::moveFinishedBookToCompleted(currentBookPath, movedPath); + } + if (SETTINGS.removeFinishedBooksFromRecents) { + RECENT_BOOKS.removeBook(currentBookPath); + } + activityManager.goToReader(nextBookPath); + return; + } + requestUpdate(); + }); +} + void TxtReaderActivity::initializeReader() { if (initialized) { return; diff --git a/src/activities/reader/TxtReaderActivity.h b/src/activities/reader/TxtReaderActivity.h index 4230a75f..6d54c09a 100644 --- a/src/activities/reader/TxtReaderActivity.h +++ b/src/activities/reader/TxtReaderActivity.h @@ -50,6 +50,7 @@ class TxtReaderActivity final : public Activity { // Consume a persisted bookmark-jump request (from GlobalBookmarksActivity) for // this TXT file. Rewrites progress.bin before initializeReader() reads it. void applyPendingBookmarkJump(); + void launchFinishedBookFlow(); public: explicit TxtReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr txt) diff --git a/src/activities/reader/XtcReaderActivity.cpp b/src/activities/reader/XtcReaderActivity.cpp index 51935b0e..527bdffb 100644 --- a/src/activities/reader/XtcReaderActivity.cpp +++ b/src/activities/reader/XtcReaderActivity.cpp @@ -140,8 +140,7 @@ void XtcReaderActivity::loop() { const std::string nextBookPath = BookFinished::findNextBookInDirectory(currentBookPath, std::string(), std::string()); startActivityForResult( - std::make_unique(renderer, mappedInput, currentBookPath, nextBookPath, - SETTINGS.moveFinishedBooksToCompleted), + std::make_unique(renderer, mappedInput, currentBookPath, nextBookPath), [this, nextBookPath, currentBookPath](const ActivityResult& result) { if (result.isCancelled) { requestUpdate();