chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,333 @@
|
||||
import Foundation
|
||||
import 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")
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
struct 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 {
|
||||
Section {
|
||||
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)
|
||||
} header: {
|
||||
Text(L("Accounts"))
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user