Pdf reflow rework (#51)
* 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.
This commit is contained in:
parent
acf282d4c7
commit
c61a264a65
11 changed files with 940 additions and 419 deletions
|
|
@ -337,11 +337,11 @@ fun EpubReaderScreen(
|
|||
val isReflowFile = uiState.selectedBookId?.endsWith("_reflow") == true
|
||||
val originalBookId = if (isReflowFile) uiState.selectedBookId!!.removeSuffix("_reflow") else null
|
||||
|
||||
val onOpenOriginal: (() -> Unit)? = if (originalBookId != null) {
|
||||
{
|
||||
val onOpenOriginal: ((Int) -> Unit)? = if (originalBookId != null) {
|
||||
{ currentChapter ->
|
||||
val originalItem = uiState.recentFiles.find { it.bookId == originalBookId }
|
||||
if (originalItem != null) {
|
||||
viewModel.onRecentFileClicked(originalItem)
|
||||
viewModel.switchToFileSeamlessly(originalItem, currentChapter)
|
||||
} else {
|
||||
viewModel.showBanner("Original PDF not found.", true)
|
||||
}
|
||||
|
|
@ -388,7 +388,7 @@ fun EpubReaderHost(
|
|||
onRenderModeChange: (RenderMode) -> Unit,
|
||||
customFonts: List<CustomFontEntity>,
|
||||
onImportFont: (Uri) -> Unit,
|
||||
onToggleReflow: (() -> Unit)? = null
|
||||
onToggleReflow: ((Int) -> Unit)? = null
|
||||
) {
|
||||
val view = LocalView.current
|
||||
val context = LocalContext.current
|
||||
|
|
@ -3114,7 +3114,16 @@ fun EpubReaderHost(
|
|||
onOpenTtsSettings = { showTtsSettingsSheet = true },
|
||||
onOpenDictionarySettings = { showDictionarySettingsSheet = true },
|
||||
onOpenDeviceVoiceSettings = { showDeviceVoiceSettingsSheet = true },
|
||||
onToggleReflow = onToggleReflow,
|
||||
onToggleReflow = if (onToggleReflow != null) {
|
||||
{
|
||||
val activeChapter = if (currentRenderMode == RenderMode.PAGINATED) {
|
||||
currentChapterInPaginatedMode ?: currentChapterIndex
|
||||
} else {
|
||||
currentChapterIndex
|
||||
}
|
||||
onToggleReflow(activeChapter)
|
||||
}
|
||||
} else null,
|
||||
)
|
||||
|
||||
val autoScrollPadding by androidx.compose.animation.core.animateDpAsState(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue