mirror of
https://github.com/dredx/prole.git
synced 2026-09-24 16:24:32 +00:00
- Default to Application Window mode with full app menu; status bar overlay remains available - Restore clickable startup Splash Tip (5s) with animated GIF and live counter; use light theme (Aqua) - Status bar item: monospaced "P" icon; left click shows overlay (status mode) or main window (app mode) - Overlay: add Maximize button (□) to toggle back to main window; keep click‑through elsewhere - Global hotkey Cmd+Opt+Shift+P toggles modes; Prole menu item mirrors the same toggle and updates title dynamically - Application menu (Prole): Show Status Bar / Show Main Window (contextual), Refresh Now, Quit - Application Window layout: non‑scrolling, vertical 1‑line rows (svc, k3s aggregate, local) with top‑right timestamp; bottom‑left controls (⟳ Refresh, _ Minimize) - Parameterize endpoints via `prole.properties` (bundled + user override). Replace legacy raspberry with retropie defaults - ServiceChecker + UI read endpoints from Config loader; tooltips/labels reflect configured hosts/ports - Build script: generate `Info.plist` with `LSUIElement=false`; bundle resources (`prole-type.gif`, `prole.properties`); ad‑hoc codesign. Universal build supported - Documentation: rewrite README with technical build/run/config details and operational posture Files: - proleStatus/Sources/: AppDelegate.swift, OverlayWindow.swift, StatusView.swift, StatusItemController.swift, SplashTipWindowController.swift, MainWindowController.swift, AppStatusView.swift, ServiceChecker.swift, Config.swift - proleStatus/build.sh - proleStatus/prole.properties - proleStatus/README.md Notes: - Build verified via `./build.sh build` (arm64). App starts in App Window mode with light theme; menu + hotkey + overlay toggle operate as intended
79 lines
3.1 KiB
Swift
79 lines
3.1 KiB
Swift
|
|
// Timestamp
|
|
let now = Date()
|
|
timestampLabel.stringValue = timeFormatter.string(from: now)
|
|
|
|
// SVC
|
|
lightSvc.state = c.svcReachable ? .green : .red
|
|
labelSvc.stringValue = "svc: \(cfg.svcHost):\(cfg.svcPort) \(c.svcReachable ? "✓" : "✗") \(c.svcLatency >= 0 ? "(\(c.svcLatency) ms)" : "")"
|
|
labelSvc.toolTip = c.tooltipForSvc()
|
|
|
|
// K3s aggregate: retropie + pi
|
|
let aggCount = (c.raspberryReachable ? 1 : 0) + (c.piReachable ? 1 : 0)
|
|
lightK3s.state = aggCount == 2 ? .green : (aggCount == 1 ? .yellow : .red)
|
|
labelK3s.stringValue = "k3s: \(cfg.retropieHost) \(c.raspberryReachable ? "✓" : "✗"), \(cfg.piHost) \(c.piReachable ? "✓" : "✗")"
|
|
labelK3s.toolTip = c.tooltipForAggregateK3s()
|
|
|
|
// Local
|
|
lightLocal.state = c.localReachable ? .green : .red
|
|
labelLocal.stringValue = "local: \(cfg.localHost):\(cfg.localPort) \(c.localReachable ? "✓" : "✗") \(c.localLatency >= 0 ? "(\(c.localLatency) ms)" : "")"
|
|
labelLocal.toolTip = c.tooltipForLocal()
|
|
|
|
// Port forwards
|
|
if let m = pfManager {
|
|
let running = m.runningCount
|
|
let total = m.details.count
|
|
lightPF.state = m.allRunning ? .green : .red
|
|
labelPF.stringValue = total > 0 ? "kubectl port-forwards: \(running)/\(total) running" : "kubectl port-forwards: none configured"
|
|
labelPF.toolTip = "Managed processes: \(running)/\(total) running"
|
|
renderPFDetails(m)
|
|
} else {
|
|
lightPF.state = .red
|
|
labelPF.stringValue = "kubectl port-forwards: disabled"
|
|
labelPF.toolTip = "To enable, set pf.enabled=true in prole.properties"
|
|
clearPFDetails()
|
|
}
|
|
|
|
needsLayout = true
|
|
}
|
|
|
|
// MARK: - PF Details rendering
|
|
private func clearPFDetails() {
|
|
pfDetailsStack.arrangedSubviews.forEach { v in
|
|
pfDetailsStack.removeArrangedSubview(v)
|
|
v.removeFromSuperview()
|
|
}
|
|
}
|
|
|
|
private func renderPFDetails(_ manager: PortForwardManager) {
|
|
clearPFDetails()
|
|
let details = manager.details
|
|
guard !details.isEmpty else { return }
|
|
|
|
for d in details {
|
|
let dot = TrafficLight()
|
|
dot.state = d.running ? .green : .red
|
|
|
|
let pidText: String
|
|
if let pid = d.pid, pid > 0 {
|
|
pidText = "PID \(pid)"
|
|
} else {
|
|
pidText = "PID -"
|
|
}
|
|
|
|
let label = NSTextField(labelWithString: "\(pidText) • \(d.running ? "running" : "stopped") — \(d.command)")
|
|
label.font = NSFont.systemFont(ofSize: NSFont.systemFontSize(for: .small))
|
|
label.textColor = .secondaryLabelColor
|
|
label.lineBreakMode = .byTruncatingMiddle
|
|
|
|
let row = NSStackView(views: [dot, label])
|
|
row.orientation = .horizontal
|
|
row.alignment = .centerY
|
|
row.spacing = 8
|
|
row.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
pfDetailsStack.addArrangedSubview(row)
|
|
}
|
|
}
|
|
}
|