import SwiftUI struct SettingsView: View { @Environment(\.language) var language @AppStorage("contentPath") var contentPath: String = "" @AppStorage("outputPath") var outputPath: String = "" @EnvironmentObject var content: Content @State private var isSelectingContentFolder = false @State private var showFileImporter = false var body: some View { VStack(alignment: .leading) { Text("Content Folder") .font(.headline) TextField("Content Folder", text: $contentPath) Button(action: selectContentFolder) { Text("Select folder") } Text("Output Folder") .font(.headline) TextField("Output Folder", text: $outputPath) Button(action: selectOutputFolder) { Text("Select folder") } Text("Feed") .font(.headline) Button(action: generateFeed) { Text("Generate") } } .padding() .fileImporter( isPresented: $showFileImporter, allowedContentTypes: [.folder], onCompletion: didSelectContentFolder) } // MARK: Folder selection private func selectContentFolder() { isSelectingContentFolder = true //showFileImporter = true guard let url = savePanelUsingOpenPanel(key: "contentPathBookmark") else { return } self.contentPath = url.path() } private func selectOutputFolder() { isSelectingContentFolder = false //showFileImporter = true guard let url = savePanelUsingOpenPanel(key: "outputPathBookmark") else { return } self.outputPath = url.path() } private func didSelectContentFolder(_ result: Result) { switch result { case .success(let url): didSelect(folder: url) case .failure(let error): print("Failed to select content folder: \(error)") } } private func didSelect(folder: URL) { let path = folder.absoluteString .replacingOccurrences(of: "file://", with: "") if isSelectingContentFolder { self.contentPath = path saveSecurityScopedBookmark(folder, key: "contentPathBookmark") } else { self.outputPath = path saveSecurityScopedBookmark(folder, key: "outputPathBookmark") } } // MARK: Feed private func generateFeed() { guard outputPath != "" else { print("Invalid output path") return } let url = URL(fileURLWithPath: outputPath) guard FileManager.default.fileExists(atPath: url.path) else { print("Missing output folder") return } content.generateFeed(for: language, bookmarkKey: "outputPathBookmark") } func savePanelUsingOpenPanel(key: String) -> URL? { let panel = NSOpenPanel() // Sets up so user can only select a single directory panel.canChooseFiles = false panel.canChooseDirectories = true panel.allowsMultipleSelection = false panel.showsHiddenFiles = false panel.title = "Select Save Directory" panel.prompt = "Select Save Directory" let response = panel.runModal() guard response == .OK else { return nil } guard let url = panel.url else { return nil } saveSecurityScopedBookmark(url, key: key) return url } func saveSecurityScopedBookmark(_ url: URL, key: String) { do { let bookmarkData = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil) UserDefaults.standard.set(bookmarkData, forKey: key) print("Security-scoped bookmark saved.") } catch { print("Failed to create security-scoped bookmark: \(error)") } } } #Preview { SettingsView() }