mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-27 15:17:38 +00:00
88 lines
3.3 KiB
Swift
88 lines
3.3 KiB
Swift
import AppKit
|
|
import Foundation
|
|
import os.log
|
|
|
|
private let logger = Logger(subsystem: BundleIdentifiers.loggerSubsystem, category: "StatusBarIconController")
|
|
|
|
/// Manages the visual appearance of the status bar item's button.
|
|
///
|
|
/// This class is responsible for updating the icon and title of the status bar button
|
|
/// based on the application's state, such as server status and active sessions.
|
|
@MainActor
|
|
final class StatusBarIconController {
|
|
private weak var button: NSStatusBarButton?
|
|
|
|
/// Initializes the icon controller with the status bar button.
|
|
/// - Parameter button: The `NSStatusBarButton` to manage.
|
|
init(button: NSStatusBarButton?) {
|
|
self.button = button
|
|
}
|
|
|
|
/// Updates the entire visual state of the status bar button.
|
|
///
|
|
/// - Parameters:
|
|
/// - serverManager: The manager for the VibeTunnel server.
|
|
/// - sessionMonitor: The monitor for active terminal sessions.
|
|
func update(serverManager: ServerManager, sessionMonitor: SessionMonitor) {
|
|
guard let button else { return }
|
|
|
|
// Update icon based on server status
|
|
updateIcon(isServerRunning: serverManager.isRunning)
|
|
|
|
// Update session count display
|
|
let sessions = sessionMonitor.sessions.values.filter(\.isRunning)
|
|
let activeSessions = sessions.filter { session in
|
|
if let activityStatus = session.activityStatus?.specificStatus?.status {
|
|
return !activityStatus.isEmpty
|
|
}
|
|
return false
|
|
}
|
|
|
|
let activeCount = activeSessions.count
|
|
let totalCount = sessions.count
|
|
let idleCount = totalCount - activeCount
|
|
|
|
let indicator = formatSessionIndicator(activeCount: activeCount, idleCount: idleCount)
|
|
button.title = indicator.isEmpty ? "" : " " + indicator
|
|
}
|
|
|
|
/// Updates the icon of the status bar button based on the server's running state.
|
|
/// - Parameter isServerRunning: A boolean indicating if the server is running.
|
|
private func updateIcon(isServerRunning: Bool) {
|
|
guard let button else { return }
|
|
|
|
// Always use the same icon - it's already set as a template in the asset catalog
|
|
guard let image = NSImage(named: "menubar") else {
|
|
logger.warning("menubar icon not found")
|
|
return
|
|
}
|
|
|
|
// The image is already configured as a template in Contents.json,
|
|
// but we set it explicitly to be safe
|
|
image.isTemplate = true
|
|
button.image = image
|
|
|
|
// Use opacity to indicate server state:
|
|
// - 1.0 (fully opaque) when server is running
|
|
// - 0.5 (semi-transparent) when server is stopped
|
|
button.alphaValue = isServerRunning ? 1.0 : 0.5
|
|
}
|
|
|
|
/// Formats the session count indicator with a minimalist style.
|
|
/// - Parameters:
|
|
/// - activeCount: The number of active sessions.
|
|
/// - idleCount: The number of idle sessions.
|
|
/// - Returns: A formatted string representing the session counts.
|
|
private func formatSessionIndicator(activeCount: Int, idleCount: Int) -> String {
|
|
let totalCount = activeCount + idleCount
|
|
guard totalCount > 0 else { return "" }
|
|
|
|
if activeCount == 0 {
|
|
return String(totalCount)
|
|
} else if activeCount == totalCount {
|
|
return "● \(activeCount)"
|
|
} else {
|
|
return "\(activeCount) | \(idleCount)"
|
|
}
|
|
}
|
|
}
|