diff --git a/Xcodes/Backend/AppState.swift b/Xcodes/Backend/AppState.swift index 3f5731e..c02f204 100644 --- a/Xcodes/Backend/AppState.swift +++ b/Xcodes/Backend/AppState.swift @@ -55,6 +55,13 @@ class AppState: ObservableObject { @Published var error: Error? @Published var authError: Error? + + // MARK: Advanced Preferences + @Published var localPath = "" { + didSet { + Current.defaults.set(localPath, forKey: "localPath") + } + } // MARK: - Publisher Cancellables @@ -84,6 +91,11 @@ class AppState: ObservableObject { try? loadCachedAvailableXcodes() checkIfHelperIsInstalled() setupAutoInstallTimer() + setupDefaults() + } + + func setupDefaults() { + localPath = Current.defaults.string(forKey: "localPath") ?? Path.defaultXcodesApplicationSupport.string } // MARK: Timer @@ -393,6 +405,11 @@ class AppState: ObservableObject { guard let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version == id }) else { return } NSWorkspace.shared.activateFileViewerSelecting([installedXcode.path.url]) } + + func reveal(path: String) { + let url = URL(fileURLWithPath: path) + NSWorkspace.shared.activateFileViewerSelecting([url]) + } /// Make an Xcode active, a.k.a select it, in the `xcode-select` sense. /// diff --git a/Xcodes/Backend/Path+.swift b/Xcodes/Backend/Path+.swift index ba20bef..1aecb83 100644 --- a/Xcodes/Backend/Path+.swift +++ b/Xcodes/Backend/Path+.swift @@ -1,6 +1,19 @@ import Path +import Foundation extension Path { - static let xcodesApplicationSupport = Path.applicationSupport/"com.robotsandpencils.XcodesApp" - static let cacheFile = xcodesApplicationSupport/"available-xcodes.json" + static let defaultXcodesApplicationSupport = Path.applicationSupport/"com.robotsandpencils.XcodesApp" + static var xcodesApplicationSupport: Path { + guard let savedApplicationSupport = Current.defaults.string(forKey: "localPath") else { + return defaultXcodesApplicationSupport + } + guard let path = Path(savedApplicationSupport) else { + return defaultXcodesApplicationSupport + } + return path + } + + static var cacheFile: Path { + return xcodesApplicationSupport/"available-xcodes.json" + } } diff --git a/Xcodes/Frontend/Preferences/AdvancedPreferencePane.swift b/Xcodes/Frontend/Preferences/AdvancedPreferencePane.swift index 9606456..9868e6f 100644 --- a/Xcodes/Frontend/Preferences/AdvancedPreferencePane.swift +++ b/Xcodes/Frontend/Preferences/AdvancedPreferencePane.swift @@ -1,13 +1,52 @@ import AppleAPI import SwiftUI +import Path struct AdvancedPreferencePane: View { @EnvironmentObject var appState: AppState + @AppStorage("dataSource") var dataSource: DataSource = .xcodeReleases @AppStorage("downloader") var downloader: Downloader = .aria2 var body: some View { VStack(alignment: .leading, spacing: 20) { + + GroupBox(label: Text("Local Cache Path")) { + VStack(alignment: .leading) { + HStack(alignment: .top, spacing: 5) { + Text(appState.localPath).font(.footnote) + .fixedSize(horizontal: false, vertical: true) + .lineLimit(2) + Button(action: { appState.reveal(path: appState.localPath) }) { + Image(systemName: "arrow.right.circle.fill") + } + .buttonStyle(PlainButtonStyle()) + .help("Reveal in Finder") + .fixedSize() + } + Button("Change") { + let panel = NSOpenPanel() + panel.allowsMultipleSelection = false + panel.canChooseDirectories = true + panel.canChooseFiles = false + panel.canCreateDirectories = true + panel.allowedContentTypes = [.folder] + panel.directoryURL = URL(fileURLWithPath: appState.localPath) + + if panel.runModal() == .OK { + + guard let pathURL = panel.url, let path = Path(url: pathURL) else { return } + self.appState.localPath = path.string + } + } + Text("Xcodes caches available Xcode versions and temporary downloads new versions to a directory") + .font(.footnote) + .fixedSize(horizontal: false, vertical: true) + } + + } + .groupBoxStyle(PreferencesGroupBoxStyle()) + GroupBox(label: Text("Data Source")) { VStack(alignment: .leading) { Picker("Data Source", selection: $dataSource) { @@ -66,7 +105,7 @@ struct AdvancedPreferencePane: View { } .groupBoxStyle(PreferencesGroupBoxStyle()) } - .frame(width: 400) + .frame(width: 500) } private var dataSourceFootnote: NSAttributedString { diff --git a/Xcodes/Frontend/Preferences/GeneralPreferencePane.swift b/Xcodes/Frontend/Preferences/GeneralPreferencePane.swift index 35d5eaf..548545b 100644 --- a/Xcodes/Frontend/Preferences/GeneralPreferencePane.swift +++ b/Xcodes/Frontend/Preferences/GeneralPreferencePane.swift @@ -21,7 +21,7 @@ struct GeneralPreferencePane: View { } .groupBoxStyle(PreferencesGroupBoxStyle()) } - .frame(width: 400) + .frame(width: 500) } } diff --git a/Xcodes/Frontend/Preferences/UpdatesPreferencePane.swift b/Xcodes/Frontend/Preferences/UpdatesPreferencePane.swift index 69de839..e159887 100644 --- a/Xcodes/Frontend/Preferences/UpdatesPreferencePane.swift +++ b/Xcodes/Frontend/Preferences/UpdatesPreferencePane.swift @@ -50,7 +50,7 @@ struct UpdatesPreferencePane: View { } .groupBoxStyle(PreferencesGroupBoxStyle()) } - .frame(width: 400) + .frame(width: 500) } private var lastUpdatedString: String {