mirror of
https://github.com/dredx/prole.git
synced 2026-09-27 19:14:31 +00:00
- Replace direct script invocation with `$PROLE_HOME/env.sh` wrapper for consistent environment setup across all components. - Update runtime processes to dynamically resolve `$PROLE_HOME` or fallback to `$HOME/.prole`. - Deprecate `init-port-forwards.sh` script bundling; remove from LaunchAgentManager and build system. - Overhaul `env.sh` generation to include execution capability, customizable paths, and improved error handling. - Standardize app name and paths to "Prole Tools" across all files and UI elements. - Adjust build output to align with new structure, including executable naming and resource packaging.
103 lines
3.4 KiB
Swift
103 lines
3.4 KiB
Swift
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() }
|
|
}
|