feat: implemented initial version of hiding feature#744
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new persisted preference that lets users hide Cotabby’s menu bar status item while keeping the app running, with a reopen “recovery” path that surfaces Settings when the user relaunches Cotabby without the icon visible.
Changes:
- Introduces
isMenuBarIconVisibleacross settings data/model/store and persists it toUserDefaults. - Conditionally inserts/removes the
MenuBarExtrascene via a scene-level@AppStorageprojection. - Implements reopen handling to open Settings when the app is reopened while the menu bar icon is hidden, plus updates/expands test coverage.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| Cotabby/App/Core/CotabbyApp.swift | Makes the menu bar scene optional via MenuBarExtra(isInserted:) driven by @AppStorage. |
| Cotabby/App/Core/AppDelegate.swift | Adds applicationShouldHandleReopen recovery behavior when the icon is hidden. |
| Cotabby/Models/SuggestionSettingsData.swift | Extends the durable settings payload with isMenuBarIconVisible. |
| Cotabby/Models/SuggestionSettingsModel.swift | Adds published state + setter that persists isMenuBarIconVisible. |
| Cotabby/Support/SuggestionSettingsStore.swift | Adds the new defaults key, load defaulting behavior, and save plumbing. |
| Cotabby/UI/Settings/Panes/AppearancePaneView.swift | Adds the Settings toggle and binding for menu bar icon visibility. |
| Cotabby/UI/Settings/SettingsIndex.swift | Adds a new searchable SettingsItem entry for the toggle. |
| CotabbyTests/SuggestionSettingsModelTests.swift | Extends model round-trip tests to include the new preference. |
| CotabbyTests/SuggestionSettingsStoreTests.swift | Adds default + round-trip persistence tests for the new preference. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Owner
|
@akramj13 fix copilot feedback.
|
… only Addresses Copilot review on FuJacob#744: the MenuBarExtra binding setter no longer writes the visibility preference twice. It now calls setMenuBarIconVisible only; the @AppStorage projection observes the same UserDefaults key, so the getter and scene re-evaluate from that single write and can't drift if model-side validation is added. The hasVisibleWindows reopen guard flagged by Greptile is already consulted in the current head, so no change was needed there.
Contributor
Author
|
This change also solves #705 |
Comment on lines
+159
to
+165
| guard !suggestionSettings.isMenuBarIconVisible else { | ||
| return true | ||
| } | ||
|
|
||
| guard !flag else { | ||
| return false | ||
| } |
Owner
- Open Settings on manual cold launch when menu bar icon is hidden - Keep login-item launches silent - Verify Settings window specifically during reopen recovery - Add 8 recovery-policy test cases - Validate cold-launch recovery flow end-to-end
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Contributor
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
Contributor
Author
FuJacob
approved these changes
Jun 28, 2026
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.
This pull request adds a new user preference to allow hiding Cotabby's menu bar icon while keeping the app running in the background. It introduces a toggle in Settings for controlling the visibility of the menu bar status item, ensures the app remains accessible by showing Settings when relaunched with the icon hidden, and persists this preference across launches. The implementation spans UI, model, persistence, and test updates.
Menu Bar Icon Visibility Preference:
isMenuBarIconVisibleproperty toSuggestionSettingsDataandSuggestionSettingsModel, with corresponding getter, setter, and persistence logic inSuggestionSettingsStore.CotabbyAppto conditionally insert theMenuBarExtrascene based on the new preference, using a SwiftUI binding that syncs with the settings model and persists changes.SettingsItemto support the new toggle, including title, icon, description, search terms, and categorization under the Appearance section.App Behavior and Recovery:
applicationShouldHandleReopeninAppDelegateto show Settings if the app is reopened while the menu bar icon is hidden, ensuring users can always access the app's UI.Testing and Persistence:
Solves #742
Greptile Summary
This PR introduces a user preference to hide Cotabby's menu bar status item while keeping the app running, with Settings as the recovery surface when the icon is hidden. The implementation is cleanly layered across model, store, UI, and AppDelegate, and includes a dedicated
MenuBarRecoveryPolicypure-policy type with a thorough test matrix.isMenuBarIconVisiblepreference propagates fromSuggestionSettingsData→SuggestionSettingsModel→SuggestionSettingsStoreand drives aMenuBarExtra(isInserted:)binding inCotabbyAppvia@AppStorage, so SwiftUI re-evaluates scene insertion exactly once per UserDefaults write without double-persisting the value.applicationShouldHandleReopen), with each decision delegated to the testableMenuBarRecoveryPolicyenum.⌘Qas a keyboard shortcut.Confidence Score: 5/5
Safe to merge — the changes are well-scoped, the recovery paths are fully tested, and no existing behaviour is altered for users who keep the icon visible.
All three layers of the feature (model/store, scene binding, and AppKit lifecycle) are internally consistent. The @AppStorage / settings-model split is the most unusual pattern in the PR, but the comment explains the intent and the data flow is correct: a single UserDefaults write drives both the @published model property and the SwiftUI scene re-evaluation without risk of divergence. The MenuBarRecoveryPolicy decision matrix is fully covered by unit tests, including the miniaturised-window and non-Settings-window edge cases.
No files require special attention.
Important Files Changed
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant User participant AppearancePaneView participant SuggestionSettingsModel participant UserDefaults participant CotabbyApp participant MenuBarExtra participant AppDelegate participant MenuBarRecoveryPolicy participant SettingsCoordinator User->>AppearancePaneView: Toggle Show Cotabby in Menu Bar OFF AppearancePaneView->>SuggestionSettingsModel: setMenuBarIconVisible(false) SuggestionSettingsModel->>UserDefaults: saveMenuBarIconVisible(false) UserDefaults-->>CotabbyApp: "@AppStorage update isMenuBarIconVisible = false" CotabbyApp-->>MenuBarExtra: "isInserted binding = false" MenuBarExtra-->>User: Status item removed User->>AppDelegate: Re-opens app (Finder/Dock) AppDelegate->>MenuBarRecoveryPolicy: shouldLetAppKitHandleReopen(...) MenuBarRecoveryPolicy-->>AppDelegate: false AppDelegate->>SettingsCoordinator: showSettings() SettingsCoordinator-->>User: Settings window shown as recovery surface%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant User participant AppearancePaneView participant SuggestionSettingsModel participant UserDefaults participant CotabbyApp participant MenuBarExtra participant AppDelegate participant MenuBarRecoveryPolicy participant SettingsCoordinator User->>AppearancePaneView: Toggle Show Cotabby in Menu Bar OFF AppearancePaneView->>SuggestionSettingsModel: setMenuBarIconVisible(false) SuggestionSettingsModel->>UserDefaults: saveMenuBarIconVisible(false) UserDefaults-->>CotabbyApp: "@AppStorage update isMenuBarIconVisible = false" CotabbyApp-->>MenuBarExtra: "isInserted binding = false" MenuBarExtra-->>User: Status item removed User->>AppDelegate: Re-opens app (Finder/Dock) AppDelegate->>MenuBarRecoveryPolicy: shouldLetAppKitHandleReopen(...) MenuBarRecoveryPolicy-->>AppDelegate: false AppDelegate->>SettingsCoordinator: showSettings() SettingsCoordinator-->>User: Settings window shown as recovery surfaceComments Outside Diff (1)
Cotabby/UI/Settings/Panes/AppearancePaneView.swift, line 50-57 (link)When
isMenuBarIconVisibleisfalsethe word-count badge has nowhere to render, yet the toggle stays enabled and its value is preserved. A user who hides the icon, notices the toggle is still "on," and tries to turn it off will have no visible effect — which reads as broken. Disabling the toggle (.disabled(!suggestionSettings.isMenuBarIconVisible)) when the icon is hidden would make the dependency explicit and avoid the confusion.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Reviews (10): Last reviewed commit: "fix: resolve menu bar settings conflicts..." | Re-trigger Greptile