mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-06 15:47:39 +03:00
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) {
|
if (skipChapter) {
|
||||||
// We don't want to delete the section mid-render, so grab the semaphore
|
// We don't want to delete the section mid-render, so grab the semaphore
|
||||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||||
nextPageNumber = 0;
|
// Show immediate feedback for long-press skip, then schedule delayed action (500ms)
|
||||||
currentSpineIndex = nextReleased ? currentSpineIndex + 1 : currentSpineIndex - 1;
|
showSkipPopup("Skipping");
|
||||||
section.reset();
|
delayedSkipPending = true;
|
||||||
|
delayedSkipDir = nextReleased ? +1 : -1;
|
||||||
|
delayedSkipExecuteAtMs = millis() + 500;
|
||||||
xSemaphoreGive(renderingMutex);
|
xSemaphoreGive(renderingMutex);
|
||||||
updateRequired = true;
|
// Do not perform the skip immediately; it will be executed in display loop after delay
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,11 +231,21 @@ void EpubReaderActivity::loop() {
|
|||||||
|
|
||||||
void EpubReaderActivity::displayTaskLoop() {
|
void EpubReaderActivity::displayTaskLoop() {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
const uint32_t now = millis();
|
||||||
if (updateRequired) {
|
if (updateRequired) {
|
||||||
updateRequired = false;
|
updateRequired = false;
|
||||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||||
renderScreen();
|
renderScreen();
|
||||||
xSemaphoreGive(renderingMutex);
|
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);
|
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,
|
void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int orientedMarginTop,
|
||||||
const int orientedMarginRight, const int orientedMarginBottom,
|
const int orientedMarginRight, const int orientedMarginBottom,
|
||||||
const int orientedMarginLeft) {
|
const int orientedMarginLeft) {
|
||||||
|
|||||||
@ -16,6 +16,9 @@ class EpubReaderActivity final : public ActivityWithSubactivity {
|
|||||||
int nextPageNumber = 0;
|
int nextPageNumber = 0;
|
||||||
int pagesUntilFullRefresh = 0;
|
int pagesUntilFullRefresh = 0;
|
||||||
bool updateRequired = false;
|
bool updateRequired = false;
|
||||||
|
bool delayedSkipPending = false;
|
||||||
|
int delayedSkipDir = 0;
|
||||||
|
uint32_t delayedSkipExecuteAtMs = 0;
|
||||||
const std::function<void()> onGoBack;
|
const std::function<void()> onGoBack;
|
||||||
const std::function<void()> onGoHome;
|
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,
|
void renderContents(std::unique_ptr<Page> page, int orientedMarginTop, int orientedMarginRight,
|
||||||
int orientedMarginBottom, int orientedMarginLeft);
|
int orientedMarginBottom, int orientedMarginLeft);
|
||||||
void renderStatusBar(int orientedMarginRight, int orientedMarginBottom, int orientedMarginLeft) const;
|
void renderStatusBar(int orientedMarginRight, int orientedMarginBottom, int orientedMarginLeft) const;
|
||||||
|
void showSkipPopup(const char* text);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EpubReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr<Epub> epub,
|
explicit EpubReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr<Epub> epub,
|
||||||
|
|||||||
@ -132,6 +132,16 @@ void XtcReaderActivity::loop() {
|
|||||||
const int skipAmount = skipPages ? 10 : 1;
|
const int skipAmount = skipPages ? 10 : 1;
|
||||||
|
|
||||||
if (prevReleased) {
|
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)) {
|
if (currentPage >= static_cast<uint32_t>(skipAmount)) {
|
||||||
currentPage -= skipAmount;
|
currentPage -= skipAmount;
|
||||||
} else {
|
} else {
|
||||||
@ -139,6 +149,16 @@ void XtcReaderActivity::loop() {
|
|||||||
}
|
}
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
} else if (nextReleased) {
|
} 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;
|
currentPage += skipAmount;
|
||||||
if (currentPage >= xtc->getPageCount()) {
|
if (currentPage >= xtc->getPageCount()) {
|
||||||
currentPage = xtc->getPageCount(); // Allow showing "End of book"
|
currentPage = xtc->getPageCount(); // Allow showing "End of book"
|
||||||
@ -149,11 +169,29 @@ void XtcReaderActivity::loop() {
|
|||||||
|
|
||||||
void XtcReaderActivity::displayTaskLoop() {
|
void XtcReaderActivity::displayTaskLoop() {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
const uint32_t now = millis();
|
||||||
if (updateRequired) {
|
if (updateRequired) {
|
||||||
updateRequired = false;
|
updateRequired = false;
|
||||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||||
renderScreen();
|
renderScreen();
|
||||||
xSemaphoreGive(renderingMutex);
|
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);
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
@ -177,6 +215,19 @@ void XtcReaderActivity::renderScreen() {
|
|||||||
saveProgress();
|
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() {
|
void XtcReaderActivity::renderPage() {
|
||||||
const uint16_t pageWidth = xtc->getPageWidth();
|
const uint16_t pageWidth = xtc->getPageWidth();
|
||||||
const uint16_t pageHeight = xtc->getPageHeight();
|
const uint16_t pageHeight = xtc->getPageHeight();
|
||||||
@ -359,6 +410,8 @@ void XtcReaderActivity::renderPage() {
|
|||||||
bitDepth);
|
bitDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scheduleSkipMessage removed: delayed skip now handled via delayedSkip* fields
|
||||||
|
|
||||||
void XtcReaderActivity::saveProgress() const {
|
void XtcReaderActivity::saveProgress() const {
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (SdMan.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) {
|
if (SdMan.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) {
|
||||||
|
|||||||
@ -21,6 +21,10 @@ class XtcReaderActivity final : public ActivityWithSubactivity {
|
|||||||
uint32_t currentPage = 0;
|
uint32_t currentPage = 0;
|
||||||
int pagesUntilFullRefresh = 0;
|
int pagesUntilFullRefresh = 0;
|
||||||
bool updateRequired = false;
|
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()> onGoBack;
|
||||||
const std::function<void()> onGoHome;
|
const std::function<void()> onGoHome;
|
||||||
|
|
||||||
@ -30,6 +34,7 @@ class XtcReaderActivity final : public ActivityWithSubactivity {
|
|||||||
void renderPage();
|
void renderPage();
|
||||||
void saveProgress() const;
|
void saveProgress() const;
|
||||||
void loadProgress();
|
void loadProgress();
|
||||||
|
void showSkipPopup(const char* text);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit XtcReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr<Xtc> xtc,
|
explicit XtcReaderActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::unique_ptr<Xtc> xtc,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user