Peter Steinbergerfix: apply selected app languagea01bf8c6 months agoHistory
156 lines · 6.0 KB · Swift
RawDownload
import AppKitimport CodexBarCoreimport SwiftUI enum PreferencesTab: String, CaseIterable, Hashable {    case general    case providers    case display    case advanced    case about    case debug     static let defaultWidth: CGFloat = 546    static let providersWidth: CGFloat = 792    static let windowHeight: CGFloat = 638     var title: String {        switch self {        case .general: L("tab_general")        case .providers: L("tab_providers")        case .display: L("tab_display")        case .advanced: L("tab_advanced")        case .about: L("tab_about")        case .debug: L("tab_debug")        }    }     var preferredWidth: CGFloat {        self == .providers ? PreferencesTab.providersWidth : PreferencesTab.defaultWidth    }     var preferredHeight: CGFloat {        PreferencesTab.windowHeight    }} @MainActorstruct PreferencesView: View {    @Bindable var settings: SettingsStore    @Bindable var store: UsageStore    let updater: UpdaterProviding    @Bindable var selection: PreferencesSelection    let managedCodexAccountCoordinator: ManagedCodexAccountCoordinator    let codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator    let runProviderLoginFlow: @MainActor (UsageProvider) async -> Void    @State private var contentWidth: CGFloat = PreferencesTab.general.preferredWidth    @State private var contentHeight: CGFloat = PreferencesTab.general.preferredHeight     init(        settings: SettingsStore,        store: UsageStore,        updater: UpdaterProviding,        selection: PreferencesSelection,        managedCodexAccountCoordinator: ManagedCodexAccountCoordinator = ManagedCodexAccountCoordinator(),        codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator? = nil,        runProviderLoginFlow: @escaping @MainActor (UsageProvider) async -> Void = { _ in })    {        self.settings = settings        self.store = store        self.updater = updater        self.selection = selection        self.managedCodexAccountCoordinator = managedCodexAccountCoordinator        self.codexAccountPromotionCoordinator = codexAccountPromotionCoordinator            ?? CodexAccountPromotionCoordinator(                settingsStore: settings,                usageStore: store,                managedAccountCoordinator: managedCodexAccountCoordinator)        self.runProviderLoginFlow = runProviderLoginFlow    }     var body: some View {        TabView(selection: self.$selection.tab) {            GeneralPane(settings: self.settings, store: self.store)                .tabItem { Label(L("tab_general"), systemImage: "gearshape") }                .tag(PreferencesTab.general)             ProvidersPane(                settings: self.settings,                store: self.store,                managedCodexAccountCoordinator: self.managedCodexAccountCoordinator,                codexAccountPromotionCoordinator: self.codexAccountPromotionCoordinator,                runProviderLoginFlow: self.runProviderLoginFlow)                .tabItem { Label(L("tab_providers"), systemImage: "square.grid.2x2") }                .tag(PreferencesTab.providers)             DisplayPane(settings: self.settings, store: self.store)                .tabItem { Label(L("tab_display"), systemImage: "eye") }                .tag(PreferencesTab.display)             AdvancedPane(settings: self.settings)                .tabItem { Label(L("tab_advanced"), systemImage: "slider.horizontal.3") }                .tag(PreferencesTab.advanced)             AboutPane(updater: self.updater)                .tabItem { Label(L("tab_about"), systemImage: "info.circle") }                .tag(PreferencesTab.about)             if self.settings.debugMenuEnabled {                DebugPane(settings: self.settings, store: self.store)                    .tabItem { Label(L("tab_debug"), systemImage: "ladybug") }                    .tag(PreferencesTab.debug)            }        }        .id(self.settings.appLanguage)        .padding(.horizontal, 24)        .padding(.vertical, 16)        .frame(width: self.contentWidth, height: self.contentHeight)        .onAppear {            self.updateLayout(for: self.selection.tab, animate: false)            self.ensureValidTabSelection()        }        .onChange(of: self.selection.tab) { _, newValue in            self.updateLayout(for: newValue, animate: true)        }        .onChange(of: self.settings.debugMenuEnabled) { _, _ in            self.ensureValidTabSelection()        }    }     private func updateLayout(for tab: PreferencesTab, animate: Bool) {        let change = {            self.contentWidth = tab.preferredWidth            self.contentHeight = tab.preferredHeight        }        if animate {            withAnimation(.spring(response: 0.32, dampingFraction: 0.85)) { change() }        } else {            change()        }        Self.resizeSettingsWindow(width: tab.preferredWidth, height: tab.preferredHeight, animate: animate)    }     private static let settingsWindowIdentifier = "com_apple_SwiftUI_Settings_window"    private static let knownTabTitles = Set(PreferencesTab.allCases.map(\.title))     private static func resizeSettingsWindow(width: CGFloat, height: CGFloat, animate: Bool) {        guard let window = NSApp.windows.first(where: {            $0.identifier?.rawValue == settingsWindowIdentifier                || knownTabTitles.contains($0.title)        }) else { return }        let toolbarHeight = window.frame.height - window.contentLayoutRect.height        guard toolbarHeight > 0 else { return }        let newSize = NSSize(width: width, height: height + toolbarHeight)        var frame = window.frame        frame.origin.y += frame.size.height - newSize.height        frame.size = newSize        window.setFrame(frame, display: true, animate: animate)    }     private func ensureValidTabSelection() {        if !self.settings.debugMenuEnabled, self.selection.tab == .debug {            self.selection.tab = .general            self.updateLayout(for: .general, animate: true)        }    }}