621 lines · 23.2 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 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,        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.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 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)            }        }        return (label: L("Balance"), value: rawPlan)    }     var body: some View {        ScrollView {            VStack(alignment: .leading, spacing: 16) {                let labelWidth = self.detailLabelWidth                ProviderDetailHeaderView(                    provider: self.provider,                    store: self.store,                    isEnabled: self.$isEnabled,                    subtitle: self.subtitle,                    model: self.model,                    labelWidth: labelWidth,                    onRefresh: self.onRefresh)                 ProviderMetricsInlineView(                    provider: self.provider,                    model: self.model,                    isEnabled: self.isEnabled,                    labelWidth: labelWidth)                 if let errorDisplay {                    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.hasSettings {                    ProviderSettingsSection(title: L("Settings")) {                        ForEach(self.settingsPickers) { picker in                            ProviderSettingsPickerRowView(picker: picker)                        }                        if let tokenAccounts = self.settingsTokenAccounts,                           tokenAccounts.isVisible?() ?? true                        {                            ProviderSettingsTokenAccountsRowView(descriptor: tokenAccounts)                        }                        ForEach(self.settingsFields) { field in                            ProviderSettingsFieldRowView(field: field)                        }                        ForEach(self.settingsActions) { descriptor in                            ProviderSettingsActionsRowView(descriptor: descriptor)                        }                        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 {                    ProviderSettingsSection(title: L("Options")) {                        ForEach(self.settingsToggles) { toggle in                            ProviderSettingsToggleRowView(toggle: toggle)                        }                    }                }            }            .frame(maxWidth: ProviderSettingsMetrics.detailMaxWidth, alignment: .leading)            .padding(.vertical, 12)            .padding(.horizontal, 8)        }        .frame(maxWidth: .infinity, alignment: .leading)    }     private var hasSettings: Bool {        !self.settingsPickers.isEmpty ||            !self.settingsFields.isEmpty ||            !self.settingsActions.isEmpty ||            self.settingsTokenAccounts != nil ||            self.settingsOrganizations != nil    }     private var detailLabelWidth: CGFloat {        var infoLabels = [L("State"), L("Source"), L("Version"), L("Updated")]        if self.store.status(for: self.provider) != nil {            infoLabels.append(L("Status"))        }        if !self.model.email.isEmpty {            infoLabels.append(L("Account"))        }        if self.provider == .kiro,           self.model.metrics.isEmpty == false        {            infoLabels.append(L("Auth"))        }        if let planRow = Self.planRow(provider: self.provider, planText: self.model.planText) {            infoLabels.append(planRow.label)        }         var metricLabels = self.model.metrics.map { metric in            Self.metricTitle(provider: self.provider, metric: metric)        }        if self.model.creditsText != nil {            metricLabels.append(L("Credits"))        }        if let providerCost = self.model.providerCost {            metricLabels.append(providerCost.title)        }        if self.model.tokenUsage != nil {            metricLabels.append(L("Cost"))        }         let infoWidth = ProviderSettingsMetrics.labelWidth(            for: infoLabels,            font: ProviderSettingsMetrics.infoLabelFont())        let metricWidth = ProviderSettingsMetrics.labelWidth(            for: metricLabels,            font: ProviderSettingsMetrics.metricLabelFont())        return max(infoWidth, metricWidth)    }} @MainActorprivate struct ProviderDetailHeaderView: View {    let provider: UsageProvider    @Bindable var store: UsageStore    @Binding var isEnabled: Bool    let subtitle: String    let model: UsageMenuCardView.Model    let labelWidth: CGFloat    let onRefresh: () -> Void     var body: some View {        VStack(alignment: .leading, spacing: 12) {            HStack(alignment: .center, spacing: 12) {                ProviderDetailBrandIcon(provider: self.provider)                 VStack(alignment: .leading, spacing: 4) {                    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(.bordered)                .controlSize(.small)                .help(L("Refresh"))                 Toggle("", isOn: self.$isEnabled)                    .labelsHidden()                    .toggleStyle(.switch)                    .controlSize(.small)            }             ProviderDetailInfoGrid(                provider: self.provider,                store: self.store,                isEnabled: self.isEnabled,                model: self.model,                labelWidth: self.labelWidth)        }    }     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 ProviderDetailInfoGrid: View {    let provider: UsageProvider    @Bindable var store: UsageStore    let isEnabled: Bool    let model: UsageMenuCardView.Model    let labelWidth: CGFloat     var body: some View {        let status = self.store.status(for: self.provider)        let source = self.store.sourceLabel(for: self.provider)        let version = self.store.version(for: self.provider) ?? L("not detected")        let updated = self.updatedText        let email = self.model.email        let enabledText = self.isEnabled ? L("Enabled") : L("Disabled")         Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 6) {            ProviderDetailInfoRow(label: L("State"), value: enabledText, labelWidth: self.labelWidth)            ProviderDetailInfoRow(label: L("Source"), value: source, labelWidth: self.labelWidth)            ProviderDetailInfoRow(label: L("Version"), value: version, labelWidth: self.labelWidth)            ProviderDetailInfoRow(label: L("Updated"), value: updated, labelWidth: self.labelWidth)             if let status {                ProviderDetailInfoRow(                    label: L("Status"),                    value: status.description ?? status.indicator.label,                    labelWidth: self.labelWidth)            }             if !email.isEmpty {                ProviderDetailInfoRow(label: L("Account"), value: email, labelWidth: self.labelWidth)            }             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, labelWidth: self.labelWidth)            }             if let planRow = ProviderDetailView<EmptyView>.planRow(                provider: self.provider,                planText: self.model.planText)            {                ProviderDetailInfoRow(label: planRow.label, value: planRow.value, labelWidth: self.labelWidth)            }        }        .font(.footnote)        .foregroundStyle(.secondary)    }     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    let labelWidth: CGFloat     var body: some View {        GridRow {            Text(self.label)                .frame(width: self.labelWidth, alignment: .leading)            Text(self.value)                .lineLimit(2)        }    }} @MainActorstruct ProviderMetricsInlineView: View {    let provider: UsageProvider    let model: UsageMenuCardView.Model    let isEnabled: Bool    let labelWidth: CGFloat     var body: some View {        let hasMetrics = !self.model.metrics.isEmpty        let hasUsageNotes = !self.model.usageNotes.isEmpty        let hasCredits = self.model.creditsText != nil        let hasProviderCost = self.model.providerCost != nil        let hasTokenUsage = self.model.tokenUsage != nil        ProviderSettingsSection(            title: L("Usage"),            spacing: 8,            verticalPadding: 6,            horizontalPadding: 0)        {            if !hasMetrics, !hasUsageNotes, !hasProviderCost, !hasCredits, !hasTokenUsage {                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,                        labelWidth: self.labelWidth)                }                 if hasUsageNotes {                    ProviderUsageNotesInlineView(                        notes: self.model.usageNotes,                        labelWidth: self.labelWidth,                        alignsWithMetricContent: hasMetrics)                }                 if let credits = self.model.creditsText {                    ProviderMetricInlineTextRow(                        title: L("Credits"),                        value: credits,                        labelWidth: self.labelWidth)                }                 if let providerCost = self.model.providerCost {                    ProviderMetricInlineCostRow(                        section: providerCost,                        progressColor: self.model.progressColor,                        labelWidth: self.labelWidth)                }                 if let tokenUsage = self.model.tokenUsage {                    ProviderMetricInlineTextRow(                        title: L("Cost"),                        value: tokenUsage.sessionLine,                        labelWidth: self.labelWidth)                    ProviderMetricInlineTextRow(                        title: "",                        value: tokenUsage.monthLine,                        labelWidth: self.labelWidth)                }            }        }    }     private var placeholderText: String {        if !self.isEnabled {            return L("Disabled — no recent data")        }        return self.model.placeholder.map(L) ?? L("No usage yet")    }} private struct ProviderMetricInlineRow: View {    let metric: UsageMenuCardView.Model.Metric    let title: String    let progressColor: Color    let labelWidth: CGFloat     var body: some View {        HStack(alignment: .top, spacing: 10) {            Text(self.title)                .font(.subheadline.weight(.semibold))                .lineLimit(1)                .frame(width: self.labelWidth, alignment: .leading)             VStack(alignment: .leading, spacing: 4) {                switch ProviderDetailView<EmptyView>.metricInlinePresentation(self.metric) {                case let .status(statusText):                    Text(statusText)                        .font(.footnote)                        .foregroundStyle(.secondary)                case .progress:                    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)                        .frame(minWidth: ProviderSettingsMetrics.metricBarWidth, maxWidth: .infinity)                     HStack(alignment: .firstTextBaseline, spacing: 8) {                        Text(self.metric.percentLabel)                            .font(.footnote)                            .foregroundStyle(.secondary)                            .monospacedDigit()                        Spacer(minLength: 8)                        if let resetText = self.metric.resetText, !resetText.isEmpty {                            Text(resetText)                                .font(.footnote)                                .foregroundStyle(.secondary)                        }                    }                     let hasLeftDetail = self.metric.detailLeftText?.isEmpty == false

Lines 1–500 of 621.