diff options
| author | Fuwn <[email protected]> | 2025-03-03 03:08:52 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-03-03 03:08:52 -0800 |
| commit | 2646279dc1378d0c63e91372486baa85d83590bd (patch) | |
| tree | 740abe2babf8e4ca9d9c4b86f64f2e4301533a98 | |
| parent | feat: Development commit (diff) | |
| download | sora-testing-2646279dc1378d0c63e91372486baa85d83590bd.tar.xz sora-testing-2646279dc1378d0c63e91372486baa85d83590bd.zip | |
feat: Development commit
| -rw-r--r-- | Localizable.xcstrings | 12 | ||||
| -rw-r--r-- | Sora/Data/JSONFileDocument.swift | 26 | ||||
| -rw-r--r-- | Sora/Data/Settings/SettingsManager.swift | 4 | ||||
| -rw-r--r-- | Sora/Sora.entitlements | 2 | ||||
| -rw-r--r-- | Sora/Views/Settings/Section/SettingsExportView.swift | 78 | ||||
| -rw-r--r-- | Sora/Views/Settings/SettingsView.swift | 4 |
6 files changed, 125 insertions, 1 deletions
diff --git a/Localizable.xcstrings b/Localizable.xcstrings index f263594..ee67e2a 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -97,6 +97,15 @@ "Enable \"Share Image\" Shortcut" : { }, + "Export" : { + + }, + "Export Bookmarks" : { + + }, + "Export Failed" : { + + }, "Image Quality" : { }, @@ -125,6 +134,9 @@ "No matching items found" : { }, + "OK" : { + + }, "On %@ from %@" : { "localizations" : { "en" : { diff --git a/Sora/Data/JSONFileDocument.swift b/Sora/Data/JSONFileDocument.swift new file mode 100644 index 0000000..bc41616 --- /dev/null +++ b/Sora/Data/JSONFileDocument.swift @@ -0,0 +1,26 @@ +import SwiftUI +import UniformTypeIdentifiers + +struct JSONFileDocument: FileDocument { + static var readableContentTypes: [UTType] { [.json] } + + var data: Data + + init(_ data: Data) throws { + self.data = data + } + + init(configuration: ReadConfiguration) throws { + guard let data = configuration.file.regularFileContents else { + throw CocoaError(.fileReadCorruptFile) + } + + self.data = data + } + + func fileWrapper( + configuration: WriteConfiguration // swiftlint:disable:this unused_parameter + ) throws -> FileWrapper { + FileWrapper(regularFileWithContents: data) + } +} diff --git a/Sora/Data/Settings/SettingsManager.swift b/Sora/Data/Settings/SettingsManager.swift index c9590be..7d38d0f 100644 --- a/Sora/Data/Settings/SettingsManager.swift +++ b/Sora/Data/Settings/SettingsManager.swift @@ -125,6 +125,10 @@ class SettingsManager: ObservableObject { bookmarks.removeAll { $0.id == id } } + func exportBookmarks() throws -> Data { + try JSONEncoder().encode(bookmarks) + } + // MARK: - Search History Management func removeSearchHistoryEntry(at offsets: IndexSet) { searchHistory.remove(atOffsets: offsets) diff --git a/Sora/Sora.entitlements b/Sora/Sora.entitlements index a2c464c..264aa0a 100644 --- a/Sora/Sora.entitlements +++ b/Sora/Sora.entitlements @@ -6,7 +6,7 @@ <true/> <key>com.apple.security.assets.pictures.read-write</key> <true/> - <key>com.apple.security.files.user-selected.read-only</key> + <key>com.apple.security.files.user-selected.read-write</key> <true/> <key>com.apple.security.network.client</key> <true/> diff --git a/Sora/Views/Settings/Section/SettingsExportView.swift b/Sora/Views/Settings/Section/SettingsExportView.swift new file mode 100644 index 0000000..2e9723e --- /dev/null +++ b/Sora/Views/Settings/Section/SettingsExportView.swift @@ -0,0 +1,78 @@ +import SwiftUI +import UniformTypeIdentifiers + +struct SettingsExportView: View { + @EnvironmentObject private var settings: SettingsManager + @State private var isFileExporterPresented = false + @State private var exportError: Error? + + var body: some View { + Button("Export Bookmarks") { + exportBookmarksToFile() + } + #if os(macOS) + .frame(maxWidth: .infinity, alignment: .trailing) + .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 + .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.") + } + } + + private func exportBookmarksToFile() { + do { + #if os(macOS) + _ = try settings.exportBookmarks() + isFileExporterPresented = true + + #elseif os(iOS) + let data = try settings.exportBookmarks() + let temporaryURL = FileManager.default.temporaryDirectory + .appendingPathComponent("sora_bookmarks.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 + } + } +} diff --git a/Sora/Views/Settings/SettingsView.swift b/Sora/Views/Settings/SettingsView.swift index 4f00cbd..82738c8 100644 --- a/Sora/Views/Settings/SettingsView.swift +++ b/Sora/Views/Settings/SettingsView.swift @@ -22,6 +22,10 @@ struct SettingsView: View { SettingsSearchView() } + Section(header: Text("Export")) { + SettingsExportView() + } + Section(header: Text("Settings")) { Button("Reset to Defaults") { settings.resetToDefaults() |