Add TXT file reader support (#240)
## Summary * **What is the goal of this PR?** Add support for reading plain text (.txt) files, enabling users to browse, read, and track progress in TXT documents alongside existing EPUB and XTC formats. * **What changes are included?** - New Txt library for loading and parsing plain text files - New TxtReaderActivity with streaming page rendering using 8KB chunks to handle large files without memory issues on ESP32-C3 - Page index caching system (index.bin) for instant re-open after sleep or app restart - Progress bar UI during initial file indexing (matching EPUB style) - Word wrapping with proper UTF-8 support - Cover image support for TXT files: - Primary: image with same filename as TXT (e.g., book.jpg for book.txt) - Fallback: cover.bmp/jpg/jpeg in the same folder - JPG to BMP conversion using existing converter - Sleep screen cover mode now works with TXT files - File browser now shows .txt files ## Additional Context * Add any other information that might be helpful for the reviewer * Memory constraints: The streaming approach was necessary because ESP32-C3 only has 320KB RAM. A 700KB TXT file cannot be loaded entirely into memory, so we read 8KB chunks and build a page offset index instead. * Cache invalidation: The page index cache automatically invalidates when file size, viewport width, or lines per page changes (e.g., font size or orientation change). * Performance: First open requires indexing (with progress bar), subsequent opens load from cache instantly. * Cover image format: PNG is detected but not supported for conversion (no PNG decoder available). Only BMP and JPG/JPEG work.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <Epub.h>
|
||||
#include <GfxRenderer.h>
|
||||
#include <SDCardManager.h>
|
||||
#include <Txt.h>
|
||||
#include <Xtc.h>
|
||||
|
||||
#include "CrossPointSettings.h"
|
||||
@@ -207,6 +208,7 @@ void SleepActivity::renderCoverSleepScreen() const {
|
||||
std::string coverBmpPath;
|
||||
bool cropped = SETTINGS.sleepScreenCoverMode == CrossPointSettings::SLEEP_SCREEN_COVER_MODE::CROP;
|
||||
|
||||
// Check if the current book is XTC, TXT, or EPUB
|
||||
if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".xtc") ||
|
||||
StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".xtch")) {
|
||||
// Handle XTC file
|
||||
@@ -222,6 +224,20 @@ void SleepActivity::renderCoverSleepScreen() const {
|
||||
}
|
||||
|
||||
coverBmpPath = lastXtc.getCoverBmpPath();
|
||||
} else if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".txt")) {
|
||||
// Handle TXT file - looks for cover image in the same folder
|
||||
Txt lastTxt(APP_STATE.openEpubPath, "/.crosspoint");
|
||||
if (!lastTxt.load()) {
|
||||
Serial.println("[SLP] Failed to load last TXT");
|
||||
return renderDefaultSleepScreen();
|
||||
}
|
||||
|
||||
if (!lastTxt.generateCoverBmp()) {
|
||||
Serial.println("[SLP] No cover image found for TXT file");
|
||||
return renderDefaultSleepScreen();
|
||||
}
|
||||
|
||||
coverBmpPath = lastTxt.getCoverBmpPath();
|
||||
} else if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".epub")) {
|
||||
// Handle EPUB file
|
||||
Epub lastEpub(APP_STATE.openEpubPath, "/.crosspoint");
|
||||
|
||||
Reference in New Issue
Block a user