147 lines
4.9 KiB
Swift
147 lines
4.9 KiB
Swift
import SwiftUI
|
|
import LaunchAtLogin
|
|
import SwiftData
|
|
import AppKit
|
|
|
|
class MenuBarManager: ObservableObject {
|
|
@Published var isMenuBarOnly: Bool {
|
|
didSet {
|
|
UserDefaults.standard.set(isMenuBarOnly, forKey: "IsMenuBarOnly")
|
|
updateAppActivationPolicy()
|
|
}
|
|
}
|
|
|
|
private var updaterViewModel: UpdaterViewModel
|
|
private var whisperState: WhisperState
|
|
private var container: ModelContainer
|
|
private var enhancementService: AIEnhancementService
|
|
private var aiService: AIService
|
|
private var hotkeyManager: HotkeyManager
|
|
private var mainWindow: NSWindow? // Store window reference
|
|
|
|
init(updaterViewModel: UpdaterViewModel,
|
|
whisperState: WhisperState,
|
|
container: ModelContainer,
|
|
enhancementService: AIEnhancementService,
|
|
aiService: AIService,
|
|
hotkeyManager: HotkeyManager) {
|
|
self.isMenuBarOnly = UserDefaults.standard.bool(forKey: "IsMenuBarOnly")
|
|
self.updaterViewModel = updaterViewModel
|
|
self.whisperState = whisperState
|
|
self.container = container
|
|
self.enhancementService = enhancementService
|
|
self.aiService = aiService
|
|
self.hotkeyManager = hotkeyManager
|
|
updateAppActivationPolicy()
|
|
}
|
|
|
|
func toggleMenuBarOnly() {
|
|
isMenuBarOnly.toggle()
|
|
}
|
|
|
|
private func updateAppActivationPolicy() {
|
|
DispatchQueue.main.async { [weak self] in
|
|
guard let self = self else { return }
|
|
|
|
// Clean up existing window if switching to menu bar mode
|
|
if self.isMenuBarOnly && self.mainWindow != nil {
|
|
self.mainWindow?.close()
|
|
self.mainWindow = nil
|
|
}
|
|
|
|
// Update activation policy
|
|
if self.isMenuBarOnly {
|
|
NSApp.setActivationPolicy(.accessory)
|
|
} else {
|
|
NSApp.setActivationPolicy(.regular)
|
|
}
|
|
}
|
|
}
|
|
|
|
func openMainWindowAndNavigate(to destination: String) {
|
|
print("MenuBarManager: Navigating to \(destination)")
|
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
guard let self = self else { return }
|
|
|
|
if self.isMenuBarOnly {
|
|
NSApp.setActivationPolicy(.accessory)
|
|
} else {
|
|
NSApp.setActivationPolicy(.regular)
|
|
}
|
|
|
|
// Activate the app
|
|
NSApp.activate(ignoringOtherApps: true)
|
|
|
|
// Clean up existing window if it's no longer valid
|
|
if let existingWindow = self.mainWindow, !existingWindow.isVisible {
|
|
self.mainWindow = nil
|
|
}
|
|
|
|
// Get or create main window
|
|
if self.mainWindow == nil {
|
|
self.mainWindow = self.createMainWindow()
|
|
}
|
|
|
|
guard let window = self.mainWindow else { return }
|
|
|
|
// Make the window key and order front
|
|
window.makeKeyAndOrderFront(nil)
|
|
window.center() // Always center the window for consistent positioning
|
|
|
|
// 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)")
|
|
}
|
|
}
|
|
}
|
|
|
|
private func createMainWindow() -> NSWindow {
|
|
print("MenuBarManager: Creating new main window")
|
|
|
|
// Create the content view with all required environment objects
|
|
let contentView = ContentView()
|
|
.environmentObject(whisperState)
|
|
.environmentObject(hotkeyManager)
|
|
.environmentObject(self)
|
|
.environmentObject(updaterViewModel)
|
|
.environmentObject(enhancementService)
|
|
.environmentObject(aiService)
|
|
.environment(\.modelContext, ModelContext(container))
|
|
|
|
// Create window using WindowManager
|
|
let hostingView = NSHostingView(rootView: contentView)
|
|
let window = WindowManager.shared.createMainWindow(contentView: hostingView)
|
|
|
|
// Set window delegate to handle window closing
|
|
let delegate = WindowDelegate { [weak self] in
|
|
self?.mainWindow = nil
|
|
}
|
|
window.delegate = delegate
|
|
|
|
print("MenuBarManager: Window setup complete")
|
|
|
|
return window
|
|
}
|
|
}
|
|
|
|
// Window delegate to handle window closing
|
|
class WindowDelegate: NSObject, NSWindowDelegate {
|
|
let onClose: () -> Void
|
|
|
|
init(onClose: @escaping () -> Void) {
|
|
self.onClose = onClose
|
|
super.init()
|
|
}
|
|
|
|
func windowWillClose(_ notification: Notification) {
|
|
onClose()
|
|
}
|
|
}
|
|
|