From b6ce599b20a468d42fe0c3b3bb25d435af8167da Mon Sep 17 00:00:00 2001 From: Julia Nguyen Date: Fri, 26 Jun 2026 16:22:20 -0400 Subject: [PATCH] fix: address release review feedback --- USER_GUIDE.md | 12 ++--- lib/hal/HalDisplay.h | 6 +-- src/activities/reader/EpubReaderActivity.cpp | 22 +++++----- src/network/html/FilesPage.html | 46 ++++++++++++++++---- 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/USER_GUIDE.md b/USER_GUIDE.md index e97fc4fd..51e284c5 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -131,12 +131,12 @@ If you don't already have the plugin installed: 3. Open Calibre → Preferences → Plugins → Load plugin from file → Select the zip file. 4. Restart Calibre. -#### Configuring the Crosspoint Plugin in Calibre +#### Configuring the CrossPoint Plugin in Calibre 1. In Calibre select Preferences. 2. In the Preferences dialog select Plugins. 3. In Plugins search for "crosspoint". 4. Click on "Customize plugin". -5. Update the value for "Host" to match the IP for the x4. +5. Update the value for "Host" to match the IP for your device. 6. Leave the other settings as they are. 7. [optional] Modify the "Upload path" to point to a subfolder other than the root "/" folder. Enter this as a path relative to the root folder. Example: `/mybooks` 8. Restart Calibre. @@ -145,20 +145,20 @@ If you don't already have the plugin installed: #### Uploading Books -To upload a book using the Crosspoint plugin in Calibre: +To upload a book using the CrossPoint plugin in Calibre: 1. On the device: File Transfer -> Calibre Wireless, then join a network. 2. Select one or more books. -3. Right click on that selection. +3. Right-click on that selection. 4. Select "Send to Device" > "Send to main memory" -The Crosspoint plugin will connect to the x4, create a folder for the book's author in the root folder (or the folder you configured for the plugin), then copy the book into that folder. +The CrossPoint plugin will connect to your device, create a folder for the book's author in the root folder (or the folder you configured for the plugin), then copy the book into that folder. Image #### Removing a Book -Books cannot be removed from the x4 through Calibre. Use the web interface instead. +Books cannot be removed from your device through Calibre. Use the web interface instead. ### 3.6 Settings diff --git a/lib/hal/HalDisplay.h b/lib/hal/HalDisplay.h index 9b35254a..7b21a72f 100644 --- a/lib/hal/HalDisplay.h +++ b/lib/hal/HalDisplay.h @@ -55,9 +55,9 @@ class HalDisplay { void preconditionGrayscale(uint16_t x, uint16_t y, uint16_t w, uint16_t h); // Display the framebuffer as the base frame for a grayscale overlay that - // follows. X3 uses the OEM differential base waveform ("AA-pre-BW(mid)"); - // other panels display normally with `fallback` mode (previous behavior). - // Deliberately does NOT force the X3 resync that displayBuffer(HALF) does. + // follows. On X3, HALF fallback first requests a resync to match + // displayBuffer(HALF); FAST fallback keeps the OEM differential base waveform + // ("AA-pre-BW(mid)"). Other panels display normally with `fallback` mode. void displayGrayscaleBase(RefreshMode fallback = HALF_REFRESH, bool turnOffScreen = false); void copyGrayscaleBuffers(const uint8_t* lsbBuffer, const uint8_t* msbBuffer); diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 6e1a1978..5948fd9a 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -83,9 +83,10 @@ ProgressRange getPageProgressRange(const std::shared_ptr& epub, const int return {epub->calculateProgress(spineIndex, start), epub->calculateProgress(spineIndex, end)}; } -bool bookmarkMatchesProgress(const BookmarkEntry& bookmark, const SavedProgressPosition& progress, +bool bookmarkMatchesProgress(const BookmarkEntry& bookmark, const int spineIndex, const int page, const int pageCount, const ProgressRange& pageRange) { - if (bookmark.xpath == progress.xpath) { + if (bookmark.computedSpineIndex == spineIndex && bookmark.computedChapterPageCount == pageCount && + bookmark.computedChapterProgress == page) { return true; } @@ -1311,10 +1312,12 @@ void EpubReaderActivity::addBookmark() { const ProgressRange pageRange = getPageProgressRange(epub, currentSpineIndex, currentPage, pageCount); const size_t bookmarkCountBeforeToggle = cachedBookmarks.size(); - cachedBookmarks.erase( - std::remove_if(cachedBookmarks.begin(), cachedBookmarks.end(), - [&](const BookmarkEntry& b) { return bookmarkMatchesProgress(b, progress, pageRange); }), - cachedBookmarks.end()); + cachedBookmarks.erase(std::remove_if(cachedBookmarks.begin(), cachedBookmarks.end(), + [&](const BookmarkEntry& b) { + return bookmarkMatchesProgress(b, currentSpineIndex, currentPage, pageCount, + pageRange); + }), + cachedBookmarks.end()); if (cachedBookmarks.size() != bookmarkCountBeforeToggle) { bookmarkRemoved = true; currentPageBookmarked = false; @@ -1353,12 +1356,7 @@ void EpubReaderActivity::updateBookmarkFlag() { const ProgressRange pageRange = getPageProgressRange(epub, currentSpineIndex, section->currentPage, section->pageCount); currentPageBookmarked = std::any_of(cachedBookmarks.begin(), cachedBookmarks.end(), [&](const BookmarkEntry& b) { - if (b.computedSpineIndex == currentSpineIndex && b.computedChapterPageCount == section->pageCount && - b.computedChapterProgress == section->currentPage) { - return true; - } - const float bp = std::clamp(b.percentage, 0.0f, 1.0f); - return bp + bookmarkProgressEpsilon >= pageRange.start && bp - bookmarkProgressEpsilon <= pageRange.end; + return bookmarkMatchesProgress(b, currentSpineIndex, section->currentPage, section->pageCount, pageRange); }); } diff --git a/src/network/html/FilesPage.html b/src/network/html/FilesPage.html index 36f38b0e..8572b3e1 100644 --- a/src/network/html/FilesPage.html +++ b/src/network/html/FilesPage.html @@ -1895,15 +1895,43 @@ const fileTable = document.getElementById('file-table'); const segments = currentPath.split('/').filter(Boolean); - const crumbs = ['🏠 Home']; - segments.forEach(function(segment, index) { - const path = '/' + segments.slice(0, index + 1).join('/'); - crumbs.push('' + escapeHtml(segment) + ''); - }); - // The last crumb is the current location: render as plain text, not a link. - const lastSegment = segments.length ? escapeHtml(segments[segments.length - 1]) : '🏠 Home'; - crumbs[crumbs.length - 1] = '' + lastSegment + ''; - breadcrumbs.innerHTML = crumbs.join(''); + breadcrumbs.replaceChildren(); + + const appendSep = function() { + const sep = document.createElement('span'); + sep.className = 'sep'; + sep.textContent = '›'; + breadcrumbs.appendChild(sep); + }; + + const appendLink = function(label, href) { + const link = document.createElement('a'); + link.href = href; + link.textContent = label; + breadcrumbs.appendChild(link); + }; + + const appendCurrent = function(label) { + const current = document.createElement('span'); + current.className = 'current'; + current.textContent = label; + breadcrumbs.appendChild(current); + }; + + if (segments.length === 0) { + appendCurrent('🏠 Home'); + } else { + appendLink('🏠 Home', '/files'); + segments.forEach(function(segment, index) { + appendSep(); + if (index === segments.length - 1) { + appendCurrent(segment); + } else { + const path = '/' + segments.slice(0, index + 1).join('/'); + appendLink(segment, '/files?path=' + encodeURIComponent(path)); + } + }); + } let files = []; try {