Add skip notification and delay before action
This commit is contained in:
parent
eae951a286
commit
e3b0c924c6
@ -186,11 +186,13 @@ void EpubReaderActivity::loop() {
|
||||
if (skipChapter) {
|
||||
// We don't want to delete the section mid-render, so grab the semaphore
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
nextPageNumber = 0;
|
||||
currentSpineIndex = nextReleased ? currentSpineIndex + 1 : currentSpineIndex - 1;
|
||||
section.reset();
|
||||
// Show immediate feedback for long-press skip, then schedule delayed action (500ms)
|
||||
showSkipPopup("Skipping");
|
||||
delayedSkipPending = true;
|
||||
delayedSkipDir = nextReleased ? +1 : -1;
|
||||
delayedSkipExecuteAtMs = millis() + 500;
|
||||
xSemaphoreGive(renderingMutex);
|
||||
updateRequired = true;
|
||||
// Do not perform the skip immediately; it will be executed in display loop after delay
|
||||
return;
|
||||
}
|
||||
|
||||
@ -229,11 +231,21 @@ void EpubReaderActivity::loop() {
|
||||
|
||||
void EpubReaderActivity::displayTaskLoop() {
|
||||
while (true) {
|
||||
const uint32_t now = millis();
|
||||
if (updateRequired) {
|
||||
updateRequired = false;
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
renderScreen();
|
||||
xSemaphoreGive(renderingMutex);
|
||||
} else if (delayedSkipPending && now >= delayedSkipExecuteAtMs) {
|
||||
// Execute the delayed chapter skip now
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
nextPageNumber = 0;
|
||||
currentSpineIndex += delayedSkipDir;
|
||||
section.reset();
|
||||
delayedSkipPending = false;
|
||||
xSemaphoreGive(renderingMutex);
|
||||
updateRequired = true;
|
||||
}
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
@ -385,6 +397,19 @@ void EpubReaderActivity::renderScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
void EpubReaderActivity::showSkipPopup(const char* text) {
|
||||
constexpr int boxMargin = 20;
|
||||
const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, text);
|
||||
const int boxWidth = textWidth + boxMargin * 2;
|
||||
const int boxHeight = renderer.getLineHeight(UI_12_FONT_ID) + boxMargin * 2;
|
||||
const int boxX = (renderer.getScreenWidth() - boxWidth) / 2;
|
||||
constexpr int boxY = 50;
|
||||
renderer.fillRect(boxX, boxY, boxWidth, boxHeight, false);
|
||||
renderer.drawText(UI_12_FONT_ID, boxX + boxMargin, boxY + boxMargin, text);
|
||||
renderer.drawRect(boxX + 5, boxY + 5, boxWidth - 10, boxHeight - 10);
|
||||
renderer.displayBuffer(EInkDisplay::FAST_REFRESH);
|
||||
}
|
||||
|
||||
void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int orientedMarginTop,
|
||||
const int orientedMarginRight, const int orientedMarginBottom,
|
||||
const int orientedMarginLeft) {
|
||||
|
||||
@ -16,6 +16,9 @@ class EpubReaderActivity final : public ActivityWithSubactivity {
|
||||
int nextPageNumber = 0;
|
||||
int pagesUntilFullRefresh = 0;
|
||||
bool updateRequired = false;
|
||||
bool delayedSkipPending = false;
|
||||
int delayedSkipDir = 0;
|
||||
uint32_t delayedSkipExecuteAtMs = 0;
|
||||
const std::function<void()> onGoBack;
|
||||
const std::function<void()> onGoHome;
|
||||
|
||||
@ -25,6 +28,7 @@ class EpubReaderActivity final : public ActivityWithSubactivity {
|
||||
void renderContents(std::unique_ptr<Page> page, int orientedMarginTop, int orientedMarginRight,
|
||||
int orientedMarginBottom, int orientedMarginLeft);
|
||||
void renderStatusBar(int orientedMarginRight, int orientedMarginBottom, int orientedMarginLeft) const;
|
||||
void showSkipPopup(const char* text);
|
||||
|
||||
public:
|
||||
explicit EpubReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr<Epub> epub,
|
||||
|
||||
@ -132,6 +132,16 @@ void XtcReaderActivity::loop() {
|
||||
const int skipAmount = skipPages ? 10 : 1;
|
||||
|
||||
if (prevReleased) {
|
||||
if (skipPages) {
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
showSkipPopup("Skipping");
|
||||
delayedSkipPending = true;
|
||||
delayedSkipDir = -1;
|
||||
delayedSkipAmount = skipAmount;
|
||||
delayedSkipExecuteAtMs = millis() + 500;
|
||||
xSemaphoreGive(renderingMutex);
|
||||
return;
|
||||
}
|
||||
if (currentPage >= static_cast<uint32_t>(skipAmount)) {
|
||||
currentPage -= skipAmount;
|
||||
} else {
|
||||
@ -139,6 +149,16 @@ void XtcReaderActivity::loop() {
|
||||
}
|
||||
updateRequired = true;
|
||||
} else if (nextReleased) {
|
||||
if (skipPages) {
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
showSkipPopup("Skipping");
|
||||
delayedSkipPending = true;
|
||||
delayedSkipDir = +1;
|
||||
delayedSkipAmount = skipAmount;
|
||||
delayedSkipExecuteAtMs = millis() + 500;
|
||||
xSemaphoreGive(renderingMutex);
|
||||
return;
|
||||
}
|
||||
currentPage += skipAmount;
|
||||
if (currentPage >= xtc->getPageCount()) {
|
||||
currentPage = xtc->getPageCount(); // Allow showing "End of book"
|
||||
@ -149,11 +169,29 @@ void XtcReaderActivity::loop() {
|
||||
|
||||
void XtcReaderActivity::displayTaskLoop() {
|
||||
while (true) {
|
||||
const uint32_t now = millis();
|
||||
if (updateRequired) {
|
||||
updateRequired = false;
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
renderScreen();
|
||||
xSemaphoreGive(renderingMutex);
|
||||
} else if (delayedSkipPending && now >= delayedSkipExecuteAtMs) {
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
if (delayedSkipDir < 0) {
|
||||
if (currentPage >= delayedSkipAmount) {
|
||||
currentPage -= delayedSkipAmount;
|
||||
} else {
|
||||
currentPage = 0;
|
||||
}
|
||||
} else {
|
||||
currentPage += delayedSkipAmount;
|
||||
if (currentPage >= xtc->getPageCount()) {
|
||||
currentPage = xtc->getPageCount();
|
||||
}
|
||||
}
|
||||
delayedSkipPending = false;
|
||||
xSemaphoreGive(renderingMutex);
|
||||
updateRequired = true;
|
||||
}
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
@ -177,6 +215,19 @@ void XtcReaderActivity::renderScreen() {
|
||||
saveProgress();
|
||||
}
|
||||
|
||||
void XtcReaderActivity::showSkipPopup(const char* text) {
|
||||
constexpr int boxMargin = 20;
|
||||
const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, text);
|
||||
const int boxWidth = textWidth + boxMargin * 2;
|
||||
const int boxHeight = renderer.getLineHeight(UI_12_FONT_ID) + boxMargin * 2;
|
||||
const int boxX = (renderer.getScreenWidth() - boxWidth) / 2;
|
||||
constexpr int boxY = 50;
|
||||
renderer.fillRect(boxX, boxY, boxWidth, boxHeight, false);
|
||||
renderer.drawText(UI_12_FONT_ID, boxX + boxMargin, boxY + boxMargin, text);
|
||||
renderer.drawRect(boxX + 5, boxY + 5, boxWidth - 10, boxHeight - 10);
|
||||
renderer.displayBuffer(EInkDisplay::FAST_REFRESH);
|
||||
}
|
||||
|
||||
void XtcReaderActivity::renderPage() {
|
||||
const uint16_t pageWidth = xtc->getPageWidth();
|
||||
const uint16_t pageHeight = xtc->getPageHeight();
|
||||
@ -359,6 +410,8 @@ void XtcReaderActivity::renderPage() {
|
||||
bitDepth);
|
||||
}
|
||||
|
||||
// scheduleSkipMessage removed: delayed skip now handled via delayedSkip* fields
|
||||
|
||||
void XtcReaderActivity::saveProgress() const {
|
||||
FsFile f;
|
||||
if (SdMan.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) {
|
||||
|
||||
@ -21,6 +21,10 @@ class XtcReaderActivity final : public ActivityWithSubactivity {
|
||||
uint32_t currentPage = 0;
|
||||
int pagesUntilFullRefresh = 0;
|
||||
bool updateRequired = false;
|
||||
bool delayedSkipPending = false;
|
||||
int delayedSkipDir = 0;
|
||||
uint32_t delayedSkipExecuteAtMs = 0;
|
||||
uint32_t delayedSkipAmount = 0;
|
||||
const std::function<void()> onGoBack;
|
||||
const std::function<void()> onGoHome;
|
||||
|
||||
@ -30,6 +34,7 @@ class XtcReaderActivity final : public ActivityWithSubactivity {
|
||||
void renderPage();
|
||||
void saveProgress() const;
|
||||
void loadProgress();
|
||||
void showSkipPopup(const char* text);
|
||||
|
||||
public:
|
||||
explicit XtcReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr<Xtc> xtc,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user