Skip to content

fix(macos): convert the file a Finder alias points to - #551

Merged
KnifeLemon merged 2 commits into
KnifeLemon:mainfrom
mendax-iitm:fix/macos-finder-aliases
Oct 26, 2026
Merged

KnifeLemon merged 2 commits into
KnifeLemon:mainfrom
mendax-iitm:fix/macos-finder-aliases

Conversation

@mendax-iitm

Copy link
Copy Markdown
Contributor

What does this change?

Finder aliases dropped on the donut (or selected in Finder) now convert the file they point to, the way Windows already follows .lnk shortcuts (#159). Before, the alias file itself reached Filee and was reported as unsupported; IPlatformServices.ShortcutTarget noted that macOS aliases "aren't followed yet".

  • MacOSPlatformServices.ShortcutTarget → NativeMethods.AliasTarget, using CFURLCreateBookmarkDataFromFile + CFURLCreateByResolvingBookmarkData (CoreFoundation only, no Finder Automation permission needed).
  • Resolution passes kCFURLBookmarkResolutionWithoutUIMask | WithoutMountingMask, so a drag never waits on a dialog or a network volume. A broken alias, or a file that isn't an alias, returns null and stays as it is (same contract as Windows).
  • The resolved path is normalized to NFC: CoreFoundation returns the decomposed file system representation, which would otherwise not match dropped paths with Korean (or accented) names, so de-duplication in ResolveShortcuts would miss.
  • NativeMethods.CreateAlias writes real alias files for the tests (like ShellLinks.Create on Windows).

No UI strings, no new dependencies.

Type of change

  • Bug fix
  • New feature or improvement
  • New format or engine
  • Translation
  • Documentation
  • Build, CI or dependencies

How was it tested?

  • dotnet format --verify-no-changes
  • dotnet test — Filee.Platform.Tests (80 passed, 27 skipped for other OSes, including the 2 new MacOSAliasTests) and Filee.Core.Tests (602 passed) on macOS 27 arm64. The new tests mirror WindowsShortcutTests: file, folder, broken alias, non-alias, missing path, and an alias dropped together with its target.
  • Tried it in the app: not yet tried with a real drag in the GUI build.

Checklist

  • New UI strings are in all src/Filee.App/Assets/i18n/*.json files (none added)
  • New third-party code or binaries are listed in THIRD-PARTY-NOTICES.md (none)
  • The PR does one thing

Dropping a Finder alias on the donut, or picking one in Finder, sent the
alias file itself to Filee, which reported it as unsupported. Windows
already follows .lnk shortcuts (KnifeLemon#159); macOS now does the same through
CFURLCreateBookmarkDataFromFile / CFURLCreateByResolvingBookmarkData.

Resolution never shows UI or mounts a volume, so a drag never waits on a
server. A broken alias, or a file that isn't an alias, stays as it is.
The resolved path is NFC so it matches dropped paths ("보고서" names).

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the bug Something isn't working label Oct 24, 2026
@mendax-iitm

Copy link
Copy Markdown
Contributor Author

Hi @KnifeLemon, thanks for Filee!

This PR is small and self-contained (macOS only, no UI strings, tests mirror WindowsShortcutTests), so I hope it's easy to review. If it looks good, could you merge it? Happy to change anything you'd prefer done differently.

I've been comparing Filee on macOS with other Mac file utilities and would like to keep contributing. Below is what I'd propose, roughly in order. Could you tell me which of these you'd welcome, so I open an issue with a plan first for the bigger ones (as in #524) and don't send PRs you don't want?

macOS

  1. ✅ Follow Finder aliases (this PR)
  2. Drags from file managers other than Finder (macOS: QSpace Pro drags and Services don't deliver file URLs to Filee (donut gets no files) #160, QSpace)
  3. Look into the open macOS bugs: [MacOS] Donut Toolbar bug #251, 맥os 단축키 툴바가 작동하지 않는 것 같습니다 #135, macOS: DonutFlipTests.T5 sees no highlight on the sub-slice #533, CI: App tests on macOS Intel slow down as the run goes on #540
  4. Docs: Shortcuts.app recipes calling the filee CLI
  5. Notarized .dmg (MacOS flags the downloaded release as malware #265, [Feature Request] macOS 빌드 dmg 배포 및 설치/업데이트 방식 개선 #379): needs your Developer ID, so I can only help with the workflow side

Small wins from open issues
6. 4:5 crop ratio (#542)
7. Show what a preset accepts on hover (#548)
8. Metadata removal for PDFs (#362), PDF cropping (#475)

New features
9. Compress to a target size ("under 10 MB" for email/chat): video via two-pass bitrate from duration, images by searching quality, PDF by stepping compressor settings
10. Read QR codes from images and PDFs
11. Audio tools: trim silent ends, mono/stereo, audio → waveform video
12. Share actions: share sheet / AirDrop, copy paths
13. Keep C2PA Content Credentials through conversion (unless "Remove metadata" is on) and show an "AI-generated / edited with" badge on Home
14. Bigger interactive tools (design issue first): redaction for pictures/PDF/video, markup and signature, a floating shelf that collects files across drags

Thanks again!

@KnifeLemon KnifeLemon left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks @mendax-iitm, and welcome! This fills the gap IPlatformServices called out, using only CoreFoundation and no Automation permission. Resolving without UI or mounting is the right call for something a drag waits on, and the tests mirror WindowsShortcutTests closely. A few things before it goes in:

  1. Please try a real drag. The tests call ShortcutTarget and ResolveShortcuts directly. The point of the change is what arrives through Avalonia's drop (DraggedFiles.Local on the donut and the Home drop zone) plus RadialController.ShowForFiles for the Finder selection shortcut and the Services menu. Could you drag a file alias, a folder alias and a broken alias from Finder onto the donut, and use the selection shortcut on an alias, and say what you saw?
  2. NativeMethods.CreateAlias releases the error twice when CFURLCreateBookmarkData fails. Release(error) runs right after the call, and again in the if (data == 0) block on the same CFErrorRef, which crashes the test host instead of throwing the IOException. Release it once.
  3. Every dropped path is opened to look for a bookmark. Windows only reads files ending in .lnk. Here CFURLCreateBookmarkDataFromFile runs for every path, twice per drag (DragEnter, then Drop) and on the UI thread, so a drop of a few hundred photos (or files on a slow network share) pays for it before the donut reacts. Checking kCFURLIsAliasFileKey first with CFURLCopyResourcePropertyForKey (metadata only) and calling the bookmark APIs only when it's true would keep non-aliases free.
  4. An alias whose original is in the Trash. Bookmarks follow a moved file, so such an alias may resolve into ~/.Trash, and Filee would convert the trashed file and save the result inside the Trash, where nobody will find it. Could you check, and if so, treat a target inside a Trash folder (~/.Trash, /Volumes/*/.Trashes) as broken?

