diff --git a/ef-CHANGELOG.md b/ef-CHANGELOG.md index 74aa02d..1cd3649 100644 --- a/ef-CHANGELOG.md +++ b/ef-CHANGELOG.md @@ -32,9 +32,16 @@ Base: CrossPoint Reader 0.15.0 - **Display Quality**: Changed flashing screen to half refresh for cleaner appearance - **Timing**: Adjusted pre-flash script timing for half refresh completion +### Upstream Merges + +- **PR #522 - HAL Abstraction Layer**: Merged hardware abstraction layer refactor introducing `HalDisplay` and `HalGPIO` classes, decoupling application code from direct hardware access +- **PR #603 - Sunlight Fading Fix**: Added user-toggleable setting to turn off display between refreshes, mitigating the sunlight fading issue on e-ink displays + - New "Sunlight Fading Fix" toggle in Display settings (OFF/ON) + - Passes `turnOffScreen` parameter through display stack when enabled + ### Files Changed -- `src/main.cpp` - flash screen fixes, cover buffer free on File Transfer entry +- `src/main.cpp` - flash screen fixes, cover buffer free on File Transfer entry, fading fix integration - `scripts/pre_flash.py` - timing adjustments for full refresh - `src/network/CrossPointWebServer.cpp` - JSON batching, removed MD5 from listings - `src/network/CrossPointWebServer.h` - removed md5 from FileInfo, simplified sendContentSafe @@ -42,6 +49,16 @@ Base: CrossPoint Reader 0.15.0 - `src/activities/network/CrossPointWebServerActivity.h` - QR code cache members - `src/activities/network/WifiSelectionActivity.cpp` - WiFi scan memory optimization - `lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp` - flush buffer before style changes +- `lib/hal/HalDisplay.h` - new HAL abstraction for display (PR #522), turnOffScreen parameter (PR #603) +- `lib/hal/HalDisplay.cpp` - HAL display implementation with fading fix passthrough +- `lib/hal/HalGPIO.h` - new HAL abstraction for GPIO (PR #522) +- `lib/hal/HalGPIO.cpp` - HAL GPIO implementation +- `lib/GfxRenderer/GfxRenderer.h` - updated for HAL layer, added fadingFix member +- `lib/GfxRenderer/GfxRenderer.cpp` - updated for HAL layer, passes fadingFix to display +- `src/CrossPointSettings.h` - added fadingFix setting +- `src/CrossPointSettings.cpp` - fadingFix persistence +- `src/activities/settings/SettingsActivity.cpp` - added Sunlight Fading Fix toggle +- `open-x4-sdk` - updated submodule with turnOffScreen support in EInkDisplay --- diff --git a/lib/Epub/Epub/ParsedText.cpp b/lib/Epub/Epub/ParsedText.cpp index c381d7e..8f7695f 100644 --- a/lib/Epub/Epub/ParsedText.cpp +++ b/lib/Epub/Epub/ParsedText.cpp @@ -380,19 +380,15 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const // *** CRITICAL STEP: CONSUME DATA USING MOVE + ERASE *** // Move first lineWordCount elements from words into lineWords - std::vector lineWords( - std::make_move_iterator(words.begin()), - std::make_move_iterator(words.begin() + lineWordCount)); + std::vector lineWords(std::make_move_iterator(words.begin()), + std::make_move_iterator(words.begin() + lineWordCount)); words.erase(words.begin(), words.begin() + lineWordCount); - std::vector lineWordStyles( - std::make_move_iterator(wordStyles.begin()), - std::make_move_iterator(wordStyles.begin() + lineWordCount)); + std::vector lineWordStyles(std::make_move_iterator(wordStyles.begin()), + std::make_move_iterator(wordStyles.begin() + lineWordCount)); wordStyles.erase(wordStyles.begin(), wordStyles.begin() + lineWordCount); - std::vector lineWordUnderlines( - wordUnderlines.begin(), - wordUnderlines.begin() + lineWordCount); + std::vector lineWordUnderlines(wordUnderlines.begin(), wordUnderlines.begin() + lineWordCount); wordUnderlines.erase(wordUnderlines.begin(), wordUnderlines.begin() + lineWordCount); for (auto& word : lineWords) { diff --git a/lib/Epub/Epub/blocks/BlockStyle.h b/lib/Epub/Epub/blocks/BlockStyle.h index a52d0c7..b426ef6 100644 --- a/lib/Epub/Epub/blocks/BlockStyle.h +++ b/lib/Epub/Epub/blocks/BlockStyle.h @@ -9,11 +9,11 @@ * Padding is treated similarly to margins for rendering purposes. */ struct BlockStyle { - int8_t marginTop = 0; // 0-2 lines - int8_t marginBottom = 0; // 0-2 lines - int8_t paddingTop = 0; // 0-2 lines (treated same as margin) - int8_t paddingBottom = 0; // 0-2 lines (treated same as margin) - int16_t textIndent = 0; // pixels (first line indent) - int16_t marginLeft = 0; // pixels (horizontal indent for entire block) + int8_t marginTop = 0; // 0-2 lines + int8_t marginBottom = 0; // 0-2 lines + int8_t paddingTop = 0; // 0-2 lines (treated same as margin) + int8_t paddingBottom = 0; // 0-2 lines (treated same as margin) + int16_t textIndent = 0; // pixels (first line indent) + int16_t marginLeft = 0; // pixels (horizontal indent for entire block) bool hasLeftBorder = false; // draw vertical bar in left margin (for blockquotes) }; diff --git a/lib/Epub/Epub/blocks/TextBlock.h b/lib/Epub/Epub/blocks/TextBlock.h index e94e9af..24ee726 100644 --- a/lib/Epub/Epub/blocks/TextBlock.h +++ b/lib/Epub/Epub/blocks/TextBlock.h @@ -2,9 +2,9 @@ #include #include -#include #include #include +#include #include "Block.h" #include "BlockStyle.h" @@ -30,7 +30,8 @@ class TextBlock final : public Block { public: explicit TextBlock(std::vector words, std::vector word_xpos, std::vector word_styles, const Style style, - const BlockStyle& blockStyle = BlockStyle(), std::vector word_underlines = std::vector()) + const BlockStyle& blockStyle = BlockStyle(), + std::vector word_underlines = std::vector()) : words(std::move(words)), wordXpos(std::move(word_xpos)), wordStyles(std::move(word_styles)), diff --git a/lib/StarDict/StarDict.cpp b/lib/StarDict/StarDict.cpp index 29ccb76..4d53354 100644 --- a/lib/StarDict/StarDict.cpp +++ b/lib/StarDict/StarDict.cpp @@ -299,8 +299,7 @@ bool StarDict::decompressDefinition(uint32_t offset, uint32_t size, std::string& const uint32_t endChunk = (offset + size - 1) / dzInfo.chunkLength; const uint32_t startOffsetInChunk = offset % dzInfo.chunkLength; - Serial.printf("[DICT-DBG] Chunks: start=%lu, end=%lu, total=%u\n", - startChunk, endChunk, dzInfo.chunkCount); + Serial.printf("[DICT-DBG] Chunks: start=%lu, end=%lu, total=%u\n", startChunk, endChunk, dzInfo.chunkCount); if (endChunk >= dzInfo.chunkCount) { Serial.printf("[DICT-DBG] endChunk %lu >= chunkCount %u\n", endChunk, dzInfo.chunkCount); @@ -324,16 +323,16 @@ bool StarDict::decompressDefinition(uint32_t offset, uint32_t size, std::string& // Allocate buffers - allocate inflator FIRST (smallest) to reduce fragmentation impact // tinfl_decompressor is ~11KB, so total allocations are ~85KB - Serial.printf("[DICT-DBG] Allocating inflator=%u, comp=%lu, decomp=%u bytes\n", - sizeof(tinfl_decompressor), maxCompressedSize, dzInfo.chunkLength); - + Serial.printf("[DICT-DBG] Allocating inflator=%u, comp=%lu, decomp=%u bytes\n", sizeof(tinfl_decompressor), + maxCompressedSize, dzInfo.chunkLength); + auto* inflator = static_cast(malloc(sizeof(tinfl_decompressor))); if (!inflator) { Serial.printf("[DICT-DBG] inflator alloc failed! (need %u bytes)\n", sizeof(tinfl_decompressor)); file.close(); return false; } - + auto* compressedBuf = static_cast(malloc(maxCompressedSize)); if (!compressedBuf) { Serial.printf("[DICT-DBG] compressedBuf alloc failed!\n"); @@ -469,8 +468,7 @@ StarDict::LookupResult StarDict::lookup(const std::string& word) { return result; } - Serial.printf("[DICT-DBG] Searching for: '%s' (normalized: '%s')\n", - word.c_str(), normalizedSearch.c_str()); + Serial.printf("[DICT-DBG] Searching for: '%s' (normalized: '%s')\n", word.c_str(), normalizedSearch.c_str()); // First try .idx (main entries) - use prefix jump table for fast lookup const std::string idxPath = basePath + ".idx"; @@ -487,8 +485,8 @@ StarDict::LookupResult StarDict::lookup(const std::string& word) { const uint16_t prefixIdx = DictPrefixIndex::prefixToIndex(normalizedSearch[0], normalizedSearch[1]); position = DictPrefixIndex::dictPrefixOffsets[prefixIdx]; } - Serial.printf("[DICT-DBG] Starting at position %lu (prefix: %c%c)\n", - position, normalizedSearch[0], normalizedSearch[1]); + Serial.printf("[DICT-DBG] Starting at position %lu (prefix: %c%c)\n", position, normalizedSearch[0], + normalizedSearch[1]); bool found = false; uint32_t wordCount = 0; @@ -501,20 +499,19 @@ StarDict::LookupResult StarDict::lookup(const std::string& word) { } wordCount++; if (wordCount % 50000 == 0) { - Serial.printf("[DICT-DBG] Progress: %lu words scanned, pos=%lu, current='%s'\n", - wordCount, position, currentWord.c_str()); + Serial.printf("[DICT-DBG] Progress: %lu words scanned, pos=%lu, current='%s'\n", wordCount, position, + currentWord.c_str()); } // Use stardictStrcmp for case-insensitive matching const int cmp = stardictStrcmp(normalizedSearch, currentWord); if (cmp == 0) { - Serial.printf("[DICT-DBG] MATCH: '%s' == '%s' (offset=%lu, size=%lu)\n", - normalizedSearch.c_str(), currentWord.c_str(), dictOffset, dictSize); + Serial.printf("[DICT-DBG] MATCH: '%s' == '%s' (offset=%lu, size=%lu)\n", normalizedSearch.c_str(), + currentWord.c_str(), dictOffset, dictSize); std::string definition; - const bool loaded = useUncompressed - ? readDefinitionDirect(dictOffset, dictSize, definition) - : decompressDefinition(dictOffset, dictSize, definition); + const bool loaded = useUncompressed ? readDefinitionDirect(dictOffset, dictSize, definition) + : decompressDefinition(dictOffset, dictSize, definition); if (loaded) { Serial.printf("[DICT-DBG] Definition loaded, %u bytes\n", definition.length()); if (!found) { @@ -537,8 +534,7 @@ StarDict::LookupResult StarDict::lookup(const std::string& word) { // may not land exactly at target position } - Serial.printf("[DICT-DBG] Search complete: %lu words scanned, found=%s\n", - wordCount, found ? "YES" : "NO"); + Serial.printf("[DICT-DBG] Search complete: %lu words scanned, found=%s\n", wordCount, found ? "YES" : "NO"); idxFile.close(); // If not found in main index, try synonym file with prefix jump @@ -591,9 +587,8 @@ StarDict::LookupResult StarDict::lookup(const std::string& word) { uint32_t dictOffset, dictSize; if (readWordAtPosition(idxFile2, pos, mainWord, dictOffset, dictSize)) { std::string definition; - const bool loaded = useUncompressed - ? readDefinitionDirect(dictOffset, dictSize, definition) - : decompressDefinition(dictOffset, dictSize, definition); + const bool loaded = useUncompressed ? readDefinitionDirect(dictOffset, dictSize, definition) + : decompressDefinition(dictOffset, dictSize, definition); if (loaded) { result.word = synWord; result.definition = definition; diff --git a/platformio.ini b/platformio.ini index c9d5c93..6ef1df5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -3,7 +3,7 @@ default_envs = default [crosspoint] # 0.15.0 CrossPoint base, ef-1.0.0 is the first release of the ef branch -version = 0.15.ef-1.0.4 +version = 0.15.ef-1.0.5 [base] platform = espressif32 @ 6.12.0 diff --git a/src/BookManager.cpp b/src/BookManager.cpp index 3b20a08..ffebf2d 100644 --- a/src/BookManager.cpp +++ b/src/BookManager.cpp @@ -378,7 +378,8 @@ bool BookManager::clearBookCache(const std::string& bookPath, bool preserveProgr dir.close(); } - Serial.printf("[%lu] [%s] Cache cleared: %d items deleted, %d failed\n", millis(), LOG_TAG, deletedCount, failedCount); + Serial.printf("[%lu] [%s] Cache cleared: %d items deleted, %d failed\n", millis(), LOG_TAG, deletedCount, + failedCount); return failedCount == 0; } diff --git a/src/activities/dictionary/DictionaryResultActivity.cpp b/src/activities/dictionary/DictionaryResultActivity.cpp index 9db2ca6..6b0422e 100644 --- a/src/activities/dictionary/DictionaryResultActivity.cpp +++ b/src/activities/dictionary/DictionaryResultActivity.cpp @@ -98,7 +98,7 @@ void DictionaryResultActivity::loop() { // At end of cached pages but more content available - parse next chunk Serial.printf("[DICT-DBG] Parsing next chunk on navigation (page %d)\n", currentPage); parseNextChunk(); - + // After parsing (and possible page trimming), check if we can advance // Note: Don't compare page counts - trimming may keep size the same while adding new content if (currentPage < static_cast(pages.size()) - 1) { @@ -143,9 +143,9 @@ void DictionaryResultActivity::paginateDefinition() { // With HTML overhead, multiply by ~2, plus buffer for finding break points constexpr size_t CHUNK_SIZE_BASE = 1500; // Base chunk size const size_t chunkSize = std::max(CHUNK_SIZE_BASE, static_cast(linesPerPage * 120)); - - Serial.printf("[DICT-DBG] Chunked parsing: defLen=%u, chunkSize=%u, linesPerPage=%d\n", - rawDefinition.length(), chunkSize, linesPerPage); + + Serial.printf("[DICT-DBG] Chunked parsing: defLen=%u, chunkSize=%u, linesPerPage=%d\n", rawDefinition.length(), + chunkSize, linesPerPage); // Determine how much to parse for first page size_t parseEnd; @@ -158,20 +158,18 @@ void DictionaryResultActivity::paginateDefinition() { parseEnd = findHtmlBreakPoint(rawDefinition, chunkSize / 2, chunkSize); hasMoreContent = (parseEnd < rawDefinition.length()); } - + // Extract the chunk to parse std::string chunk = rawDefinition.substr(0, parseEnd); parsePosition = parseEnd; - - Serial.printf("[DICT-DBG] Parsing first chunk: 0-%u of %u, hasMore=%d\n", - parseEnd, rawDefinition.length(), hasMoreContent); + + Serial.printf("[DICT-DBG] Parsing first chunk: 0-%u of %u, hasMore=%d\n", parseEnd, rawDefinition.length(), + hasMoreContent); // Parse this chunk into TextBlocks std::vector> allBlocks; DictHtmlParser::parse(chunk, UI_10_FONT_ID, renderer, textWidth, - [&allBlocks](std::shared_ptr block) { - allBlocks.push_back(block); - }); + [&allBlocks](std::shared_ptr block) { allBlocks.push_back(block); }); Serial.printf("[DICT-DBG] First chunk parsed, %u TextBlocks\n", allBlocks.size()); if (allBlocks.empty()) { @@ -209,27 +207,27 @@ void DictionaryResultActivity::paginateDefinition() { if (!currentPageBlocks.empty()) { pages.push_back(currentPageBlocks); } - + Serial.printf("[DICT-DBG] Initial pagination: %u pages\n", pages.size()); } size_t DictionaryResultActivity::findHtmlBreakPoint(const std::string& html, size_t searchStart, size_t maxPos) { // Search backwards from maxPos for good HTML break points // Priority: ,

