diff --git a/USER_GUIDE.md b/USER_GUIDE.md index b411140e..0c852691 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -96,6 +96,10 @@ The Settings screen allows you to configure the device's behavior. There are a f - Left, Right, Back, Confirm - Left, Back, Confirm, Right - **Side Button Layout (reader)**: Swap the order of the up and down volume buttons from Previous/Next to Next/Previous. This change is only in effect when reading. +- **Long-press Chapter Skip**: Set whether long-pressing page turn buttons skip to the next/previous chapter. + - "Chapter Skip" (default) - Long-pressing skips to next/previous chapter + - "Page Scroll" - Long-pressing scrolls a page up/down +- Swap the order of the up and down volume buttons from Previous/Next to Next/Previous. This change is only in effect when reading. - **Reader Font Family**: Choose the font used for reading: - "Bookerly" (default) - Amazon's reading font - "Noto Sans" - Google's sans-serif font @@ -144,6 +148,9 @@ If the **Short Power Button Click** setting is set to "Page Turn", you can also * **Next Chapter:** Press and **hold** the **Right** (or **Volume Down**) button briefly, then release. * **Previous Chapter:** Press and **hold** the **Left** (or **Volume Up**) button briefly, then release. +This feature can be disabled in **[Settings](#35-settings)** to help avoid changing chapters by mistake. + + ### System Navigation * **Return to Book Selection:** Press **Back** to close the book and return to the **[Book Selection](#32-book-selection)** screen. * **Return to Home:** Press and **hold** the **Back** button to close the book and return to the **[Home](#31-home-screen)** screen. diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index 3c2de573..1d7e2ab3 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -25,7 +25,7 @@ constexpr int NUM_ITALIC_TAGS = sizeof(ITALIC_TAGS) / sizeof(ITALIC_TAGS[0]); const char* IMAGE_TAGS[] = {"img"}; constexpr int NUM_IMAGE_TAGS = sizeof(IMAGE_TAGS) / sizeof(IMAGE_TAGS[0]); -const char* SKIP_TAGS[] = {"head", "table"}; +const char* SKIP_TAGS[] = {"head"}; constexpr int NUM_SKIP_TAGS = sizeof(SKIP_TAGS) / sizeof(SKIP_TAGS[0]); bool isWhitespace(const char c) { return c == ' ' || c == '\r' || c == '\n' || c == '\t'; } @@ -63,13 +63,44 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* return; } - if (matches(name, IMAGE_TAGS, NUM_IMAGE_TAGS)) { - // TODO: Start processing image tags + // Special handling for tables - show placeholder text instead of dropping silently + if (strcmp(name, "table") == 0) { + // Add placeholder text + self->startNewTextBlock(TextBlock::CENTER_ALIGN); + if (self->currentTextBlock) { + self->currentTextBlock->addWord("[Table omitted]", EpdFontFamily::ITALIC); + } + + // Skip table contents self->skipUntilDepth = self->depth; self->depth += 1; return; } + if (matches(name, IMAGE_TAGS, NUM_IMAGE_TAGS)) { + // TODO: Start processing image tags + std::string alt; + if (atts != nullptr) { + for (int i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "alt") == 0) { + alt = "[Image: " + std::string(atts[i + 1]) + "]"; + } + } + Serial.printf("[%lu] [EHP] Image alt: %s\n", millis(), alt.c_str()); + + self->startNewTextBlock(TextBlock::CENTER_ALIGN); + self->italicUntilDepth = min(self->italicUntilDepth, self->depth); + self->depth += 1; + self->characterData(userData, alt.c_str(), alt.length()); + + } else { + // Skip for now + self->skipUntilDepth = self->depth; + self->depth += 1; + return; + } + } + if (matches(name, SKIP_TAGS, NUM_SKIP_TAGS)) { // start skip self->skipUntilDepth = self->depth; diff --git a/lib/GfxRenderer/GfxRenderer.cpp b/lib/GfxRenderer/GfxRenderer.cpp index 28022e90..7072fed8 100644 --- a/lib/GfxRenderer/GfxRenderer.cpp +++ b/lib/GfxRenderer/GfxRenderer.cpp @@ -468,7 +468,10 @@ int GfxRenderer::getLineHeight(const int fontId) const { } void GfxRenderer::drawButtonHints(const int fontId, const char* btn1, const char* btn2, const char* btn3, - const char* btn4) const { + const char* btn4) { + const Orientation orig_orientation = getOrientation(); + setOrientation(Orientation::Portrait); + const int pageHeight = getScreenHeight(); constexpr int buttonWidth = 106; constexpr int buttonHeight = 40; @@ -481,12 +484,15 @@ void GfxRenderer::drawButtonHints(const int fontId, const char* btn1, const char // Only draw if the label is non-empty if (labels[i] != nullptr && labels[i][0] != '\0') { const int x = buttonPositions[i]; + fillRect(x, pageHeight - buttonY, buttonWidth, buttonHeight, false); drawRect(x, pageHeight - buttonY, buttonWidth, buttonHeight); const int textWidth = getTextWidth(fontId, labels[i]); const int textX = x + (buttonWidth - 1 - textWidth) / 2; drawText(fontId, textX, pageHeight - buttonY + textYOffset, labels[i]); } } + + setOrientation(orig_orientation); } void GfxRenderer::drawSideButtonHints(const int fontId, const char* topBtn, const char* bottomBtn) const { diff --git a/lib/GfxRenderer/GfxRenderer.h b/lib/GfxRenderer/GfxRenderer.h index 9d341bcc..b1fea69b 100644 --- a/lib/GfxRenderer/GfxRenderer.h +++ b/lib/GfxRenderer/GfxRenderer.h @@ -84,7 +84,7 @@ class GfxRenderer { EpdFontFamily::Style style = EpdFontFamily::REGULAR) const; // UI Components - void drawButtonHints(int fontId, const char* btn1, const char* btn2, const char* btn3, const char* btn4) const; + void drawButtonHints(int fontId, const char* btn1, const char* btn2, const char* btn3, const char* btn4); void drawSideButtonHints(int fontId, const char* topBtn, const char* bottomBtn) const; private: diff --git a/platformio.ini b/platformio.ini index cbe47fe9..ef27ffd5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -45,9 +45,9 @@ lib_deps = InputManager=symlink://open-x4-sdk/libs/hardware/InputManager EInkDisplay=symlink://open-x4-sdk/libs/display/EInkDisplay SDCardManager=symlink://open-x4-sdk/libs/hardware/SDCardManager - ArduinoJson @ 7.4.2 - QRCode @ 0.0.1 - links2004/WebSockets @ ^2.4.1 + bblanchon/ArduinoJson @ 7.4.2 + ricmoo/QRCode @ 0.0.1 + links2004/WebSockets @ 2.7.3 [env:default] extends = base diff --git a/src/activities/network/WifiSelectionActivity.cpp b/src/activities/network/WifiSelectionActivity.cpp index a8653f43..07d44418 100644 --- a/src/activities/network/WifiSelectionActivity.cpp +++ b/src/activities/network/WifiSelectionActivity.cpp @@ -37,6 +37,14 @@ void WifiSelectionActivity::onEnter() { savePromptSelection = 0; forgetPromptSelection = 0; + // Cache MAC address for display + uint8_t mac[6]; + WiFi.macAddress(mac); + char macStr[32]; + snprintf(macStr, sizeof(macStr), "MAC address: %02x-%02x-%02x-%02x-%02x-%02x", mac[0], mac[1], mac[2], mac[3], mac[4], + mac[5]); + cachedMacAddress = std::string(macStr); + // Trigger first update to show scanning message updateRequired = true; @@ -572,6 +580,9 @@ void WifiSelectionActivity::renderNetworkList() const { renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 90, countStr); } + // Show MAC address above the network count and legend + renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 105, cachedMacAddress.c_str()); + // Draw help text renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 75, "* = Encrypted | + = Saved"); const auto labels = mappedInput.mapLabels("« Back", "Connect", "", ""); diff --git a/src/activities/network/WifiSelectionActivity.h b/src/activities/network/WifiSelectionActivity.h index 33ea26b1..0a7e7166 100644 --- a/src/activities/network/WifiSelectionActivity.h +++ b/src/activities/network/WifiSelectionActivity.h @@ -62,6 +62,9 @@ class WifiSelectionActivity final : public ActivityWithSubactivity { // Password to potentially save (from keyboard or saved credentials) std::string enteredPassword; + // Cached MAC address string for display + std::string cachedMacAddress; + // Whether network was connected using a saved password (skip save prompt) bool usedSavedPassword = false; diff --git a/src/activities/reader/XtcReaderActivity.cpp b/src/activities/reader/XtcReaderActivity.cpp index 9cdf5c97..a211e61c 100644 --- a/src/activities/reader/XtcReaderActivity.cpp +++ b/src/activities/reader/XtcReaderActivity.cpp @@ -127,7 +127,7 @@ void XtcReaderActivity::loop() { return; } - const bool skipPages = mappedInput.getHeldTime() > skipPageMs; + const bool skipPages = SETTINGS.longPressChapterSkip && mappedInput.getHeldTime() > skipPageMs; const int skipAmount = skipPages ? 10 : 1; if (prevReleased) {