import AppKit final class StatusItemController { struct Actions { let onLeftClick: () -> Void let onToggleStatusBar: () -> Void let onToggleAppWindow: () -> Void let onRefresh: () -> Void let onQuit: () -> Void } private var statusItem: NSStatusItem? private let actions: Actions private var stateStatusBarVisible: Bool = true private var stateAppWindowVisible: Bool = false init(actions: Actions) { self.actions = actions createStatusItemIfNeeded() } func setState(statusBarVisible: Bool, appWindowVisible: Bool) { self.stateStatusBarVisible = statusBarVisible self.stateAppWindowVisible = appWindowVisible } func hideStatusItem() { if let item = statusItem { NSStatusBar.system.removeStatusItem(item) statusItem = nil } } func showStatusItem() { createStatusItemIfNeeded() } var isVisible: Bool { statusItem != nil } private func createStatusItemIfNeeded() { guard statusItem == nil else { return } let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) statusItem = item if let button = item.button { let font = NSFont.monospacedSystemFont(ofSize: 13, weight: .bold) button.image = nil button.attributedTitle = NSAttributedString(string: "P", attributes: [ .font: font ]) button.target = self button.action = #selector(handleClick) button.sendAction(on: [.leftMouseUp, .rightMouseUp]) button.toolTip = "ProleStatus" } } @objc private func handleClick(_ sender: Any?) { guard let event = NSApp.currentEvent else { actions.onLeftClick(); return } switch event.type { case .rightMouseUp: showMenu() default: actions.onLeftClick() } } private func showMenu() { guard let button = statusItem?.button else { return } let menu = NSMenu(title: "ProleStatus") let statusBarTitle = stateStatusBarVisible ? "Hide Status Bar Icon" : "Show Status Bar Icon" let appWindowTitle = stateAppWindowVisible ? "Hide Application Window" : "Show Application Window" let sbItem = NSMenuItem(title: statusBarTitle, action: #selector(toggleStatusBar), keyEquivalent: "") sbItem.target = self menu.addItem(sbItem) let winItem = NSMenuItem(title: appWindowTitle, action: #selector(toggleAppWindow), keyEquivalent: "") winItem.target = self menu.addItem(winItem) menu.addItem(.separator()) let refreshItem = NSMenuItem(title: "Refresh Now", action: #selector(refreshNow), keyEquivalent: "r") refreshItem.target = self menu.addItem(refreshItem) menu.addItem(.separator()) let quitItem = NSMenuItem(title: "Quit ProleStatus", action: #selector(quitApp), keyEquivalent: "q") quitItem.target = self menu.addItem(quitItem) let point = NSPoint(x: 0, y: button.bounds.minY - 3) menu.popUp(positioning: nil, at: point, in: button) } @objc private func toggleStatusBar() { actions.onToggleStatusBar() } @objc private func toggleAppWindow() { actions.onToggleAppWindow() } @objc private func refreshNow() { actions.onRefresh() } @objc private func quitApp() { actions.onQuit() } }