Skip to content

ClearPDF 2.0.0: editors, optional Office engine, liquid glass everywhere - #17

Merged
Chethan616 merged 57 commits into
mainfrom
feat/editor-overhaul
Sep 26, 2026
Merged

Chethan616 merged 57 commits into
mainfrom
feat/editor-overhaul

Conversation

@Chethan616

Copy link
Copy Markdown
Owner

ClearPDF 2.0.0 — editors, optional Office engine, liquid-glass everywhere

Editors

  • Spreadsheet editor (xlsx): real cell styling (fills, fonts, borders, alignment, merges, frozen panes, column widths, theme colours with tint), sticky headers, sheet tabs, formula bar, glass formatting toolbar + colour picker, data-validation dropdowns, insert/delete rows & columns, undo/redo, save/save-as that patches only changed parts of the .xlsx. Styled PDF export.
  • Image editor: crop (ratios, straighten, flip, perspective, shape masks), 13 adjustments, 22 filters, drawing (brushes, shapes, arrows, blur/pixelate, fill), text, background removal, watermark, resize, format, EXIF — non-destructive with undo/redo. Adapted from ImageToolbox (Apache-2.0).
  • PDF text selection rebuilt: long-press word selection, native handles, magnifier, character-level drag across lines/columns/pages, edge autoscroll, liquid-glass toolbar that morphs into its overflow and colour row.

Optional Office engine (powered by LibreOffice)

  • Two flavors: play (Play Feature Delivery, on-demand module) and foss (in-app download, pinned + SHA-256 verified).
  • Runs in an isolated :office process; silently falls back to the built-in renderers.
  • Proper fontconfig setup so documents use the bundled Office-metric fonts (Carlito, Caladea, Liberation).
  • The viewer shows when a file was rendered by the engine.

Design system

  • New glass primitives: segmented control, colour picker, dialog, bottom sheet, progress bar, tool dock; squash-and-stretch thumbs; upstream backdrop fixes hand-ported.
  • Unified liquid-glass "Save changes?" card on every screen that can lose edits (PDF/Office viewer, xlsx, image editor, fill form, page organizer).
  • Vivid tinted buttons with per-tool accent colours; remaining solid dialogs/cards converted to glass.
  • Recents long-press menu rebuilt as a glass context menu that grows out of the pressed row.
  • Onboarding: new "Edit, not just view" page, per-page CTA colours. Default theme: Light, no wallpaper.

