Преглед изворни кода

feat: implement Import/Export options

Sam Jaffe пре 2 недеља
родитељ
комит
7c8604c105

+ 4 - 0
Todos/TodosApp.swift

@@ -41,6 +41,10 @@ struct TodosApp: App {
           .modelContainer(sharedModelContainer)
         SaveAsMenu()
           .modelContainer(sharedModelContainer)
+        ExportMenu()
+          .modelContainer(sharedModelContainer)
+        ImportMenu()
+          .modelContainer(sharedModelContainer)
       }
     }
     

+ 15 - 8
Todos/View/Menu/ExportMenu.swift

@@ -1,5 +1,5 @@
 //
-//  SaveAsMenu.swift
+//  ExportMenu.swift
 //  Todos
 //
 //  Created by Sam Jaffe on 3/1/26.
@@ -9,22 +9,29 @@ import SwiftUI
 import SwiftData
 import UniformTypeIdentifiers
 
-struct SaveAsMenu: View {
+struct ExportMenu: View {
   @Environment(\.modelContext) private var modelContext
-  
+  @AppStorage(UserDefaultsKeys.Category) var allGroups = CodableArray<Category>()
+  @AppStorage(UserDefaultsKeys.UrlHints) var allHints = CodableArray<URLHint>()
+
   @Query private var items: [Project]
   @State private var showingExporter = false
 
   var body: some View {
-    Button("Save As") {
+    Button("Export") {
       showingExporter = true
     }
-    .keyboardShortcut("S", modifiers: [.command, .shift])
+    .keyboardShortcut("E", modifiers: [.command, .shift])
     .fileExporter(isPresented: $showingExporter, document: StubDocument(),
-                  contentType: .yaml) { result in
+                  contentType: .json) { result in
       switch result {
       case .success(let url):
-        SaveController.save(items, to: url)
+        let transfer = Transfer(projects: items, hints: allHints, categories: allGroups)
+        guard let data = try? JSONEncoder().encode(transfer)
+        else {
+          return
+        }
+        SaveController.save(data: data, to: url)
       case .failure(let error):
         print(error.localizedDescription)
       }
@@ -33,5 +40,5 @@ struct SaveAsMenu: View {
 }
 
 #Preview {
-  SaveAsMenu()
+  ExportMenu()
 }

+ 19 - 11
Todos/View/Menu/ImportMenu.swift

@@ -1,5 +1,5 @@
 //
-//  SaveAsMenu.swift
+//  ImportMenu.swift
 //  Todos
 //
 //  Created by Sam Jaffe on 3/1/26.
@@ -9,29 +9,37 @@ import SwiftUI
 import SwiftData
 import UniformTypeIdentifiers
 
-struct ExportMenu: View {
+struct ImportMenu: View {
   @Environment(\.modelContext) private var modelContext
   @AppStorage(UserDefaultsKeys.Category) var allGroups = CodableArray<Category>()
   @AppStorage(UserDefaultsKeys.UrlHints) var allHints = CodableArray<URLHint>()
 
-  @Query private var items: [Project]
   @State private var showingExporter = false
 
   var body: some View {
-    Button("Export") {
+    Button("Import") {
       showingExporter = true
     }
-    .keyboardShortcut("E", modifiers: [.command])
-    .fileExporter(isPresented: $showingExporter, document: StubDocument(),
-                  contentType: .json) { result in
+    .keyboardShortcut("I", modifiers: [.command, .shift])
+    .fileImporter(isPresented: $showingExporter, allowedContentTypes: [.json]) { result in
       switch result {
       case .success(let url):
-        let transfer = Transfer(projects: items, hints: allHints, categories: allGroups)
-        guard let data = try? JSONEncoder().encode(transfer)
+        
+        guard let data = try? Data(contentsOf: url),
+              let transfer = try? JSONDecoder().decode(Transfer.self, from: data)
         else {
           return
         }
-        SaveController.save(data: data, to: url)
+        
+        do {
+          try modelContext.container.erase()
+          
+          transfer.projects.forEach(modelContext.insert)
+          allGroups = transfer.categories
+          allHints = transfer.hints
+        } catch {
+          print(error.localizedDescription)
+        }
       case .failure(let error):
         print(error.localizedDescription)
       }
@@ -40,5 +48,5 @@ struct ExportMenu: View {
 }
 
 #Preview {
-  SaveAsMenu()
+  ImportMenu()
 }

+ 12 - 0
Todos/ViewModel/Transfer.swift

@@ -6,3 +6,15 @@
 //
 
 import Foundation
+
+final class Transfer : Codable {
+  var projects: [Project]
+  var hints: [URLHint]
+  var categories: [Category]
+  
+  init(projects: [Project], hints: [URLHint], categories: [Category]) {
+    self.projects = projects
+    self.hints = hints
+    self.categories = categories
+  }
+}