#include "BookInfoActivity.h" #include #include #include #include #include #include #include "components/UITheme.h" #include "fontIds.h" void BookInfoActivity::onEnter() { Activity::onEnter(); std::string fileName = filePath; const size_t lastSlash = filePath.rfind('/'); if (lastSlash != std::string::npos) { fileName = filePath.substr(lastSlash + 1); } FsFile file; if (Storage.openFileForRead("BIF", filePath, file)) { fileSize = file.fileSize(); file.close(); } if (FsHelpers::hasEpubExtension(fileName)) { Epub epub(filePath, "/.crosspoint"); if (epub.load(false, true)) { title = epub.getTitle(); author = epub.getAuthor(); series = epub.getSeries(); seriesIndex = epub.getSeriesIndex(); description = epub.getDescription(); language = epub.getLanguage(); } } if (title.empty()) { title = fileName; } requestUpdate(); } void BookInfoActivity::onExit() { Activity::onExit(); } void BookInfoActivity::loop() { if (mappedInput.wasReleased(MappedInputManager::Button::Back) || mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { ActivityResult r; r.isCancelled = true; setResult(std::move(r)); finish(); return; } if (mappedInput.wasReleased(MappedInputManager::Button::Down)) { if (scrollOffset + renderer.getScreenHeight() < contentHeight) { scrollOffset += renderer.getScreenHeight() / 3; requestUpdate(); } } if (mappedInput.wasReleased(MappedInputManager::Button::Up)) { if (scrollOffset > 0) { scrollOffset -= renderer.getScreenHeight() / 3; if (scrollOffset < 0) scrollOffset = 0; requestUpdate(); } } } void BookInfoActivity::render(RenderLock&&) { renderer.clearScreen(); const int pageW = renderer.getScreenWidth(); const int pageH = renderer.getScreenHeight(); constexpr int margin = 20; constexpr int labelValueGap = 4; constexpr int sectionGap = 14; constexpr int maxWrappedLines = 30; const int contentW = pageW - margin * 2; const int lineH10 = renderer.getLineHeight(UI_10_FONT_ID); const int lineH12 = renderer.getLineHeight(UI_12_FONT_ID); int y = margin - scrollOffset; auto drawLabel = [&](const char* label) { renderer.drawText(UI_10_FONT_ID, margin, y, label, true, EpdFontFamily::BOLD); y += lineH10 + labelValueGap; }; auto drawWrapped = [&](int fontId, const std::string& text, int lineH, EpdFontFamily::Style style) { auto lines = renderer.wrappedText(fontId, text.c_str(), contentW, maxWrappedLines, style); for (const auto& line : lines) { renderer.drawText(fontId, margin, y, line.c_str(), true, style); y += lineH; } y += sectionGap; }; // Title drawWrapped(UI_12_FONT_ID, title, lineH12, EpdFontFamily::BOLD); // Author if (!author.empty()) { drawLabel(tr(STR_AUTHOR)); drawWrapped(UI_12_FONT_ID, author, lineH12, EpdFontFamily::REGULAR); } // Series if (!series.empty()) { drawLabel(tr(STR_SERIES)); std::string seriesStr = series; if (!seriesIndex.empty()) { seriesStr += " #" + seriesIndex; } drawWrapped(UI_12_FONT_ID, seriesStr, lineH12, EpdFontFamily::REGULAR); } // Language if (!language.empty()) { drawLabel(tr(STR_LANGUAGE)); drawWrapped(UI_12_FONT_ID, language, lineH12, EpdFontFamily::REGULAR); } // File size if (fileSize > 0) { drawLabel(tr(STR_FILE_SIZE)); drawWrapped(UI_12_FONT_ID, formatFileSize(fileSize), lineH12, EpdFontFamily::REGULAR); } // Description if (!description.empty()) { drawLabel(tr(STR_DESCRIPTION)); drawWrapped(UI_12_FONT_ID, description, lineH12, EpdFontFamily::REGULAR); } contentHeight = y + scrollOffset; // Button hints const char* scrollHint = contentHeight > pageH ? tr(STR_DIR_DOWN) : ""; const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", scrollHint, ""); GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4); renderer.displayBuffer(); } std::string BookInfoActivity::formatFileSize(size_t bytes) { char buf[32]; if (bytes < 1024) { snprintf(buf, sizeof(buf), "%u B", static_cast(bytes)); } else if (bytes < 1024 * 1024) { snprintf(buf, sizeof(buf), "%.1f KB", static_cast(bytes) / 1024.0f); } else { snprintf(buf, sizeof(buf), "%.1f MB", static_cast(bytes) / (1024.0f * 1024.0f)); } return buf; }