632 lines · 25.6 KB · Swift
RawDownload
import CodexBarCoreimport SwiftUI @MainActorstruct ProviderSettingsToggleRowView: View {    let toggle: ProviderSettingsToggleDescriptor     var body: some View {        let isEnabled = self.toggle.isEnabled?() ?? true        VStack(alignment: .leading, spacing: 8) {            HStack(alignment: .firstTextBaseline, spacing: 12) {                VStack(alignment: .leading, spacing: 4) {                    Text(L(self.toggle.title))                        .font(.subheadline.weight(.semibold))                        .foregroundStyle(isEnabled ? .primary : .tertiary)                    Text(L(self.toggle.subtitle))                        .font(.footnote)                        .foregroundStyle(isEnabled ? .secondary : .tertiary)                        .fixedSize(horizontal: false, vertical: true)                }                Spacer(minLength: 8)                Toggle("", isOn: self.toggle.binding)                    .labelsHidden()                    .toggleStyle(.switch)            }             if self.toggle.binding.wrappedValue {                if let status = self.toggle.statusText?(), !status.isEmpty {                    Text(status)                        .font(.footnote)                        .foregroundStyle(.secondary)                        .lineLimit(4)                        .fixedSize(horizontal: false, vertical: true)                }                 let actions = self.toggle.actions.filter { $0.isVisible?() ?? true }                if !actions.isEmpty {                    HStack(spacing: 10) {                        ForEach(actions) { action in                            Button(L(action.title)) {                                Task { @MainActor in                                    await action.perform()                                }                            }                            .applyProviderSettingsButtonStyle(action.style)                            .controlSize(.small)                        }                    }                }            }        }        .disabled(!isEnabled)        .onChange(of: self.toggle.binding.wrappedValue) { _, enabled in            guard let onChange = self.toggle.onChange else { return }            Task { @MainActor in                await onChange(enabled)            }        }        .task(id: self.toggle.binding.wrappedValue) {            guard self.toggle.binding.wrappedValue else { return }            guard let onAppear = self.toggle.onAppearWhenEnabled else { return }            await onAppear()        }    }} @MainActorstruct ProviderSettingsPickerRowView: View {    let picker: ProviderSettingsPickerDescriptor     var body: some View {        let isEnabled = self.picker.isEnabled?() ?? true        let subtitle = self.picker.dynamicSubtitle?() ?? self.picker.subtitle        let trimmedSubtitle = subtitle.trimmingCharacters(in: .whitespacesAndNewlines)        LabeledContent {            HStack(spacing: 8) {                if let trailingText = self.picker.trailingText?(), !trailingText.isEmpty {                    Text(trailingText)                        .font(.footnote)                        .foregroundStyle(.secondary)                        .lineLimit(1)                        .truncationMode(.tail)                }                 let visibleActions = self.picker.trailingActions.filter { $0.isVisible?() ?? true }                ForEach(visibleActions) { action in                    Button(L(action.title)) {                        Task { @MainActor in                            await action.perform()                        }                    }                    .applyProviderSettingsButtonStyle(action.style)                    .controlSize(.small)                }                 Picker("", selection: self.picker.binding) {                    ForEach(self.picker.options) { option in                        Text(L(option.title)).tag(option.id)                    }                }                .labelsHidden()                .pickerStyle(.menu)                .fixedSize()            }        } label: {            SettingsRowLabel(                L(self.picker.title),                subtitle: trimmedSubtitle.isEmpty ? nil : L(trimmedSubtitle))        }        .disabled(!isEnabled)        .onChange(of: self.picker.binding.wrappedValue) { _, selection in            guard let onChange = self.picker.onChange else { return }            Task { @MainActor in                await onChange(selection)            }        }    }} /// Renders a provider settings field descriptor as its own grouped-form section:/// title becomes the header, subtitle/footer text become the footer, and the/// placeholder stays inside the field.@MainActorstruct ProviderSettingsFieldRowView: View {    let field: ProviderSettingsFieldDescriptor     var body: some View {        let trimmedTitle = self.field.title.trimmingCharacters(in: .whitespacesAndNewlines)        Section {            self.fieldView             let actions = self.field.actions.filter { $0.isVisible?() ?? true }            if !actions.isEmpty {                HStack(spacing: 10) {                    ForEach(actions) { action in                        Button(L(action.title)) {                            Task { @MainActor in                                await action.perform()                            }                        }                        .applyProviderSettingsButtonStyle(action.style)                        .controlSize(.small)                    }                }            }        } header: {            if !trimmedTitle.isEmpty {                Text(L(trimmedTitle))            }        } footer: {            self.footerView        }    }     private var fieldView: some View {        let prompt = (self.field.placeholder?.isEmpty == false) ? Text(L(self.field.placeholder ?? "")) : nil        return Group {            switch self.field.kind {            case .plain:                TextField(text: self.field.binding, prompt: prompt) {                    EmptyView()                }            case .secure:                SecureField(text: self.field.binding, prompt: prompt) {                    EmptyView()                }            }        }        .labelsHidden()        .textFieldStyle(.plain)        .onTapGesture { self.field.onActivate?() }    }     @ViewBuilder    private var footerView: some View {        let trimmedSubtitle = self.field.subtitle.trimmingCharacters(in: .whitespacesAndNewlines)        let footer = (self.field.footerText?.isEmpty == false) ? self.field.footerText : nil        if !trimmedSubtitle.isEmpty || footer != nil {            SettingsSectionFooter {                VStack(alignment: .leading, spacing: 3) {                    if !trimmedSubtitle.isEmpty {                        Text(L(trimmedSubtitle))                    }                    if let footer {                        Text(L(footer))                    }                }            }        }    }} @MainActorstruct ProviderSettingsActionsRowView: View {    let descriptor: ProviderSettingsActionsDescriptor     var body: some View {        VStack(alignment: .leading, spacing: 8) {            Text(L(self.descriptor.title))                .font(.subheadline.weight(.semibold))             if !self.descriptor.subtitle.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {                Text(L(self.descriptor.subtitle))                    .font(.footnote)                    .foregroundStyle(.secondary)                    .fixedSize(horizontal: false, vertical: true)            }             let actions = self.descriptor.actions.filter { $0.isVisible?() ?? true }            if !actions.isEmpty {                HStack(spacing: 10) {                    ForEach(actions) { action in                        Button(L(action.title)) {                            Task { @MainActor in                                await action.perform()                            }                        }                        .applyProviderSettingsButtonStyle(action.style)                        .controlSize(.small)                    }                }            }        }    }} @MainActorstruct ProviderSettingsTokenAccountsRowView: View {    struct TeamAccountDraft: Equatable {        var teamMode: Bool        var organizationID: String        var projectID: String         func normalizedForPersistence() -> Self {            guard self.teamMode else {                return Self(teamMode: false, organizationID: "", projectID: "")            }            return Self(                teamMode: true,                organizationID: self.organizationID.trimmingCharacters(in: .whitespacesAndNewlines),                projectID: self.projectID.trimmingCharacters(in: .whitespacesAndNewlines))        }    }     let descriptor: ProviderSettingsTokenAccountsDescriptor    @State private var newLabel: String = ""    @State private var newToken: String = ""    @State private var newOrgID: String = ""    @State private var newProjectID: String = ""    @State private var newTeamMode = false    @State private var teamDrafts: [UUID: TeamAccountDraft] = [:]     var body: some View {        Section {            let accounts = self.descriptor.accounts()            if accounts.isEmpty {                Text(L("No token accounts yet."))                    .font(.footnote)                    .foregroundStyle(.secondary)            } else {                ForEach(Array(accounts.enumerated()), id: \.element.id) { index, account in                    VStack(alignment: .leading, spacing: 8) {                        HStack(alignment: .center, spacing: 10) {                            Button {                                self.descriptor.setActiveIndex(index)                            } label: {                                HStack(alignment: .center, spacing: 8) {                                    Image(systemName: self.isActive(index: index, accountCount: accounts.count) ?                                        "checkmark.circle.fill" : "circle")                                        .font(.system(size: 13, weight: .medium))                                        .foregroundStyle(self.isActive(index: index, accountCount: accounts.count) ?                                            Color.accentColor : Color.secondary)                                    Text(account.displayName)                                        .font(                                            .footnote.weight(                                                self.isActive(index: index, accountCount: accounts.count) ?                                                    .semibold : .regular))                                        .foregroundStyle(.primary)                                    Spacer(minLength: 0)                                }                                .contentShape(Rectangle())                            }                            .buttonStyle(.plain)                             Button(L("Remove")) {                                self.descriptor.removeAccount(account.id)                            }                            .buttonStyle(.bordered)                            .controlSize(.small)                        }                        if self.descriptor.showsTeamModeControls {                            self.teamModeEditor(account: account)                        }                    }                }            }             if self.descriptor.primaryAddAction == nil {                VStack(alignment: .leading, spacing: 8) {                    HStack(spacing: 8) {                        TextField(text: self.$newLabel, prompt: Text(L("Label"))) {                            EmptyView()                        }                        .labelsHidden()                        .textFieldStyle(.roundedBorder)                        .font(.footnote)                        .frame(maxWidth: 160)                        SecureField(text: self.$newToken, prompt: Text(L(self.descriptor.placeholder))) {                            EmptyView()                        }                        .labelsHidden()                        .textFieldStyle(.roundedBorder)                        .font(.footnote)                        Button(L("Add")) {                            let label = self.newLabel.trimmingCharacters(in: .whitespacesAndNewlines)                            let token = self.newToken.trimmingCharacters(in: .whitespacesAndNewlines)                            guard !label.isEmpty, !token.isEmpty else { return }                            let orgID = self.descriptor.showsOrganizationField                                ? self.newOrgID.trimmingCharacters(in: .whitespacesAndNewlines)                                : ""                            let teamOrgID = self.newOrgID.trimmingCharacters(in: .whitespacesAndNewlines)                            let projectID = self.newProjectID.trimmingCharacters(in: .whitespacesAndNewlines)                            let usageScope = self.descriptor.showsTeamModeControls                                ? (self.newTeamMode ? "team" : "personal")                                : nil                            let accountOrganizationID = if self.newTeamMode {                                teamOrgID.isEmpty ? nil : teamOrgID                            } else {                                orgID.isEmpty ? nil : orgID                            }                            let accountWorkspaceID = self.newTeamMode && !projectID.isEmpty ? projectID : nil                            self.descriptor.addAccount(                                label,                                token,                                usageScope,                                accountOrganizationID,                                accountWorkspaceID)                            self.newLabel = ""                            self.newToken = ""                            self.newOrgID = ""                            self.newProjectID = ""                            self.newTeamMode = false                        }                        .buttonStyle(.bordered)                        .controlSize(.small)                        .disabled(Self.isAddDisabled(                            label: self.newLabel,                            token: self.newToken,                            showsTeamModeControls: self.descriptor.showsTeamModeControls,                            teamMode: self.newTeamMode,                            teamContext: (organizationID: self.newOrgID, projectID: self.newProjectID)))                    }                    if self.descriptor.showsOrganizationField {                        TextField(text: self.$newOrgID, prompt: Text(L("Org ID (optional)"))) {                            EmptyView()                        }                        .labelsHidden()                        .textFieldStyle(.roundedBorder)                        .font(.footnote)                        .help(                            L("Optional organization ID for accounts linked to multiple Anthropic organizations."))                    }                    if self.descriptor.showsTeamModeControls {                        Toggle(L("Team mode"), isOn: self.$newTeamMode)                            .toggleStyle(.checkbox)                            .font(.footnote)                        if self.newTeamMode {                            HStack(spacing: 8) {                                TextField(text: self.$newOrgID, prompt: Text(L("Organization ID"))) {                                    EmptyView()                                }                                .labelsHidden()                                .textFieldStyle(.roundedBorder)                                .font(.footnote)                                TextField(text: self.$newProjectID, prompt: Text(L("Project ID"))) {                                    EmptyView()                                }                                .labelsHidden()                                .textFieldStyle(.roundedBorder)                                .font(.footnote)                            }                        }                    }                }            }             HStack(spacing: 10) {                Button(L("Open token file")) {                    self.descriptor.openConfigFile()                }                .buttonStyle(.link)                .controlSize(.small)                Button(L("Reload")) {                    self.descriptor.reloadFromDisk()                }                .buttonStyle(.link)                .controlSize(.small)                 Spacer(minLength: 0)                 if let title = self.descriptor.primaryAddActionTitle,                   let action = self.descriptor.primaryAddAction                {                    Button(L(title)) {                        Task { @MainActor in                            await action()                        }                    }                    .buttonStyle(.bordered)                    .controlSize(.small)                }            }        } header: {            Text(L(self.descriptor.title))        } footer: {            if !self.descriptor.subtitle.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {                SettingsSectionFooter(L(self.descriptor.subtitle))            }        }    }     private func isActive(index: Int, accountCount: Int) -> Bool {        guard accountCount > 0 else { return false }        let selectedIndex = min(self.descriptor.activeIndex(), max(0, accountCount - 1))        return selectedIndex == index    }     private func teamModeEditor(account: ProviderTokenAccount) -> some View {        let draft = self.teamDraft(for: account)        let original = Self.teamAccountDraft(for: account)        return VStack(alignment: .leading, spacing: 6) {            Toggle(L("Team mode"), isOn: self.teamModeDraftBinding(account: account))                .toggleStyle(.checkbox)                .font(.footnote)            if draft.teamMode {                HStack(spacing: 8) {                    TextField(                        text: self.organizationIDDraftBinding(account: account),                        prompt: Text(L("Organization ID")))                    {                        EmptyView()                    }                    .labelsHidden()                    .textFieldStyle(.roundedBorder)                    .font(.footnote)                    TextField(                        text: self.projectIDDraftBinding(account: account),                        prompt: Text(L("Project ID")))                    {                        EmptyView()                    }                    .labelsHidden()                    .textFieldStyle(.roundedBorder)                    .font(.footnote)                }            }            Button(L("apply")) {                self.applyTeamDraft(account: account)            }            .buttonStyle(.bordered)            .controlSize(.small)            .disabled(Self.isTeamDraftApplyDisabled(draft: draft, original: original))        }        .padding(.leading, 24)    }     private func teamModeDraftBinding(account: ProviderTokenAccount) -> Binding<Bool> {        Binding(            get: { self.teamDraft(for: account).teamMode },            set: { enabled in                self.updateTeamDraft(account: account) { draft in                    draft.teamMode = enabled                }            })    }     private func organizationIDDraftBinding(account: ProviderTokenAccount) -> Binding<String> {        Binding(            get: { self.teamDraft(for: account).organizationID },            set: { value in                self.updateTeamDraft(account: account) { draft in                    draft.organizationID = value                }            })    }     private func projectIDDraftBinding(account: ProviderTokenAccount) -> Binding<String> {        Binding(            get: { self.teamDraft(for: account).projectID },            set: { value in                self.updateTeamDraft(account: account) { draft in                    draft.projectID = value                }            })    }     private func teamDraft(for account: ProviderTokenAccount) -> TeamAccountDraft {        self.teamDrafts[account.id] ?? Self.teamAccountDraft(for: account)    } 

Lines 1–500 of 632.