280 lines · 8.6 KB · Swift
RawDownload
import CodexBarCoreimport Foundationimport 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)@MainActorstruct ProviderSettingsContext {    let provider: UsageProvider    let settings: SettingsStore    let store: UsageStore     let boolBinding: (ReferenceWritableKeyPath<SettingsStore, Bool>) -> Binding<Bool>    let stringBinding: (ReferenceWritableKeyPath<SettingsStore, String>) -> Binding<String>     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<SettingsStore, Bool>) -> Binding<Bool>,        stringBinding: @escaping (ReferenceWritableKeyPath<SettingsStore, String>) -> Binding<String>,        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.@MainActorstruct ProviderSettingsConfirmation {    let title: String    let message: String    let confirmTitle: String    let onConfirm: () -> Void} /// Shared toggle descriptor rendered in the Providers settings pane.@MainActorstruct ProviderSettingsToggleDescriptor: Identifiable {    let id: String    let title: String    let subtitle: String    let binding: Binding<Bool>     /// 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<Bool>,        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.@MainActorstruct 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<String>    let actions: [ProviderSettingsActionDescriptor]    let isVisible: (() -> Bool)?    let onActivate: (() -> Void)?} /// Shared action row descriptor rendered in the Providers settings pane.@MainActorstruct 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.@MainActorstruct 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 addAccount: (_ label: String, _ token: String, _ organizationID: 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.@MainActorstruct 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.@MainActorstruct ProviderSettingsPickerDescriptor: Identifiable {    let id: String    let title: String    let subtitle: String    let dynamicSubtitle: (() -> String?)?    let binding: Binding<String>    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,        dynamicSubtitle: (() -> String?)? = nil,        binding: Binding<String>,        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.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.@MainActorstruct ProviderSettingsActionDescriptor: Identifiable {    enum Style {        case bordered        case link    }     let id: String    let title: String    let style: Style    let isVisible: (() -> Bool)?    let perform: () async -> Void}