Refactor sleep cover overlay: BookOverlayInfo struct, multi-line layout, 4 color modes (White/Gray/Black/Off)
This commit is contained in:
@@ -0,0 +1,413 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
// THIS FILE IS AUTO-GENERATED BY gen_i18n.py. DO NOT EDIT.
|
||||
|
||||
// Forward declaration for string arrays
|
||||
namespace i18n_strings {
|
||||
extern const char* const STRINGS_EN[];
|
||||
extern const char* const STRINGS_ES[];
|
||||
extern const char* const STRINGS_FR[];
|
||||
extern const char* const STRINGS_DE[];
|
||||
extern const char* const STRINGS_CS[];
|
||||
extern const char* const STRINGS_PO[];
|
||||
extern const char* const STRINGS_RU[];
|
||||
extern const char* const STRINGS_SV[];
|
||||
extern const char* const STRINGS_RO[];
|
||||
extern const char* const STRINGS_CA[];
|
||||
extern const char* const STRINGS_UK[];
|
||||
extern const char* const STRINGS_BE[];
|
||||
extern const char* const STRINGS_IT[];
|
||||
extern const char* const STRINGS_PL[];
|
||||
extern const char* const STRINGS_FI[];
|
||||
extern const char* const STRINGS_DA[];
|
||||
extern const char* const STRINGS_NL[];
|
||||
extern const char* const STRINGS_TR[];
|
||||
extern const char* const STRINGS_KK[];
|
||||
} // namespace i18n_strings
|
||||
|
||||
// Language enum
|
||||
enum class Language : uint8_t {
|
||||
EN = 0,
|
||||
ES = 1,
|
||||
FR = 2,
|
||||
DE = 3,
|
||||
CS = 4,
|
||||
PT = 5,
|
||||
RU = 6,
|
||||
SV = 7,
|
||||
RO = 8,
|
||||
CA = 9,
|
||||
UK = 10,
|
||||
BE = 11,
|
||||
IT = 12,
|
||||
PL = 13,
|
||||
FI = 14,
|
||||
DA = 15,
|
||||
NL = 16,
|
||||
TR = 17,
|
||||
KK = 18,
|
||||
_COUNT
|
||||
};
|
||||
|
||||
// Language display names (defined in I18nStrings.cpp)
|
||||
extern const char* const LANGUAGE_NAMES[];
|
||||
|
||||
// Character sets for each language (defined in I18nStrings.cpp)
|
||||
extern const char* const CHARACTER_SETS[];
|
||||
|
||||
// String IDs
|
||||
enum class StrId : uint16_t {
|
||||
STR_CROSSPOINT,
|
||||
STR_BOOTING,
|
||||
STR_SLEEPING,
|
||||
STR_ENTERING_SLEEP,
|
||||
STR_BROWSE_FILES,
|
||||
STR_FILE_TRANSFER,
|
||||
STR_SETTINGS_TITLE,
|
||||
STR_CONTINUE_READING,
|
||||
STR_NO_OPEN_BOOK,
|
||||
STR_START_READING,
|
||||
STR_NO_FILES_FOUND,
|
||||
STR_SELECT_CHAPTER,
|
||||
STR_NO_CHAPTERS,
|
||||
STR_END_OF_BOOK,
|
||||
STR_EMPTY_CHAPTER,
|
||||
STR_INDEXING,
|
||||
STR_MEMORY_ERROR,
|
||||
STR_PAGE_LOAD_ERROR,
|
||||
STR_EMPTY_FILE,
|
||||
STR_OUT_OF_BOUNDS,
|
||||
STR_LOADING,
|
||||
STR_LOADING_POPUP,
|
||||
STR_WIFI_NETWORKS,
|
||||
STR_NO_NETWORKS,
|
||||
STR_NETWORKS_FOUND,
|
||||
STR_SCANNING,
|
||||
STR_CONNECTING,
|
||||
STR_CONNECTED,
|
||||
STR_CONNECTION_FAILED,
|
||||
STR_FORGET_NETWORK,
|
||||
STR_SAVE_PASSWORD,
|
||||
STR_PRESS_OK_SCAN,
|
||||
STR_JOIN_NETWORK,
|
||||
STR_CREATE_HOTSPOT,
|
||||
STR_JOIN_DESC,
|
||||
STR_HOTSPOT_DESC,
|
||||
STR_STARTING_HOTSPOT,
|
||||
STR_HOTSPOT_MODE,
|
||||
STR_CONNECT_WIFI_HINT,
|
||||
STR_OPEN_URL_HINT,
|
||||
STR_OR_HTTP_PREFIX,
|
||||
STR_SCAN_QR_HINT,
|
||||
STR_CALIBRE_WIRELESS,
|
||||
STR_CALIBRE_WEB_URL,
|
||||
STR_NETWORK_LEGEND,
|
||||
STR_MAC_ADDRESS,
|
||||
STR_CHECKING_WIFI,
|
||||
STR_ENTER_WIFI_PASSWORD,
|
||||
STR_TO_PREFIX,
|
||||
STR_CALIBRE_RECEIVING,
|
||||
STR_CALIBRE_RECEIVED,
|
||||
STR_CALIBRE_INSTRUCTION_1,
|
||||
STR_CALIBRE_INSTRUCTION_2,
|
||||
STR_CALIBRE_INSTRUCTION_3,
|
||||
STR_CALIBRE_INSTRUCTION_4,
|
||||
STR_CAT_DISPLAY,
|
||||
STR_CAT_READER,
|
||||
STR_CAT_CONTROLS,
|
||||
STR_CAT_SYSTEM,
|
||||
STR_SLEEP_SCREEN,
|
||||
STR_SLEEP_COVER_MODE,
|
||||
STR_HIDE_BATTERY,
|
||||
STR_EXTRA_SPACING,
|
||||
STR_TEXT_AA,
|
||||
STR_IMAGES,
|
||||
STR_IMAGES_DISPLAY,
|
||||
STR_IMAGES_PLACEHOLDER,
|
||||
STR_IMAGES_SUPPRESS,
|
||||
STR_SHORT_PWR_BTN,
|
||||
STR_ORIENTATION,
|
||||
STR_SIDE_BTN_LAYOUT,
|
||||
STR_LONG_PRESS_SKIP,
|
||||
STR_FONT_FAMILY,
|
||||
STR_FONT_SIZE,
|
||||
STR_LINE_SPACING,
|
||||
STR_SCREEN_MARGIN,
|
||||
STR_PARA_ALIGNMENT,
|
||||
STR_HYPHENATION,
|
||||
STR_TIME_TO_SLEEP,
|
||||
STR_SHOW_HIDDEN_FILES,
|
||||
STR_REFRESH_FREQ,
|
||||
STR_KOREADER_SYNC,
|
||||
STR_CHECK_UPDATES,
|
||||
STR_LANGUAGE,
|
||||
STR_CLEAR_READING_CACHE,
|
||||
STR_USERNAME,
|
||||
STR_PASSWORD,
|
||||
STR_SYNC_SERVER_URL,
|
||||
STR_DOCUMENT_MATCHING,
|
||||
STR_AUTHENTICATE,
|
||||
STR_KOREADER_USERNAME,
|
||||
STR_KOREADER_PASSWORD,
|
||||
STR_FILENAME,
|
||||
STR_BINARY,
|
||||
STR_SET_CREDENTIALS_FIRST,
|
||||
STR_WIFI_CONN_FAILED,
|
||||
STR_AUTHENTICATING,
|
||||
STR_AUTH_SUCCESS,
|
||||
STR_KOREADER_AUTH,
|
||||
STR_SYNC_READY,
|
||||
STR_AUTH_FAILED,
|
||||
STR_DONE,
|
||||
STR_CLEAR_CACHE_WARNING_1,
|
||||
STR_CLEAR_CACHE_WARNING_2,
|
||||
STR_CLEAR_CACHE_WARNING_3,
|
||||
STR_CLEAR_CACHE_WARNING_4,
|
||||
STR_CLEARING_CACHE,
|
||||
STR_CACHE_CLEARED,
|
||||
STR_ITEMS_REMOVED,
|
||||
STR_FAILED_LOWER,
|
||||
STR_CLEAR_CACHE_FAILED,
|
||||
STR_CHECK_SERIAL_OUTPUT,
|
||||
STR_DARK,
|
||||
STR_LIGHT,
|
||||
STR_CUSTOM,
|
||||
STR_COVER,
|
||||
STR_NONE_OPT,
|
||||
STR_FIT,
|
||||
STR_CROP,
|
||||
STR_NEVER,
|
||||
STR_IN_READER,
|
||||
STR_ALWAYS,
|
||||
STR_IGNORE,
|
||||
STR_SLEEP,
|
||||
STR_PAGE_TURN,
|
||||
STR_PORTRAIT,
|
||||
STR_LANDSCAPE_CW,
|
||||
STR_INVERTED,
|
||||
STR_LANDSCAPE_CCW,
|
||||
STR_PREV_NEXT,
|
||||
STR_NEXT_PREV,
|
||||
STR_BOOKERLY,
|
||||
STR_NOTO_SANS,
|
||||
STR_OPEN_DYSLEXIC,
|
||||
STR_SMALL,
|
||||
STR_MEDIUM,
|
||||
STR_LARGE,
|
||||
STR_X_LARGE,
|
||||
STR_TIGHT,
|
||||
STR_NORMAL,
|
||||
STR_WIDE,
|
||||
STR_JUSTIFY,
|
||||
STR_ALIGN_LEFT,
|
||||
STR_CENTER,
|
||||
STR_ALIGN_RIGHT,
|
||||
STR_MIN_1,
|
||||
STR_MIN_5,
|
||||
STR_MIN_10,
|
||||
STR_MIN_15,
|
||||
STR_MIN_30,
|
||||
STR_PAGES_1,
|
||||
STR_PAGES_5,
|
||||
STR_PAGES_10,
|
||||
STR_PAGES_15,
|
||||
STR_PAGES_30,
|
||||
STR_UPDATE,
|
||||
STR_CHECKING_UPDATE,
|
||||
STR_NEW_UPDATE,
|
||||
STR_CURRENT_VERSION,
|
||||
STR_NEW_VERSION,
|
||||
STR_UPDATING,
|
||||
STR_NO_UPDATE,
|
||||
STR_UPDATE_FAILED,
|
||||
STR_UPDATE_COMPLETE,
|
||||
STR_POWER_ON_HINT,
|
||||
STR_NO_ENTRIES,
|
||||
STR_DOWNLOADING,
|
||||
STR_DOWNLOAD_FAILED,
|
||||
STR_ERROR_MSG,
|
||||
STR_UNNAMED,
|
||||
STR_NO_SERVER_URL,
|
||||
STR_FETCH_FEED_FAILED,
|
||||
STR_PARSE_FEED_FAILED,
|
||||
STR_NETWORK_PREFIX,
|
||||
STR_IP_ADDRESS_PREFIX,
|
||||
STR_ERROR_GENERAL_FAILURE,
|
||||
STR_ERROR_NETWORK_NOT_FOUND,
|
||||
STR_ERROR_CONNECTION_TIMEOUT,
|
||||
STR_SD_CARD,
|
||||
STR_BACK,
|
||||
STR_EXIT,
|
||||
STR_HOME,
|
||||
STR_SELECT,
|
||||
STR_SELECTED,
|
||||
STR_TOGGLE,
|
||||
STR_CONFIRM,
|
||||
STR_CANCEL,
|
||||
STR_CONNECT,
|
||||
STR_OPEN,
|
||||
STR_DOWNLOAD,
|
||||
STR_RETRY,
|
||||
STR_YES,
|
||||
STR_NO,
|
||||
STR_SHOW,
|
||||
STR_HIDE,
|
||||
STR_STATE_ON,
|
||||
STR_STATE_OFF,
|
||||
STR_NOT_SET,
|
||||
STR_DIR_LEFT,
|
||||
STR_DIR_RIGHT,
|
||||
STR_DIR_UP,
|
||||
STR_DIR_DOWN,
|
||||
STR_OK_BUTTON,
|
||||
STR_SLEEP_COVER_FILTER,
|
||||
STR_FILTER_CONTRAST,
|
||||
STR_CUSTOMISE_STATUS_BAR,
|
||||
STR_CHAPTER_PAGE_COUNT,
|
||||
STR_BOOK_PROGRESS_PERCENTAGE,
|
||||
STR_PROGRESS_BAR,
|
||||
STR_PROGRESS_BAR_THICKNESS,
|
||||
STR_PROGRESS_BAR_THIN,
|
||||
STR_PROGRESS_BAR_MEDIUM,
|
||||
STR_PROGRESS_BAR_THICK,
|
||||
STR_BOOK,
|
||||
STR_CHAPTER,
|
||||
STR_EXAMPLE_CHAPTER,
|
||||
STR_EXAMPLE_BOOK,
|
||||
STR_PREVIEW,
|
||||
STR_TITLE,
|
||||
STR_BATTERY,
|
||||
STR_UI_THEME,
|
||||
STR_THEME_CLASSIC,
|
||||
STR_THEME_LYRA,
|
||||
STR_THEME_LYRA_EXTENDED,
|
||||
STR_SUNLIGHT_FADING_FIX,
|
||||
STR_REMAP_FRONT_BUTTONS,
|
||||
STR_OPDS_BROWSER,
|
||||
STR_COVER_CUSTOM,
|
||||
STR_MENU_RECENT_BOOKS,
|
||||
STR_NO_RECENT_BOOKS,
|
||||
STR_CALIBRE_DESC,
|
||||
STR_FORGET_AND_REMOVE,
|
||||
STR_FORGET_BUTTON,
|
||||
STR_CALIBRE_STARTING,
|
||||
STR_CALIBRE_SETUP,
|
||||
STR_CALIBRE_STATUS,
|
||||
STR_CLEAR_BUTTON,
|
||||
STR_DEFAULT_VALUE,
|
||||
STR_REMAP_PROMPT,
|
||||
STR_UNASSIGNED,
|
||||
STR_ALREADY_ASSIGNED,
|
||||
STR_REMAP_RESET_HINT,
|
||||
STR_REMAP_CANCEL_HINT,
|
||||
STR_HW_BACK_LABEL,
|
||||
STR_HW_CONFIRM_LABEL,
|
||||
STR_HW_LEFT_LABEL,
|
||||
STR_HW_RIGHT_LABEL,
|
||||
STR_GO_TO_PERCENT,
|
||||
STR_GO_HOME_BUTTON,
|
||||
STR_SYNC_PROGRESS,
|
||||
STR_DELETE_CACHE,
|
||||
STR_DELETE,
|
||||
STR_DISPLAY_QR,
|
||||
STR_CHAPTER_PREFIX,
|
||||
STR_PAGES_SEPARATOR,
|
||||
STR_BOOK_PREFIX,
|
||||
STR_CALIBRE_URL_HINT,
|
||||
STR_PERCENT_STEP_HINT,
|
||||
STR_SYNCING_TIME,
|
||||
STR_CALC_HASH,
|
||||
STR_HASH_FAILED,
|
||||
STR_FETCH_PROGRESS,
|
||||
STR_UPLOAD_PROGRESS,
|
||||
STR_NO_CREDENTIALS_MSG,
|
||||
STR_KOREADER_SETUP_HINT,
|
||||
STR_PROGRESS_FOUND,
|
||||
STR_REMOTE_LABEL,
|
||||
STR_LOCAL_LABEL,
|
||||
STR_PAGE_OVERALL_FORMAT,
|
||||
STR_PAGE_TOTAL_OVERALL_FORMAT,
|
||||
STR_DEVICE_FROM_FORMAT,
|
||||
STR_APPLY_REMOTE,
|
||||
STR_UPLOAD_LOCAL,
|
||||
STR_NO_REMOTE_MSG,
|
||||
STR_UPLOAD_PROMPT,
|
||||
STR_UPLOAD_SUCCESS,
|
||||
STR_SYNC_FAILED_MSG,
|
||||
STR_SECTION_PREFIX,
|
||||
STR_UPLOAD,
|
||||
STR_BOOK_S_STYLE,
|
||||
STR_EMBEDDED_STYLE,
|
||||
STR_OPDS_SERVER_URL,
|
||||
STR_FOOTNOTES,
|
||||
STR_NO_FOOTNOTES,
|
||||
STR_LINK,
|
||||
STR_SCREENSHOT_BUTTON,
|
||||
STR_AUTO_TURN_ENABLED,
|
||||
STR_AUTO_TURN_PAGES_PER_MIN,
|
||||
STR_SLEEP_COVER_OVERLAY,
|
||||
STR_OVERLAY_WHITE,
|
||||
STR_OVERLAY_GRAY,
|
||||
STR_OVERLAY_BLACK,
|
||||
STR_OVERLAY_OFF,
|
||||
// Sentinel - must be last
|
||||
_COUNT
|
||||
};
|
||||
|
||||
// Helper function to get string array for a language
|
||||
inline const char* const* getStringArray(Language lang) {
|
||||
switch (lang) {
|
||||
case Language::EN:
|
||||
return i18n_strings::STRINGS_EN;
|
||||
case Language::ES:
|
||||
return i18n_strings::STRINGS_ES;
|
||||
case Language::FR:
|
||||
return i18n_strings::STRINGS_FR;
|
||||
case Language::DE:
|
||||
return i18n_strings::STRINGS_DE;
|
||||
case Language::CS:
|
||||
return i18n_strings::STRINGS_CS;
|
||||
case Language::PT:
|
||||
return i18n_strings::STRINGS_PO;
|
||||
case Language::RU:
|
||||
return i18n_strings::STRINGS_RU;
|
||||
case Language::SV:
|
||||
return i18n_strings::STRINGS_SV;
|
||||
case Language::RO:
|
||||
return i18n_strings::STRINGS_RO;
|
||||
case Language::CA:
|
||||
return i18n_strings::STRINGS_CA;
|
||||
case Language::UK:
|
||||
return i18n_strings::STRINGS_UK;
|
||||
case Language::BE:
|
||||
return i18n_strings::STRINGS_BE;
|
||||
case Language::IT:
|
||||
return i18n_strings::STRINGS_IT;
|
||||
case Language::PL:
|
||||
return i18n_strings::STRINGS_PL;
|
||||
case Language::FI:
|
||||
return i18n_strings::STRINGS_FI;
|
||||
case Language::DA:
|
||||
return i18n_strings::STRINGS_DA;
|
||||
case Language::NL:
|
||||
return i18n_strings::STRINGS_NL;
|
||||
case Language::TR:
|
||||
return i18n_strings::STRINGS_TR;
|
||||
case Language::KK:
|
||||
return i18n_strings::STRINGS_KK;
|
||||
default:
|
||||
return i18n_strings::STRINGS_EN;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to get language count
|
||||
constexpr uint8_t getLanguageCount() { return static_cast<uint8_t>(Language::_COUNT); }
|
||||
|
||||
// Sorted language indices by code (auto-generated by gen_i18n.py)
|
||||
// Order: English, Беларуская, Català, Čeština, Dansk, Deutsch, Español, Suomi, Français, Italiano, Қазақша, Nederlands,
|
||||
// Polski, Português (Brasil), Română, Русский, Svenska, Türkçe, Українська
|
||||
constexpr uint8_t SORTED_LANGUAGE_INDICES[] = {0, 11, 9, 4, 15, 3, 1, 14, 2, 12, 18, 16, 13, 5, 8, 6, 7, 17, 10};
|
||||
|
||||
static_assert(sizeof(SORTED_LANGUAGE_INDICES) / sizeof(SORTED_LANGUAGE_INDICES[0]) == getLanguageCount(),
|
||||
"SORTED_LANGUAGE_INDICES size mismatch");
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#include "I18nKeys.h"
|
||||
|
||||
// THIS FILE IS AUTO-GENERATED BY gen_i18n.py. DO NOT EDIT.
|
||||
|
||||
namespace i18n_strings {
|
||||
|
||||
extern const char* const STRINGS_EN[];
|
||||
extern const char* const STRINGS_ES[];
|
||||
extern const char* const STRINGS_FR[];
|
||||
extern const char* const STRINGS_DE[];
|
||||
extern const char* const STRINGS_CS[];
|
||||
extern const char* const STRINGS_PO[];
|
||||
extern const char* const STRINGS_RU[];
|
||||
extern const char* const STRINGS_SV[];
|
||||
extern const char* const STRINGS_RO[];
|
||||
extern const char* const STRINGS_CA[];
|
||||
extern const char* const STRINGS_UK[];
|
||||
extern const char* const STRINGS_BE[];
|
||||
extern const char* const STRINGS_IT[];
|
||||
extern const char* const STRINGS_PL[];
|
||||
extern const char* const STRINGS_FI[];
|
||||
extern const char* const STRINGS_DA[];
|
||||
extern const char* const STRINGS_NL[];
|
||||
extern const char* const STRINGS_TR[];
|
||||
extern const char* const STRINGS_KK[];
|
||||
|
||||
} // namespace i18n_strings
|
||||
@@ -291,3 +291,7 @@ STR_SCREENSHOT_BUTTON: "Take screenshot"
|
||||
STR_AUTO_TURN_ENABLED: "Auto Turn Enabled: "
|
||||
STR_AUTO_TURN_PAGES_PER_MIN: "Auto Turn (Pages Per Minute)"
|
||||
STR_SLEEP_COVER_OVERLAY: "Sleep Screen Info Overlay"
|
||||
STR_OVERLAY_WHITE: "White"
|
||||
STR_OVERLAY_GRAY: "Gray"
|
||||
STR_OVERLAY_BLACK: "Black"
|
||||
STR_OVERLAY_OFF: "Off"
|
||||
|
||||
@@ -144,7 +144,7 @@ class CrossPointSettings {
|
||||
// Sleep screen cover filter
|
||||
uint8_t sleepScreenCoverFilter = NO_FILTER;
|
||||
// Apply information overlay with reading progress on sleep cover
|
||||
uint8_t sleepCoverOverlay = 1;
|
||||
uint8_t sleepCoverOverlay = 0;
|
||||
// Status bar settings (statusBar retained for migration only)
|
||||
uint8_t statusBar = FULL;
|
||||
uint8_t statusBarChapterPageCount = 1;
|
||||
|
||||
+4
-2
@@ -23,8 +23,10 @@ inline const std::vector<SettingInfo>& getSettingsList() {
|
||||
SettingInfo::Enum(StrId::STR_SLEEP_COVER_FILTER, &CrossPointSettings::sleepScreenCoverFilter,
|
||||
{StrId::STR_NONE_OPT, StrId::STR_FILTER_CONTRAST, StrId::STR_INVERTED},
|
||||
"sleepScreenCoverFilter", StrId::STR_CAT_DISPLAY),
|
||||
SettingInfo::Toggle(StrId::STR_SLEEP_COVER_OVERLAY, &CrossPointSettings::sleepCoverOverlay, "sleepCoverOverlay",
|
||||
StrId::STR_CAT_DISPLAY),
|
||||
SettingInfo::Enum(
|
||||
StrId::STR_SLEEP_COVER_OVERLAY, &CrossPointSettings::sleepCoverOverlay,
|
||||
{StrId::STR_OVERLAY_WHITE, StrId::STR_OVERLAY_GRAY, StrId::STR_OVERLAY_BLACK, StrId::STR_OVERLAY_OFF},
|
||||
"sleepCoverOverlay", StrId::STR_CAT_DISPLAY),
|
||||
SettingInfo::Enum(StrId::STR_HIDE_BATTERY, &CrossPointSettings::hideBatteryPercentage,
|
||||
{StrId::STR_NEVER, StrId::STR_IN_READER, StrId::STR_ALWAYS}, "hideBatteryPercentage",
|
||||
StrId::STR_CAT_DISPLAY),
|
||||
|
||||
@@ -137,20 +137,15 @@ void SleepActivity::renderDefaultSleepScreen() const {
|
||||
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
|
||||
}
|
||||
|
||||
std::string SleepActivity::getBookOverlayText(const std::string& bookPath) const {
|
||||
std::string title;
|
||||
std::string author;
|
||||
std::string progressLine = "Reading..."; // Default progress text
|
||||
BookOverlayInfo SleepActivity::getBookOverlayInfo(const std::string& bookPath) const {
|
||||
BookOverlayInfo info;
|
||||
|
||||
// Extract metadata based on file type
|
||||
if (StringUtils::checkFileExtension(bookPath, ".xtc") || StringUtils::checkFileExtension(bookPath, ".xtch")) {
|
||||
// Handle XTC file
|
||||
if (FsHelpers::checkFileExtension(bookPath, ".xtc") || FsHelpers::checkFileExtension(bookPath, ".xtch")) {
|
||||
Xtc xtc(bookPath, "/.crosspoint");
|
||||
if (xtc.load()) {
|
||||
title = xtc.getTitle();
|
||||
author = xtc.getAuthor();
|
||||
info.title = xtc.getTitle();
|
||||
info.author = xtc.getAuthor();
|
||||
|
||||
// Load progress - XTC stores current page
|
||||
FsFile f;
|
||||
if (Storage.openFileForRead("SLP", xtc.getCachePath() + "/progress.bin", f)) {
|
||||
uint8_t data[4];
|
||||
@@ -159,65 +154,55 @@ std::string SleepActivity::getBookOverlayText(const std::string& bookPath) const
|
||||
(static_cast<uint32_t>(data[2]) << 16) | (static_cast<uint32_t>(data[3]) << 24);
|
||||
uint32_t totalPages = xtc.getPageCount();
|
||||
float progress = xtc.calculateProgress(currentPage) * 100.0f;
|
||||
char progressStr[32];
|
||||
snprintf(progressStr, sizeof(progressStr), "%lu/%u %.0f%%", (unsigned long)currentPage + 1, totalPages,
|
||||
progress);
|
||||
progressLine = progressStr;
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "Reading progress: Page %lu/%u - %.0f%%", (unsigned long)currentPage + 1,
|
||||
totalPages, progress);
|
||||
info.progressText = buf;
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
} else if (StringUtils::checkFileExtension(bookPath, ".txt")) {
|
||||
// Handle TXT file
|
||||
} else if (FsHelpers::checkFileExtension(bookPath, ".txt")) {
|
||||
Txt txt(bookPath, "/.crosspoint");
|
||||
if (txt.load()) {
|
||||
title = txt.getTitle();
|
||||
// TXT files don't have author metadata
|
||||
info.title = txt.getTitle();
|
||||
|
||||
// Load progress - TXT stores current page
|
||||
FsFile f;
|
||||
if (Storage.openFileForRead("SLP", txt.getCachePath() + "/progress.bin", f)) {
|
||||
uint8_t data[4];
|
||||
if (f.read(data, 4) == 4) {
|
||||
uint32_t currentPage = data[0] + (data[1] << 8);
|
||||
|
||||
// Load total pages from page index cache
|
||||
uint32_t totalPages = 0;
|
||||
FsFile indexFile;
|
||||
if (Storage.openFileForRead("SLP", txt.getCachePath() + "/index.bin", indexFile)) {
|
||||
// Read numPages directly (it's at a fixed offset after headers)
|
||||
// Skip: magic(4) + version(4) + fileSize(4) + cachedWidth(4) + cachedLines(4) + fontId(4) + margin(4) +
|
||||
// alignment(4) = 32 bytes
|
||||
indexFile.seek(32);
|
||||
if (indexFile.read(reinterpret_cast<uint8_t*>(&totalPages), sizeof(totalPages)) == sizeof(totalPages)) {
|
||||
// Successfully read totalPages
|
||||
}
|
||||
indexFile.close();
|
||||
}
|
||||
|
||||
if (totalPages > 0) {
|
||||
float progress = (currentPage + 1) * 100.0f / totalPages;
|
||||
char progressStr[32];
|
||||
snprintf(progressStr, sizeof(progressStr), "%lu/%u %.0f%%", (unsigned long)currentPage + 1, totalPages,
|
||||
progress);
|
||||
progressLine = progressStr;
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "Reading progress: Page %lu/%u - %.0f%%", (unsigned long)currentPage + 1,
|
||||
totalPages, progress);
|
||||
info.progressText = buf;
|
||||
} else {
|
||||
char progressStr[16];
|
||||
snprintf(progressStr, sizeof(progressStr), "Page %lu", (unsigned long)currentPage + 1);
|
||||
progressLine = progressStr;
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "Reading progress: Page %lu", (unsigned long)currentPage + 1);
|
||||
info.progressText = buf;
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
} else if (StringUtils::checkFileExtension(bookPath, ".epub")) {
|
||||
// Handle EPUB file
|
||||
} else if (FsHelpers::checkFileExtension(bookPath, ".epub")) {
|
||||
Epub epub(bookPath, "/.crosspoint");
|
||||
if (epub.load(true, true)) { // Skip CSS loading for metadata only
|
||||
title = epub.getTitle();
|
||||
author = epub.getAuthor();
|
||||
if (epub.load(true, true)) {
|
||||
info.title = epub.getTitle();
|
||||
info.author = epub.getAuthor();
|
||||
|
||||
// Load progress and get chapter information
|
||||
FsFile f;
|
||||
if (Storage.openFileForRead("SLP", epub.getCachePath() + "/progress.bin", f)) {
|
||||
uint8_t data[6];
|
||||
@@ -229,21 +214,20 @@ std::string SleepActivity::getBookOverlayText(const std::string& bookPath) const
|
||||
float chapterProgress = static_cast<float>(currentPage) / static_cast<float>(pageCount);
|
||||
float bookProgress = epub.calculateProgress(currentSpineIndex, chapterProgress) * 100.0f;
|
||||
|
||||
// Get chapter name from TOC
|
||||
const int tocIndex = epub.getTocIndexForSpineIndex(currentSpineIndex);
|
||||
std::string chapterName;
|
||||
if (tocIndex == -1) {
|
||||
chapterName = "Unnamed Chapter";
|
||||
} else {
|
||||
if (tocIndex != -1) {
|
||||
const auto tocItem = epub.getTocItem(tocIndex);
|
||||
chapterName = tocItem.title;
|
||||
info.chapterName = tocItem.title;
|
||||
char suffix[64];
|
||||
snprintf(suffix, sizeof(suffix), " - Page %d/%d - %.0f%%", currentPage + 1, pageCount, bookProgress);
|
||||
info.progressSuffix = suffix;
|
||||
info.progressText = "Chapter: " + info.chapterName + info.progressSuffix;
|
||||
} else {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "Reading progress: Page %d/%d - %.0f%%", currentPage + 1, pageCount,
|
||||
bookProgress);
|
||||
info.progressText = buf;
|
||||
}
|
||||
|
||||
// Create chapter info line with chapter name and progress
|
||||
char chapterProgressStr[128];
|
||||
snprintf(chapterProgressStr, sizeof(chapterProgressStr), "%s: %d/%d %.0f%%", chapterName.c_str(),
|
||||
currentPage + 1, pageCount, bookProgress);
|
||||
progressLine = chapterProgressStr;
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
@@ -251,18 +235,7 @@ std::string SleepActivity::getBookOverlayText(const std::string& bookPath) const
|
||||
}
|
||||
}
|
||||
|
||||
// Format overlay text (two lines)
|
||||
std::string overlayText;
|
||||
if (!title.empty()) {
|
||||
overlayText = title;
|
||||
if (!author.empty()) {
|
||||
overlayText += " - " + author;
|
||||
}
|
||||
overlayText += "\n"; // New line
|
||||
overlayText += progressLine;
|
||||
}
|
||||
|
||||
return overlayText;
|
||||
return info;
|
||||
}
|
||||
|
||||
void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const {
|
||||
@@ -286,7 +259,7 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const {
|
||||
ratio = (1.0f - cropX) * static_cast<float>(bitmap.getWidth()) / static_cast<float>(bitmap.getHeight());
|
||||
}
|
||||
x = 0;
|
||||
y = std::round((static_cast<float>(pageHeight) - static_cast<float>(pageWidth) / ratio) / 2);
|
||||
y = 0;
|
||||
LOG_DBG("SLP", "Centering with ratio %f to y=%d", ratio, y);
|
||||
} else {
|
||||
// image taller than viewport ratio, scaled down image needs to be centered horizontally
|
||||
@@ -302,7 +275,7 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const {
|
||||
} else {
|
||||
// center the image
|
||||
x = (pageWidth - bitmap.getWidth()) / 2;
|
||||
y = (pageHeight - bitmap.getHeight()) / 2;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
LOG_DBG("SLP", "drawing to %d x %d", x, y);
|
||||
@@ -317,43 +290,70 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const {
|
||||
renderer.invertScreen();
|
||||
}
|
||||
|
||||
// Draw overlay text if provided
|
||||
const std::string overlayText = SETTINGS.sleepCoverOverlay ? getBookOverlayText(APP_STATE.openEpubPath) : "";
|
||||
const uint8_t overlayMode = SETTINGS.sleepCoverOverlay;
|
||||
const BookOverlayInfo overlayInfo = overlayMode < 3 ? getBookOverlayInfo(APP_STATE.openEpubPath) : BookOverlayInfo{};
|
||||
const auto drawOverlay = [&]() {
|
||||
if (overlayText.empty()) {
|
||||
const bool hasTitle = !overlayInfo.title.empty();
|
||||
const bool hasProgress = !overlayInfo.progressText.empty();
|
||||
const bool hasAuthor = !overlayInfo.author.empty();
|
||||
if (!hasTitle && !hasAuthor && !hasProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Split text into lines
|
||||
size_t newlinePos = overlayText.find('\n');
|
||||
std::string line1 = (newlinePos != std::string::npos) ? overlayText.substr(0, newlinePos) : overlayText;
|
||||
std::string line2 = (newlinePos != std::string::npos && newlinePos + 1 < overlayText.length())
|
||||
? overlayText.substr(newlinePos + 1)
|
||||
: "";
|
||||
const int lineHeight12 = renderer.getLineHeight(BOOKERLY_12_FONT_ID);
|
||||
const int lineHeight10 = renderer.getLineHeight(UI_10_FONT_ID);
|
||||
constexpr int lineSpacing = 3;
|
||||
constexpr int sectionSpacing = 10;
|
||||
const int availableWidth = pageWidth - 20;
|
||||
|
||||
// Truncate lines if too long for the screen
|
||||
line1 = renderer.truncatedText(UI_10_FONT_ID, line1.c_str(), pageWidth - 20);
|
||||
line2 = renderer.truncatedText(UI_10_FONT_ID, line2.c_str(), pageWidth - 20);
|
||||
int textBlockHeight = 0;
|
||||
if (hasTitle) textBlockHeight += lineHeight12;
|
||||
if (hasAuthor) textBlockHeight += lineSpacing + lineHeight10;
|
||||
if (hasProgress) textBlockHeight += sectionSpacing + lineHeight10;
|
||||
|
||||
// Compute overlay height to exactly fit the text lines with equal top/bottom padding
|
||||
const int lineHeight = renderer.getLineHeight(UI_10_FONT_ID);
|
||||
constexpr int lineSpacing = 4;
|
||||
constexpr int overlayPadding = 10;
|
||||
const int numLines = line2.empty() ? 1 : 2;
|
||||
const int textBlockHeight = numLines * lineHeight + (numLines - 1) * lineSpacing;
|
||||
const int overlayHeight = textBlockHeight + overlayPadding * 2;
|
||||
const int overlayY = pageHeight - overlayHeight - 20;
|
||||
renderer.fillRect(0, overlayY, pageWidth, overlayHeight, false); // White background
|
||||
const bool textBlack = (overlayMode != 2);
|
||||
const int topPadding = lineHeight12 / 3;
|
||||
const int bottomPadding = lineHeight10 * 2 / 3;
|
||||
const int overlayHeight = textBlockHeight + topPadding + bottomPadding;
|
||||
const int overlayY = pageHeight - overlayHeight;
|
||||
|
||||
// Center text block vertically in the overlay rectangle
|
||||
const int textStartY = overlayY + (overlayHeight - textBlockHeight) / 2;
|
||||
const int textX1 = (pageWidth - renderer.getTextWidth(UI_10_FONT_ID, line1.c_str())) / 2;
|
||||
renderer.drawText(UI_10_FONT_ID, textX1, textStartY, line1.c_str(), true); // Black text
|
||||
if (overlayMode == 1) {
|
||||
renderer.fillRectDither(0, overlayY, pageWidth, overlayHeight, Color::LightGray);
|
||||
} else {
|
||||
renderer.fillRect(0, overlayY, pageWidth, overlayHeight, overlayMode == 2);
|
||||
}
|
||||
|
||||
if (!line2.empty()) {
|
||||
const int line2Y = textStartY + lineHeight + lineSpacing;
|
||||
const int textX2 = (pageWidth - renderer.getTextWidth(UI_10_FONT_ID, line2.c_str())) / 2;
|
||||
renderer.drawText(UI_10_FONT_ID, textX2, line2Y, line2.c_str(), true); // Black text
|
||||
int currentY = overlayY + topPadding;
|
||||
|
||||
if (hasTitle) {
|
||||
const std::string titleStr =
|
||||
renderer.truncatedText(BOOKERLY_12_FONT_ID, overlayInfo.title.c_str(), availableWidth, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(BOOKERLY_12_FONT_ID, currentY, titleStr.c_str(), textBlack, EpdFontFamily::BOLD);
|
||||
currentY += lineHeight12 + lineSpacing;
|
||||
}
|
||||
|
||||
if (hasAuthor) {
|
||||
const std::string authorStr = renderer.truncatedText(UI_10_FONT_ID, overlayInfo.author.c_str(), availableWidth);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, currentY, authorStr.c_str(), textBlack);
|
||||
currentY += lineHeight10 + sectionSpacing;
|
||||
}
|
||||
|
||||
if (hasProgress) {
|
||||
std::string progressStr;
|
||||
if (!overlayInfo.chapterName.empty()) {
|
||||
const std::string prefix = "Chapter: ";
|
||||
const int prefixWidth = renderer.getTextWidth(UI_10_FONT_ID, prefix.c_str());
|
||||
const int suffixWidth = renderer.getTextWidth(UI_10_FONT_ID, overlayInfo.progressSuffix.c_str());
|
||||
const int maxChapterWidth = availableWidth - prefixWidth - suffixWidth;
|
||||
const std::string truncatedChapter =
|
||||
maxChapterWidth > 0
|
||||
? renderer.truncatedText(UI_10_FONT_ID, overlayInfo.chapterName.c_str(), maxChapterWidth)
|
||||
: "";
|
||||
progressStr = prefix + truncatedChapter + overlayInfo.progressSuffix;
|
||||
} else {
|
||||
progressStr = renderer.truncatedText(UI_10_FONT_ID, overlayInfo.progressText.c_str(), availableWidth);
|
||||
}
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, currentY, progressStr.c_str(), textBlack);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../Activity.h"
|
||||
|
||||
class Bitmap;
|
||||
|
||||
struct BookOverlayInfo {
|
||||
std::string title;
|
||||
std::string author;
|
||||
std::string progressText;
|
||||
std::string chapterName;
|
||||
std::string progressSuffix;
|
||||
};
|
||||
|
||||
class SleepActivity final : public Activity {
|
||||
public:
|
||||
explicit SleepActivity(GfxRenderer& renderer, MappedInputManager& mappedInput)
|
||||
@@ -15,5 +26,5 @@ class SleepActivity final : public Activity {
|
||||
void renderCoverSleepScreen() const;
|
||||
void renderBitmapSleepScreen(const Bitmap& bitmap) const;
|
||||
void renderBlankSleepScreen() const;
|
||||
std::string getBookOverlayText(const std::string& bookPath) const;
|
||||
BookOverlayInfo getBookOverlayInfo(const std::string& bookPath) const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user