Skip to content

Dev#3

Merged
dqez merged 5 commits intomainfrom
dev
Feb 2, 2026
Merged

Dev#3
dqez merged 5 commits intomainfrom
dev

Conversation

@dqez
Copy link
Owner

@dqez dqez commented Feb 2, 2026

No description provided.

Copilot AI review requested due to automatic review settings February 2, 2026 11:30
@dqez dqez merged commit e47a937 into main Feb 2, 2026
5 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the app’s viewing experience by enhancing PDF zoom behavior, adding in-document search for Office WebView rendering, improving Office parsers to include embedded images (and DOCX page-break markers), and redesigning the home screen UI.

Changes:

  • Move PDF pinch-to-zoom from per-page to a global zoom/pan applied to the page list.
  • Add a search UI for Office documents and plumb access to the underlying WebView.
  • Extract and embed images into generated HTML for DOCX/XLSX; refresh home screen visuals and README docs.

Reviewed changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
img.png Adds/updates an image asset used by the project.
app/src/main/java/com/zeq/simple/reader/ui/screens/PdfViewerScreen.kt Introduces global zoom/pan gestures applied to the PDF LazyColumn.
app/src/main/java/com/zeq/simple/reader/ui/screens/OfficeViewerScreen.kt Adds search UI and WebView reference wiring; introduces (currently unused) image viewer code.
app/src/main/java/com/zeq/simple/reader/ui/screens/HomeScreen.kt Redesigns the home screen with animations, quick actions, and footer link.
app/src/main/java/com/zeq/simple/reader/parser/XlsxParser.kt Extracts and embeds XLSX sheet images as base64 HTML and adds related CSS.
app/src/main/java/com/zeq/simple/reader/parser/DocxParser.kt Extracts embedded DOCX images as base64 HTML and adds page-break markers/styling.
README.md Documents the modernized design/animations.
README_VI.md Vietnamese README updates to reflect the redesigned UI/animations.
Comments suppressed due to low confidence (1)

