The menu bar icon is now a hamburger whose panel gathers every other
app's status item via the Accessibility API, so tray icons no longer
need to be hunted down across the menu bar. Items can be opened from
the panel, and a best-effort toggle pushes them off the real menu bar
so they only live there.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4.1-flash
67 lines
1.9 KiB
Swift
67 lines
1.9 KiB
Swift
import SwiftUI
|
|
import AppKit
|
|
import ServiceManagement
|
|
|
|
@main
|
|
struct SimpleTopBarApp: App {
|
|
@NSApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
|
|
|
|
var body: some Scene {
|
|
MenuBarExtra("SimpleTopBar", systemImage: "line.3.horizontal") {
|
|
TopBarView(
|
|
model: AppListModel.shared,
|
|
menuBar: MenuBarItemManager.shared,
|
|
hider: MenuBarHider.shared
|
|
)
|
|
}
|
|
.menuBarExtraStyle(.window)
|
|
}
|
|
}
|
|
|
|
final class AppDelegate: NSObject, NSApplicationDelegate {
|
|
func applicationDidFinishLaunching(_ notification: Notification) {
|
|
if CommandLine.arguments.contains("--self-test") {
|
|
runSelfTest()
|
|
return
|
|
}
|
|
|
|
// Single instance: stale copies keep a menu bar icon around after an
|
|
// update and swallow clicks meant for the new instance.
|
|
let myPid = ProcessInfo.processInfo.processIdentifier
|
|
let others = NSRunningApplication.runningApplications(withBundleIdentifier: "dev.tzgyn.simpletopbar")
|
|
.filter { $0.processIdentifier != myPid }
|
|
for other in others {
|
|
other.forceTerminate()
|
|
}
|
|
|
|
AppListModel.shared.start()
|
|
MenuBarItemManager.shared.start()
|
|
MenuBarHider.shared.prepare()
|
|
}
|
|
|
|
func applicationWillTerminate(_ notification: Notification) {
|
|
// Never leave the menu bar resized behind us.
|
|
MenuBarHider.shared.restore()
|
|
}
|
|
}
|
|
|
|
enum LoginItem {
|
|
static var isEnabled: Bool {
|
|
SMAppService.mainApp.status == .enabled
|
|
}
|
|
|
|
static func toggle() -> Bool {
|
|
let service = SMAppService.mainApp
|
|
do {
|
|
if service.status == .enabled {
|
|
try service.unregister()
|
|
} else {
|
|
try service.register()
|
|
}
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
}
|