178 lines · 5.9 KB · Swift
RawDownload
import AppKitimport CodexBarCoreimport 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.@MainActorfinal 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<Void, Never>?     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            }        }    }}