I've gotten the following lines of code working.
import SwiftUI
@main
struct MyStatusApp_App: App {
#if os(macOS)
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#endif
@StateObject private var statusBarViewModel = StatusBarViewModel()
var body: some Scene {
WindowGroup {
ContentView()
.onDisappear {
NSApplication.shared.terminate(self)
}
.environmentObject(statusBarViewModel)
}
.defaultSize(width: 640, height: 360)
}
}
#if os(macOS)
class AppDelegate: NSObject, NSApplicationDelegate {
let fileManager = FileManager.default
func applicationDidFinishLaunching(_ notification: Notification) {
hideTitleBar()
NSApp.setActivationPolicy(.accessory)
}
func applicationWillFinishLaunching(_ notification: Notification) {
NSWindow.allowsAutomaticWindowTabbing = false
}
}
#endif
// ContentView.swift //
import SwiftUI
struct ContentView: View {
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@EnvironmentObject var statusBarViewModel: StatusBarViewModel
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Button("Click me!") {
if let statusItem = statusBarViewModel.statusItem {
if let button = statusItem.button {
if statusBarViewModel.popover == nil {
let popover = NSPopover()
statusBarViewModel.popover = popover
popover.behavior = .transient
popover.animates = false
popover.contentViewController = NSHostingController(rootView: NotificationView())
}
statusBarViewModel.popover?.show(relativeTo: button.bounds, of: button, preferredEdge: .minY)
}
}
}
}
.frame(width: 200, height: 100)
.onAppear {
statusBarViewModel.makeStatusMenu()
}
}
}
class StatusBarViewModel: ObservableObject {
@Published var statusItem: NSStatusItem!
@Published var popover: NSPopover?
func makeStatusMenu() {
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
if let button = statusItem.button {
if let image = NSImage(named: "statusImage") {
button.image = image
}
}
}
}