import SwiftUI import UniformTypeIdentifiers struct SettingsSectionImportExportView: View { @EnvironmentObject private var settings: SettingsManager @State private var isFileExporterPresented = false @State private var isFileImporterPresented = false @State private var exportError: Error? @State private var importError: Error? private let dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd_HH-mm-ss" return formatter }() var body: some View { Group { Button("Import Bookmarks") { isFileImporterPresented = true } Button("Export Bookmarks") { exportBookmarksToFile() } } #if os(macOS) .trailingFrame() .fileExporter( isPresented: $isFileExporterPresented, document: try? JSONFileDocument(settings.exportBookmarks()), contentType: .json, defaultFilename: "sora_bookmarks.json" ) { result in switch result { case .success: break case .failure(let error): exportError = error } } #endif .fileImporter( isPresented: $isFileImporterPresented, allowedContentTypes: [.json], allowsMultipleSelection: false ) { result in handleImportResult(result) } .alert( "Export Failed", isPresented: Binding( get: { exportError != nil }, set: { if !$0 { exportError = nil } } ) ) { Button("OK", role: .cancel) { () } } message: { Text(exportError?.localizedDescription ?? "An unknown error occurred while exporting.") } .alert( "Import Failed", isPresented: Binding( get: { importError != nil }, set: { if !$0 { importError = nil } } ) ) { Button("OK", role: .cancel) { () } } message: { Text(importError?.localizedDescription ?? "An unknown error occurred while importing.") } } private func exportBookmarksToFile() { do { let data = try settings.exportBookmarks() let timestamp = dateFormatter.string(from: Date()) #if os(macOS) _ = data isFileExporterPresented = true #elseif os(iOS) let temporaryURL = FileManager.default.temporaryDirectory .appendingPathComponent("sora_bookmarks_\(timestamp).json") try data.write(to: temporaryURL) let activityController = UIActivityViewController( activityItems: [temporaryURL], applicationActivities: nil ) if let windowScene = UIApplication.shared.connectedScenes .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene, let rootViewController = windowScene.windows.first?.rootViewController { activityController.popoverPresentationController?.sourceView = rootViewController.view rootViewController.present(activityController, animated: true) } activityController.completionWithItemsHandler = { _, _, _, _ in try? FileManager.default.removeItem(at: temporaryURL) } #endif } catch { exportError = error } } private func handleImportResult(_ result: Result<[URL], Error>) { do { guard let selectedFile = try result.get().first else { return } guard selectedFile.startAccessingSecurityScopedResource() else { throw ImportError.accessDenied } defer { selectedFile.stopAccessingSecurityScopedResource() } let data = try Data(contentsOf: selectedFile) try settings.importBookmarks(from: data) } catch { importError = error } } private enum ImportError: Error { case accessDenied } }