Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
Extract NSStatusItem hacks
Browse files Browse the repository at this point in the history
  • Loading branch information
josh committed Apr 26, 2024
1 parent 2a64746 commit 4d98c6d
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 17 deletions.
4 changes: 4 additions & 0 deletions Aware.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
0347D59B2BAF8CB200C5741E /* NotificationCenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0347D59A2BAF8CB200C5741E /* NotificationCenterTests.swift */; };
0347D59D2BAF9A3F00C5741E /* SuspendingClock+Drift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0347D59C2BAF9A3F00C5741E /* SuspendingClock+Drift.swift */; };
0347D59F2BAFB97300C5741E /* BackgroundTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0347D59E2BAFB97300C5741E /* BackgroundTask.swift */; };
035820952BDB11880099E707 /* View+NSStatusItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035820942BDB11880099E707 /* View+NSStatusItem.swift */; platformFilters = (macos, ); };
036569CE2B9A40C8003D3DCA /* MenuBarTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036569CD2B9A40C8003D3DCA /* MenuBarTimelineView.swift */; platformFilters = (macos, ); };
036DA9B52B7AF52E0066B4B2 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036DA9B42B7AF52E0066B4B2 /* App.swift */; };
036EBD1B1C1408C200121D0B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 036EBD1A1C1408C200121D0B /* Assets.xcassets */; };
Expand Down Expand Up @@ -68,6 +69,7 @@
0347D59A2BAF8CB200C5741E /* NotificationCenterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCenterTests.swift; sourceTree = "<group>"; };
0347D59C2BAF9A3F00C5741E /* SuspendingClock+Drift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SuspendingClock+Drift.swift"; sourceTree = "<group>"; };
0347D59E2BAFB97300C5741E /* BackgroundTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundTask.swift; sourceTree = "<group>"; };
035820942BDB11880099E707 /* View+NSStatusItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+NSStatusItem.swift"; sourceTree = "<group>"; };
036569CD2B9A40C8003D3DCA /* MenuBarTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarTimelineView.swift; sourceTree = "<group>"; };
036DA9B42B7AF52E0066B4B2 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
036EBD151C1408C200121D0B /* Aware.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Aware.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -164,6 +166,7 @@
036569CD2B9A40C8003D3DCA /* MenuBarTimelineView.swift */,
0341CB692B9C2CC800CC0C96 /* NSEvent+AsyncStream.swift */,
032E60AD2BD74BEF008BB2B4 /* SettingsView.swift */,
035820942BDB11880099E707 /* View+NSStatusItem.swift */,
);
path = macOS;
sourceTree = "<group>";
Expand Down Expand Up @@ -322,6 +325,7 @@
036569CE2B9A40C8003D3DCA /* MenuBarTimelineView.swift in Sources */,
0341CB6A2B9C2CC800CC0C96 /* NSEvent+AsyncStream.swift in Sources */,
032E60AE2BD74BEF008BB2B4 /* SettingsView.swift in Sources */,
035820952BDB11880099E707 /* View+NSStatusItem.swift in Sources */,
03409BC42B897F7C00EF8EE9 /* ActivityMonitor.swift in Sources */,
0394D1772B84630E00FE7020 /* TimerTextView.swift in Sources */,
0394D1752B845FB400FE7020 /* TimerView.swift in Sources */,
Expand Down
21 changes: 4 additions & 17 deletions Aware/macOS/MenuBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct MenuBar: Scene {

struct TimerMenuBarLabel: View {
@State private var timerState = TimerState()
@State private var statusBarButton: NSStatusBarButton?
@State private var statusItem: NSStatusItem?

// User configurable idle time in seconds (defaults to 2 minutes)
@AppStorage("userIdleSeconds") private var userIdleSeconds: Int = 120
Expand Down Expand Up @@ -65,27 +65,14 @@ struct TimerMenuBarLabel: View {
}
logger.log("Finished ActivityMonitor updates task: \(timerState, privacy: .public)")
}
.onAppear {
statusBarButton = findStatusBarItem()?.button
}
.bindStatusItem($statusItem)
.onChange(of: timerState.isIdle) { _, isIdle in
assert(statusBarButton != nil)
statusBarButton?.appearsDisabled = isIdle
assert(statusItem?.button != nil, "missing statusItem button")
statusItem?.button?.appearsDisabled = isIdle
}
}
}

// Hack to get underlying NSStatusItem for MenuBarExtra
// https://github.com/orchetect/MenuBarExtraAccess/blob/main/Sources/MenuBarExtraAccess/MenuBarExtraUtils.swift
@MainActor
private func findStatusBarItem() -> NSStatusItem? {
for window in NSApp.windows where window.className == "NSStatusBarWindow" {
return window.value(forKey: "statusItem") as? NSStatusItem
}
assertionFailure("couldn't find NSStatusBarWindow")
return nil
}

struct MenuBarContentView: View {
var body: some View {
SettingsLink()
Expand Down
30 changes: 30 additions & 0 deletions Aware/macOS/View+NSStatusItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// View+NSStatusItem.swift
// Aware
//
// Created by Joshua Peek on 4/25/24.
//

#if canImport(AppKit)

import AppKit
import SwiftUI

extension View {
@MainActor
func bindStatusItem(_ statusItem: Binding<NSStatusItem?>) -> some View {
onAppear {
let statusItems = NSApp.windows.filter { window in
window.className == "NSStatusBarWindow"
}.compactMap { window in
window.value(forKey: "statusItem") as? NSStatusItem
}

assert(!statusItems.isEmpty, "no NSStatusItems found")
assert(statusItems.count == 1, "multiple NSStatusItems found")
statusItem.wrappedValue = statusItems.first
}
}
}

#endif

0 comments on commit 4d98c6d

Please sign in to comment.