625 lines · 22.5 KB · Swift
RawDownload
import CodexBarCoreimport SwiftUI enum ProviderMetricInlinePresentation: Equatable {    case progress    case status(String)} @MainActorstruct ProviderDetailView<SupplementaryContent: View>: View {    let provider: UsageProvider    @Bindable var store: UsageStore    @Binding var isEnabled: Bool    let subtitle: String    let model: UsageMenuCardView.Model    let openAIWebDiagnostic: String?    let settingsPickers: [ProviderSettingsPickerDescriptor]    let settingsToggles: [ProviderSettingsToggleDescriptor]    let settingsFields: [ProviderSettingsFieldDescriptor]    let settingsActions: [ProviderSettingsActionsDescriptor]    let settingsTokenAccounts: ProviderSettingsTokenAccountsDescriptor?    let settingsOrganizations: ProviderSettingsOrganizationsDescriptor?    let errorDisplay: ProviderErrorDisplay?    @Binding var isErrorExpanded: Bool    let onCopyError: (String) -> Void    let onRefresh: () -> Void    let supplementarySettingsContent: SupplementaryContent    let showsSupplementarySettingsContent: Bool     init(        provider: UsageProvider,        store: UsageStore,        isEnabled: Binding<Bool>,        subtitle: String,        model: UsageMenuCardView.Model,        openAIWebDiagnostic: String?,        settingsPickers: [ProviderSettingsPickerDescriptor],        settingsToggles: [ProviderSettingsToggleDescriptor],        settingsFields: [ProviderSettingsFieldDescriptor],        settingsActions: [ProviderSettingsActionsDescriptor] = [],        settingsTokenAccounts: ProviderSettingsTokenAccountsDescriptor?,        settingsOrganizations: ProviderSettingsOrganizationsDescriptor? = nil,        errorDisplay: ProviderErrorDisplay?,        isErrorExpanded: Binding<Bool>,        onCopyError: @escaping (String) -> Void,        onRefresh: @escaping () -> Void,        showsSupplementarySettingsContent: Bool = false,        @ViewBuilder supplementarySettingsContent: () -> SupplementaryContent)    {        self.provider = provider        self.store = store        self._isEnabled = isEnabled        self.subtitle = subtitle        self.model = model        self.openAIWebDiagnostic = openAIWebDiagnostic        self.settingsPickers = settingsPickers        self.settingsToggles = settingsToggles        self.settingsFields = settingsFields        self.settingsActions = settingsActions        self.settingsTokenAccounts = settingsTokenAccounts        self.settingsOrganizations = settingsOrganizations        self.errorDisplay = errorDisplay        self._isErrorExpanded = isErrorExpanded        self.onCopyError = onCopyError        self.onRefresh = onRefresh        self.showsSupplementarySettingsContent = showsSupplementarySettingsContent        self.supplementarySettingsContent = supplementarySettingsContent()    }     static func metricTitle(provider: UsageProvider, metric: UsageMenuCardView.Model.Metric) -> String {        L(UsageMenuCardView.popupMetricTitle(provider: provider, metric: metric))    }     static func metricInlinePresentation(        _ metric: UsageMenuCardView.Model.Metric) -> ProviderMetricInlinePresentation    {        if let statusText = metric.statusText {            return .status(statusText)        }        return .progress    }     static func planRow(provider: UsageProvider, planText: String?) -> (label: String, value: String)? {        guard let rawPlan = planText?.trimmingCharacters(in: .whitespacesAndNewlines),              !rawPlan.isEmpty        else {            return nil        }        guard provider == .openrouter || provider == .mimo || provider == .moonshot || provider == .poe else {            return (label: L("Plan"), value: rawPlan)        }         let prefix = "Balance:"        if rawPlan.hasPrefix(prefix) {            let valueStart = rawPlan.index(rawPlan.startIndex, offsetBy: prefix.count)            let trimmedValue = rawPlan[valueStart...].trimmingCharacters(in: .whitespacesAndNewlines)            if !trimmedValue.isEmpty {                return (label: L("Balance"), value: trimmedValue)            }        }        if provider == .mimo {            return (label: L("Plan"), value: rawPlan)        }        return (label: L("Balance"), value: rawPlan)    }     private var menuBarSettingsPickers: [ProviderSettingsPickerDescriptor] {        self.settingsPickers.filter { $0.placement == .menuBar }    }     private var connectionSettingsPickers: [ProviderSettingsPickerDescriptor] {        self.settingsPickers.filter { $0.placement == .connection }    }     var body: some View {        Form {            Section {                ProviderDetailHeaderRow(                    provider: self.provider,                    store: self.store,                    isEnabled: self.$isEnabled,                    subtitle: self.subtitle,                    onRefresh: self.onRefresh)                 ProviderDetailInfoRows(                    provider: self.provider,                    store: self.store,                    isEnabled: self.isEnabled,                    model: self.model)            }             Section {                ProviderMetricsInlineView(                    provider: self.provider,                    model: self.model,                    openAIWebDiagnostic: self.openAIWebDiagnostic,                    isEnabled: self.isEnabled,                    isRefreshing: self.store.refreshingProviders.contains(self.provider))            } header: {                Text(L("Usage"))            }             if let errorDisplay {                Section {                    ProviderErrorView(                        title: String(                            format: L("last_fetch_failed_with_provider"),                            self.store.metadata(for: self.provider).displayName),                        display: errorDisplay,                        isExpanded: self.$isErrorExpanded,                        onCopy: { self.onCopyError(errorDisplay.full) })                }            }             if !self.menuBarSettingsPickers.isEmpty {                Section {                    ForEach(self.menuBarSettingsPickers) { picker in                        ProviderSettingsPickerRowView(picker: picker)                    }                } header: {                    Text(L("provider_section_menu_bar"))                }            }             if !self.connectionSettingsPickers.isEmpty || !self.settingsActions.isEmpty {                Section {                    ForEach(self.connectionSettingsPickers) { picker in                        ProviderSettingsPickerRowView(picker: picker)                    }                    ForEach(self.settingsActions) { descriptor in                        ProviderSettingsActionsRowView(descriptor: descriptor)                    }                } header: {                    Text(L("provider_section_connection"))                }            }             if let tokenAccounts = self.settingsTokenAccounts,               tokenAccounts.isVisible?() ?? true            {                ProviderSettingsTokenAccountsRowView(descriptor: tokenAccounts)            }             ForEach(self.settingsFields) { field in                ProviderSettingsFieldRowView(field: field)            }             if let organizations = self.settingsOrganizations {                ProviderSettingsOrganizationsRowView(descriptor: organizations)            }             if self.showsSupplementarySettingsContent {                self.supplementarySettingsContent            }             ProviderQuotaWarningSettingsView(provider: self.provider, settings: self.store.settings)             if !self.settingsToggles.isEmpty {                Section {                    ForEach(self.settingsToggles) { toggle in                        ProviderSettingsToggleRowView(toggle: toggle)                    }                } header: {                    Text(L("Options"))                }            }        }        .formStyle(.grouped)        .scrollContentBackground(.hidden)    }} @MainActorprivate struct ProviderDetailHeaderRow: View {    let provider: UsageProvider    @Bindable var store: UsageStore    @Binding var isEnabled: Bool    let subtitle: String    let onRefresh: () -> Void     var body: some View {        HStack(alignment: .center, spacing: 12) {            ProviderDetailBrandIcon(provider: self.provider)             VStack(alignment: .leading, spacing: 2) {                Text(self.store.metadata(for: self.provider).displayName)                    .font(.title3.weight(.semibold))                 Text(self.detailSubtitle)                    .font(.footnote)                    .foregroundStyle(.secondary)            }             Spacer(minLength: 12)             Button {                self.onRefresh()            } label: {                Image(systemName: "arrow.clockwise")            }            .buttonStyle(.borderless)            .help(L("Refresh"))             Toggle(L("Enabled"), isOn: self.$isEnabled)                .labelsHidden()                .toggleStyle(.switch)                .controlSize(.small)        }        .padding(.vertical, 2)    }     private var detailSubtitle: String {        let lines = self.subtitle.split(separator: "\n", omittingEmptySubsequences: false)        guard lines.count >= 2 else { return self.subtitle }        let first = lines[0]        let rest = lines.dropFirst().joined(separator: "\n")        let tail = rest.trimmingCharacters(in: .whitespacesAndNewlines)        if tail.isEmpty { return String(first) }        return "\(first) • \(tail)"    }} @MainActorprivate struct ProviderDetailBrandIcon: View {    let provider: UsageProvider     var body: some View {        if let brand = ProviderBrandIcon.image(for: self.provider) {            Image(nsImage: brand)                .resizable()                .scaledToFit()                .frame(width: 28, height: 28)                .foregroundStyle(.secondary)                .accessibilityHidden(true)        } else {            Image(systemName: "circle.dotted")                .font(.system(size: 24, weight: .regular))                .foregroundStyle(.secondary)                .accessibilityHidden(true)        }    }} @MainActorprivate struct ProviderDetailInfoRows: View {    let provider: UsageProvider    @Bindable var store: UsageStore    let isEnabled: Bool    let model: UsageMenuCardView.Model     var body: some View {        ProviderDetailInfoRow(label: L("Source"), value: self.store.sourceLabel(for: self.provider))        ProviderDetailInfoRow(label: L("Version"), value: self.store.version(for: self.provider) ?? L("not detected"))        ProviderDetailInfoRow(label: L("Updated"), value: self.updatedText)         if let status = self.store.status(for: self.provider) {            ProviderDetailInfoRow(label: L("Status"), value: status.description ?? status.indicator.label)        }         if !self.model.email.isEmpty {            ProviderDetailInfoRow(label: L("Account"), value: self.model.email)        }         if self.provider == .kiro,           let authMethod = self.store.snapshot(for: self.provider)?.loginMethod(for: .kiro),           !authMethod.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty        {            ProviderDetailInfoRow(label: L("Auth"), value: authMethod)        }         if let planRow = ProviderDetailView<EmptyView>.planRow(            provider: self.provider,            planText: self.model.planText)        {            ProviderDetailInfoRow(label: planRow.label, value: planRow.value)        }    }     private var updatedText: String {        if let updated = self.store.snapshot(for: self.provider)?.updatedAt {            return UsageFormatter.updatedString(from: updated)        }        if self.store.refreshingProviders.contains(self.provider) {            return L("Refreshing")        }        if self.store.unavailableMessage(for: self.provider) != nil {            return L("Unavailable")        }        return L("Not fetched yet")    }} private struct ProviderDetailInfoRow: View {    let label: String    let value: String     var body: some View {        LabeledContent(self.label) {            Text(self.value)                .foregroundStyle(.secondary)                .multilineTextAlignment(.trailing)                .lineLimit(2)                .textSelection(.enabled)        }    }} @MainActorstruct ProviderMetricsInlineView: View {    let provider: UsageProvider    let model: UsageMenuCardView.Model    let openAIWebDiagnostic: String?    let isEnabled: Bool    let isRefreshing: Bool     struct InfoRow: Identifiable, Equatable {        enum ID: Hashable {            case credits            case openAIWeb        }         let id: ID        let label: String        let value: String    }     static func infoRows(        for model: UsageMenuCardView.Model,        openAIWebDiagnostic: String?) -> [InfoRow]    {        var rows: [InfoRow] = []        if let credits = model.creditsText {            rows.append(InfoRow(id: .credits, label: L("Credits"), value: credits))        }        if let diagnostic = openAIWebDiagnostic {            rows.append(InfoRow(id: .openAIWeb, label: L("OpenAI web extras"), value: diagnostic))        }        return rows    }     var body: some View {        let hasMetrics = !self.model.metrics.isEmpty        let hasUsageNotes = !self.model.usageNotes.isEmpty        let infoRows = Self.infoRows(for: self.model, openAIWebDiagnostic: self.openAIWebDiagnostic)        let hasProviderCost = self.model.providerCost != nil        let hasTokenUsage = self.model.tokenUsage != nil        let hasResetCredits = self.model.codexResetCredits != nil         if !hasMetrics, !hasUsageNotes, !hasProviderCost, infoRows.isEmpty, !hasTokenUsage, !hasResetCredits {            Text(self.placeholderText)                .font(.footnote)                .foregroundStyle(.secondary)        } else {            ForEach(self.model.metrics, id: \.id) { metric in                ProviderMetricInlineRow(                    metric: metric,                    title: ProviderDetailView<EmptyView>.metricTitle(provider: self.provider, metric: metric),                    progressColor: self.model.progressColor)            }             if hasUsageNotes {                VStack(alignment: .leading, spacing: 4) {                    ForEach(Array(self.model.usageNotes.enumerated()), id: \.offset) { _, note in                        Text(note)                            .font(.footnote)                            .foregroundStyle(.secondary)                            .lineLimit(2)                            .fixedSize(horizontal: false, vertical: true)                    }                }            }             ForEach(infoRows) { row in                ProviderDetailInfoRow(label: row.label, value: row.value)            }             if let resetCredits = self.model.codexResetCredits {                ProviderCodexResetCreditsInlineRow(presentation: resetCredits)            }             if let providerCost = self.model.providerCost {                ProviderMetricInlineCostRow(                    section: providerCost,                    progressColor: self.model.progressColor)            }             if let tokenUsage = self.model.tokenUsage {                ProviderMetricInlineTextRow(                    title: L("Cost"),                    value: tokenUsage.sessionLine)                ProviderMetricInlineTextRow(title: "", value: tokenUsage.monthLine)                if self.model.provider == .codex, let hint = tokenUsage.hintLine, !hint.isEmpty {                    ProviderMetricInlineTextRow(title: "", value: hint)                }            }        }    }     private var placeholderText: String {        Self.placeholderText(            isEnabled: self.isEnabled,            isRefreshing: self.isRefreshing,            modelPlaceholder: self.model.placeholder)    }     static func placeholderText(        isEnabled: Bool,        isRefreshing: Bool,        modelPlaceholder: String?) -> String    {        if !isEnabled {            return L("Disabled — no recent data")        }        if isRefreshing {            return L("Refreshing")        }        return modelPlaceholder.map(L) ?? L("No usage yet")    }} private struct ProviderMetricInlineRow: View {    let metric: UsageMenuCardView.Model.Metric    let title: String    let progressColor: Color     var body: some View {        VStack(alignment: .leading, spacing: 4) {            switch ProviderDetailView<EmptyView>.metricInlinePresentation(self.metric) {            case let .status(statusText):                HStack(alignment: .firstTextBaseline, spacing: 8) {                    Text(self.title)                        .font(.subheadline.weight(.semibold))                        .lineLimit(1)                    Spacer(minLength: 8)                    Text(statusText)                        .font(.footnote)                        .foregroundStyle(.secondary)                }            case .progress:                HStack(alignment: .firstTextBaseline, spacing: 8) {                    Text(self.title)                        .font(.subheadline.weight(.semibold))                        .lineLimit(1)                    Spacer(minLength: 8)                    Text(self.metric.percentLabel)                        .font(.footnote)                        .foregroundStyle(.secondary)                        .monospacedDigit()                }                 UsageProgressBar(                    percent: self.metric.percent,                    tint: self.progressColor,                    accessibilityLabel: self.metric.percentStyle.accessibilityLabel,                    pacePercent: self.metric.pacePercent,                    paceOnTop: self.metric.paceOnTop,                    warningMarkerPercents: self.metric.warningMarkerPercents,                    workdayMarkerPercents: self.metric.workdayMarkerPercents)                    .frame(maxWidth: .infinity) 

Lines 1–500 of 625.