app/src/main/java/com/zeq/simple/reader/ui/screens/OfficeViewerScreen.kt:288

  • With the new search UI, recompositions will happen frequently (e.g., on every keystroke). Because AndroidView’s update block always calls loadDataWithBaseURL, the WebView will reload the entire document repeatedly, resetting scroll position and search matches. Gate the load so it only runs when htmlContent actually changes (e.g., compare against a remembered last-loaded value).
                // Notify that WebView is created
                onWebViewCreated(this)
            }
        },
        update = { webView ->
            // Load HTML content as data URI (no file access needed)
            webView.loadDataWithBaseURL(
                null, // No base URL
                htmlContent,
                "text/html",
                "UTF-8",

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +369 to +382
/**
* Performs text search in WebView using JavaScript.
* Highlights all matches with yellow background.
*/
private fun performSearch(webView: WebView, query: String) {
if (query.isEmpty()) {
clearSearch(webView)
return
}

// Use WebView's built-in find functionality (API level 16+)
@Suppress("DEPRECATION")
webView.findAllAsync(query)
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The KDoc for performSearch says it uses JavaScript and “highlights all matches with yellow background”, but the implementation uses WebView’s built-in findAllAsync, which doesn’t apply custom highlight styling. Update the comment to match the actual behavior (or implement the described JS-based highlighting).

Copilot uses AI. Check for mistakes.
.padding(24.dp)
.scale(scale),
horizontalAlignment = Alignment.CenterHorizontally,
// verticalArrangement = Arrangement.Center
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the stray commented-out verticalArrangement line; leaving commented code in production UI code makes it harder to maintain and review future layout changes.

Suggested change
// verticalArrangement = Arrangement.Center

Copilot uses AI. Check for mistakes.
Text("💡")
Spacer(modifier = Modifier.width(12.dp))
Text(
text = "Tip: You can widely open documents directly from your file manager.",
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI copy issue: “Tip: You can widely open documents directly from your file manager.” is ungrammatical and may confuse users. Consider rephrasing it (e.g., “Tip: You can also open documents directly from your file manager.”).

Suggested change
text = "Tip: You can widely open documents directly from your file manager.",
text = "Tip: You can also open documents directly from your file manager.",

Copilot uses AI. Check for mistakes.
Comment on lines 301 to 309
@Composable
private fun FormatChip(
fun QuickActionCard(
emoji: String,
label: String,
color: Color,
modifier: Modifier = Modifier
textColor: Color,
modifier: Modifier = Modifier,
onClick: () -> Unit
) {
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QuickActionCard is declared as a public top-level composable, but it’s only used inside HomeScreen.kt. Making it public expands the module’s API surface unnecessarily; mark it private (or move it to a shared UI component module/package if it’s intended for reuse).

Copilot uses AI. Check for mistakes.
Comment on lines +137 to +148
// Extract and display images from the sheet
val sheetImages = extractImagesFromSheet(sheet)
if (sheetImages.isNotEmpty()) {
htmlBuilder.append("<div class=\"sheet-images\">\n")
htmlBuilder.append("<h3>📎 Images in this sheet (${sheetImages.size})</h3>\n")
htmlBuilder.append("<div class=\"image-grid\">\n")
sheetImages.forEach { imageHtml ->
htmlBuilder.append(imageHtml)
}
htmlBuilder.append("</div>\n")
htmlBuilder.append("</div>\n")
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Embedding every extracted image as base64 directly into the generated HTML can massively increase memory usage (base64 expansion + very large HTML strings) and may cause OOMs or WebView load failures on sheets with large/many images. Consider adding limits (max image count / max total bytes), downscaling images, or providing an option to skip images.

Copilot uses AI. Check for mistakes.
Comment on lines +177 to 191
Box(
modifier = modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTransformGestures { _, pan, zoom, _ ->
scale = (scale * zoom).coerceIn(1f, 3f)
if (scale > 1f) {
offsetX += pan.x
offsetY += pan.y
} else {
offsetX = 0f
offsetY = 0f
}
}
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parent pointerInput { detectTransformGestures(...) } will consume pointer changes and can prevent LazyColumn from receiving drag events, breaking normal one-finger scrolling. Consider using transformable with proper nested-scroll interop, or only handling gestures when 2+ pointers are down so single-finger drags still scroll the list.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +123
// is DocumentState.ImageLoaded -> {
// Column {
// Text(
// text = s.fileName,
// maxLines = 1,
// overflow = TextOverflow.Ellipsis,
// style = MaterialTheme.typography.titleMedium
// )
// Text(
// text = s.mimeType ?: "Image File",
// style = MaterialTheme.typography.bodySmall,
// color = MaterialTheme.colorScheme.onSurfaceVariant
// )
// }
// }
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are large commented-out DocumentState.ImageLoaded blocks left in the screen. If image viewing isn’t supported yet, consider removing these commented sections (or fully wiring the state and UI) to keep the file maintainable.

Suggested change
// is DocumentState.ImageLoaded -> {
// Column {
// Text(
// text = s.fileName,
// maxLines = 1,
// overflow = TextOverflow.Ellipsis,
// style = MaterialTheme.typography.titleMedium
// )
// Text(
// text = s.mimeType ?: "Image File",
// style = MaterialTheme.typography.bodySmall,
// color = MaterialTheme.colorScheme.onSurfaceVariant
// )
// }
// }
is DocumentState.ImageLoaded -> {
Column {
Text(
text = s.fileName,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleMedium
)
Text(
text = s.mimeType ?: "Image File",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +328 to +337
// Get dimensions if available
val width = picture.width
val height = picture.depth

val dimensionAttr = if (width > 0 && height > 0) {
" style=\"max-width: 100%; width: ${width}px; height: auto;\""
} else {
""
}

Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XWPFPicture.width/depth are not pixel values in Apache POI (they’re typically document units such as EMUs). Using them directly as px in inline CSS can make images render at absurd sizes. Prefer relying on CSS max-width:100% only, or convert POI units to pixels via POI’s Units helpers before emitting a width: style.

Suggested change
// Get dimensions if available
val width = picture.width
val height = picture.depth
val dimensionAttr = if (width > 0 && height > 0) {
" style=\"max-width: 100%; width: ${width}px; height: auto;\""
} else {
""
}
// Use responsive styling without assuming POI dimensions are pixels
val dimensionAttr = " style=\"max-width: 100%; height: auto;\""

Copilot uses AI. Check for mistakes.
Comment on lines +311 to +316
val pictureData = picture.pictureData ?: return null
val imageBytes = pictureData.data ?: return null

// Convert to base64
val base64Image = Base64.encodeToString(imageBytes, Base64.NO_WRAP)

Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DOCX images are embedded as base64 data URIs, which can dramatically increase the resulting HTML size and memory usage for documents with large/many images. Consider applying size/count limits or downscaling before encoding to reduce the risk of OOM and improve load time in WebView.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants