#include "ReaderActivity.h" #include #include #include #include #include "CrossPointSettings.h" #include "Epub.h" #include "EpubReaderActivity.h" #include "SdCardFontSystem.h" #include "Txt.h" #include "TxtReaderActivity.h" #include "Xtc.h" #include "XtcReaderActivity.h" #include "activities/util/BmpViewerActivity.h" #include "activities/util/FullScreenMessageActivity.h" #include "components/UITheme.h" bool ReaderActivity::isXtcFile(const std::string& path) { return FsHelpers::hasXtcExtension(path); } bool ReaderActivity::isTxtFile(const std::string& path) { return FsHelpers::hasTxtExtension(path) || FsHelpers::hasMarkdownExtension(path); // Treat .md as txt files (until we have a markdown reader) } bool ReaderActivity::isBmpFile(const std::string& path) { return FsHelpers::hasBmpExtension(path); } std::unique_ptr ReaderActivity::loadEpub(const std::string& path) { if (!Storage.exists(path.c_str())) { LOG_ERR("READER", "File does not exist: %s", path.c_str()); return nullptr; } auto epub = makeUniqueNoThrow(path, "/.crosspoint"); if (!epub) { LOG_ERR("READER", "Failed to allocate EPUB object"); return nullptr; } // First open: building the spine/TOC index (book.bin) takes a couple of seconds. Show the // indexing popup so it isn't a silent wait on the home screen. The cachePath/hash is known at // construction, so this check is valid before load(); a cached open loads in a blink -> no popup. if (!Storage.exists((epub->getCachePath() + "/book.bin").c_str())) { GUI.drawPopup(renderer, tr(STR_INDEXING)); } if (epub->load(true, SETTINGS.embeddedStyle == 0)) { return epub; } LOG_ERR("READER", "Failed to load epub"); return nullptr; } std::unique_ptr ReaderActivity::loadXtc(const std::string& path) { if (!Storage.exists(path.c_str())) { LOG_ERR("READER", "File does not exist: %s", path.c_str()); return nullptr; } auto xtc = makeUniqueNoThrow(path, "/.crosspoint"); if (!xtc) { LOG_ERR("READER", "Failed to allocate XTC object"); return nullptr; } if (xtc->load()) { return xtc; } LOG_ERR("READER", "Failed to load XTC"); return nullptr; } std::unique_ptr ReaderActivity::loadTxt(const std::string& path) { if (!Storage.exists(path.c_str())) { LOG_ERR("READER", "File does not exist: %s", path.c_str()); return nullptr; } auto txt = makeUniqueNoThrow(path, "/.crosspoint"); if (!txt) { LOG_ERR("READER", "Failed to allocate TXT object"); return nullptr; } if (txt->load()) { return txt; } LOG_ERR("READER", "Failed to load TXT"); return nullptr; } void ReaderActivity::goToLibrary(const std::string& fromBookPath) { // If coming from a book, start in that book's folder; otherwise start from root auto initialPath = fromBookPath.empty() ? "/" : FsHelpers::extractFolderPath(fromBookPath); activityManager.goToFileBrowser(std::move(initialPath)); } void ReaderActivity::onGoToEpubReader(std::unique_ptr epub) { const auto epubPath = epub->getPath(); currentBookPath = epubPath; activityManager.replaceActivity(std::make_unique(renderer, mappedInput, std::move(epub))); } void ReaderActivity::onGoToBmpViewer(const std::string& path) { activityManager.replaceActivity(std::make_unique(renderer, mappedInput, path)); } void ReaderActivity::onGoToXtcReader(std::unique_ptr xtc) { const auto xtcPath = xtc->getPath(); currentBookPath = xtcPath; activityManager.replaceActivity(std::make_unique(renderer, mappedInput, std::move(xtc))); } void ReaderActivity::onGoToTxtReader(std::unique_ptr txt) { const auto txtPath = txt->getPath(); currentBookPath = txtPath; activityManager.replaceActivity(std::make_unique(renderer, mappedInput, std::move(txt))); } void ReaderActivity::onEnter() { Activity::onEnter(); if (initialBookPath.empty()) { goToLibrary(); // Start from root when entering via Browse return; } sdFontSystem.ensureLoaded(renderer); currentBookPath = initialBookPath; if (isBmpFile(initialBookPath)) { onGoToBmpViewer(initialBookPath); } else if (isXtcFile(initialBookPath)) { auto xtc = loadXtc(initialBookPath); if (!xtc) { onGoBack(); return; } onGoToXtcReader(std::move(xtc)); } else if (isTxtFile(initialBookPath)) { auto txt = loadTxt(initialBookPath); if (!txt) { onGoBack(); return; } onGoToTxtReader(std::move(txt)); } else { auto epub = loadEpub(initialBookPath); if (!epub) { onGoBack(); return; } onGoToEpubReader(std::move(epub)); } } void ReaderActivity::onGoBack() { finish(); }