Once those are done it's ready to merge when CI is green.

@KnifeLemon

Copy link
Copy Markdown
Owner

Thanks for the list, and for offering to plan first. Here's where things stand:

First, though, the points in the review on this PR. Once those are in, it's ready to merge.

…irst, Trash targets broken

- CreateAlias released the CFErrorRef twice when CFURLCreateBookmarkData failed.
- Check kCFURLIsAliasFileKey (metadata only) before reading a bookmark, so
  ordinary dropped files never open on the UI thread.
- A bookmark follows its file into ~/.Trash or a volume's .Trashes; treat
  such a target as broken instead of converting into the Trash.
@mendax-iitm

Copy link
Copy Markdown
Contributor Author

Thanks for the careful review. All four points are addressed in 23b17d1:

  1. Real drag: On macOS, I dragged from Finder onto both the donut (Option-drag) and the Home drop zone:

    • a file alias (report alias → report.txt) offers the target's tools (txt);
    • a folder alias (photos alias) behaves like the folder itself (only "Compress into one archive");
    • a broken alias stays as itself (only the archive tool takes it).

    Nothing hung or crashed.

  2. Double release: CreateAlias now releases the CFErrorRef once. A new test checks that a missing target throws IOException instead of crashing the host.

  3. Metadata first: kCFURLIsAliasFileKey is now checked with CFURLCopyResourcePropertyForKey before any bookmark call, so ordinary dropped files are never opened.

  4. Trash: Confirmed. A trashed original resolved to ~/.Trash/<name> 17-59-10-764.txt. Targets in ~/.Trash or a volume's .Trashes are now treated as broken, with a test.

@KnifeLemon KnifeLemon left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks @mendax-iitm, 23b17d1 covers all four. The drag results are what we were after. The error is now released once, with a test for the missing-target case. Ordinary files stop at the kCFURLIsAliasFileKey check before any bookmark call, and a target in ~/.Trash or a volume's .Trashes counts as broken. The Finder selection shortcut goes through the same ResolveShortcuts as the drop, so a separate run there isn't needed. It can be merged once CI is green.

@KnifeLemon
KnifeLemon merged commit 4dec69e into KnifeLemon:main Oct 26, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants