feat: side-by-side cover layout for BookInfo in landscape
In landscape orientation the cover is pinned on the left panel (filling the content height) while metadata fields scroll independently on the right. Portrait layout is unchanged. Made-with: Cursor
This commit is contained in:
@@ -43,6 +43,10 @@ std::string normalizeWhitespace(const std::string& s) {
|
||||
void BookInfoActivity::onEnter() {
|
||||
Activity::onEnter();
|
||||
|
||||
const auto orient = renderer.getOrientation();
|
||||
isLandscape = orient == GfxRenderer::Orientation::LandscapeClockwise ||
|
||||
orient == GfxRenderer::Orientation::LandscapeCounterClockwise;
|
||||
|
||||
std::string fileName = filePath;
|
||||
const size_t lastSlash = filePath.rfind('/');
|
||||
if (lastSlash != std::string::npos) {
|
||||
@@ -58,6 +62,11 @@ void BookInfoActivity::onEnter() {
|
||||
}
|
||||
}
|
||||
|
||||
const auto& metrics = UITheme::getInstance().getMetrics();
|
||||
const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing;
|
||||
const int contentBottom = renderer.getScreenHeight() - metrics.buttonHintsHeight - metrics.verticalSpacing;
|
||||
const int coverH = isLandscape ? (contentBottom - contentTop) : (renderer.getScreenHeight() * 2 / 5);
|
||||
|
||||
BookMetadataCache::BookMetadata meta;
|
||||
|
||||
if (FsHelpers::hasEpubExtension(fileName)) {
|
||||
@@ -74,7 +83,6 @@ void BookInfoActivity::onEnter() {
|
||||
meta = epub.getMetadata();
|
||||
meta.description = normalizeWhitespace(meta.description);
|
||||
|
||||
const int coverH = renderer.getScreenHeight() * 2 / 5;
|
||||
if (epub.generateThumbBmp(coverH)) {
|
||||
coverBmpPath = epub.getThumbBmpPath(coverH);
|
||||
} else {
|
||||
@@ -103,7 +111,6 @@ void BookInfoActivity::onEnter() {
|
||||
meta.title = xtc.getTitle();
|
||||
meta.author = xtc.getAuthor();
|
||||
|
||||
const int coverH = renderer.getScreenHeight() * 2 / 5;
|
||||
if (xtc.generateThumbBmp(coverH)) {
|
||||
coverBmpPath = xtc.getThumbBmpPath(coverH);
|
||||
} else {
|
||||
@@ -132,8 +139,30 @@ void BookInfoActivity::onExit() { Activity::onExit(); }
|
||||
|
||||
void BookInfoActivity::buildLayout(const BookMetadataCache::BookMetadata& meta, size_t fileSize) {
|
||||
const auto& metrics = UITheme::getInstance().getMetrics();
|
||||
const int pageW = renderer.getScreenWidth();
|
||||
const int sidePad = metrics.contentSidePadding;
|
||||
const int contentW = renderer.getScreenWidth() - sidePad * 2;
|
||||
|
||||
if (!coverBmpPath.empty()) {
|
||||
FsFile file;
|
||||
if (Storage.openFileForRead("BIF", coverBmpPath, file)) {
|
||||
Bitmap bitmap(file);
|
||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||
coverDisplayHeight = bitmap.getHeight();
|
||||
coverDisplayWidth = bitmap.getWidth();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
coverPanelWidth = 0;
|
||||
if (isLandscape && coverDisplayWidth > 0) {
|
||||
coverPanelWidth = std::min(coverDisplayWidth + sidePad * 2, pageW * 2 / 5);
|
||||
}
|
||||
|
||||
const int contentW = isLandscape && coverPanelWidth > 0
|
||||
? pageW - coverPanelWidth - sidePad
|
||||
: pageW - sidePad * 2;
|
||||
|
||||
fields.reserve(13);
|
||||
|
||||
auto addField = [&](const char* label, const std::string& text, bool bold, EpdFontFamily::Style style) {
|
||||
@@ -185,19 +214,8 @@ void BookInfoActivity::buildLayout(const BookMetadataCache::BookMetadata& meta,
|
||||
const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing;
|
||||
int h = contentTop;
|
||||
|
||||
if (!coverBmpPath.empty()) {
|
||||
FsFile file;
|
||||
if (Storage.openFileForRead("BIF", coverBmpPath, file)) {
|
||||
Bitmap bitmap(file);
|
||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||
coverDisplayHeight = bitmap.getHeight();
|
||||
coverDisplayWidth = bitmap.getWidth();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
if (coverDisplayHeight > 0) {
|
||||
h += coverDisplayHeight + COVER_GAP;
|
||||
}
|
||||
if (!isLandscape && coverDisplayHeight > 0 && !coverBmpPath.empty()) {
|
||||
h += coverDisplayHeight + COVER_GAP;
|
||||
}
|
||||
|
||||
for (const auto& field : fields) {
|
||||
@@ -255,9 +273,23 @@ void BookInfoActivity::render(RenderLock&&) {
|
||||
const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing;
|
||||
const int contentBottom = pageH - metrics.buttonHintsHeight - metrics.verticalSpacing;
|
||||
|
||||
if (isLandscape && coverPanelWidth > 0 && !coverBmpPath.empty() && coverDisplayHeight > 0) {
|
||||
FsFile file;
|
||||
if (Storage.openFileForRead("BIF", coverBmpPath, file)) {
|
||||
Bitmap bitmap(file);
|
||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||
const int availH = contentBottom - contentTop;
|
||||
const int coverX = (coverPanelWidth - coverDisplayWidth) / 2;
|
||||
renderer.drawBitmap1Bit(bitmap, coverX, contentTop, coverDisplayWidth, availH);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
const int fieldX = (isLandscape && coverPanelWidth > 0) ? coverPanelWidth : sidePad;
|
||||
int y = contentTop - scrollOffset;
|
||||
|
||||
if (!coverBmpPath.empty() && coverDisplayHeight > 0) {
|
||||
if (!isLandscape && !coverBmpPath.empty() && coverDisplayHeight > 0) {
|
||||
if (y + coverDisplayHeight > 0 && y < contentBottom) {
|
||||
FsFile file;
|
||||
if (Storage.openFileForRead("BIF", coverBmpPath, file)) {
|
||||
@@ -277,7 +309,7 @@ void BookInfoActivity::render(RenderLock&&) {
|
||||
|
||||
if (field.label) {
|
||||
if (y + lineH10 > contentTop && y < contentBottom) {
|
||||
renderer.drawText(UI_10_FONT_ID, sidePad, y, field.label, true, EpdFontFamily::BOLD);
|
||||
renderer.drawText(UI_10_FONT_ID, fieldX, y, field.label, true, EpdFontFamily::BOLD);
|
||||
}
|
||||
y += lineH10 + LABEL_VALUE_GAP;
|
||||
}
|
||||
@@ -286,7 +318,7 @@ void BookInfoActivity::render(RenderLock&&) {
|
||||
for (const auto& line : field.lines) {
|
||||
if (y >= contentBottom) break;
|
||||
if (y + lineH12 > contentTop) {
|
||||
renderer.drawText(UI_12_FONT_ID, sidePad, y, line.c_str(), true, style);
|
||||
renderer.drawText(UI_12_FONT_ID, fieldX, y, line.c_str(), true, style);
|
||||
}
|
||||
y += lineH12;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user