diff options
| author | Fuwn <[email protected]> | 2025-03-03 03:15:53 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-03-03 03:15:53 -0800 |
| commit | 682147c550ae1d6512b2fc5984993f395ff44e06 (patch) | |
| tree | 90b4b0fd868fb8f6cb472deee28c8c21f19e747a | |
| parent | feat: Development commit (diff) | |
| download | sora-testing-682147c550ae1d6512b2fc5984993f395ff44e06.tar.xz sora-testing-682147c550ae1d6512b2fc5984993f395ff44e06.zip | |
feat: Development commit
| -rw-r--r-- | Localizable.xcstrings | 12 | ||||
| -rw-r--r-- | Sora/Data/Settings/SettingsManager.swift | 8 | ||||
| -rw-r--r-- | Sora/Views/Settings/Section/SettingsImportExportView.swift (renamed from Sora/Views/Settings/Section/SettingsExportView.swift) | 53 | ||||
| -rw-r--r-- | Sora/Views/Settings/SettingsView.swift | 4 |
4 files changed, 69 insertions, 8 deletions
diff --git a/Localizable.xcstrings b/Localizable.xcstrings index ee67e2a..8deab4f 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -97,9 +97,6 @@ "Enable \"Share Image\" Shortcut" : { }, - "Export" : { - - }, "Export Bookmarks" : { }, @@ -109,6 +106,15 @@ "Image Quality" : { }, + "Import & Export" : { + + }, + "Import Bookmarks" : { + + }, + "Import Failed" : { + + }, "Loading %@…" : { }, diff --git a/Sora/Data/Settings/SettingsManager.swift b/Sora/Data/Settings/SettingsManager.swift index 7d38d0f..0ad3973 100644 --- a/Sora/Data/Settings/SettingsManager.swift +++ b/Sora/Data/Settings/SettingsManager.swift @@ -129,6 +129,14 @@ class SettingsManager: ObservableObject { try JSONEncoder().encode(bookmarks) } + func importBookmarks(from data: Data) throws { + let importedBookmarks = try JSONDecoder().decode([SettingsBookmark].self, from: data) + let existingIDs = Set(bookmarks.map(\.id)) + let newBookmarks = importedBookmarks.filter { !existingIDs.contains($0.id) } + + bookmarks.append(contentsOf: newBookmarks) + } + // MARK: - Search History Management func removeSearchHistoryEntry(at offsets: IndexSet) { searchHistory.remove(atOffsets: offsets) diff --git a/Sora/Views/Settings/Section/SettingsExportView.swift b/Sora/Views/Settings/Section/SettingsImportExportView.swift index 2e9723e..983b175 100644 --- a/Sora/Views/Settings/Section/SettingsExportView.swift +++ b/Sora/Views/Settings/Section/SettingsImportExportView.swift @@ -1,14 +1,22 @@ import SwiftUI import UniformTypeIdentifiers -struct SettingsExportView: View { +struct SettingsImportExportView: 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? var body: some View { - Button("Export Bookmarks") { - exportBookmarksToFile() + Group { + Button("Import Bookmarks") { + isFileImporterPresented = true + } + + Button("Export Bookmarks") { + exportBookmarksToFile() + } } #if os(macOS) .frame(maxWidth: .infinity, alignment: .trailing) @@ -27,6 +35,13 @@ struct SettingsExportView: View { } } #endif + .fileImporter( + isPresented: $isFileImporterPresented, + allowedContentTypes: [.json], + allowsMultipleSelection: false + ) { result in + handleImportResult(result) + } .alert( "Export Failed", isPresented: Binding( @@ -38,6 +53,17 @@ struct SettingsExportView: View { } 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() { @@ -75,4 +101,25 @@ struct SettingsExportView: View { 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 + } } diff --git a/Sora/Views/Settings/SettingsView.swift b/Sora/Views/Settings/SettingsView.swift index 82738c8..59271ad 100644 --- a/Sora/Views/Settings/SettingsView.swift +++ b/Sora/Views/Settings/SettingsView.swift @@ -22,8 +22,8 @@ struct SettingsView: View { SettingsSearchView() } - Section(header: Text("Export")) { - SettingsExportView() + Section(header: Text("Import & Export")) { + SettingsImportExportView() } Section(header: Text("Settings")) { |