This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import AppKit
|
||||
import Foundation
|
||||
|
||||
@MainActor
|
||||
protocol XcodeCleanRunningMonitoring: AnyObject {
|
||||
var isXcodeRunning: Bool { get }
|
||||
var onStateChange: (() -> Void)? { get set }
|
||||
|
||||
func start()
|
||||
func stop()
|
||||
func refresh()
|
||||
}
|
||||
|
||||
@MainActor
|
||||
final class XcodeCleanRunningMonitor: XcodeCleanRunningMonitoring {
|
||||
nonisolated static let xcodeBundleIdentifier = "com.apple.dt.Xcode"
|
||||
|
||||
private(set) var isXcodeRunning: Bool = false
|
||||
var onStateChange: (() -> Void)?
|
||||
|
||||
private var observers: [NSObjectProtocol] = []
|
||||
private let workspace: NSWorkspace
|
||||
|
||||
init(workspace: NSWorkspace = .shared) {
|
||||
self.workspace = workspace
|
||||
}
|
||||
|
||||
func start() {
|
||||
guard observers.isEmpty else { return }
|
||||
|
||||
let center = workspace.notificationCenter
|
||||
let launched = center.addObserver(
|
||||
forName: NSWorkspace.didLaunchApplicationNotification,
|
||||
object: nil,
|
||||
queue: .main
|
||||
) { [weak self] notification in
|
||||
guard let app = notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication,
|
||||
app.bundleIdentifier == Self.xcodeBundleIdentifier
|
||||
else { return }
|
||||
Task { @MainActor [weak self] in self?.refresh() }
|
||||
}
|
||||
|
||||
let terminated = center.addObserver(
|
||||
forName: NSWorkspace.didTerminateApplicationNotification,
|
||||
object: nil,
|
||||
queue: .main
|
||||
) { [weak self] notification in
|
||||
guard let app = notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication,
|
||||
app.bundleIdentifier == Self.xcodeBundleIdentifier
|
||||
else { return }
|
||||
Task { @MainActor [weak self] in self?.refresh() }
|
||||
}
|
||||
|
||||
observers = [launched, terminated]
|
||||
refresh()
|
||||
}
|
||||
|
||||
func stop() {
|
||||
for observer in observers {
|
||||
workspace.notificationCenter.removeObserver(observer)
|
||||
}
|
||||
observers.removeAll()
|
||||
}
|
||||
|
||||
func refresh() {
|
||||
let nextValue = workspace.runningApplications.contains { app in
|
||||
app.bundleIdentifier == Self.xcodeBundleIdentifier
|
||||
}
|
||||
guard nextValue != isXcodeRunning else { return }
|
||||
isXcodeRunning = nextValue
|
||||
onStateChange?()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user