import CodexBarCore import Foundation import SwiftUI /// Settings UI context passed to provider implementations. /// /// Providers use this to: /// - bind to `SettingsStore` values /// - read current provider state from `UsageStore` /// - surface transient status text (e.g. "Importing cookies…") /// - request a shared confirmation alert (no provider-specific UI) @MainActor struct ProviderSettingsContext { let provider: UsageProvider let settings: SettingsStore let store: UsageStore let boolBinding: (ReferenceWritableKeyPath) -> Binding let stringBinding: (ReferenceWritableKeyPath) -> Binding let statusText: (String) -> String? let setStatusText: (String, String?) -> Void let lastAppActiveRunAt: (String) -> Date? let setLastAppActiveRunAt: (String, Date?) -> Void let requestConfirmation: (ProviderSettingsConfirmation) -> Void let runLoginFlow: () async -> Void init( provider: UsageProvider, settings: SettingsStore, store: UsageStore, boolBinding: @escaping (ReferenceWritableKeyPath) -> Binding, stringBinding: @escaping (ReferenceWritableKeyPath) -> Binding, statusText: @escaping (String) -> String?, setStatusText: @escaping (String, String?) -> Void, lastAppActiveRunAt: @escaping (String) -> Date?, setLastAppActiveRunAt: @escaping (String, Date?) -> Void, requestConfirmation: @escaping (ProviderSettingsConfirmation) -> Void, runLoginFlow: @escaping () async -> Void = {}) { self.provider = provider self.settings = settings self.store = store self.boolBinding = boolBinding self.stringBinding = stringBinding self.statusText = statusText self.setStatusText = setStatusText self.lastAppActiveRunAt = lastAppActiveRunAt self.setLastAppActiveRunAt = setLastAppActiveRunAt self.requestConfirmation = requestConfirmation self.runLoginFlow = runLoginFlow } } /// Shared confirmation alert descriptor. /// /// Providers can request confirmations (e.g. permission prompts) without supplying custom UI. @MainActor struct ProviderSettingsConfirmation { let title: String let message: String let confirmTitle: String let onConfirm: () -> Void } /// Shared toggle descriptor rendered in the Providers settings pane. @MainActor struct ProviderSettingsToggleDescriptor: Identifiable { let id: String let title: String let subtitle: String let binding: Binding /// Optional short status text shown under the toggle when enabled. let statusText: (() -> String?)? /// Optional actions shown under the toggle when enabled. let actions: [ProviderSettingsActionDescriptor] /// Optional runtime visibility gate. let isVisible: (() -> Bool)? /// Optional runtime enabled gate. let isEnabled: (() -> Bool)? /// Called whenever the toggle changes. let onChange: ((_ enabled: Bool) async -> Void)? /// Called when the app becomes active (used for "retry after permission grant" flows). let onAppDidBecomeActive: (() async -> Void)? /// Called when the view appears while the toggle is enabled. let onAppearWhenEnabled: (() async -> Void)? init( id: String, title: String, subtitle: String, binding: Binding, statusText: (() -> String?)?, actions: [ProviderSettingsActionDescriptor], isVisible: (() -> Bool)?, isEnabled: (() -> Bool)? = nil, onChange: ((_ enabled: Bool) async -> Void)?, onAppDidBecomeActive: (() async -> Void)?, onAppearWhenEnabled: (() async -> Void)?) { self.id = id self.title = title self.subtitle = subtitle self.binding = binding self.statusText = statusText self.actions = actions self.isVisible = isVisible self.isEnabled = isEnabled self.onChange = onChange self.onAppDidBecomeActive = onAppDidBecomeActive self.onAppearWhenEnabled = onAppearWhenEnabled } } /// Shared text field descriptor rendered in the Providers settings pane. @MainActor struct ProviderSettingsFieldDescriptor: Identifiable { enum Kind { case plain case secure } let id: String let title: String let subtitle: String var footerText: String? let kind: Kind let placeholder: String? let binding: Binding let actions: [ProviderSettingsActionDescriptor] let isVisible: (() -> Bool)? let onActivate: (() -> Void)? } /// Shared action row descriptor rendered in the Providers settings pane. @MainActor struct ProviderSettingsActionsDescriptor: Identifiable { let id: String let title: String let subtitle: String let actions: [ProviderSettingsActionDescriptor] let isVisible: (() -> Bool)? } /// Shared token account descriptor rendered in the Providers settings pane. @MainActor struct ProviderSettingsTokenAccountsDescriptor: Identifiable { let id: String let title: String let subtitle: String let placeholder: String let provider: UsageProvider let isVisible: (() -> Bool)? let accounts: () -> [ProviderTokenAccount] let activeIndex: () -> Int let setActiveIndex: (Int) -> Void let showsOrganizationField: Bool let showsTeamModeControls: Bool let addAccount: ( _ label: String, _ token: String, _ usageScope: String?, _ organizationID: String?, _ workspaceID: String?) -> Void let updateAccount: ( _ accountID: UUID, _ usageScope: String?, _ organizationID: String?, _ workspaceID: String?) -> Void let removeAccount: (_ accountID: UUID) -> Void let primaryAddActionTitle: String? let primaryAddAction: (() async -> Void)? let openConfigFile: () -> Void let reloadFromDisk: () -> Void } /// Shared organizations descriptor rendered in the Providers settings pane. /// /// Used by providers that let the user opt in to additional account scopes /// (e.g. Kilo organizations) shown alongside the personal account. @MainActor struct ProviderSettingsOrganizationsDescriptor: Identifiable { struct Entry: Identifiable { let id: String let title: String let subtitle: String? let localizesTitle: Bool let localizesSubtitle: Bool let isEnabled: Bool let isLocked: Bool init( id: String, title: String, subtitle: String?, localizesTitle: Bool = true, localizesSubtitle: Bool = true, isEnabled: Bool, isLocked: Bool) { self.id = id self.title = title self.subtitle = subtitle self.localizesTitle = localizesTitle self.localizesSubtitle = localizesSubtitle self.isEnabled = isEnabled self.isLocked = isLocked } } struct RefreshOutcome { let success: Bool let errorMessage: String? } let id: String let title: String let subtitle: String? let entries: () -> [Entry] let onToggle: (String, Bool) -> Void let onRefresh: () async -> RefreshOutcome let canRefresh: () -> Bool } /// Shared picker descriptor rendered in the Providers settings pane. enum ProviderSettingsPickerPlacement: Equatable { case menuBar case connection } @MainActor struct ProviderSettingsPickerDescriptor: Identifiable { let id: String let title: String let subtitle: String let placement: ProviderSettingsPickerPlacement let dynamicSubtitle: (() -> String?)? let binding: Binding let options: [ProviderSettingsPickerOption] let isVisible: (() -> Bool)? let isEnabled: (() -> Bool)? let onChange: ((_ selection: String) async -> Void)? let trailingText: (() -> String?)? init( id: String, title: String, subtitle: String, placement: ProviderSettingsPickerPlacement = .connection, dynamicSubtitle: (() -> String?)? = nil, binding: Binding, options: [ProviderSettingsPickerOption], isVisible: (() -> Bool)?, isEnabled: (() -> Bool)? = nil, onChange: ((_ selection: String) async -> Void)?, trailingText: (() -> String?)? = nil) { self.id = id self.title = title self.subtitle = subtitle self.placement = placement self.dynamicSubtitle = dynamicSubtitle self.binding = binding self.options = options self.isVisible = isVisible self.isEnabled = isEnabled self.onChange = onChange self.trailingText = trailingText } } struct ProviderSettingsPickerOption: Identifiable { let id: String let title: String } /// Shared action descriptor rendered under a settings toggle. @MainActor struct ProviderSettingsActionDescriptor: Identifiable { enum Style { case bordered case link } let id: String let title: String let style: Style let isVisible: (() -> Bool)? let perform: () async -> Void }