Initial commit
This commit is contained in:
156
macos/Runner/AppDelegate.swift
Normal file
156
macos/Runner/AppDelegate.swift
Normal file
@@ -0,0 +1,156 @@
|
||||
import Cocoa
|
||||
import FlutterMacOS
|
||||
import ServiceManagement
|
||||
|
||||
@main
|
||||
class AppDelegate: FlutterAppDelegate {
|
||||
|
||||
var statusItem: NSStatusItem?
|
||||
|
||||
override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
let controller = mainFlutterWindow?.contentViewController as! FlutterViewController
|
||||
let channel = FlutterMethodChannel(
|
||||
name: "com.igox.busylight_buddy/autostart",
|
||||
binaryMessenger: controller.engine.binaryMessenger
|
||||
)
|
||||
|
||||
channel.setMethodCallHandler { [weak self] call, result in
|
||||
switch call.method {
|
||||
|
||||
case "isEnabled":
|
||||
if #available(macOS 13.0, *) {
|
||||
result(SMAppService.mainApp.status == .enabled)
|
||||
} else {
|
||||
let plist = self?.launchAgentURL()
|
||||
result(FileManager.default.fileExists(atPath: plist?.path ?? ""))
|
||||
}
|
||||
|
||||
case "setEnabled":
|
||||
guard let args = call.arguments as? [String: Any],
|
||||
let enabled = args["enabled"] as? Bool else {
|
||||
result(FlutterError(code: "INVALID_ARGS", message: nil, details: nil))
|
||||
return
|
||||
}
|
||||
// Register/unregister autostart
|
||||
if #available(macOS 13.0, *) {
|
||||
do {
|
||||
if enabled {
|
||||
try SMAppService.mainApp.register()
|
||||
} else {
|
||||
try SMAppService.mainApp.unregister()
|
||||
}
|
||||
} catch {
|
||||
result(FlutterError(code: "AUTOSTART_ERROR", message: error.localizedDescription, details: nil))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
self?.setLaunchAgentLegacy(enabled: enabled)
|
||||
}
|
||||
|
||||
// Toggle dock icon and menu bar extra
|
||||
if enabled {
|
||||
self?.setupMenuBarExtra()
|
||||
NSApp.setActivationPolicy(.accessory) // hide from dock
|
||||
} else {
|
||||
self?.removeMenuBarExtra()
|
||||
NSApp.setActivationPolicy(.regular) // show in dock
|
||||
}
|
||||
|
||||
result(nil)
|
||||
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
super.applicationDidFinishLaunching(notification)
|
||||
|
||||
// Restore menu bar extra on launch if autostart was previously enabled
|
||||
let isAutostart: Bool
|
||||
if #available(macOS 13.0, *) {
|
||||
isAutostart = SMAppService.mainApp.status == .enabled
|
||||
} else {
|
||||
isAutostart = FileManager.default.fileExists(atPath: launchAgentURL().path)
|
||||
}
|
||||
if isAutostart {
|
||||
setupMenuBarExtra()
|
||||
NSApp.setActivationPolicy(.accessory)
|
||||
}
|
||||
}
|
||||
|
||||
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||
// When in menu bar mode, closing the window should not quit the app
|
||||
return statusItem == nil
|
||||
}
|
||||
|
||||
// ── Menu bar extra ──────────────────────────────────────────────────────
|
||||
|
||||
func setupMenuBarExtra() {
|
||||
guard statusItem == nil else { return }
|
||||
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
|
||||
if let button = statusItem?.button {
|
||||
// Use the app icon scaled to menu bar size
|
||||
button.image = NSImage(named: NSImage.Name("AppIcon"))
|
||||
button.image?.size = NSSize(width: 18, height: 18)
|
||||
button.image?.isTemplate = false
|
||||
button.action = #selector(statusItemClicked)
|
||||
button.target = self
|
||||
}
|
||||
// Right-click menu
|
||||
let menu = NSMenu()
|
||||
menu.addItem(NSMenuItem(title: "Show BusyLight Buddy", action: #selector(showApp), keyEquivalent: ""))
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
menu.addItem(NSMenuItem(title: "Quit", action: #selector(quitApp), keyEquivalent: "q"))
|
||||
statusItem?.menu = menu
|
||||
}
|
||||
|
||||
func removeMenuBarExtra() {
|
||||
if let item = statusItem {
|
||||
NSStatusBar.system.removeStatusItem(item)
|
||||
statusItem = nil
|
||||
}
|
||||
}
|
||||
|
||||
@objc func statusItemClicked() {
|
||||
showApp()
|
||||
}
|
||||
|
||||
@objc func showApp() {
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
mainFlutterWindow?.makeKeyAndOrderFront(nil)
|
||||
}
|
||||
|
||||
@objc func quitApp() {
|
||||
removeMenuBarExtra()
|
||||
NSApp.terminate(nil)
|
||||
}
|
||||
|
||||
// ── Legacy LaunchAgent fallback (macOS < 13) ────────────────────────────
|
||||
|
||||
private func launchAgentURL() -> URL {
|
||||
let home = FileManager.default.homeDirectoryForCurrentUser
|
||||
return home
|
||||
.appendingPathComponent("Library/LaunchAgents")
|
||||
.appendingPathComponent("com.igox.busylight_buddy.plist")
|
||||
}
|
||||
|
||||
private func setLaunchAgentLegacy(enabled: Bool) {
|
||||
let url = launchAgentURL()
|
||||
if enabled {
|
||||
let execURL = Bundle.main.executableURL!.path
|
||||
let plist: [String: Any] = [
|
||||
"Label": "com.igox.busylight_buddy",
|
||||
"ProgramArguments": [execURL],
|
||||
"RunAtLoad": true,
|
||||
"KeepAlive": false,
|
||||
]
|
||||
try? (plist as NSDictionary).write(to: url)
|
||||
} else {
|
||||
try? FileManager.default.removeItem(at: url)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user