331 lines · 12.5 KB · Swift
RawDownload
import Foundationimport SwiftUI protocol CodexAmbientLoginRunning: Sendable {    func run(timeout: TimeInterval) async -> CodexLoginRunner.Result} struct DefaultCodexAmbientLoginRunner: CodexAmbientLoginRunning {    func run(timeout: TimeInterval) async -> CodexLoginRunner.Result {        await CodexLoginRunner.run(timeout: timeout)    }} struct CodexAccountsSectionNotice: Equatable {    enum Tone: Equatable {        case secondary        case warning    }     let text: String    let tone: Tone} struct CodexAccountsSectionState: Equatable {    let visibleAccounts: [CodexVisibleAccount]    let activeVisibleAccountID: String?    let liveVisibleAccountID: String?    let hasUnreadableManagedAccountStore: Bool    let isAuthenticatingManagedAccount: Bool    let authenticatingManagedAccountID: UUID?    let isRemovingManagedAccount: Bool    let isAuthenticatingLiveAccount: Bool    let isPromotingSystemAccount: Bool    let notice: CodexAccountsSectionNotice?     var showsActivePicker: Bool {        self.visibleAccounts.count > 1    }     var singleVisibleAccount: CodexVisibleAccount? {        self.visibleAccounts.count == 1 ? self.visibleAccounts.first : nil    }     var systemVisibleAccount: CodexVisibleAccount? {        guard let liveVisibleAccountID else { return nil }        return self.visibleAccounts.first { $0.id == liveVisibleAccountID }    }     var showsSystemPicker: Bool {        self.visibleAccounts.count > 1 || (self.liveVisibleAccountID == nil && !self.visibleAccounts.isEmpty)    }     var systemDisplayName: String {        self.systemVisibleAccount?.displayName ?? L("No system account")    }     var canAddAccount: Bool {        !self.hasUnreadableManagedAccountStore &&            !self.isAuthenticatingManagedAccount &&            !self.isRemovingManagedAccount &&            !self.isAuthenticatingLiveAccount &&            !self.isPromotingSystemAccount    }     var addAccountTitle: String {        if self.isAuthenticatingManagedAccount, self.authenticatingManagedAccountID == nil {            return L("Adding Account…")        }        return L("Add Account")    }     func showsLiveBadge(for account: CodexVisibleAccount) -> Bool {        account.isLive    }     var isSystemSelectionDisabled: Bool {        self.hasUnreadableManagedAccountStore ||            self.isAuthenticatingManagedAccount ||            self.isRemovingManagedAccount ||            self.isAuthenticatingLiveAccount ||            self.isPromotingSystemAccount    }     func canPromoteToSystem(_ account: CodexVisibleAccount) -> Bool {        guard self.isSystemSelectionDisabled == false else { return false }        guard account.id != self.liveVisibleAccountID else { return false }        return account.storedAccountID != nil    }     func canReauthenticate(_ account: CodexVisibleAccount) -> Bool {        guard account.canReauthenticate else { return false }        guard self.isAuthenticatingManagedAccount == false else { return false }        guard self.isRemovingManagedAccount == false else { return false }        guard self.isAuthenticatingLiveAccount == false else { return false }        guard self.isPromotingSystemAccount == false else { return false }        if account.storedAccountID != nil {            return self.hasUnreadableManagedAccountStore == false        }        return true    }     func canRemove(_ account: CodexVisibleAccount) -> Bool {        guard account.canRemove else { return false }        guard self.isAuthenticatingManagedAccount == false else { return false }        guard self.isRemovingManagedAccount == false else { return false }        guard self.isAuthenticatingLiveAccount == false else { return false }        guard self.isPromotingSystemAccount == false else { return false }        return self.hasUnreadableManagedAccountStore == false    }     func reauthenticateTitle(for account: CodexVisibleAccount) -> String {        if let accountID = account.storedAccountID,           self.isAuthenticatingManagedAccount,           self.authenticatingManagedAccountID == accountID        {            return L("Re-authenticating…")        }        if account.storedAccountID == nil, self.isAuthenticatingLiveAccount {            return L("Re-authenticating…")        }        return L("Re-auth")    }} @MainActorstruct CodexAccountsSectionView: View {    let state: CodexAccountsSectionState    let setActiveVisibleAccount: (String) -> Void    let reauthenticateAccount: (CodexVisibleAccount) -> Void    let removeAccount: (CodexVisibleAccount) -> Void    let requestSystemVisibleAccount: (String) -> Void    let addAccount: () -> Void     var body: some View {        ProviderSettingsSection(title: L("Accounts")) {            if let selection = self.activeSelectionBinding {                VStack(alignment: .leading, spacing: 6) {                    HStack(alignment: .firstTextBaseline, spacing: 10) {                        Text(L("Active"))                            .font(.subheadline.weight(.semibold))                            .frame(width: ProviderSettingsMetrics.pickerLabelWidth, alignment: .leading)                         Picker("", selection: selection) {                            ForEach(self.state.visibleAccounts) { account in                                Text(account.displayName).tag(account.id)                            }                        }                        .labelsHidden()                        .pickerStyle(.menu)                        .controlSize(.small)                         Spacer(minLength: 0)                    }                     Text(L("Choose which Codex account CodexBar should follow."))                        .font(.footnote)                        .foregroundStyle(.secondary)                     self.systemRow(selection: self.systemSelectionBinding)                }                .disabled(                    self.state.isAuthenticatingManagedAccount ||                        self.state.isRemovingManagedAccount ||                        self.state.isAuthenticatingLiveAccount ||                        self.state.isPromotingSystemAccount)            } else if let account = self.state.singleVisibleAccount {                VStack(alignment: .leading, spacing: 6) {                    HStack(alignment: .firstTextBaseline, spacing: 10) {                        Text(L("Account"))                            .font(.subheadline.weight(.semibold))                            .frame(width: ProviderSettingsMetrics.pickerLabelWidth, alignment: .leading)                         Text(account.displayName)                            .font(.subheadline)                         Spacer(minLength: 0)                    }                     self.systemRow(selection: nil)                }            }             if self.state.visibleAccounts.isEmpty {                Text(L("No Codex accounts detected yet."))                    .font(.footnote)                    .foregroundStyle(.secondary)            } else {                VStack(alignment: .leading, spacing: 10) {                    ForEach(self.state.visibleAccounts) { account in                        CodexAccountsSectionRowView(                            account: account,                            showsSystemBadge: self.state.showsLiveBadge(for: account),                            reauthenticateTitle: self.state.reauthenticateTitle(for: account),                            canReauthenticate: self.state.canReauthenticate(account),                            canRemove: self.state.canRemove(account),                            onReauthenticate: { self.reauthenticateAccount(account) },                            onRemove: { self.removeAccount(account) })                    }                }            }             if let notice = self.state.notice {                Text(notice.text)                    .font(.footnote)                    .foregroundStyle(notice.tone == .warning ? .red : .secondary)                    .fixedSize(horizontal: false, vertical: true)            }             Button(self.state.addAccountTitle) {                self.addAccount()            }            .buttonStyle(.bordered)            .controlSize(.small)            .disabled(self.state.canAddAccount == false)        }    }     private var activeSelectionBinding: Binding<String>? {        guard self.state.showsActivePicker else { return nil }        let fallbackID = self.state.activeVisibleAccountID ?? self.state.visibleAccounts.first?.id        guard let fallbackID else { return nil }        return Binding(            get: { self.state.activeVisibleAccountID ?? fallbackID },            set: { self.setActiveVisibleAccount($0) })    }     private var systemSelectionBinding: Binding<String>? {        guard self.state.showsSystemPicker else { return nil }        guard let liveVisibleAccountID = self.state.liveVisibleAccountID else { return nil }        return Binding(            get: { self.state.liveVisibleAccountID ?? liveVisibleAccountID },            set: { self.requestSystemVisibleAccount($0) })    }     @ViewBuilder    private func systemRow(selection: Binding<String>?) -> some View {        HStack(alignment: .firstTextBaseline, spacing: 10) {            Text(L("System"))                .font(.subheadline.weight(.semibold))                .frame(width: ProviderSettingsMetrics.pickerLabelWidth, alignment: .leading)             if let selection {                Picker("", selection: selection) {                    ForEach(self.state.visibleAccounts) { account in                        Text(account.displayName)                            .tag(account.id)                    }                }                .labelsHidden()                .pickerStyle(.menu)                .controlSize(.small)                .disabled(self.state.isSystemSelectionDisabled)            } else if self.state.showsSystemPicker {                Menu {                    ForEach(self.state.visibleAccounts) { account in                        Button(account.displayName) {                            self.requestSystemVisibleAccount(account.id)                        }                        .disabled(self.state.canPromoteToSystem(account) == false)                    }                } label: {                    Text(self.state.systemDisplayName)                        .font(.subheadline)                        .foregroundStyle(.secondary)                }                .disabled(self.state.isSystemSelectionDisabled)            } else {                Text(self.state.systemDisplayName)                    .font(.subheadline)                    .foregroundStyle(self.state.systemVisibleAccount == nil ? .secondary : .primary)            }             Spacer(minLength: 0)        }         Text(L("The default Codex account on this Mac."))            .font(.footnote)            .foregroundStyle(.secondary)    }} private struct CodexAccountsSectionRowView: View {    let account: CodexVisibleAccount    let showsSystemBadge: Bool    let reauthenticateTitle: String    let canReauthenticate: Bool    let canRemove: Bool    let onReauthenticate: () -> Void    let onRemove: () -> Void     var body: some View {        HStack(alignment: .center, spacing: 12) {            VStack(alignment: .leading, spacing: 2) {                HStack(alignment: .firstTextBaseline, spacing: 6) {                    Text(self.account.displayName)                        .font(.subheadline.weight(.semibold))                    if self.showsSystemBadge {                        Text(L("(System)"))                            .font(.caption.weight(.semibold))                            .foregroundStyle(.secondary)                    }                }                if let health = self.account.authenticationHealthLabel {                    Text(health)                        .font(.caption)                        .foregroundStyle(.orange)                }            }             Spacer(minLength: 8)             if self.account.canReauthenticate {                Button(self.reauthenticateTitle) {                    self.onReauthenticate()                }                .buttonStyle(.bordered)                .controlSize(.small)                .disabled(self.canReauthenticate == false)            }             if self.account.canRemove {                Button(L("Remove")) {                    self.onRemove()                }                .buttonStyle(.bordered)                .controlSize(.small)                .disabled(self.canRemove == false)            }        }    }}