diff --git a/Sources/AgentBar/App/AppDelegate.swift b/Sources/AgentBar/App/AppDelegate.swift index 9750b22..897531b 100644 --- a/Sources/AgentBar/App/AppDelegate.swift +++ b/Sources/AgentBar/App/AppDelegate.swift @@ -5,8 +5,6 @@ import SwiftUI @MainActor final class AppDelegate: NSObject, NSApplicationDelegate, NSPopoverDelegate, SPUUpdaterDelegate { - private static let statusItemWidth: CGFloat = 76 - private let store = QuotaStore() private let updateNotificationService = AppUpdateNotificationService() private var statusItem: NSStatusItem? @@ -43,14 +41,22 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSPopoverDelegate, SPU } private func configureStatusItem() { - let item = NSStatusBar.system.statusItem(withLength: Self.statusItemWidth) + let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) statusItem = item guard let button = item.button else { return } - let view = MenuBarQuotaView(frame: NSRect(x: 0, y: 0, width: Self.statusItemWidth, height: NSStatusBar.system.thickness)) + let view = MenuBarQuotaView( + frame: NSRect( + x: 0, + y: 0, + width: 0, + height: NSStatusBar.system.thickness + ) + ) + item.length = view.preferredWidth view.target = self view.action = #selector(togglePopover(_:)) view.translatesAutoresizingMaskIntoConstraints = false @@ -145,10 +151,19 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSPopoverDelegate, SPU } private func updateMenuBarTitle() { - menuBarView?.update( + guard let menuBarView else { + return + } + + menuBarView.update( snapshot: store.snapshot, statusMessage: store.statusMessage ) + + let preferredWidth = menuBarView.preferredWidth + if statusItem?.length != preferredWidth { + statusItem?.length = preferredWidth + } } private func showCLIUpgradeAlertIfNeeded(_ message: String?) { diff --git a/Sources/AgentBar/UI/MenuBarQuotaView.swift b/Sources/AgentBar/UI/MenuBarQuotaView.swift index d529d7a..41289d7 100644 --- a/Sources/AgentBar/UI/MenuBarQuotaView.swift +++ b/Sources/AgentBar/UI/MenuBarQuotaView.swift @@ -1,10 +1,32 @@ import AppKit final class MenuBarQuotaView: NSControl { + private enum Metrics { + static let horizontalPadding: CGFloat = 6 + static let iconSize: CGFloat = 18 + static let iconSpacing: CGFloat = 5 + static let textSpacing: CGFloat = 5 + } + private let iconView = NSImageView() private let weekPrefixLabel = NSTextField(labelWithString: I18n.current.shortWeek) private let weekPercentLabel = NSTextField(labelWithString: "--") + var preferredWidth: CGFloat { + ceil( + Metrics.horizontalPadding * 2 + + Metrics.iconSize + + Metrics.iconSpacing + + weekPrefixLabel.intrinsicContentSize.width + + Metrics.textSpacing + + weekPercentLabel.intrinsicContentSize.width + ) + } + + override var intrinsicContentSize: NSSize { + NSSize(width: preferredWidth, height: NSStatusBar.system.thickness) + } + override init(frame frameRect: NSRect) { super.init(frame: frameRect) setup() @@ -18,16 +40,17 @@ final class MenuBarQuotaView: NSControl { func update(snapshot: QuotaSnapshot?, statusMessage: String) { toolTip = statusMessage - guard let snapshot else { + if let snapshot { + weekPrefixLabel.stringValue = snapshot.weekly.shortTitle + weekPercentLabel.stringValue = "\(Int(snapshot.weekly.remainingPercent.rounded()))%" + weekPercentLabel.textColor = quotaColor(forRemainingPercent: snapshot.weekly.remainingPercent) + } else { weekPrefixLabel.stringValue = I18n.current.shortWeek weekPercentLabel.stringValue = "--" weekPercentLabel.textColor = .secondaryLabelColor - return } - weekPrefixLabel.stringValue = snapshot.weekly.shortTitle - weekPercentLabel.stringValue = "\(Int(snapshot.weekly.remainingPercent.rounded()))%" - weekPercentLabel.textColor = quotaColor(forRemainingPercent: snapshot.weekly.remainingPercent) + invalidateIntrinsicContentSize() } override func mouseDown(with event: NSEvent) { @@ -69,13 +92,13 @@ final class MenuBarQuotaView: NSControl { NSLayoutConstraint.activate([ heightAnchor.constraint(equalToConstant: NSStatusBar.system.thickness), - iconView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 6), + iconView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: Metrics.horizontalPadding), iconView.centerYAnchor.constraint(equalTo: centerYAnchor), - iconView.widthAnchor.constraint(equalToConstant: 18), - iconView.heightAnchor.constraint(equalToConstant: 18), + iconView.widthAnchor.constraint(equalToConstant: Metrics.iconSize), + iconView.heightAnchor.constraint(equalToConstant: Metrics.iconSize), - weekRow.leadingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: 5), - weekRow.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -6), + weekRow.leadingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: Metrics.iconSpacing), + weekRow.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -Metrics.horizontalPadding), weekRow.centerYAnchor.constraint(equalTo: centerYAnchor), ]) } @@ -85,7 +108,7 @@ final class MenuBarQuotaView: NSControl { row.orientation = .horizontal row.alignment = .centerY row.distribution = .gravityAreas - row.spacing = 5 + row.spacing = Metrics.textSpacing row.translatesAutoresizingMaskIntoConstraints = false return row