mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2025-12-19 15:47:40 +03:00
Combine reader activities under ReaderActivity
This commit is contained in:
parent
83012b2d0d
commit
a9b4d99ac4
@ -9,6 +9,8 @@
|
|||||||
constexpr uint8_t STATE_FILE_VERSION = 1;
|
constexpr uint8_t STATE_FILE_VERSION = 1;
|
||||||
constexpr char STATE_FILE[] = "/sd/.crosspoint/state.bin";
|
constexpr char STATE_FILE[] = "/sd/.crosspoint/state.bin";
|
||||||
|
|
||||||
|
CrossPointState CrossPointState::instance;
|
||||||
|
|
||||||
bool CrossPointState::saveToFile() const {
|
bool CrossPointState::saveToFile() const {
|
||||||
std::ofstream outputFile(STATE_FILE);
|
std::ofstream outputFile(STATE_FILE);
|
||||||
serialization::writePod(outputFile, STATE_FILE_VERSION);
|
serialization::writePod(outputFile, STATE_FILE_VERSION);
|
||||||
|
|||||||
@ -3,11 +3,20 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class CrossPointState {
|
class CrossPointState {
|
||||||
|
// Static instance
|
||||||
|
static CrossPointState instance;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string openEpubPath;
|
std::string openEpubPath;
|
||||||
~CrossPointState() = default;
|
~CrossPointState() = default;
|
||||||
|
|
||||||
|
// Get singleton instance
|
||||||
|
static CrossPointState& getInstance() { return instance; }
|
||||||
|
|
||||||
bool saveToFile() const;
|
bool saveToFile() const;
|
||||||
|
|
||||||
bool loadFromFile();
|
bool loadFromFile();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper macro to access settings
|
||||||
|
#define APP_STATE CrossPointState::getInstance()
|
||||||
|
|||||||
21
src/activities/ActivityWithSubactivity.cpp
Normal file
21
src/activities/ActivityWithSubactivity.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include "ActivityWithSubactivity.h"
|
||||||
|
|
||||||
|
void ActivityWithSubactivity::exitActivity() {
|
||||||
|
if (subActivity) {
|
||||||
|
subActivity->onExit();
|
||||||
|
subActivity.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivityWithSubactivity::enterNewActivity(Activity* activity) {
|
||||||
|
subActivity.reset(activity);
|
||||||
|
subActivity->onEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivityWithSubactivity::loop() {
|
||||||
|
if (subActivity) {
|
||||||
|
subActivity->loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivityWithSubactivity::onExit() { exitActivity(); }
|
||||||
17
src/activities/ActivityWithSubactivity.h
Normal file
17
src/activities/ActivityWithSubactivity.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Activity.h"
|
||||||
|
|
||||||
|
class ActivityWithSubactivity : public Activity {
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<Activity> subActivity = nullptr;
|
||||||
|
void exitActivity();
|
||||||
|
void enterNewActivity(Activity* activity);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ActivityWithSubactivity(GfxRenderer& renderer, InputManager& inputManager)
|
||||||
|
: Activity(renderer, inputManager) {}
|
||||||
|
void loop() override;
|
||||||
|
void onExit() override;
|
||||||
|
};
|
||||||
@ -45,7 +45,7 @@ void HomeActivity::loop() {
|
|||||||
|
|
||||||
if (inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
|
if (inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
|
||||||
if (selectorIndex == 0) {
|
if (selectorIndex == 0) {
|
||||||
onFileSelectionOpen();
|
onReaderOpen();
|
||||||
} else if (selectorIndex == 1) {
|
} else if (selectorIndex == 1) {
|
||||||
onSettingsOpen();
|
onSettingsOpen();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ class HomeActivity final : public Activity {
|
|||||||
SemaphoreHandle_t renderingMutex = nullptr;
|
SemaphoreHandle_t renderingMutex = nullptr;
|
||||||
int selectorIndex = 0;
|
int selectorIndex = 0;
|
||||||
bool updateRequired = false;
|
bool updateRequired = false;
|
||||||
const std::function<void()> onFileSelectionOpen;
|
const std::function<void()> onReaderOpen;
|
||||||
const std::function<void()> onSettingsOpen;
|
const std::function<void()> onSettingsOpen;
|
||||||
|
|
||||||
static constexpr int menuItemCount = 2;
|
static constexpr int menuItemCount = 2;
|
||||||
@ -22,9 +22,9 @@ class HomeActivity final : public Activity {
|
|||||||
void render() const;
|
void render() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit HomeActivity(GfxRenderer& renderer, InputManager& inputManager,
|
explicit HomeActivity(GfxRenderer& renderer, InputManager& inputManager, const std::function<void()>& onReaderOpen,
|
||||||
const std::function<void()>& onFileSelectionOpen, const std::function<void()>& onSettingsOpen)
|
const std::function<void()>& onSettingsOpen)
|
||||||
: Activity(renderer, inputManager), onFileSelectionOpen(onFileSelectionOpen), onSettingsOpen(onSettingsOpen) {}
|
: Activity(renderer, inputManager), onReaderOpen(onReaderOpen), onSettingsOpen(onSettingsOpen) {}
|
||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void onExit() override;
|
void onExit() override;
|
||||||
void loop() override;
|
void loop() override;
|
||||||
|
|||||||
68
src/activities/reader/ReaderActivity.cpp
Normal file
68
src/activities/reader/ReaderActivity.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "ReaderActivity.h"
|
||||||
|
|
||||||
|
#include <SD.h>
|
||||||
|
|
||||||
|
#include "CrossPointState.h"
|
||||||
|
#include "Epub.h"
|
||||||
|
#include "EpubReaderActivity.h"
|
||||||
|
#include "FileSelectionActivity.h"
|
||||||
|
#include "activities/util/FullScreenMessageActivity.h"
|
||||||
|
|
||||||
|
std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {
|
||||||
|
if (!SD.exists(path.c_str())) {
|
||||||
|
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto epub = std::unique_ptr<Epub>(new Epub(path, "/.crosspoint"));
|
||||||
|
if (epub->load()) {
|
||||||
|
return epub;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("[%lu] [ ] Failed to load epub\n", millis());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReaderActivity::onSelectEpubFile(const std::string& path) {
|
||||||
|
exitActivity();
|
||||||
|
enterNewActivity(new FullScreenMessageActivity(renderer, inputManager, "Loading..."));
|
||||||
|
|
||||||
|
auto epub = loadEpub(path);
|
||||||
|
if (epub) {
|
||||||
|
APP_STATE.openEpubPath = path;
|
||||||
|
APP_STATE.saveToFile();
|
||||||
|
onGoToEpubReader(std::move(epub));
|
||||||
|
} else {
|
||||||
|
exitActivity();
|
||||||
|
enterNewActivity(new FullScreenMessageActivity(renderer, inputManager, "Failed to load epub", REGULAR,
|
||||||
|
EInkDisplay::HALF_REFRESH));
|
||||||
|
delay(2000);
|
||||||
|
onGoToFileSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReaderActivity::onGoToFileSelection() {
|
||||||
|
exitActivity();
|
||||||
|
enterNewActivity(new FileSelectionActivity(
|
||||||
|
renderer, inputManager, [this](const std::string& path) { onSelectEpubFile(path); }, onGoBack));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReaderActivity::onGoToEpubReader(std::unique_ptr<Epub> epub) {
|
||||||
|
exitActivity();
|
||||||
|
enterNewActivity(new EpubReaderActivity(renderer, inputManager, std::move(epub), [this] { onGoToFileSelection(); }));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReaderActivity::onEnter() {
|
||||||
|
if (initialEpubPath.empty()) {
|
||||||
|
onGoToFileSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto epub = loadEpub(initialEpubPath);
|
||||||
|
if (!epub) {
|
||||||
|
onGoBack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onGoToEpubReader(std::move(epub));
|
||||||
|
}
|
||||||
24
src/activities/reader/ReaderActivity.h
Normal file
24
src/activities/reader/ReaderActivity.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "../ActivityWithSubactivity.h"
|
||||||
|
|
||||||
|
class Epub;
|
||||||
|
|
||||||
|
class ReaderActivity final : public ActivityWithSubactivity {
|
||||||
|
std::string initialEpubPath;
|
||||||
|
const std::function<void()> onGoBack;
|
||||||
|
static std::unique_ptr<Epub> loadEpub(const std::string& path);
|
||||||
|
|
||||||
|
void onSelectEpubFile(const std::string& path);
|
||||||
|
void onGoToFileSelection();
|
||||||
|
void onGoToEpubReader(std::unique_ptr<Epub> epub);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ReaderActivity(GfxRenderer& renderer, InputManager& inputManager, std::string initialEpubPath,
|
||||||
|
const std::function<void()>& onGoBack)
|
||||||
|
: ActivityWithSubactivity(renderer, inputManager),
|
||||||
|
initialEpubPath(std::move(initialEpubPath)),
|
||||||
|
onGoBack(onGoBack) {}
|
||||||
|
void onEnter() override;
|
||||||
|
};
|
||||||
63
src/main.cpp
63
src/main.cpp
@ -19,8 +19,7 @@
|
|||||||
#include "activities/boot_sleep/BootActivity.h"
|
#include "activities/boot_sleep/BootActivity.h"
|
||||||
#include "activities/boot_sleep/SleepActivity.h"
|
#include "activities/boot_sleep/SleepActivity.h"
|
||||||
#include "activities/home/HomeActivity.h"
|
#include "activities/home/HomeActivity.h"
|
||||||
#include "activities/reader/EpubReaderActivity.h"
|
#include "activities/reader/ReaderActivity.h"
|
||||||
#include "activities/reader/FileSelectionActivity.h"
|
|
||||||
#include "activities/settings/SettingsActivity.h"
|
#include "activities/settings/SettingsActivity.h"
|
||||||
#include "activities/util/FullScreenMessageActivity.h"
|
#include "activities/util/FullScreenMessageActivity.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -43,7 +42,6 @@ EInkDisplay einkDisplay(EPD_SCLK, EPD_MOSI, EPD_CS, EPD_DC, EPD_RST, EPD_BUSY);
|
|||||||
InputManager inputManager;
|
InputManager inputManager;
|
||||||
GfxRenderer renderer(einkDisplay);
|
GfxRenderer renderer(einkDisplay);
|
||||||
Activity* currentActivity;
|
Activity* currentActivity;
|
||||||
CrossPointState appState;
|
|
||||||
|
|
||||||
// Fonts
|
// Fonts
|
||||||
EpdFont bookerlyFont(&bookerly_2b);
|
EpdFont bookerlyFont(&bookerly_2b);
|
||||||
@ -67,21 +65,6 @@ constexpr unsigned long POWER_BUTTON_SLEEP_MS = 500;
|
|||||||
// Auto-sleep timeout (10 minutes of inactivity)
|
// Auto-sleep timeout (10 minutes of inactivity)
|
||||||
constexpr unsigned long AUTO_SLEEP_TIMEOUT_MS = 10 * 60 * 1000;
|
constexpr unsigned long AUTO_SLEEP_TIMEOUT_MS = 10 * 60 * 1000;
|
||||||
|
|
||||||
std::unique_ptr<Epub> loadEpub(const std::string& path) {
|
|
||||||
if (!SD.exists(path.c_str())) {
|
|
||||||
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto epub = std::unique_ptr<Epub>(new Epub(path, "/.crosspoint"));
|
|
||||||
if (epub->load()) {
|
|
||||||
return epub;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial.printf("[%lu] [ ] Failed to load epub\n", millis());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void exitActivity() {
|
void exitActivity() {
|
||||||
if (currentActivity) {
|
if (currentActivity) {
|
||||||
currentActivity->onExit();
|
currentActivity->onExit();
|
||||||
@ -151,30 +134,11 @@ void enterDeepSleep() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onGoHome();
|
void onGoHome();
|
||||||
void onGoToFileSelection();
|
void onGoToReader(const std::string& initialEpubPath) {
|
||||||
void onSelectEpubFile(const std::string& path) {
|
|
||||||
exitActivity();
|
exitActivity();
|
||||||
enterNewActivity(new FullScreenMessageActivity(renderer, inputManager, "Loading..."));
|
enterNewActivity(new ReaderActivity(renderer, inputManager, initialEpubPath, onGoHome));
|
||||||
|
|
||||||
auto epub = loadEpub(path);
|
|
||||||
if (epub) {
|
|
||||||
appState.openEpubPath = path;
|
|
||||||
appState.saveToFile();
|
|
||||||
exitActivity();
|
|
||||||
enterNewActivity(new EpubReaderActivity(renderer, inputManager, std::move(epub), onGoToFileSelection));
|
|
||||||
} else {
|
|
||||||
exitActivity();
|
|
||||||
enterNewActivity(new FullScreenMessageActivity(renderer, inputManager, "Failed to load epub", REGULAR,
|
|
||||||
EInkDisplay::HALF_REFRESH));
|
|
||||||
delay(2000);
|
|
||||||
onGoToFileSelection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onGoToFileSelection() {
|
|
||||||
exitActivity();
|
|
||||||
enterNewActivity(new FileSelectionActivity(renderer, inputManager, onSelectEpubFile, onGoHome));
|
|
||||||
}
|
}
|
||||||
|
void onGoToReaderHome() { onGoToReader(std::string()); }
|
||||||
|
|
||||||
void onGoToSettings() {
|
void onGoToSettings() {
|
||||||
exitActivity();
|
exitActivity();
|
||||||
@ -183,7 +147,7 @@ void onGoToSettings() {
|
|||||||
|
|
||||||
void onGoHome() {
|
void onGoHome() {
|
||||||
exitActivity();
|
exitActivity();
|
||||||
enterNewActivity(new HomeActivity(renderer, inputManager, onGoToFileSelection, onGoToSettings));
|
enterNewActivity(new HomeActivity(renderer, inputManager, onGoToReaderHome, onGoToSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
@ -216,19 +180,12 @@ void setup() {
|
|||||||
SD.begin(SD_SPI_CS, SPI, SPI_FQ);
|
SD.begin(SD_SPI_CS, SPI, SPI_FQ);
|
||||||
|
|
||||||
SETTINGS.loadFromFile();
|
SETTINGS.loadFromFile();
|
||||||
appState.loadFromFile();
|
APP_STATE.loadFromFile();
|
||||||
if (!appState.openEpubPath.empty()) {
|
if (APP_STATE.openEpubPath.empty()) {
|
||||||
auto epub = loadEpub(appState.openEpubPath);
|
|
||||||
if (epub) {
|
|
||||||
exitActivity();
|
|
||||||
enterNewActivity(new EpubReaderActivity(renderer, inputManager, std::move(epub), onGoHome));
|
|
||||||
// Ensure we're not still holding the power button before leaving setup
|
|
||||||
waitForPowerRelease();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onGoHome();
|
onGoHome();
|
||||||
|
} else {
|
||||||
|
onGoToReader(APP_STATE.openEpubPath);
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure we're not still holding the power button before leaving setup
|
// Ensure we're not still holding the power button before leaving setup
|
||||||
waitForPowerRelease();
|
waitForPowerRelease();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user