115 lines
3.8 KiB
C++
115 lines
3.8 KiB
C++
#pragma once
|
|
#include <Epub.h>
|
|
|
|
#include <memory>
|
|
|
|
#include "ChapterXPathIndexer.h"
|
|
#include "CrossPointState.h"
|
|
#include "KOReaderSyncClient.h"
|
|
#include "ProgressMapper.h"
|
|
#include "activities/Activity.h"
|
|
|
|
/**
|
|
* Activity for syncing reading progress with KOReader sync server.
|
|
*
|
|
* This activity is launched as a standalone replacement screen, not as a
|
|
* child activity of the reader. The reader persists a compact handoff record,
|
|
* is destroyed to reclaim memory before WiFi/TLS work begins, and a fresh
|
|
* reader instance is reopened after sync completes or is cancelled.
|
|
*
|
|
* Shared pipeline:
|
|
* 1. Connect to WiFi (if not connected)
|
|
* 2. Optionally sync NTP (if stale)
|
|
* 3. Calculate document hash
|
|
*
|
|
* Intent-specific behavior:
|
|
* - COMPARE: fetch remote progress, show full comparison screen, let user
|
|
* choose Apply or Upload.
|
|
* - PULL_REMOTE: fetch and map remote progress, show success feedback, then
|
|
* persist an applied SyncResult for the reopened reader.
|
|
* - PUSH_LOCAL: compute local mapping, warm session with GET, then upload via
|
|
* reused connection to avoid a second full TLS handshake.
|
|
*/
|
|
class KOReaderSyncActivity final : public Activity {
|
|
public:
|
|
explicit KOReaderSyncActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::string& epubPath,
|
|
int currentSpineIndex, int currentPage, int totalPagesInSpine,
|
|
uint16_t paragraphIndex = 0, bool hasParagraphIndex = false, uint32_t xhtmlSeekHint = 0,
|
|
KOReaderSyncIntentState syncIntent = KOReaderSyncIntentState::COMPARE)
|
|
: Activity("KOReaderSync", renderer, mappedInput),
|
|
epubPath(epubPath),
|
|
currentSpineIndex(currentSpineIndex),
|
|
currentPage(currentPage),
|
|
totalPagesInSpine(totalPagesInSpine),
|
|
localParagraphIndex(paragraphIndex),
|
|
hasLocalParagraphIndex(hasParagraphIndex),
|
|
localXhtmlSeekHint(xhtmlSeekHint),
|
|
syncIntent(syncIntent),
|
|
remoteProgress{},
|
|
remotePosition{},
|
|
localProgress{} {}
|
|
|
|
void onEnter() override;
|
|
void onExit() override;
|
|
void loop() override;
|
|
void render(RenderLock&&) override;
|
|
bool preventAutoSleep() override { return state == CONNECTING || state == SYNCING; }
|
|
|
|
private:
|
|
enum State {
|
|
WIFI_SELECTION,
|
|
CONNECTING,
|
|
SYNCING,
|
|
SHOWING_RESULT,
|
|
UPLOADING,
|
|
UPLOAD_COMPLETE,
|
|
APPLY_COMPLETE,
|
|
NO_REMOTE_PROGRESS,
|
|
SYNC_FAILED,
|
|
NO_CREDENTIALS
|
|
};
|
|
|
|
std::shared_ptr<Epub> epub;
|
|
std::string epubPath;
|
|
int currentSpineIndex;
|
|
int currentPage;
|
|
int totalPagesInSpine;
|
|
uint16_t localParagraphIndex;
|
|
bool hasLocalParagraphIndex;
|
|
uint32_t localXhtmlSeekHint;
|
|
KOReaderSyncIntentState syncIntent = KOReaderSyncIntentState::COMPARE;
|
|
|
|
State state = WIFI_SELECTION;
|
|
std::string statusMessage;
|
|
std::string documentHash;
|
|
|
|
// Remote progress data
|
|
bool hasRemoteProgress = false;
|
|
bool remotePositionMapped = false;
|
|
KOReaderProgress remoteProgress;
|
|
CrossPointPosition remotePosition;
|
|
|
|
// Local progress as KOReader format (for display)
|
|
KOReaderPosition localProgress;
|
|
std::string remoteChapterLabel;
|
|
std::string localChapterLabel;
|
|
|
|
// Selection in result screen (0=Apply, 1=Upload)
|
|
int selectedOption = 0;
|
|
|
|
// Timestamp when completion state was entered (for auto-close)
|
|
unsigned long uploadCompleteTime = 0;
|
|
bool closeRequested = false;
|
|
|
|
void onWifiSelectionComplete(bool success);
|
|
void performSync();
|
|
void performUpload();
|
|
void closeCancelled();
|
|
void resumeReader(KOReaderSyncOutcomeState outcome, const SyncResult* appliedResult = nullptr);
|
|
bool ensureEpubLoadedForMapping();
|
|
void releaseEpubForMapping();
|
|
bool computeLocalProgressAndChapter();
|
|
void computeRemoteChapter();
|
|
bool ensureRemotePositionMapped(bool closeSessionBeforeMapping = true);
|
|
};
|