Fixes & performance

  • Release crash on launch (R8 stripped WorkManager's Room constructor).
  • xlsx viewer: janky frames 57% → 1% idle (grid isolated from the sensor-driven glass highlight); search debounced off the main thread; tabs no longer jump above the keyboard.
  • assembleRelease works with the dynamic feature module (module only joins bundle builds).

Build notes

  • Tasks are now per flavor: assembleFossRelease, assemblePlayRelease, bundlePlayRelease.
  • Not verified on device: the PPTX editor is not included (deliberately out of scope).

🤖 Generated with Claude Code

https://claude.ai/code/session_0171nPjdHicUWe7QHfjUHJae

Chethan616 and others added 30 commits September 6, 2026 19:18
Text selection:
- The handle-drag gesture's pointerInput was keyed on selectedOcrRanges
  — the exact value the gesture itself mutates on every move
  (onSelectOcrRange inside updateRange()). The instant a drag moved
  past touch slop, that update fired, Compose saw the key change, and
  cancelled + restarted the gesture coroutine mid-drag. The restarted
  awaitEachGesture then waited on a fresh touch-down that never came
  (the same finger was still down), so a handle drag died after the
  first movement regardless of direction. Fixed by reading the
  selection via rememberUpdatedState instead of keying on it.
- Replaced the symmetric "balloon on a flat neck" handle shape with
  the actual Android/Chrome/Google Docs construction: a circle with
  one sharp corner notched out exactly at the anchor point, asymmetric
  per side (each handle's bulge leans into the selection it bounds).
  Verified geometrically (numeric assertions + rendered PNG previews)
  before implementing in Kotlin.
- The highlight band between the handles is now a fully-rounded
  capsule (radius = half its own height) instead of a flat rectangle
  with a 2-5px corner clamp, so it reads as one selection with the
  handles rather than two balloons stuck onto a separate bar.

Onboarding page 1:
- The fanned stack of format-sheets behind the assembled book sat at
  a permanent 0.20/0.34 fill alpha once landed (only the last-landing
  sheet ever fades, as the book takes over) — pale enough on the light
  background to read as dull/grey. Raised to 0.75 card / full-opacity
  lines, keeping a real contrast gap between the two so the "document
  lines" still read against the card instead of both washing into one
  flat block.
… drop VM selection state

Co-Authored-By: Claude Opus 5.5 <[email protected]>
GlassSegmentedControl, GlassColorPicker, GlassDialog (+GlassDialogAction),
GlassBottomSheet, GlassProgressBar, GlassToolbar/GlassToolButton, and the
LiquidStretch velocity squash-and-stretch helper.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0171nPjdHicUWe7QHfjUHJae
…rners crop

Ports lib/cropper (minus widgets), lib/gesture, lib/image and the free-corners
perspective cropper from ImageToolbox (Apache-2.0). OpenCV warpPerspective is
replaced with Matrix.setPolyToPoly; croppers now emit normalised geometry for a
non-destructive op stack. Adds GPUImage (T8RIN fork), exifinterface and ML Kit
subject segmentation (minSdk override, gated at runtime).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…, drop dead KMP trees

- DrawBackdropModifier/LayerBackdropModifier.update() clear the previous
  backdrop's layerCoordinates when the backdrop instance changes (upstream fix).
- effects: runtimeShaderEffect(key, agsl, uniformShaderName, block), API 33+.
- Remove uncompiled commonMain/androidMain/skikoMain copies (not in any source set).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0171nPjdHicUWe7QHfjUHJae
LiquidToggle stacked a clickable on top of DampedDragAnimation, whose
onDragStopped already handles taps, so a tap toggled twice. The drag
modifier now covers the whole switch (tap anywhere toggles once) and
accessibility gets a semantic onClick + toggleableState instead.

Toggle and slider thumbs use Modifier.liquidStretch (LiquidTracker-style
velocity squash-and-stretch) in place of the ad-hoc velocity scale.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0171nPjdHicUWe7QHfjUHJae
…lens on panels

- Modifier.progressiveBlurEdge (catalog ProgressiveBlurContent, via the new
  runtimeShaderEffect; tint-gradient fallback below API 33).
- rememberAdaptiveGlassContentColor(backdrop) (catalog AdaptiveLuminanceGlassContent).
- liquidGlassPanel and LiquidGlassCard lenses use chromaticAberration.
- THIRD_PARTY_NOTICES: AndroidLiquidGlassView (MIT) for LiquidStretch.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0171nPjdHicUWe7QHfjUHJae
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ark, bg removal, IO

Non-destructive EditOp model with normalised geometry; colour-matrix + GPUImage
adjustments and 22 presets; stroke renderer (pen/highlighter/neon/eraser/blur/
pixelate, shapes, arrows, flood fill, spray) ported from ImageToolbox draw;
text and watermark overlays; ML Kit subject-segmentation behind BackgroundRemover;
EXIF-aware decode, metadata policy and gallery export.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The play flavor ships the optional Office engine (powered by LibreOffice) as an
on-demand dynamic feature. Its binaries are fetched, size/SHA-256 verified and
unpacked at build time only when a Play bundle is built, so normal builds need
no network.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
… glass toolbar; remove Select Text mode

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…n selection is off-screen, tighter word extension

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
UniversalDocumentConverter now prints .xlsx with the viewer's painter
(fills, fonts, borders, merges, alignment), falling back to the table reflow.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ice, installers

- org.libreoffice.kit: original Kotlin binding matching the native JNI contract
- OfficeEngineStore: versioned no-backup layout, atomic commit, old version removed
  only after success; relocation of the bundle's hard-coded bootstrap paths
- OfficeEngineService in android:process=":office" with idle process kill
- OfficeEngineClient: timeout, cancellation, binder-death fallback, result cache,
  password support via LOK document-password callback
- foss: WorkManager foreground dataSync downloader with Range resume, streaming
  SHA-256 against the pinned manifest, zip-slip-safe tar.xz extraction
- play: SplitInstallManager installer for :office_engine (progress, confirmation,
  cancel, deferredUninstall)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Op-stack ViewModel with snapshot undo/redo, live slider sessions, per-op preview
cache (EditPipeline), filter thumbnails and full-resolution export with progress.
Screen: canvas stage with live stroke/text/mask previews, ported croppers for
rect/shape/perspective crop, glass context panel + GlassToolbar dock
(Crop, Adjust, Filters, Draw, Text, More), GlassBottomSheet for export/
watermark/resize/metadata/colour, GlassDialog for discarding edits.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…network

UniversalDocumentConverter.convertToPdf tries the optional Office engine when it is
installed and enabled, falling back silently to the built-in renderers.
DocxWebRenderer and HtmlToPdfConverter.convertHtml now block network loads and answer
non-asset/data/blob requests locally with a 403, so they stay offline in the foss
flavor that holds INTERNET. Safe Browsing and WebView metrics are opted out.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Liquid-glass Settings section: Not installed / downloading (GlassProgressBar + Cancel) /
installing / Play approval / installed (size, version, Update, Delete via GlassDialog),
the "Use for Office files" LiquidToggle and a LibreOffice licences link. Hidden on
unsupported ABIs. LibreOffice credited in open-source credits.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Chethan616 and others added 27 commits September 26, 2026 14:04
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ttribution

The T8RIN 8.x GPUImage fork requires compileSdk 37 + desugaring and pulls
androidx.core 1.19; upstream 2.1.0 has the same filters with no transitive deps.
Credits added to NOTICE, THIRD_PARTY_NOTICES.md and Settings > Licenses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
# Conflicts:
#	app/src/main/res/values/strings.xml
# Conflicts:
#	app/build.gradle.kts
#	app/src/main/res/values/strings.xml
# Conflicts:
#	THIRD_PARTY_NOTICES.md
#	app/build.gradle.kts
#	app/src/main/AndroidManifest.xml
#	app/src/main/java/com/chethan616/clearpdf/ui/screen/SettingsScreen.kt
#	gradle/libs.versions.toml
… buttons, xlsx perf

- Office engine hint: text and close icon follow the page-luminance ink; Get it starts the
  install and opens Settings scrolled to the engine section so progress is visible
- LiquidButton tint renders vivid on any backdrop (the Get it look); per-tool accents
  replace hard-coded blue; Settings buttons get their own colours
- xlsx: Find no longer lifts the sheet tabs above the keyboard; tab strip and share capsule
  share one 52dp baseline (nav inset was applied twice); search debounced off main thread;
  fade-only exit (scaling re-ran every glass lens per frame)
- ShareMorphButton bob animation runs only while morphed (was an always-on frame clock)
- Drop chromatic aberration from full-size panels/cards (full-screen dispersion shader cost)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…le editing; onboarding editors page + per-page CTA colours; default Light theme without wallpaper

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…rflow menu and colour row

The capsule's size now springs (GlassMotion.morph) while pages cross-fade inside it; the overflow
menu grows out of the trailing more-button edge, the colour row out of the leading edge, and
collapsing pins the same edge so the morph reverses. Show/hide pops 0.9->1 around the point
nearest the selection. Menu rows and colour dots stagger in; items get press + liquid stretch.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…angesDialog; xlsx uses it

GlassDialogAction is now a vivid LiquidButton pill (accent / red / clear glass) that refracts
the dialog's backdrop. GlassScreenScaffold can take a hoisted ScreenBackdrop so siblings of the
scaffold (dialogs, sheets) sample wallpaper + live content. xlsx save tick is clear glass.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
PDF/Office viewer tracks unexported markups (snapshot vs last export) and routes back through
the card; Save opens the save sheet and leaves once the export succeeds. Image editor, Fill
form and Page organizer use the same card; each Save performs the screen's real save, then
exits. ToolScaffold gains an overlay slot that receives the live screen backdrop.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…essed row

Long-press now lifts the row (spring past rest) over a blur-free dim scrim with a hole punched
for the row, and one glass panel scales out of the row's edge with its items cascading in. Open
and Share are vivid LiquidButtons; Pin, Open with, Details, Remove from Recents and (when the
provider supports it) a two-tap Delete File are accent-coded rows. Placed below/above the row,
clamped clear of the status bar and tab bar; dismisses on outside tap, scroll or back.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
LiquidSaveDialog was a solid card in a platform Dialog window; it now reuses LiquidSaveSheet
and refracts the live screen (Create PDF, Images to PDF, Page organizer). The GitHub star
prompt is a GlassDialog over the app's content backdrop. Lighter save-sheet scrim.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tings dialog samples live screen

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…iases, cache dir); show when the engine rendered a file

The bundle ships etc/fonts/fonts.conf.txt, so fontconfig ran with no config and no cache and
never saw Carlito/Caladea/Liberation: output fell back to arbitrary system faces. Write a real
fonts.conf and export FONTCONFIG_FILE/PATH, XDG_CACHE_HOME, HOME before LOKit init. Bump the
conversion cache key so earlier renders are regenerated.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The grid sat on a full-screen liquidGlassPanel whose opaque fill hid all refraction while its
gravity-tracking highlight re-rendered a screen-sized blur+lens every sensor tick, so the viewer
drew continuously and the share morph stuttered. Solid card, same shape and shadow.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@Chethan616
Chethan616 merged commit a031969 into main Sep 26, 2026
1 of 2 checks passed
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.

1 participant