add time left in chapter feature
This commit is contained in:
@@ -14,7 +14,7 @@ CrossPointSettings CrossPointSettings::instance;
|
||||
namespace {
|
||||
constexpr uint8_t SETTINGS_FILE_VERSION = 1;
|
||||
// Increment this when adding new persisted settings fields
|
||||
constexpr uint8_t SETTINGS_COUNT = 17;
|
||||
constexpr uint8_t SETTINGS_COUNT = 19;
|
||||
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
|
||||
} // namespace
|
||||
|
||||
@@ -46,6 +46,8 @@ bool CrossPointSettings::saveToFile() const {
|
||||
serialization::writePod(outputFile, sleepScreenCoverMode);
|
||||
serialization::writeString(outputFile, std::string(opdsServerUrl));
|
||||
serialization::writePod(outputFile, textAntiAliasing);
|
||||
serialization::writePod(outputFile, readingSpeedWpm);
|
||||
serialization::writePod(outputFile, showTimeLeftInChapter);
|
||||
outputFile.close();
|
||||
|
||||
Serial.printf("[%lu] [CPS] Settings saved to file\n", millis());
|
||||
@@ -110,6 +112,9 @@ bool CrossPointSettings::loadFromFile() {
|
||||
}
|
||||
serialization::readPod(inputFile, textAntiAliasing);
|
||||
if (++settingsRead >= fileSettingsCount) break;
|
||||
serialization::readPod(inputFile, readingSpeedWpm);
|
||||
if (++settingsRead >= fileSettingsCount) break;
|
||||
serialization::readPod(inputFile, showTimeLeftInChapter);
|
||||
} while (false);
|
||||
|
||||
inputFile.close();
|
||||
|
||||
@@ -61,6 +61,10 @@ class CrossPointSettings {
|
||||
// Text rendering settings
|
||||
uint8_t extraParagraphSpacing = 1;
|
||||
uint8_t textAntiAliasing = 1;
|
||||
// Reading speed (words per minute) for time-left estimate
|
||||
uint8_t readingSpeedWpm = 200;
|
||||
// Toggle to show time remaining in the current chapter
|
||||
uint8_t showTimeLeftInChapter = 0;
|
||||
// Duration of the power button press
|
||||
uint8_t shortPwrBtn = 0;
|
||||
// EPUB reading orientation settings
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
#include <GfxRenderer.h>
|
||||
#include <SDCardManager.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
|
||||
#include "CrossPointSettings.h"
|
||||
#include "CrossPointState.h"
|
||||
#include "EpubReaderChapterSelectionActivity.h"
|
||||
@@ -17,6 +21,28 @@ namespace {
|
||||
constexpr unsigned long skipChapterMs = 700;
|
||||
constexpr unsigned long goHomeMs = 1000;
|
||||
constexpr int statusBarMargin = 19;
|
||||
|
||||
std::string formatMinutes(const float minutes) {
|
||||
if (minutes <= 0.0f) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const int totalMinutes = static_cast<int>(std::ceil(minutes));
|
||||
if (totalMinutes < 60) {
|
||||
return std::to_string(totalMinutes) + "m";
|
||||
}
|
||||
|
||||
const int hours = totalMinutes / 60;
|
||||
const int mins = totalMinutes % 60;
|
||||
|
||||
char buffer[12];
|
||||
if (mins == 0) {
|
||||
std::snprintf(buffer, sizeof(buffer), "%dh", hours);
|
||||
} else {
|
||||
std::snprintf(buffer, sizeof(buffer), "%dh %02dm", hours, mins);
|
||||
}
|
||||
return std::string(buffer);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void EpubReaderActivity::taskTrampoline(void* param) {
|
||||
@@ -428,9 +454,20 @@ void EpubReaderActivity::renderStatusBar(const int orientedMarginRight, const in
|
||||
const float sectionChapterProg = static_cast<float>(section->currentPage) / section->pageCount;
|
||||
const uint8_t bookProgress = epub->calculateProgress(currentSpineIndex, sectionChapterProg);
|
||||
|
||||
std::string timeLeftText;
|
||||
if (SETTINGS.showTimeLeftInChapter && SETTINGS.readingSpeedWpm > 0) {
|
||||
const uint32_t wordsLeft = section->getWordsLeftFrom(section->currentPage);
|
||||
if (wordsLeft > 0) {
|
||||
const float minutesLeft = static_cast<float>(wordsLeft) /
|
||||
static_cast<float>(std::max<uint8_t>(1, SETTINGS.readingSpeedWpm));
|
||||
timeLeftText = formatMinutes(minutesLeft);
|
||||
}
|
||||
}
|
||||
|
||||
// Right aligned text for progress counter
|
||||
const std::string progress = std::to_string(section->currentPage + 1) + "/" + std::to_string(section->pageCount) +
|
||||
" " + std::to_string(bookProgress) + "%";
|
||||
" " + std::to_string(bookProgress) + "%" +
|
||||
(timeLeftText.empty() ? std::string() : " " + timeLeftText + " left");
|
||||
progressTextWidth = renderer.getTextWidth(SMALL_FONT_ID, progress.c_str());
|
||||
renderer.drawText(SMALL_FONT_ID, renderer.getScreenWidth() - orientedMarginRight - progressTextWidth, textY,
|
||||
progress.c_str());
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
// Define the static settings list
|
||||
namespace {
|
||||
constexpr int settingsCount = 18;
|
||||
constexpr int settingsCount = 20;
|
||||
const SettingInfo settingsList[settingsCount] = {
|
||||
// Should match with SLEEP_SCREEN_MODE
|
||||
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
||||
@@ -35,6 +35,8 @@ const SettingInfo settingsList[settingsCount] = {
|
||||
SettingInfo::Value("Reader Screen Margin", &CrossPointSettings::screenMargin, {5, 40, 5}),
|
||||
SettingInfo::Enum("Reader Paragraph Alignment", &CrossPointSettings::paragraphAlignment,
|
||||
{"Justify", "Left", "Center", "Right"}),
|
||||
SettingInfo::Value("Reading Speed (WPM)", &CrossPointSettings::readingSpeedWpm, {80, 240, 10}),
|
||||
SettingInfo::Toggle("Show Time Left", &CrossPointSettings::showTimeLeftInChapter),
|
||||
SettingInfo::Enum("Time to Sleep", &CrossPointSettings::sleepTimeout,
|
||||
{"1 min", "5 min", "10 min", "15 min", "30 min"}),
|
||||
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency,
|
||||
|
||||
Reference in New Issue
Block a user