feat: Finder integration (right-click compress + dock drop)#15
Merged
Conversation
Adds a headless compression path triggered by macOS's open-document event so users can right-click a PDF, choose "Open With → compress[pdf]", and get a native notification when the work is done — no main window, no in-app interaction needed. The flow always writes a `_compressed.pdf` sibling and never overwrites the original, even if the in-app Overwrite setting is enabled, because the Finder context has no preview/confirm step. Output folder and preset are still read from the user's saved settings, and a new "Finder right-click preset" control in the settings panel lets users choose Max/Balanced/Minimal as the default. - tauri.conf.json: declare PDF file association (role: Viewer); start the main window hidden so headless launches don't flash a UI - Cargo.toml: add tauri-plugin-single-instance and tokio (time) - compress.rs: extract compress_files_inner returning outcomes so the headless flow can tally success/failure for the notification - headless.rs (new): filter PDF paths, force Suffix naming, run compression, post a summary notification - lib.rs: install single-instance plugin, handle RunEvent::Opened, defer window-show 400ms so file-open launches stay headless - settings.rs: add default_preset field with serde default for migration - DetailPanel.svelte: new "Finder right-click preset" radios Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The settings block at the bottom of DetailPanel was reading as a SwiftUI System Settings form — three field headers, ten stacked radio rows, a long hint paragraph — which is exactly what the project's design context calls out as the thing to avoid. Replaces it with a Raycast-style preference layout: one horizontal row per setting, single-word label on the left, segmented control on the right. - Three settings collapse from ~10 rows to 3 - Real <input type="radio"> kept inside styled <label class="segment"> so keyboard nav and ARIA semantics stay intact - Conditional detail rows (folder picker, overwrite warning) appear indented under their parent setting, aligned to the control column - Section heading dropped; the subtle divider above is the separator - Long right-click hint replaced with a native title tooltip on the "Right-click" label - Folder path: bumped to accent blue so the selected value reads as meaningful, uses direction: rtl so long paths truncate from the start (you always see the leaf folder) - Choose button: bg-overlay + full border + accent hover, sits flush on the panel background instead of in a chip container Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Default preset segmented control showed the same three labels (Max/Balanced/Minimal) as the per-file Quality control above, creating a confusing collision when a user was looking at a selected file — two identical-looking selectors visible at once. Folds Default preset into a collapsed-by-default Advanced disclosure so the per-file Quality preset is the only preset selector visible during normal use. Output and Naming stay visible: they affect every compression (in-app and right-click), and Naming has the destructive overwrite warning that needs to be glanceable. - Custom Svelte disclosure with Svelte's slide transition, 180ms with cubicOut easing; respects prefers-reduced-motion - Hand-pathed SVG chevron rotates 90° on expand - aria-expanded + aria-controls; content conditionally rendered so screen readers don't announce the collapsed setting - Two new tests: drawer collapsed by default, click expands and reveals the radios Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ships an Automator Quick Action bundled inside the .app's Resources
and an in-app Install button in the Advanced drawer that copies it to
~/Library/Services/. Once installed, "Compress with compress[pdf]"
appears at the top level of Finder's right-click menu — no more
nesting under Open With.
The workflow runs `open -b com.pdfcompressor "$@"` so the same
RunEvent::Opened handler that powers Open With and Dock drops also
catches Quick Action invocations. Backend wiring is purely the
installer; the compression code path is unchanged.
- resources/Compress PDF.workflow/ — static Automator bundle with
NSServices restricted to Finder + PDFs (filename avoids brackets
because Tauri's bundle.resources glob reads them as a character
class; user-facing menu label is set inside the bundle's Info.plist)
- quick_action.rs — install/is_installed/uninstall commands plus a
recursive directory-copy helper that wipes the destination first so
re-installing replaces stale files
- DetailPanel Advanced drawer — new row with status text ("Not
installed" in tertiary, "Installed" in accent blue) and a button
that toggles between Install/Remove with busy state and toast
feedback. Re-reads state every time the drawer opens.
- README — new Finder integration section documenting all three
entry points: Open With, Quick Action, drop on Dock icon
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CI runs cargo clippy with -D warnings. The previous Finder integration work introduced two trivially-fixable lints: - compress.rs: hand-written `impl Default for Preset` is mechanically derivable — switch to `#[derive(Default)]` with `#[default]` on the Balanced variant. - headless.rs: a match arm with `(n, 0) if n == 1` is a redundant guard — collapse to `(1, 0)`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Minor bump for the Finder integration release: - right-click → Open With → compress[pdf] - top-level "Compress with compress[pdf]" Quick Action (install via the in-app Advanced drawer) - drop PDFs onto the Dock icon - segmented-control settings UI with an Advanced disclosure Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds three new ways to compress PDFs without opening the app's main window — all routed through a single headless code path:
/Applications, via TaurifileAssociationsand aRunEvent::Openedhandler. The PDF is compressed with the saved Output, Naming, and Default-preset settings; no window appears; a native notification reports the result.Compress PDF.workflow) bundled in Resources; the in-app Install button copies it to~/Library/Services/. The workflow shellsopen -b com.pdfcompressor "$@"so it routes back through the same Apple Event.The right-click flow always writes a
_compressed.pdfsibling regardless of the in-app Overwrite setting — Finder context has no preview/confirm step, so it refuses to destroy originals.Also refactored the settings UI: stacked radios collapsed into segmented controls, and a new Advanced disclosure houses the Default preset (so the per-file Quality preset and the headless default don't visually collide).
Commit summary
56c2aa5feat: Open With → compress[pdf] + headless compression + single-instance + RunEvent::Opened71192c0refactor: segmented-control settings layout (Raycast-style preference rows)e6de9bbrefactor: Default preset moved into Advanced drawer639fcecfeat: Quick Action bundle + in-app install/remove935226dfix(clippy): two trivially-derivable lints6add143chore: bump version to 1.5.0Test plan
cargo test— 62/62 pass (new tests inquick_action::tests,headless::tests,settings::tests)npm test— 99/99 pass (new tests for Advanced drawer + Quick Action row)cargo clippy -- -D warnings— cleancargo audit— exit 0 (existing warnings only, all pre-existing transitive Linux GTK deps not used on macOS)npm run check— cleanrelease.ymlafter tagging v1.5.0:🤖 Generated with Claude Code