115 lines
3.6 KiB
Swift
115 lines
3.6 KiB
Swift
import SwiftUI
|
|
import SwiftData
|
|
import AppKit
|
|
|
|
class MenuBarManager: ObservableObject {
|
|
@Published var isMenuBarOnly: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(isMenuBarOnly, forKey: "IsMenuBarOnly")
|
|
updateAppActivationPolicy()
|
|
}
|
|
}
|
|
|
|
private var modelContainer: ModelContainer?
|
|
private var whisperState: WhisperState?
|
|
|
|
init() {
|
|
self.isMenuBarOnly = UserDefaults.standard.bool(forKey: "IsMenuBarOnly")
|
|
updateAppActivationPolicy()
|
|
|
|
NotificationCenter.default.addObserver(
|
|
self,
|
|
selector: #selector(windowDidClose),
|
|
name: NSWindow.willCloseNotification,
|
|
object: nil
|
|
)
|
|
}
|
|
|
|
@objc private func windowDidClose(_ notification: Notification) {
|
|
guard isMenuBarOnly else { return }
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
|
let hasVisibleWindows = NSApplication.shared.windows.contains {
|
|
$0.isVisible && $0.level == .normal && !$0.styleMask.contains(.nonactivatingPanel)
|
|
}
|
|
if !hasVisibleWindows {
|
|
NSApplication.shared.setActivationPolicy(.accessory)
|
|
}
|
|
}
|
|
}
|
|
|
|
func configure(modelContainer: ModelContainer, whisperState: WhisperState) {
|
|
self.modelContainer = modelContainer
|
|
self.whisperState = whisperState
|
|
}
|
|
|
|
func toggleMenuBarOnly() {
|
|
isMenuBarOnly.toggle()
|
|
}
|
|
|
|
func applyActivationPolicy() {
|
|
updateAppActivationPolicy()
|
|
}
|
|
|
|
func focusMainWindow() {
|
|
NSApplication.shared.setActivationPolicy(.regular)
|
|
if WindowManager.shared.showMainWindow() == nil {
|
|
print("MenuBarManager: Unable to locate main window to focus")
|
|
}
|
|
}
|
|
|
|
private func updateAppActivationPolicy() {
|
|
let applyPolicy = { [weak self] in
|
|
guard let self else { return }
|
|
let application = NSApplication.shared
|
|
if self.isMenuBarOnly {
|
|
application.setActivationPolicy(.accessory)
|
|
WindowManager.shared.hideMainWindow()
|
|
} else {
|
|
application.setActivationPolicy(.regular)
|
|
WindowManager.shared.showMainWindow()
|
|
}
|
|
}
|
|
|
|
if Thread.isMainThread {
|
|
applyPolicy()
|
|
} else {
|
|
DispatchQueue.main.async(execute: applyPolicy)
|
|
}
|
|
}
|
|
|
|
func openMainWindowAndNavigate(to destination: String) {
|
|
print("MenuBarManager: Navigating to \(destination)")
|
|
|
|
NSApplication.shared.setActivationPolicy(.regular)
|
|
|
|
guard WindowManager.shared.showMainWindow() != nil else {
|
|
print("MenuBarManager: Unable to show main window for navigation")
|
|
return
|
|
}
|
|
|
|
// Post a notification to navigate to the desired destination
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
|
NotificationCenter.default.post(
|
|
name: .navigateToDestination,
|
|
object: nil,
|
|
userInfo: ["destination": destination]
|
|
)
|
|
print("MenuBarManager: Posted navigation notification for \(destination)")
|
|
}
|
|
}
|
|
|
|
func openHistoryWindow() {
|
|
guard let modelContainer = modelContainer,
|
|
let whisperState = whisperState else {
|
|
print("MenuBarManager: Dependencies not configured")
|
|
return
|
|
}
|
|
NSApplication.shared.setActivationPolicy(.regular)
|
|
HistoryWindowController.shared.showHistoryWindow(
|
|
modelContainer: modelContainer,
|
|
whisperState: whisperState
|
|
)
|
|
}
|
|
}
|