252 lines · 9.7 KB · Swift
RawDownload
import CodexBarCoreimport SwiftUI @MainActorstruct GlobalQuotaWarningSettingsView: View {    @Bindable var settings: SettingsStore     var body: some View {        VStack(alignment: .leading, spacing: 10) {            HStack(spacing: 16) {                Toggle(isOn: Binding(                    get: { self.settings.quotaWarningWindowEnabled(.session) },                    set: { self.settings.setQuotaWarningWindowEnabled(.session, enabled: $0) }))                {                    Text(L("quota_warning_session_capitalized"))                        .font(.footnote)                }                .toggleStyle(.checkbox)                 Toggle(isOn: Binding(                    get: { self.settings.quotaWarningWindowEnabled(.weekly) },                    set: { self.settings.setQuotaWarningWindowEnabled(.weekly, enabled: $0) }))                {                    Text(L("quota_warning_weekly_capitalized"))                        .font(.footnote)                }                .toggleStyle(.checkbox)            }             self.windowThresholdField(.session)            self.windowThresholdField(.weekly)             Toggle(isOn: self.$settings.quotaWarningSoundEnabled) {                Text(L("quota_warning_sound"))                    .font(.footnote)            }            .toggleStyle(.checkbox)        }        .padding(.leading, 20)    }     private func windowThresholdField(_ window: QuotaWarningWindow) -> some View {        QuotaWarningThresholdField(            title: String(format: L("quota_warning_window_warn_at"), window.localizedCapitalizedDisplayName),            subtitle: L("quota_warning_global_threshold_subtitle"),            thresholds: { self.settings.quotaWarningThresholds(window) },            setThresholds: { self.settings.setQuotaWarningThresholds(window, thresholds: $0) })            .disabled(!self.settings.quotaWarningWindowEnabled(window))            .opacity(!self.settings.quotaWarningWindowEnabled(window) ? 0.55 : 1)    }} @MainActorstruct ProviderQuotaWarningSettingsView: View {    let provider: UsageProvider    @Bindable var settings: SettingsStore     var body: some View {        ProviderSettingsSection(title: L("quota_warnings_title")) {            Text(L("quota_warning_provider_inherits"))                .font(.footnote)                .foregroundStyle(.secondary)                .fixedSize(horizontal: false, vertical: true)             self.windowRow(.session)            self.windowRow(.weekly)        }    }     private func windowRow(_ window: QuotaWarningWindow) -> some View {        VStack(alignment: .leading, spacing: 8) {            Toggle(isOn: Binding(                get: { self.settings.hasQuotaWarningOverride(provider: self.provider, window: window) },                set: { isOn in                    if isOn {                        self.settings.setQuotaWarningOverride(                            provider: self.provider,                            window: window,                            thresholds: self.settings.quotaWarningThresholds(window),                            enabled: self.settings.quotaWarningWindowEnabled(window))                    } else {                        self.settings.setQuotaWarningOverride(                            provider: self.provider,                            window: window,                            thresholds: nil,                            enabled: nil)                    }                })) {                    Text(String(format: L("quota_warning_customize_thresholds"), window.localizedDisplayName))                        .font(.subheadline.weight(.semibold))                }                .toggleStyle(.checkbox)             if self.settings.hasQuotaWarningOverride(provider: self.provider, window: window) {                Toggle(isOn: Binding(                    get: { self.settings.quotaWarningEnabled(provider: self.provider, window: window) },                    set: {                        self.settings.setQuotaWarningWindowEnabled(                            provider: self.provider,                            window: window,                            enabled: $0)                    })) {                        Text(String(format: L("quota_warning_enable_warnings"), window.localizedDisplayName))                            .font(.footnote)                    }                    .toggleStyle(.checkbox)                        .padding(.leading, 20)                 if self.settings.quotaWarningEnabled(provider: self.provider, window: window) {                    QuotaWarningThresholdField(                        title: String(                            format: L("quota_warning_window_warn_at"),                            window.localizedCapitalizedDisplayName),                        subtitle: "",                        thresholds: {                            self.settings.resolvedQuotaWarningThresholds(provider: self.provider, window: window)                        },                        setThresholds: {                            self.settings.setQuotaWarningThresholds(                                provider: self.provider,                                window: window,                                thresholds: $0)                        })                        .padding(.leading, 20)                } else {                    Text(L("quota_warning_off"))                        .font(.footnote)                        .foregroundStyle(.secondary)                        .padding(.leading, 20)                }            } else {                Text(String(format: L("quota_warning_inherited"), Self.thresholdText(                    self.settings.quotaWarningThresholds(window),                    enabled: self.settings.quotaWarningWindowEnabled(window))))                    .font(.footnote)                    .foregroundStyle(.secondary)                    .padding(.leading, 20)            }        }    }     private static func thresholdText(_ thresholds: [Int], enabled: Bool) -> String {        guard enabled else { return L("quota_warning_off") }        let text = QuotaWarningThresholds.active(thresholds).map { "\($0)%" }.joined(separator: ", ")        return text.isEmpty ? L("quota_warning_depleted_only") : text    }} extension QuotaWarningWindow {    fileprivate var localizedDisplayName: String {        switch self {        case .session: L("quota_warning_session")        case .weekly: L("quota_warning_weekly")        }    }     fileprivate var localizedCapitalizedDisplayName: String {        switch self {        case .session: L("quota_warning_session_capitalized")        case .weekly: L("quota_warning_weekly_capitalized")        }    }} @MainActorprivate struct QuotaWarningThresholdField: View {    let title: String    let subtitle: String    let thresholds: () -> [Int]    let setThresholds: ([Int]) -> Void     @State private var upperText: String = ""    @State private var lowerText: String = ""     var body: some View {        VStack(alignment: .leading, spacing: 6) {            HStack(alignment: .firstTextBaseline, spacing: 10) {                Text(self.title)                    .font(.footnote.weight(.semibold))                    .frame(width: 110, alignment: .leading)                 Text(L("quota_warning_upper"))                    .font(.footnote)                    .foregroundStyle(.secondary)                 TextField("50", text: self.$upperText)                    .textFieldStyle(.roundedBorder)                    .font(.footnote)                    .frame(width: 56)                    .onChange(of: self.upperText) { _, value in                        self.upperText = Self.filteredIntegerText(value)                    }                    .onSubmit { self.commit() }                 Text(L("quota_warning_lower"))                    .font(.footnote)                    .foregroundStyle(.secondary)                 TextField("20", text: self.$lowerText)                    .textFieldStyle(.roundedBorder)                    .font(.footnote)                    .frame(width: 56)                    .onChange(of: self.lowerText) { _, value in                        self.lowerText = Self.filteredIntegerText(value)                    }                    .onSubmit { self.commit() }                 Button(L("apply")) { self.commit() }                    .controlSize(.small)            }             if !self.subtitle.isEmpty {                Text(self.subtitle)                    .font(.footnote)                    .foregroundStyle(.secondary)                    .fixedSize(horizontal: false, vertical: true)            }        }        .onAppear { self.updateText(from: self.thresholds()) }        .onChange(of: self.thresholds()) { _, value in            self.updateText(from: value)        }    }     private func commit() {        let sanitized = QuotaWarningThresholds.resolved(            upper: Self.integer(from: self.upperText),            lower: Self.integer(from: self.lowerText))        self.updateText(from: sanitized)        self.setThresholds(sanitized)    }     private func updateText(from thresholds: [Int]) {        let pair = Self.pair(from: thresholds)        self.upperText = pair.upper.map(String.init) ?? ""        self.lowerText = pair.lower.map(String.init) ?? ""    }     private static func pair(from thresholds: [Int]) -> (upper: Int?, lower: Int?) {        let sanitized = QuotaWarningThresholds.sanitized(thresholds)        return (sanitized.first, sanitized.dropFirst().first)    }     private static func integer(from text: String) -> Int? {        guard !text.isEmpty else { return nil }        return Int(text)    }     private static func filteredIntegerText(_ text: String) -> String {        String(text.filter(\.isNumber).prefix(2))    }}