| 208 | } |
| 209 | |
| 210 | void HomeActivity::render(RenderLock&&) { |
| 211 | const auto& metrics = UITheme::getInstance().getMetrics(); |
| 212 | const auto pageWidth = renderer.getScreenWidth(); |
| 213 | const auto pageHeight = renderer.getScreenHeight(); |
| 214 | |
| 215 | renderer.clearScreen(); |
| 216 | bool bufferRestored = coverBufferStored && restoreCoverBuffer(); |
| 217 | |
| 218 | GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.homeTopPadding}, |
| 219 | metrics.homeContinueReadingInMenu && !recentBooks.empty() ? recentBooks[0].title.c_str() : nullptr); |
| 220 | |
| 221 | // Record the tile rect so storeCoverBuffer (called from the theme) knows |
| 222 | // which sub-region of the framebuffer to snapshot. ~16 KB in Portrait |
| 223 | // instead of the 48 KB full framebuffer the previous bind captured. |
| 224 | coverRectX = 0; |
| 225 | coverRectY = metrics.homeTopPadding; |
| 226 | coverRectW = pageWidth; |
| 227 | coverRectH = metrics.homeCoverTileHeight; |
| 228 | |
| 229 | GUI.drawRecentBookCover(renderer, Rect{0, metrics.homeTopPadding, pageWidth, metrics.homeCoverTileHeight}, |
| 230 | recentBooks, selectorIndex, coverRendered, coverBufferStored, bufferRestored, |
| 231 | std::bind(&HomeActivity::storeCoverBuffer, this)); |
| 232 | |
| 233 | // Build menu items dynamically |
| 234 | std::vector<const char*> menuItems = {tr(STR_BROWSE_FILES), tr(STR_MENU_RECENT_BOOKS), tr(STR_FILE_TRANSFER), |
| 235 | tr(STR_SETTINGS_TITLE)}; |
| 236 | std::vector<UIIcon> menuIcons = {Folder, Recent, Transfer, Settings}; |
| 237 | |
| 238 | if (hasOpdsServers) { |
| 239 | menuItems.insert(menuItems.begin() + 2, tr(STR_OPDS_BROWSER)); |
| 240 | menuIcons.insert(menuIcons.begin() + 2, Library); |
| 241 | } |
| 242 | |
| 243 | if (metrics.homeContinueReadingInMenu && !recentBooks.empty()) { |
| 244 | // Insert Continue Reading at the top if enabled in theme |
| 245 | menuItems.insert(menuItems.begin(), tr(STR_CONTINUE_READING)); |
| 246 | menuIcons.insert(menuIcons.begin(), Book); |
| 247 | } |
| 248 | |
| 249 | GUI.drawButtonMenu( |
| 250 | renderer, |
| 251 | Rect{0, metrics.homeTopPadding + metrics.homeCoverTileHeight + metrics.homeMenuTopOffset, pageWidth, |
| 252 | pageHeight - (metrics.headerHeight + metrics.homeTopPadding + metrics.verticalSpacing + |
| 253 | metrics.homeMenuTopOffset + metrics.buttonHintsHeight)}, |
| 254 | static_cast<int>(menuItems.size()), |
| 255 | metrics.homeContinueReadingInMenu ? selectorIndex : selectorIndex - recentBooks.size(), |
| 256 | [&menuItems](int index) { return std::string(menuItems[index]); }, |
| 257 | [&menuIcons](int index) { return menuIcons[index]; }); |
| 258 | |
| 259 | const auto labels = mappedInput.mapLabels("", tr(STR_SELECT), tr(STR_DIR_UP), tr(STR_DIR_DOWN)); |
| 260 | GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4); |
| 261 | |
| 262 | renderer.displayBuffer(); |
| 263 | |
| 264 | if (!firstRenderDone) { |
| 265 | firstRenderDone = true; |
| 266 | requestUpdate(); |
| 267 | } else if (!recentsLoaded && !recentsLoading) { |
nothing calls this directly
no test coverage detected