, , , then any '>' then whitespace - + if (maxPos >= html.length()) { return html.length(); } - + // Clamp searchStart to not exceed maxPos if (searchStart > maxPos) { searchStart = maxPos; } - + // Search for closing block tags (best break points) const char* closingTags[] = {"", "

", "", "", "", "", ""}; size_t bestBreak = std::string::npos; - + for (const char* tag : closingTags) { size_t pos = html.rfind(tag, maxPos); if (pos != std::string::npos && pos >= searchStart) { @@ -240,17 +238,17 @@ size_t DictionaryResultActivity::findHtmlBreakPoint(const std::string& html, siz } } } - + if (bestBreak != std::string::npos) { return bestBreak; } - + // Fallback: search for any '>' (end of tag) size_t tagEnd = html.rfind('>', maxPos); if (tagEnd != std::string::npos && tagEnd >= searchStart) { return tagEnd + 1; } - + // Last resort: search for whitespace for (size_t i = maxPos; i >= searchStart && i != std::string::npos; i--) { if (std::isspace(static_cast(html[i]))) { @@ -258,7 +256,7 @@ size_t DictionaryResultActivity::findHtmlBreakPoint(const std::string& html, siz } if (i == 0) break; } - + // No good break point found - use maxPos return maxPos; } @@ -269,8 +267,7 @@ void DictionaryResultActivity::parseNextChunk() { return; } - Serial.printf("[DICT-DBG] parseNextChunk starting at position %u of %u\n", - parsePosition, rawDefinition.length()); + Serial.printf("[DICT-DBG] parseNextChunk starting at position %u of %u\n", parsePosition, rawDefinition.length()); // Get margins with button hint space for all orientations int marginTop, marginRight, marginBottom, marginLeft; @@ -295,7 +292,7 @@ void DictionaryResultActivity::parseNextChunk() { // Determine parse range for this chunk size_t parseStart = parsePosition; size_t parseEnd; - + if (parsePosition + chunkSize >= rawDefinition.length()) { // This will be the last chunk parseEnd = rawDefinition.length(); @@ -315,9 +312,7 @@ void DictionaryResultActivity::parseNextChunk() { // Parse this chunk into TextBlocks std::vector> allBlocks; DictHtmlParser::parse(chunk, UI_10_FONT_ID, renderer, textWidth, - [&allBlocks](std::shared_ptr block) { - allBlocks.push_back(block); - }); + [&allBlocks](std::shared_ptr block) { allBlocks.push_back(block); }); Serial.printf("[DICT-DBG] Chunk parsed, %u TextBlocks\n", allBlocks.size()); @@ -359,39 +354,38 @@ void DictionaryResultActivity::parseNextChunk() { Serial.printf("[DICT-DBG] Trimmed old page, firstPageNumber now %d\n", firstPageNumber); } - Serial.printf("[DICT-DBG] After chunk: %u cached pages (pages %d-%d)\n", - pages.size(), firstPageNumber, firstPageNumber + static_cast(pages.size()) - 1); + Serial.printf("[DICT-DBG] After chunk: %u cached pages (pages %d-%d)\n", pages.size(), firstPageNumber, + firstPageNumber + static_cast(pages.size()) - 1); } void DictionaryResultActivity::reparseToPage(int targetPageNumber) { // Re-parse from the beginning to reach an earlier page that was trimmed // This allows backward navigation through the entire definition - + Serial.printf("[DICT-DBG] reparseToPage: target=%d, clearing and re-parsing\n", targetPageNumber); - + // Clear current state and start fresh pages.clear(); parsePosition = 0; firstPageNumber = 1; hasMoreContent = !rawDefinition.empty(); - + // Parse chunks until we have the target page while (hasMoreContent && firstPageNumber + static_cast(pages.size()) - 1 < targetPageNumber) { parseNextChunk(); } - + // Now position currentPage to show the target page - if (targetPageNumber >= firstPageNumber && - targetPageNumber < firstPageNumber + static_cast(pages.size())) { + if (targetPageNumber >= firstPageNumber && targetPageNumber < firstPageNumber + static_cast(pages.size())) { currentPage = targetPageNumber - firstPageNumber; } else { // Target page doesn't exist (definition is shorter than expected) currentPage = static_cast(pages.size()) - 1; if (currentPage < 0) currentPage = 0; } - - Serial.printf("[DICT-DBG] reparseToPage done: currentPage=%d, firstPageNumber=%d, pages=%u\n", - currentPage, firstPageNumber, pages.size()); + + Serial.printf("[DICT-DBG] reparseToPage done: currentPage=%d, firstPageNumber=%d, pages=%u\n", currentPage, + firstPageNumber, pages.size()); } void DictionaryResultActivity::displayTaskLoop() { @@ -425,8 +419,8 @@ void DictionaryResultActivity::render() const { renderer.drawCenteredText(UI_10_FONT_ID, centerY, "Word not found"); } else if (!pages.empty()) { // Draw definition text using TextBlocks with rich formatting - constexpr int headerHeight = 55; // Space for "Dictionary" + lookup word - constexpr int footerHeight = 20; // Space for page indicator + constexpr int headerHeight = 55; // Space for "Dictionary" + lookup word + constexpr int footerHeight = 20; // Space for page indicator const int textStartY = marginTop + headerHeight; const int textMargin = marginLeft + 10; const int lineHeight = renderer.getLineHeight(UI_10_FONT_ID); diff --git a/src/activities/dictionary/DictionaryResultActivity.h b/src/activities/dictionary/DictionaryResultActivity.h index 31023ce..922491c 100644 --- a/src/activities/dictionary/DictionaryResultActivity.h +++ b/src/activities/dictionary/DictionaryResultActivity.h @@ -29,8 +29,8 @@ class DictionaryResultActivity final : public Activity { // We limit cached pages to prevent memory exhaustion on long definitions static constexpr int MAX_CACHED_PAGES = 4; std::vector>> pages; - int currentPage = 0; // Index into pages vector - int firstPageNumber = 1; // The page number of pages[0] (1-based for display) + int currentPage = 0; // Index into pages vector + int firstPageNumber = 1; // The page number of pages[0] (1-based for display) bool notFound = false; // Chunked parsing state - parse definition on-demand as user navigates diff --git a/src/activities/dictionary/EpubWordSelectionActivity.cpp b/src/activities/dictionary/EpubWordSelectionActivity.cpp index ee8eee0..20492b5 100644 --- a/src/activities/dictionary/EpubWordSelectionActivity.cpp +++ b/src/activities/dictionary/EpubWordSelectionActivity.cpp @@ -1,7 +1,7 @@ #include "EpubWordSelectionActivity.h" -#include #include +#include #include #include diff --git a/src/activities/home/MyLibraryActivity.h b/src/activities/home/MyLibraryActivity.h index b09eacb..63c032e 100644 --- a/src/activities/home/MyLibraryActivity.h +++ b/src/activities/home/MyLibraryActivity.h @@ -63,9 +63,9 @@ class MyLibraryActivity final : public Activity { ActionType selectedAction = ActionType::Archive; std::string actionTargetPath; std::string actionTargetName; - int menuSelection = 0; // 0 = Archive, 1 = Delete - bool ignoreNextConfirmRelease = false; // Prevents immediate selection after long-press opens menu - bool clearCachePreserveProgress = true; // For Clear Cache: whether to preserve reading progress + int menuSelection = 0; // 0 = Archive, 1 = Delete + bool ignoreNextConfirmRelease = false; // Prevents immediate selection after long-press opens menu + bool clearCachePreserveProgress = true; // For Clear Cache: whether to preserve reading progress // Recent tab state std::vector recentBooks; diff --git a/src/activities/network/CrossPointWebServerActivity.h b/src/activities/network/CrossPointWebServerActivity.h index a787158..0894c44 100644 --- a/src/activities/network/CrossPointWebServerActivity.h +++ b/src/activities/network/CrossPointWebServerActivity.h @@ -71,14 +71,14 @@ class CrossPointWebServerActivity final : public ActivityWithSubactivity { // Avoids recomputing QR data on every render (every 30s stats refresh) // Marked mutable since QR drawing doesn't modify logical state but qrcode_getModule takes non-const bool qrCacheValid = false; - mutable QRCode qrWebBrowser; - mutable QRCode qrCompanionApp; - mutable QRCode qrCompanionAppLibrary; - mutable QRCode qrWifiConfig; // For AP mode WiFi connection QR - uint8_t qrWebBrowserBuffer[QR_BUFFER_SIZE]; - uint8_t qrCompanionAppBuffer[QR_BUFFER_SIZE]; - uint8_t qrCompanionAppLibraryBuffer[QR_BUFFER_SIZE]; - uint8_t qrWifiConfigBuffer[QR_BUFFER_SIZE]; + mutable QRCode qrWebBrowser = {}; + mutable QRCode qrCompanionApp = {}; + mutable QRCode qrCompanionAppLibrary = {}; + mutable QRCode qrWifiConfig = {}; // For AP mode WiFi connection QR + uint8_t qrWebBrowserBuffer[QR_BUFFER_SIZE] = {}; + uint8_t qrCompanionAppBuffer[QR_BUFFER_SIZE] = {}; + uint8_t qrCompanionAppLibraryBuffer[QR_BUFFER_SIZE] = {}; + uint8_t qrWifiConfigBuffer[QR_BUFFER_SIZE] = {}; static void taskTrampoline(void* param); [[noreturn]] void displayTaskLoop(); diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 2db93ca..970eb44 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -138,7 +138,7 @@ void EpubReaderActivity::onEnter() { nextPageNumber = data[2] + (data[3] << 8); hasContentOffset = false; Serial.printf("[%lu] [ERS] Loaded legacy progress (unknown version %d): spine %d, page %d\n", millis(), - version, currentSpineIndex, nextPageNumber); + version, currentSpineIndex, nextPageNumber); } } } else if (fileSize >= 4) { @@ -761,8 +761,7 @@ void EpubReaderActivity::renderScreen() { } if (section->currentPage < 0 || section->currentPage >= section->pageCount) { - Serial.printf("[%lu] [ERS] Page out of bounds: %d (max %d)\n", millis(), section->currentPage, - section->pageCount); + Serial.printf("[%lu] [ERS] Page out of bounds: %d (max %d)\n", millis(), section->currentPage, section->pageCount); renderer.drawCenteredText(UI_12_FONT_ID, 300, "Out of bounds", true, EpdFontFamily::BOLD); renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft); renderer.displayBuffer(); diff --git a/src/activities/settings/ClearCacheActivity.cpp b/src/activities/settings/ClearCacheActivity.cpp index a783462..630377e 100644 --- a/src/activities/settings/ClearCacheActivity.cpp +++ b/src/activities/settings/ClearCacheActivity.cpp @@ -237,7 +237,8 @@ void ClearCacheActivity::clearCache() { HomeActivity::freeCoverBufferIfAllocated(); MyLibraryActivity::clearThumbExistsCache(); - Serial.printf("[%lu] [CLEAR_CACHE] Cache cleared: %d items removed, %d failed\n", millis(), clearedCount, failedCount); + Serial.printf("[%lu] [CLEAR_CACHE] Cache cleared: %d items removed, %d failed\n", millis(), clearedCount, + failedCount); state = SUCCESS; updateRequired = true; diff --git a/src/activities/util/KeyboardEntryActivity.cpp b/src/activities/util/KeyboardEntryActivity.cpp index 446fe6c..ac50f87 100644 --- a/src/activities/util/KeyboardEntryActivity.cpp +++ b/src/activities/util/KeyboardEntryActivity.cpp @@ -1,7 +1,7 @@ #include "KeyboardEntryActivity.h" -#include "activities/dictionary/DictionaryMargins.h" #include "MappedInputManager.h" +#include "activities/dictionary/DictionaryMargins.h" #include "fontIds.h" // Keyboard layouts - lowercase diff --git a/src/activities/util/QuickMenuActivity.h b/src/activities/util/QuickMenuActivity.h index b9fac71..090eaf8 100644 --- a/src/activities/util/QuickMenuActivity.h +++ b/src/activities/util/QuickMenuActivity.h @@ -29,9 +29,9 @@ class QuickMenuActivity final : public Activity { const bool isPageBookmarked; // True if current page already has a bookmark // Edit mode state - bool editMode = false; // True when in edit mode - int movingIndex = -1; // Index of item being moved (-1 if none) - uint8_t localOrder[5] = {0}; // Local copy of order for editing + bool editMode = false; // True when in edit mode + int movingIndex = -1; // Index of item being moved (-1 if none) + uint8_t localOrder[5] = {0}; // Local copy of order for editing static void taskTrampoline(void* param); [[noreturn]] void displayTaskLoop(); diff --git a/src/network/CrossPointWebServer.cpp b/src/network/CrossPointWebServer.cpp index cf1a02c..a1f9d07 100644 --- a/src/network/CrossPointWebServer.cpp +++ b/src/network/CrossPointWebServer.cpp @@ -1269,9 +1269,7 @@ bool CrossPointWebServer::sendContentSafe(const char* content) const { return server->client().connected(); } -bool CrossPointWebServer::sendContentSafe(const String& content) const { - return sendContentSafe(content.c_str()); -} +bool CrossPointWebServer::sendContentSafe(const String& content) const { return sendContentSafe(content.c_str()); } bool CrossPointWebServer::copyFile(const String& srcPath, const String& destPath) const { FsFile srcFile;