import KeyboardShortcuts import SwiftUI @MainActor struct AdvancedPane: View { @Bindable var settings: SettingsStore @State private var isInstallingCLI = false @State private var cliStatus: String? var body: some View { ScrollView(.vertical, showsIndicators: true) { VStack(alignment: .leading, spacing: 16) { SettingsSection(contentSpacing: 8) { Text(L("section_keyboard_shortcut")) .font(.caption) .foregroundStyle(.secondary) .textCase(.uppercase) HStack(alignment: .center, spacing: 12) { Text(L("open_menu_shortcut_title")) .font(.body) Spacer() KeyboardShortcuts.Recorder(for: .openMenu) } Text(L("open_menu_shortcut_subtitle")) .font(.footnote) .foregroundStyle(.tertiary) } Divider() SettingsSection(contentSpacing: 10) { HStack(spacing: 12) { Button { Task { await self.installCLI() } } label: { if self.isInstallingCLI { ProgressView().controlSize(.small) } else { Text(L("install_cli")) } } .disabled(self.isInstallingCLI) if let status = self.cliStatus { Text(status) .font(.footnote) .foregroundStyle(.tertiary) .lineLimit(2) } } Text(L("install_cli_subtitle")) .font(.footnote) .foregroundStyle(.tertiary) } Divider() SettingsSection(contentSpacing: 10) { PreferenceToggleRow( title: L("show_debug_settings_title"), subtitle: L("show_debug_settings_subtitle"), binding: self.$settings.debugMenuEnabled) PreferenceToggleRow( title: L("surprise_me_title"), subtitle: L("surprise_me_subtitle"), binding: self.$settings.randomBlinkEnabled) PreferenceToggleRow( title: L("weekly_limit_confetti_title"), subtitle: L("weekly_limit_confetti_subtitle"), binding: self.$settings.confettiOnWeeklyLimitResetsEnabled) } Divider() SettingsSection(contentSpacing: 10) { PreferenceToggleRow( title: L("hide_personal_info_title"), subtitle: L("hide_personal_info_subtitle"), binding: self.$settings.hidePersonalInfo) PreferenceToggleRow( title: L("show_provider_storage_usage_title"), subtitle: L("show_provider_storage_usage_subtitle"), binding: self.$settings.providerStorageFootprintsEnabled) } Divider() SettingsSection( title: L("section_keychain_access"), caption: L("keychain_access_caption")) { PreferenceToggleRow( title: L("disable_keychain_access_title"), subtitle: L("disable_keychain_access_subtitle"), binding: self.$settings.debugDisableKeychainAccess) } } .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 20) .padding(.vertical, 12) } } } extension AdvancedPane { private func installCLI() async { if self.isInstallingCLI { return } self.isInstallingCLI = true defer { self.isInstallingCLI = false } let helperURL = Bundle.main.bundleURL.appendingPathComponent("Contents/Helpers/CodexBarCLI") let fm = FileManager.default guard fm.fileExists(atPath: helperURL.path) else { self.cliStatus = L("cli_not_found") return } let destinations = [ "/usr/local/bin/codexbar", "/opt/homebrew/bin/codexbar", ] var results: [String] = [] for dest in destinations { let dir = (dest as NSString).deletingLastPathComponent guard fm.fileExists(atPath: dir) else { continue } guard fm.isWritableFile(atPath: dir) else { results.append("No write access: \(dir)") continue } if fm.fileExists(atPath: dest) { if Self.isLink(atPath: dest, pointingTo: helperURL.path) { results.append("Installed: \(dir)") } else { results.append("Exists: \(dir)") } continue } do { try fm.createSymbolicLink(atPath: dest, withDestinationPath: helperURL.path) results.append("Installed: \(dir)") } catch { results.append("Failed: \(dir)") } } self.cliStatus = results.isEmpty ? L("no_writable_bin_dirs") : results.joined(separator: " ยท ") } private static func isLink(atPath path: String, pointingTo destination: String) -> Bool { guard let link = try? FileManager.default.destinationOfSymbolicLink(atPath: path) else { return false } let dir = (path as NSString).deletingLastPathComponent let resolved = URL(fileURLWithPath: link, relativeTo: URL(fileURLWithPath: dir)) .standardizedFileURL .path return resolved == destination } }