import AppKit import CodexBarCore import SwiftUI struct QuotaWarningAlertPresentationState { struct Presentation: Equatable { let generation: UInt let title: String let message: String } private(set) var current: Presentation? private var nextGeneration: UInt = 0 mutating func present(title: String, message: String) -> Presentation { self.nextGeneration &+= 1 let presentation = Presentation( generation: self.nextGeneration, title: title, message: message) self.current = presentation return presentation } mutating func dismiss(generation: UInt) -> Bool { guard self.current?.generation == generation else { return false } self.current = nil return true } mutating func dismiss() { self.current = nil } } /// Presents a transient, centered text alert when a quota warning threshold is crossed. /// /// Modeled after ``ScreenConfettiOverlayController``: it shows a borderless, click-through /// panel above all spaces and auto-dismisses after a short lifetime, so it never steals focus /// or blocks the user's work. @MainActor final class QuotaWarningAlertOverlayController { private static let overlayLifetime: TimeInterval = 4.5 private let logger = CodexBarLog.logger(LogCategories.sessionQuotaNotifications) private var presentationState = QuotaWarningAlertPresentationState() private var window: NSWindow? private var dismissalTask: Task? func show(title: String, message: String) { self.dismiss() guard let screen = NSScreen.main ?? NSScreen.screens.first else { self.logger.error("Cannot present quota warning overlay because no screens were found") return } let presentation = self.presentationState.present(title: title, message: message) let frame = screen.frame let contentView = QuotaWarningAlertOverlayView(title: title, message: message) .allowsHitTesting(false) let hostingView = NSHostingView(rootView: contentView) hostingView.wantsLayer = true hostingView.layer?.backgroundColor = NSColor.clear.cgColor let window = ClickThroughAlertPanel( contentRect: frame, styleMask: [.borderless, .nonactivatingPanel], backing: .buffered, defer: false, screen: screen) window.contentView = hostingView window.level = .statusBar window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary, .ignoresCycle, .stationary] window.backgroundColor = .clear window.isOpaque = false window.hasShadow = false window.ignoresMouseEvents = true window.acceptsMouseMovedEvents = false window.isMovable = false window.isReleasedWhenClosed = false window.canHide = false window.hidesOnDeactivate = false window.becomesKeyOnlyIfNeeded = false window.isExcludedFromWindowsMenu = true window.setFrame(frame, display: false) window.orderFrontRegardless() self.window = window self.logger.info("Presenting quota warning overlay") self.dismissalTask = Task { @MainActor [weak self] in try? await Task.sleep(for: .seconds(Self.overlayLifetime)) guard !Task.isCancelled else { return } guard let self, self.presentationState.dismiss(generation: presentation.generation) else { return } self.closeWindow() } } func dismiss() { self.dismissalTask?.cancel() self.dismissalTask = nil self.presentationState.dismiss() self.closeWindow() } private func closeWindow() { guard let window = self.window else { return } window.orderOut(nil) window.close() self.window = nil } } private final class ClickThroughAlertPanel: NSPanel { override var canBecomeKey: Bool { false } override var canBecomeMain: Bool { false } override var acceptsFirstResponder: Bool { false } } private struct QuotaWarningAlertOverlayView: View { let title: String let message: String @Environment(\.accessibilityReduceMotion) private var reduceMotion @State private var appeared = false var body: some View { HStack(alignment: .top, spacing: 12) { Image(systemName: "exclamationmark.triangle.fill") .font(.title2) .foregroundStyle(.orange) VStack(alignment: .leading, spacing: 4) { Text(self.title) .font(.headline) Text(self.message) .font(.subheadline) .foregroundStyle(.secondary) .fixedSize(horizontal: false, vertical: true) } } .padding(.vertical, 16) .padding(.horizontal, 20) .frame(maxWidth: 420, alignment: .leading) .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous)) .overlay( RoundedRectangle(cornerRadius: 16, style: .continuous) .strokeBorder(Color.primary.opacity(0.08))) .shadow(color: .black.opacity(0.25), radius: 24, y: 8) .scaleEffect(self.reduceMotion || self.appeared ? 1 : 0.92) .opacity(self.reduceMotion || self.appeared ? 1 : 0) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .padding(40) .allowsHitTesting(false) .accessibilityElement(children: .combine) .accessibilityLabel(self.title) .accessibilityValue(self.message) .task { guard !self.reduceMotion else { self.appeared = true return } withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) { self.appeared = true } } } }