* Fixed PDF reading position restoration during orientation change
* Refactored navigation logic in `EpubReaderScreen` and `PaginatedReader` to improve position restoration and UI consistency.
- Renamed `isNavigatingToBookmark` to `isNavigatingToPosition` and updated the overlay UI to reflect general position navigation.
- Added an orientation change listener to restore the reading position in `VERTICAL_SCROLL` mode using the last known locator.
- Improved highlight navigation in `VERTICAL_SCROLL` and `PAGINATED` modes, including chunk injection logic for highlights and fallback pagination logic.
- Implemented an anchor locator mechanism in `PaginatedReader` to preserve the reading position during layout constraint changes (e.g., orientation or resizing).
* Replaced PDF-to-Markdown reflow with an enhanced PDF-to-HTML generator.
Specific changes include:
- Replaced `PdfToMarkdownGenerator` and `PdfReflowGenerator` with `PdfToHtmlGenerator`.
- Added native bridge methods in `NativePdfiumBridge.kt` and `pdfium_bridge.cpp` to extract character bounding boxes, page objects, and image pixels.
- Implemented vertical merging of text and images in `PdfToHtmlGenerator` to maintain document layout.
- Added logic to detect and filter repeating headers and footers across PDF pages.
- Updated `ReflowWorker` to generate `.html` files instead of `.md` files and updated `FileType` handling.
- Simplified `SingleFileImporter` by removing dependencies on the legacy Markdown generator.
* Updated PDF to HTML generation to include page breaks and split HTML files into individual chapters based on page markers.
* Added junk character filtering and normalization to PDF text extraction
* - Added `allRecentFiles` to `ReaderScreenState` to track all files, including reflowed versions.
- Updated `recentFiles` in `MainViewModel` to filter out reflowed files (`_reflow`) from the main library view.
- Implemented `deleteBookPermanently` in `MainViewModel` to handle book deletion and cache cleanup.
- Added a "Delete Text View" option to the `EpubReader` controls for reflowed files.
- Improved reflow file detection in `PdfViewerScreen` by checking against `allRecentFiles`.
* Implemented a centralized data-saving mechanism in `PdfViewerScreen` using a debounced `saveAllData` function. This refactor consolidates the saving of annotations, text boxes, highlights, bookmarks, and scroll positions, adding lifecycle-aware triggers and a mutex to ensure data integrity during pauses or document navigation.
* Optimized PDF selection and annotation performance by offloading heavy operations to background threads and improving UI responsiveness.
- Moved PDF page/text opening, character range calculations, and text extraction to `Dispatchers.IO`.
- Wrapped UI updates in `updateSelectionVisuals` and selection logic with `withContext(Dispatchers.Main)`.
- Implemented a more efficient `Popup`-based magnifier to replace manual offsets and transformations.
- Updated `PdfSelectionMenuPopup` properties to prevent focus and click-outside dismissal conflicts.
* perf(pdf): native Pdfium-based reflow engine with auto-open
Migrate PDF-to-Markdown reflow generation from PDFBox to a custom
native implementation using Pdfium. This transition improves
processing speed by ~10x and significantly reduces memory overhead.
- Native JNI Bridge: Implemented `pdfium_bridge.cpp` using `dlopen`
to hook into the existing `libpdfium.so` memory space.
- Optimized Extraction: Replaced character-by-character JNI calls
with bulk array retrieval (`getPageFontSizes`, `getPageFontWeights`),
drastically reducing JNI boundary overhead.
- Enhanced Accuracy: Improved Markdown formatting logic by using
native font weight (bold) and relative font size variance (headers).
- Thread Safety: Refactored generator to process pages sequentially
while synchronized with the global `PdfiumCore.lock` to ensure
stability across concurrent UI operations.
- Seamless UX: Implemented a reactive auto-open system in the
PDF viewer that tracks user intent and navigates to the reflow
view immediately upon background task completion.
* Improved PDF to Markdown conversion and added cache cleanup.
- Implemented automated cleanup of imported file caches when deleting books.
- Enhanced `PdfToMarkdownGenerator` with support for font flags (italics), improved kerning, and smarter paragraph wrapping.
- Updated `NativePdfiumBridge` and C++ JNI code to extract font information flags from PDFium.
* Implemented seamless file switching and enhanced reflow transition logic.
Key changes include:
- Added `switchToFileSeamlessly` to `MainViewModel` to handle state transitions and navigation when switching between PDF and reflowed text views.
- Updated `generateAndImportReflowFile` to support automatic opening of the generated file at a specific page/chapter.
- Integrated `NavigationEvent` and `CompletableDeferred` to manage asynchronous navigation and state updates during file switches.
- Modified `EpubReaderScreen` and `PdfViewerScreen` to pass the current position when toggling between PDF and text modes.
- Updated `AppNavigation` to move navigation logic out of the `NavHost` and added loading overlays to viewers to improve UI feedback during transitions.
* Implemented long-press gestures(on the left and right region) for rapid scrolling(to top or bottom) in Musician Mode for both EPUB and PDF readers.
* Added support for book-specific reader settings and redesigned the format adjustment UI.
* perf: implement persistent caching and parallel parsing for single-file imports
- Replaced random UUID generation with bookId-based pathing in SingleFileImporter to enable cache reuse.
- Added a JSON metadata fast-path to return EpubBook objects instantly on subsequent opens for MD, TXT, and HTML.
- Parallelized Markdown chapter parsing using Coroutines (async/awaitAll) to leverage multicore CPUs.
* feat(pdf): implement native text highlighting and interactive selection menu
- Add `PdfUserHighlight` data model to track page index, character ranges, and normalized coordinates.
- Redesign `PdfSelectionMenuPopup` to match the EPUB reader style, featuring a color palette row and a deletion option.
- Integrate highlight rendering into the `PdfPageSelectionsLayer` using Canvas drawing.
- Add hit-testing to `detectTapGestures` to allow users to tap existing highlights to change colors or remove them.
* Implemented PDF highlight persistence, sync, and exporting.
* Improved PDF highlight exporting and visibility logic
- Fixed PDF highlight rendering by correctly calculating coordinates and merging adjacent rectangles into lines.
- Updated `PdfExporter` to include highlights in the exported document and added debug logging.
- Corrected visibility check in `PdfPageComposable` to account for vertical offsets.
- Enhanced `PdfViewerScreen` highlight creation to use merged line rectangles
* Refactored annotation synchronization logic and improved background sync reliability.
- Refactored JSON bundle creation and extraction into reusable helper functions.
- Improved stale file detection by checking all annotation types (ink, text, layout, highlights, text boxes).
- Added background annotation downloading to `SyncWorker`
- Implemented duplicate file cleanup in `GoogleDriveRepository` during uploads.
- Added a `showFeedback` flag to `syncFolderMetadata` to control UI visibility during background operations.
- Fixed a potential data loss edge case by aborting Firestore sync if the bundle upload fails.
* Improved highlight interaction and management in PDF viewer
- Implemented hit tolerance for highlight selection to improve touch detection accuracy.
- Added logic to shift highlight page indices when adding or deleting pages.
- Included highlights in the auto-pruning check for empty pages.
- Added a "Highlights" tab to the navigation drawer to list, navigate to, and delete user highlights.
- Added `SyncedFolder` data class and transitioned from a single `syncedFolderUri` to a list of `syncedFolders`.
- Implemented logic to add, remove, and persist multiple synced folders using JSON in shared preferences, including a migration path for legacy single-folder settings.
- Updated `FolderSyncWorker` to iterate through all registered folders and added an annotation sidecar preloading optimization to reduce file I/O during sync.
- Redesigned the "Folder Sync" UI in `LibraryScreen` to display a list of active folders with individual management options and a 3-folder limit.
- Refined permission handling to request both read and write access for synced folders.
* Implemented PDF reflow mode by introducing a mechanism to convert PDF content to Markdown/HTML for viewing in the EPUB reader.
Specific changes include:
- Added `PdfReflowGenerator` and `PdfToMarkdownGenerator` to handle PDF text extraction and conversion to reflowable formats.
- Updated `MainViewModel` with `toggleReflowMode` logic to switch between original PDF and reflowed views.
- Modified `RecentFileEntity` and `RecentFileDao` to persist user reflow preferences, including a Room database migration (v12 to v13).
- Updated `PdfViewerScreen` and `EpubReaderControls` to include UI options for toggling reflow mode.
- Integrated reflow preference check into the book opening workflow to automatically load the preferred view.
- Updated `AppNavigation` and `EpubReaderScreen` to support the new view switching state.
* Implemented background processing and incremental loading for PDF reflow mode.
- Added `reflowProgress` to `MainViewModel` to track and display PDF-to-Markdown conversion progress in the UI.
- Refactored `PdfToMarkdownGenerator` to generate a skeleton EPUB structure immediately while processing page content (text and images) asynchronously.
- Switched PDF text extraction to use `PDFBox` with optimized memory settings and JPEG compression for images.
- Implemented priority page processing in reflow mode, starting with the user's current page.
- Added "Clear Reflow Cache" debug option to the Home Screen.
- Enhanced `BookPaginator` to support lazy loading of chapter content from disk and improved cache hit detection.
* Refactored PDF Reflow Mode to generate standalone Markdown files instead of temporary EPUB books.
* perf(reflow): optimize PDF-to-Markdown conversion and fix viewing lag
- Re-architected PdfToMarkdownGenerator to use a single-pass stream (O(N) complexity), fixing performance bottlenecks and timeouts on large PDFs.
- Implemented "Virtual Chaptering" in SingleFileImporter for Markdown files to split content into page-level HTML files, eliminating UI lag during reading.
- Simplified ReflowWorker to delegate progress tracking and looping to the generator.
- Enhanced PdfViewerScreen with a prominent top-bar progress indicator and a completion snackbar with an "OPEN" action.
* Optimized EPUB parsing performance and fixed PDF viewer UI layout.
- Optimized `EpubParser` by implementing parallel chapter parsing using coroutines and a semaphore to limit concurrency.
- Reduced memory usage in `EpubParser` and `SingleFileImporter` by no longer storing full HTML content in memory for chapters.
- Updated `EpubXMLFileParser` to support an existing `Document` object to avoid redundant Jsoup parsing.
- Fixed an issue in `PdfViewerScreen` where the snackbar was appearing under the bottom app bar.
* Implemented folder-based annotation synchronization and legacy book ID migration.
- Added `syncLocalAnnotationsToFolder` and `importAnnotationBundle` to `RecentFilesRepository` to handle bundling ink, rich text, layouts, and text boxes into a single JSON sidecar file.
- Introduced `saveAnnotationSidecar` and `getAnnotationSidecar` in `LocalSyncUtils` to manage hidden synchronization files in linked folders using SAF.
- Updated `MainViewModel` to trigger annotation syncing on book close and added a migration utility for legacy book IDs.
- Enhanced `FolderSyncWorker` to include a dedicated phase for importing newer annotation bundles from synchronized folders.
- Fixed an ID mismatch edge case in `PdfViewerScreen` by initiating data migration when a legacy ID is detected.
- Added `selectedBookId` to `ReaderScreenState` to better track the active document across the application.
* fix(sync): resolve Syncthing file lock conflicts and annotation migration bug
- Implement atomic saves (write-to-temp then rename) for annotation sidecars in `LocalSyncUtils` to prevent `.tmp` file locking and partial writes when using third-party sync tools like Syncthing.
- Add robust conflict resolution for annotation sidecars (`resolveAndCleanAnnotationConflicts`) to automatically detect, keep the newest version, and clean up `.sync-conflict` files.
- Fix a bug in `MainViewModel.checkAndMigrateLegacyBookId` where older legacy local files would blindly overwrite newly synced annotation files by adding a timestamp-based clobber check.
* Refactored folder synchronization logic and improved migration handling
- Updated `MainViewModel` to skip synchronization until folder migration is completed and added metadata syncing when opening books.
- Modified folder migration to detach existing folder books (converting them to standard local files) before starting a fresh scan.
- Added `detachAllFolderBooks` to `RecentFileDao` and `RecentFilesRepository` to facilitate the migration process.
- Updated `MetadataExtractionWorker` to sync local metadata to the folder immediately after extraction.
- Simplified `FolderSyncWorker` by removing legacy migration lookups and streamlining the reconciliation of local and remote metadata.
- Updated `FolderMigrationDialog` UI text to reflect that books are now read directly from folders without duplication.
- Fixed various indentation and formatting issues across several files.
* Removed the `.episteme` sync directory and moved book metadata files directly to the folder root as hidden files.
- Updated `MainViewModel` to skip synchronization until folder migration is completed and added metadata syncing when opening books.
- Modified folder migration to detach existing folder books (converting them to standard local files) before starting a fresh scan.
- Added `detachAllFolderBooks` to `RecentFileDao` and `RecentFilesRepository` to facilitate the migration process.
- Updated `MetadataExtractionWorker` to sync local metadata to the folder immediately after extraction.
- Simplified `FolderSyncWorker` by removing legacy migration lookups and streamlining the reconciliation of local and remote metadata.
- Updated `FolderMigrationDialog` UI text to reflect that books are now read directly from folders without duplication.
- Fixed various indentation and formatting issues across several files.
* feat: rework Folder Sync architecture to separate Managed vs Linked books
- Introduced "Managed" (imported to app storage) vs "Linked" (SAF URI) book logic.
- Disabled Google Drive/Metadata synchronization for Folder-Linked books to respect privacy and storage.
- Updated deletion logic: Folder books are now marked as deleted in the DB to blacklist them from future auto-scans, while Managed books are permanently purged from local and cloud storage.
- Enhanced folder sync discoverability by adding a direct "Sync Folder" navigation button in Home screen.
- Implemented reactive pager navigation in MainScreen and LibraryScreen via LaunchedEffect to allow programmatic tab switching from the ViewModel.
* Implemented a local folder synchronization system to track and update book metadata across devices.
Key changes:
- Added `FolderBookMetadata` and `LocalSyncUtils` for serializing and managing metadata files in a `.episteme` directory.
- Implemented bidirectional sync in `FolderSyncWorker` to reconcile local database state with folder-based metadata using timestamps and Syncthing conflict resolution.
- Updated `MainViewModel` to trigger folder metadata sync when closing a book and verify for remote updates upon opening.
- Enhanced folder management with manual scan support via `WorkManager` and automatic cleanup of database entries when a folder is disconnected.
- Added `RecentFileDao` methods to support bulk deletion and prefix-based file lookups.
* Removed API 34 restriction for chapter processing and updated local folder sync directory name
* Increased TTS timeouts, added edge-to-edge support in MainScreen, and improved TtsChunk mapping safety
* Improved folder synchronization and metadata management.
- Added metadata-only sync option and triggered it on app start.
- Implemented hidden metadata filenames (prefixed with `.`) to reduce file clutter.
- Added automatic creation of `.nomedia` files in the sync directory.
- Enhanced sync conflict resolution by picking the latest metadata and cleaning up obsolete or orphaned files.
- Added "Sync Metadata" button to the Library screen.
- Updated UI labels for local folder sync to clarify Google Drive integration.
- Refactored `FolderSyncWorker` to support targeted metadata-only synchronization.
* Implement folder sync migration and refactoring
- Added a migration dialog to inform users about the folder sync refactor, where books are now read directly from external storage.
- Updated `MainViewModel` to handle migration state and trigger a full scan upon completion or dismissal of the dialog.
- Modified `FolderSyncWorker` to support legacy book matching during migration, updating file URIs and cleaning up internal app storage for migrated books.
- Improved synchronization logic between local and remote metadata, including cleanup of orphaned metadata files.
- Refined `RecentFileItem` updates during sync to preserve progress and bookmarks based on last modified timestamps.
* Implemented pull-to-refresh for library sync and enhanced folder file deletion.
- Added `isRefreshing` state to `MainViewModel` and integrated `PullToRefreshBox` in `HomeScreen`.
- Implemented `refreshLibrary` to trigger cloud and folder metadata synchronization.
- Updated deletion logic to physically remove files and metadata from synced local folders.
- Added a warning to the delete confirmation dialog when removing folder-synced items.
- Improved folder sync reliability by performing lazy cleanup of missing files during interaction and sync.
- Fixed a bug where sync loading indicators would not retract on failure or cancellation.
* Improved bookmark navigation and scroll synchronization in EPUB reader
- Refined bookmark navigation logic for vertical scroll mode to handle chunk injection more reliably.
- Added `isNavigatingToBookmark` state to show a loading overlay during long jumps.
- Implemented `onScrollFinished` callback in `CfiJsBridge` to synchronize UI state with WebView scroll completion.
- Updated `ChapterWebView` to use `rememberUpdatedState` for JavaScript bridge callbacks to ensure data consistency.
- Improved `getCurrentCfi` and `scrollToCfi` in `epub_reader.js` with better visibility probing and retry logic for detached nodes.
* Implemented background metadata extraction for folder sync.
Key changes:
- Added `MetadataExtractionWorker` to handle heavy metadata and cover extraction for files in the background.
- Refactored `FolderSyncWorker` to perform fast file discovery using placeholders, enqueuing the metadata worker upon completion.
- Added `getFolderBooksWithoutCovers` query to `RecentFileDao`.
- Updated UI components (`EmptyState`, `MainViewModel`) to improve user feedback during sync and provide clear setup actions.
- Enhanced `EmptyState` composable to support secondary actions and custom button text.
* Updated Library Screen UI
docs: Revamp README and add APK naming convention
This commit introduces a complete overhaul of the `README.md` to improve project presentation. Key changes include:
* Adds a new header with the app icon and a Google Play badge.
* Updates the feature graphic and includes a note distinguishing the OSS version from the Play Store version.
* Refines the "Open Source Libraries" section to be more structured.
* Moves the main preview image into the `docs` directory.
Additionally, the `app/build.gradle.kts` file is updated to configure a standardized naming convention for output APK files, including flavor, version, and build type.
* refactor copyright headers and fix README icon alignment
This commit introduces two main changes across the codebase:
The `spotless/copyright.kt` template have been updated for consistency:
* The author name is simplified from "Episteme Authors" to "Episteme".
* The contact email prefix is shortened from "Electronic mail:" to "mail:".
Second, the `README.md` file is adjusted to correct the vertical alignment of the app icon with the project title.