Skip to content

feat: macos 27 适配 - #156

Merged
wflixu merged 3 commits into
mainfrom
dev
Sep 16, 2026
Merged

wflixu merged 3 commits into
mainfrom
dev

Conversation

@wflixu

@wflixu wflixu commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Summary

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 📝 Documentation update
  • ♻️ Refactoring
  • ⚡ Performance improvement
  • 🔧 Build/CI change
  • 🧪 Test addition/update

Related Issue

Screenshots

Before After

Testing

Manual Testing

  • App launches and appears in menu bar
  • Right-click menu works correctly in Finder
  • Dark mode looks correct
  • Settings persist across restarts
  • FinderSync extension loads properly

Build Verification

# Paste the output of:
xcodebuild -project RClick.xcodeproj -scheme RClick -destination 'platform=macOS'

Checklist

  • My code follows the project's Swift 6.2 conventions (see CONTRIBUTING.md)
  • All UI is SwiftUI (no AppKit UI components)
  • I have tested on macOS 15.6+
  • I have tested with both light and dark mode
  • I have updated documentation if needed
  • My branch is up-to-date with dev

Additional Notes

wflixu and others added 3 commits September 16, 2026 22:08
RClick quit the instant it launched on macOS 27, leaving nothing behind but a
SIGTRAP crash report. The stack ended in SharedDataManager.sharedModelContainer
and the log held only _assertionFailure; the real reason — which file, and why
it would not open — died with the process.

The container was a static lazy var whose do/catch ended in fatalError, so every
possible failure collapsed into the same silent trap. The failure seen in the
wild is a build that is not properly code-signed: with no provisioning profile
backing com.apple.security.application-groups, the sandbox never puts the App
Group container in the process profile, and SQLite refuses the store with
NSSQLiteErrorDomain=23. The crash reports carry the fingerprint
(codeSigningTeamID ""), and reproducing it is just CODE_SIGNING_ALLOWED=NO.

So both fatalErrors are gone:

- SharedDataManager grows bootstrap() and a throwing makeSharedModelContainer(),
  plus a SharedStoreError that at least separates "no App Group container" from
  "container found, store unreadable"
- StartupFailure logs the cause at .fault with privacy .public so it actually
  reaches the log store, shows it in an alert, then exits cleanly. It returns
  Never, which is what lets the call sites stay non-failable
- AppDelegate opens the store in init() before anything touches AppState.
  appState had to become lazy: a default-valued property initializer runs before
  the init body, which would have inverted exactly that order

Deliberately not done: falling back to a local or in-memory store. That would
leave the app looking healthy while the extension read a different database,
which is worse than refusing to start.

Also clears the five Xcode 27 warnings and bumps to 2.3.0, build 20260916001:

- four ImplicitStrongCapture in RClickApp, where the inner [weak self] captures
  were meaningless while the enclosing closure held self strongly
- NoUseUnstructuredThrowingTask in MenuBarView, where the discarded throw is a
  cancellation we do not want to honour anyway

Verified: Debug and Release both build warning-free under Xcode 27, the test
suite passes, and the unsigned build now shows the alert and exits cleanly with
no crash report instead of trapping.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Issue #155 reports two unrelated symptoms.

Sidebar icons. Every external disk and mounted disk image showed RClick's
icon. This had already been "fixed" once — 25b69e8 replaced random badge
identifiers with an explicit empty string and closed #128 — and it came
back. The empty string is not the fix. FinderSync draws badges from loose
<identifier>.png files in the extension's Resources, and the extension
ships none (only Assets.car and the .lproj directories), so every
setBadgeIdentifier call — empty string included — hands Finder an
identifier it cannot draw and it falls back to the extension's own icon.
RClick uses no badges, so requestBadgeIdentifier is now a no-op. Not
calling is what "no badge" means.

Authorization. A grant for "/" never matched anything, so a user who added
it was left with no working grant at all and got the NSOpenPanel on
whatever they touched. hasAccess built "/" + "/" = "//" and asked whether
the target starts with that; nothing does. Matching is now done on path
components, where "/" is just ["/"] — no special case needed, and it also
cannot leak a grant for /Users/lixu onto /Users/lixu2.

That second one may be the whole of a separate report where a folder had
to be re-authorized after every reboot. With the only broad grant dead,
nothing was ever really authorized, so every operation prompted — which is
also why no log ever showed a bookmark failing to resolve.

The destructive half of restoreBookmarks is deliberately untouched: it
still deletes a grant when the bookmark fails to resolve, which is how
eight grants were lost on 2026-09-13. That is a separate defect.

Co-Authored-By: Claude Code <noreply@anthropic.com>
b697cc3 turned requestBadgeIdentifier into a no-op and justified it with a
mechanism that is not true: the comment claimed an empty string still
triggers the icon overlay, and that not calling is what stops it.

That was measured and it is false. The running extension was loaded from a
binary with no setBadgeIdentifier call anywhere in it, and the volume icons
were unchanged.

So nothing here changes at runtime. The override stays empty, which remains
the right way to say "this extension has no badges" — it ships no badge
images at all, and FinderSync can only draw badges from loose <id>.png files
in the extension's Resources. What changes is the comment: it now records
that badges were blamed twice for this symptom (25b69e8 first, closing
#128) and that neither attempt fixed it, so the next person does not repeat
them, and it points at where the cause actually appears to be — the
extension putting every volume root into directoryURLs.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@wflixu
wflixu merged commit 91e9210 into main Sep 16, 2026
1 check 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