A fork of https://github.com/crosspoint-reader/crosspoint-reader
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: Add Chapter Progress Bar status bar option (#636)

## Summary
This pull request introduces a new "Chapter Progress Bar" mode to the
status bar, allowing users to track their progress within the current
chapter in addition to the existing book-level progress options. It also
unifies and increases the progress bar height for better visibility, and
updates the settings UI to support the new mode.

Closes #636

**Status Bar/Progress Bar Enhancements:**

* Added a new `CHAPTER_PROGRESS_BAR` mode to
`CrossPointSettings::STATUS_BAR_MODE`, and updated the settings UI to
allow users to select this mode.
[[1]](diffhunk://#diff-3af36372bb6233a83387a68091b5e0651c23585c7c0a95669ed893268ca709a8R34)
[[2]](diffhunk://#diff-c55df9ec3ade843be000ba463cb75aa3df27dc34620a56c248fc4cc4e917b34bL22-R23)
* Implemented `drawChapterProgressBar` in `ScreenComponents` and
integrated it into both EPUB and TXT reader activities, so the chapter
progress bar is displayed when the new mode is selected.
[[1]](diffhunk://#diff-be271778a942f7fab0d920acd73442512346ff811a4625c011275a7ca6be3a3eL51-R64)
[[2]](diffhunk://#diff-dd410cab3a363d78172706d2ad6591f327e9b5b05f314db405db31a667af03faL16-R20)
[[3]](diffhunk://#diff-82798dedbe135495e619d4aa27a4bef560c70c7663cf43148b67a26ddde45682R518-R525)
[[4]](diffhunk://#diff-471ba9d9eb65b1a8451d41246db2aa695a42ea4ae4762163adfda4c20fec0950R563-R567)
* Updated logic in EPUB and TXT reader activities to show the correct
progress bar, progress text, and battery indicator based on the selected
status bar mode, including the new chapter progress bar mode.
[[1]](diffhunk://#diff-82798dedbe135495e619d4aa27a4bef560c70c7663cf43148b67a26ddde45682R470-R481)
[[2]](diffhunk://#diff-82798dedbe135495e619d4aa27a4bef560c70c7663cf43148b67a26ddde45682L490-R503)
[[3]](diffhunk://#diff-471ba9d9eb65b1a8451d41246db2aa695a42ea4ae4762163adfda4c20fec0950R522-R533)
[[4]](diffhunk://#diff-471ba9d9eb65b1a8451d41246db2aa695a42ea4ae4762163adfda4c20fec0950L539-R548)

**UI/Visual Tweaks:**

* Increased the progress bar height from 4 to 6 pixels for improved
visibility, and refactored code to use the new constant.
[[1]](diffhunk://#diff-dd410cab3a363d78172706d2ad6591f327e9b5b05f314db405db31a667af03faL16-R20)
[[2]](diffhunk://#diff-82798dedbe135495e619d4aa27a4bef560c70c7663cf43148b67a26ddde45682L295-R295)
[[3]](diffhunk://#diff-471ba9d9eb65b1a8451d41246db2aa695a42ea4ae4762163adfda4c20fec0950L177-R177)

These changes collectively provide users with more granular progress
tracking options and a clearer visual indicator for reading progress.


## Additional Context



---

### AI Usage

Did you use AI tools to help write this code? _**YES**_

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

authored by

Luke Stein
copilot-swe-agent[bot]
and committed by
GitHub
c3b9bc38 fb0af32e

+60 -26
+6 -1
USER_GUIDE.md
··· 13 13 - [3.2 Book Selection](#32-book-selection) 14 14 - [3.3 Reading Mode](#33-reading-mode) 15 15 - [3.4 File Upload Screen](#34-file-upload-screen) 16 + - [3.4.1 Calibre Wireless Transfers](#341-calibre-wireless-transfers) 16 17 - [3.5 Settings](#35-settings) 17 18 - [3.6 Sleep Screen](#36-sleep-screen) 18 19 - [4. Reading Mode](#4-reading-mode) 19 20 - [Page Turning](#page-turning) 20 21 - [Chapter Navigation](#chapter-navigation) 21 22 - [System Navigation](#system-navigation) 23 + - [Supported Languages](#supported-languages) 22 24 - [5. Chapter Selection Screen](#5-chapter-selection-screen) 23 25 - [6. Current Limitations \& Roadmap](#6-current-limitations--roadmap) 24 26 - [7. Troubleshooting Issues \& Escaping Bootloop](#7-troubleshooting-issues--escaping-bootloop) ··· 114 116 - **Status Bar**: Configure the status bar displayed while reading: 115 117 - "None" - No status bar 116 118 - "No Progress" - Show status bar without reading progress 117 - - "Full" - Show status bar with reading progress 119 + - "Full w/ Percentage" - Show status bar with book progress (as percentage) 120 + - "Full w/ Book Bar" - Show status bar with book progress (as bar) 121 + - "Book Bar Only" - Show book progress (as bar) 122 + - "Full w/ Chapter Bar" - Show status bar with chapter progress (as bar) 118 123 - **Hide Battery %**: Configure where to suppress the battery pecentage display in the status bar; the battery icon will still be shown: 119 124 - "Never" - Always show battery percentage (default) 120 125 - "In Reader" - Show battery percentage everywhere except in reading mode
+3 -2
src/CrossPointSettings.h
··· 37 37 NONE = 0, 38 38 NO_PROGRESS = 1, 39 39 FULL = 2, 40 - FULL_WITH_PROGRESS_BAR = 3, 41 - ONLY_PROGRESS_BAR = 4, 40 + BOOK_PROGRESS_BAR = 3, 41 + ONLY_BOOK_PROGRESS_BAR = 4, 42 + CHAPTER_PROGRESS_BAR = 5, 42 43 STATUS_BAR_MODE_COUNT 43 44 }; 44 45
+24 -10
src/activities/reader/EpubReaderActivity.cpp
··· 558 558 // Add status bar margin 559 559 if (SETTINGS.statusBar != CrossPointSettings::STATUS_BAR_MODE::NONE) { 560 560 // Add additional margin for status bar if progress bar is shown 561 - const bool showProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR || 562 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::ONLY_PROGRESS_BAR; 561 + const bool showProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR || 562 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::ONLY_BOOK_PROGRESS_BAR || 563 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 563 564 orientedMarginBottom += statusBarMargin - SETTINGS.screenMargin + 564 565 (showProgressBar ? (metrics.bookProgressBarHeight + progressBarMarginTop) : 0); 565 566 } ··· 713 714 714 715 // determine visible status bar elements 715 716 const bool showProgressPercentage = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL; 716 - const bool showProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR || 717 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::ONLY_PROGRESS_BAR; 717 + const bool showBookProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR || 718 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::ONLY_BOOK_PROGRESS_BAR; 719 + const bool showChapterProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 718 720 const bool showProgressText = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL || 719 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR; 721 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR; 722 + const bool showBookPercentage = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 720 723 const bool showBattery = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::NO_PROGRESS || 721 724 SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL || 722 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR; 725 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR || 726 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 723 727 const bool showChapterTitle = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::NO_PROGRESS || 724 728 SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL || 725 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR; 729 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR || 730 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 726 731 const bool showBatteryPercentage = 727 732 SETTINGS.hideBatteryPercentage == CrossPointSettings::HIDE_BATTERY_PERCENTAGE::HIDE_NEVER; 728 733 ··· 735 740 const float sectionChapterProg = static_cast<float>(section->currentPage) / section->pageCount; 736 741 const float bookProgress = epub->calculateProgress(currentSpineIndex, sectionChapterProg) * 100; 737 742 738 - if (showProgressText || showProgressPercentage) { 743 + if (showProgressText || showProgressPercentage || showBookPercentage) { 739 744 // Right aligned text for progress counter 740 745 char progressStr[32]; 741 746 ··· 743 748 if (showProgressPercentage) { 744 749 snprintf(progressStr, sizeof(progressStr), "%d/%d %.0f%%", section->currentPage + 1, section->pageCount, 745 750 bookProgress); 751 + } else if (showBookPercentage) { 752 + snprintf(progressStr, sizeof(progressStr), "%.0f%%", bookProgress); 746 753 } else { 747 754 snprintf(progressStr, sizeof(progressStr), "%d/%d", section->currentPage + 1, section->pageCount); 748 755 } ··· 752 759 progressStr); 753 760 } 754 761 755 - if (showProgressBar) { 762 + if (showBookProgressBar) { 756 763 // Draw progress bar at the very bottom of the screen, from edge to edge of viewable area 757 - GUI.drawBookProgressBar(renderer, static_cast<size_t>(bookProgress)); 764 + GUI.drawReadingProgressBar(renderer, static_cast<size_t>(bookProgress)); 765 + } 766 + 767 + if (showChapterProgressBar) { 768 + // Draw chapter progress bar at the very bottom of the screen, from edge to edge of viewable area 769 + const float chapterProgress = 770 + (section->pageCount > 0) ? (static_cast<float>(section->currentPage + 1) / section->pageCount) * 100 : 0; 771 + GUI.drawReadingProgressBar(renderer, static_cast<size_t>(chapterProgress)); 758 772 } 759 773 760 774 if (showBattery) {
+22 -9
src/activities/reader/TxtReaderActivity.cpp
··· 177 177 // Add status bar margin 178 178 if (SETTINGS.statusBar != CrossPointSettings::STATUS_BAR_MODE::NONE) { 179 179 // Add additional margin for status bar if progress bar is shown 180 - const bool showProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR || 181 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::ONLY_PROGRESS_BAR; 180 + const bool showProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR || 181 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::ONLY_BOOK_PROGRESS_BAR || 182 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 182 183 orientedMarginBottom += statusBarMargin - cachedScreenMargin + 183 184 (showProgressBar ? (metrics.bookProgressBarHeight + progressBarMarginTop) : 0); 184 185 } ··· 491 492 void TxtReaderActivity::renderStatusBar(const int orientedMarginRight, const int orientedMarginBottom, 492 493 const int orientedMarginLeft) const { 493 494 const bool showProgressPercentage = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL; 494 - const bool showProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR || 495 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::ONLY_PROGRESS_BAR; 495 + const bool showProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR || 496 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::ONLY_BOOK_PROGRESS_BAR; 497 + const bool showChapterProgressBar = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 496 498 const bool showProgressText = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL || 497 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR; 499 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR; 500 + const bool showBookPercentage = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 498 501 const bool showBattery = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::NO_PROGRESS || 499 502 SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL || 500 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR; 503 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR || 504 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 501 505 const bool showTitle = SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::NO_PROGRESS || 502 506 SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL || 503 - SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::FULL_WITH_PROGRESS_BAR; 507 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::BOOK_PROGRESS_BAR || 508 + SETTINGS.statusBar == CrossPointSettings::STATUS_BAR_MODE::CHAPTER_PROGRESS_BAR; 504 509 const bool showBatteryPercentage = 505 510 SETTINGS.hideBatteryPercentage == CrossPointSettings::HIDE_BATTERY_PERCENTAGE::HIDE_NEVER; 506 511 507 512 auto metrics = UITheme::getInstance().getMetrics(); 508 513 const auto screenHeight = renderer.getScreenHeight(); 514 + // Adjust text position upward when progress bar is shown to avoid overlap 509 515 const auto textY = screenHeight - orientedMarginBottom - 4; 510 516 int progressTextWidth = 0; 511 517 512 518 const float progress = totalPages > 0 ? (currentPage + 1) * 100.0f / totalPages : 0; 513 519 514 - if (showProgressText || showProgressPercentage) { 520 + if (showProgressText || showProgressPercentage || showBookPercentage) { 515 521 char progressStr[32]; 516 522 if (showProgressPercentage) { 517 523 snprintf(progressStr, sizeof(progressStr), "%d/%d %.0f%%", currentPage + 1, totalPages, progress); 524 + } else if (showBookPercentage) { 525 + snprintf(progressStr, sizeof(progressStr), "%.0f%%", progress); 518 526 } else { 519 527 snprintf(progressStr, sizeof(progressStr), "%d/%d", currentPage + 1, totalPages); 520 528 } ··· 526 534 527 535 if (showProgressBar) { 528 536 // Draw progress bar at the very bottom of the screen, from edge to edge of viewable area 529 - GUI.drawBookProgressBar(renderer, static_cast<size_t>(progress)); 537 + GUI.drawReadingProgressBar(renderer, static_cast<size_t>(progress)); 538 + } 539 + 540 + if (showChapterProgressBar) { 541 + // For text mode, treat the entire book as one chapter, so chapter progress == book progress 542 + GUI.drawReadingProgressBar(renderer, static_cast<size_t>(progress)); 530 543 } 531 544 532 545 if (showBattery) {
+3 -2
src/activities/settings/SettingsActivity.cpp
··· 25 25 SettingInfo::Enum("Sleep Screen Cover Mode", &CrossPointSettings::sleepScreenCoverMode, {"Fit", "Crop"}), 26 26 SettingInfo::Enum("Sleep Screen Cover Filter", &CrossPointSettings::sleepScreenCoverFilter, 27 27 {"None", "Contrast", "Inverted"}), 28 - SettingInfo::Enum("Status Bar", &CrossPointSettings::statusBar, 29 - {"None", "No Progress", "Full w/ Percentage", "Full w/ Progress Bar", "Progress Bar"}), 28 + SettingInfo::Enum( 29 + "Status Bar", &CrossPointSettings::statusBar, 30 + {"None", "No Progress", "Full w/ Percentage", "Full w/ Book Bar", "Book Bar Only", "Full w/ Chapter Bar"}), 30 31 SettingInfo::Enum("Hide Battery %", &CrossPointSettings::hideBatteryPercentage, {"Never", "In Reader", "Always"}), 31 32 SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency, 32 33 {"1 page", "5 pages", "10 pages", "15 pages", "30 pages"}),
+1 -1
src/components/themes/BaseTheme.cpp
··· 630 630 renderer.displayBuffer(HalDisplay::FAST_REFRESH); 631 631 } 632 632 633 - void BaseTheme::drawBookProgressBar(const GfxRenderer& renderer, const size_t bookProgress) const { 633 + void BaseTheme::drawReadingProgressBar(const GfxRenderer& renderer, const size_t bookProgress) const { 634 634 int vieweableMarginTop, vieweableMarginRight, vieweableMarginBottom, vieweableMarginLeft; 635 635 renderer.getOrientedViewableTRBL(&vieweableMarginTop, &vieweableMarginRight, &vieweableMarginBottom, 636 636 &vieweableMarginLeft);
+1 -1
src/components/themes/BaseTheme.h
··· 114 114 const std::function<std::string(int index)>& rowIcon) const; 115 115 virtual Rect drawPopup(const GfxRenderer& renderer, const char* message) const; 116 116 virtual void fillPopupProgress(const GfxRenderer& renderer, const Rect& layout, const int progress) const; 117 - virtual void drawBookProgressBar(const GfxRenderer& renderer, const size_t bookProgress) const; 117 + virtual void drawReadingProgressBar(const GfxRenderer& renderer, const size_t bookProgress) const; 118 118 };