Conversation
Fork MenuBarExtraAccess locally and add staysOpen support — when true, the window no longer auto-closes on didResignKey (e.g. switching to a clipboard manager). Adds an isPinned toggle to AppState persisted via UserDefaults, wired to the new staysOpen binding. Adds a pin button (📌) to the header that lets users toggle this behaviour.
There was a problem hiding this comment.
PR Review: fix: keep window open when pinned
Overview
This PR solves a usability problem where the Ghostly window dismisses when switching to another app (e.g., clipboard manager). The approach of forking MenuBarExtraAccess and adding a staysOpen binding is reasonable since the upstream library doesn't support this behavior.
Issues to Address
1. Missing Unit Tests
Per CLAUDE.md: "Nothing ships without automated tests. Write unit tests for all logic/model changes."
The isPinned property in AppState needs tests similar to the existing isMenuPresented tests. At minimum:
- Initial state test (reads from UserDefaults)
- Toggle test
- UserDefaults persistence test (verify
didSetwrites to UserDefaults)
2. Remove Unused Code File
LocalPackages/MenuBarExtraAccess/Sources/MenuBarExtraAccess/Unused/Unused Code.swift contains 54 lines of entirely commented-out code. This should be deleted — per CLAUDE.md, avoid backwards-compatibility hacks like keeping removed code as comments.
Looks Good
- The
staysOpenlogic indidResignKeyis well-implemented — correctly checkswindow.isVisibleto distinguish between "lost focus" vs "explicitly closed" - Pin button UI uses Catppuccin tokens (
Color.catLavender,Color.catOverlay) consistently HeaderViewsignature change is backwards-compatible via the computedsettingsManagerproperty- License attribution to original author (Steffan Andrews, MIT) is preserved
Minor Note
Consider documenting in the PR body (or a code comment) that this is a fork of orchetect/MenuBarExtraAccess v1.2.2 for future maintainability context.
Summary
Fixes Ghostly-9k3 — the window was dismissing when switching to a clipboard manager (or any other app) because
MenuBarExtraAccesscloses the window whenever it loses key status.MenuBarExtraAccesslocally (LocalPackages/MenuBarExtraAccess) and added astaysOpen: Binding<Bool>parameter tomenuBarExtraAccess(). WhenstaysOpenistrue, thedidResignKeyhandler skipswindow.close()so the window stays visible. Explicit dismissal (clicking the status item icon, Escape key) still works correctly.isPinned: BooltoAppState(stored property, persisted to UserDefaults).staysOpen: $appState.isPinnedinGhostlyApp.Test plan