From a5eb4a049f8ebfbb1c4f6117a118fbc2f67979cd Mon Sep 17 00:00:00 2001 From: breadone Date: Wed, 3 Jul 2024 18:27:17 +1200 Subject: [PATCH] data persistence is working! --- JustScanIt.xcodeproj/project.pbxproj | 12 ++++++++ JustScanIt/ContentView.swift | 41 ++++++++++++++++++++-------- JustScanIt/JustScanItApp.swift | 14 ++++++++++ JustScanIt/Model/Scan.swift | 37 +++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 12 deletions(-) create mode 100644 JustScanIt/Model/Scan.swift diff --git a/JustScanIt.xcodeproj/project.pbxproj b/JustScanIt.xcodeproj/project.pbxproj index 908f6ae..fb1d64a 100644 --- a/JustScanIt.xcodeproj/project.pbxproj +++ b/JustScanIt.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 466989CB2C34DC7B009884D1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 466989CA2C34DC7B009884D1 /* Assets.xcassets */; }; 466989CE2C34DC7B009884D1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 466989CD2C34DC7B009884D1 /* Preview Assets.xcassets */; }; 466989D62C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989D52C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift */; }; + 466989D92C35206E009884D1 /* Scan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989D82C35206E009884D1 /* Scan.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -21,6 +22,7 @@ 466989CA2C34DC7B009884D1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 466989CD2C34DC7B009884D1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 466989D52C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VNDocumentCameraViewControllerR.swift; sourceTree = ""; }; + 466989D82C35206E009884D1 /* Scan.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scan.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -53,6 +55,7 @@ 466989C52C34DC7A009884D1 /* JustScanIt */ = { isa = PBXGroup; children = ( + 466989D72C351F23009884D1 /* Model */, 466989D42C34DCB9009884D1 /* Controllers */, 466989C62C34DC7A009884D1 /* JustScanItApp.swift */, 466989C82C34DC7A009884D1 /* ContentView.swift */, @@ -78,6 +81,14 @@ path = Controllers; sourceTree = ""; }; + 466989D72C351F23009884D1 /* Model */ = { + isa = PBXGroup; + children = ( + 466989D82C35206E009884D1 /* Scan.swift */, + ); + path = Model; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -150,6 +161,7 @@ files = ( 466989C92C34DC7A009884D1 /* ContentView.swift in Sources */, 466989C72C34DC7A009884D1 /* JustScanItApp.swift in Sources */, + 466989D92C35206E009884D1 /* Scan.swift in Sources */, 466989D62C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/JustScanIt/ContentView.swift b/JustScanIt/ContentView.swift index 5aec95a..52214ea 100644 --- a/JustScanIt/ContentView.swift +++ b/JustScanIt/ContentView.swift @@ -6,12 +6,17 @@ // import SwiftUI +import SwiftData import AVKit struct ContentView: View { + @Environment(\.modelContext) var ctx + @State private var scannedImages: [UIImage] = [] @State private var isShowingVNDocumentCameraView = false + @Query var scans: [Scan] + var isAuthorized: Bool { get async { let status = AVCaptureDevice.authorizationStatus(for: .video) @@ -23,6 +28,8 @@ struct ContentView: View { // explicitly prompt them for approval. if status == .notDetermined { isAuthorized = await AVCaptureDevice.requestAccess(for: .video) + } else if status == .denied { + // TODO: show alert when denied } return isAuthorized @@ -31,19 +38,22 @@ struct ContentView: View { var body: some View { NavigationView { - Grid { - ForEach(scannedImages, id: \.self) { image in - VStack { - Image(uiImage: image) - .resizable() - .scaledToFit() - .frame(width: 100, height: 100) - .padding() + ScrollView { + ForEach(scans, id: \.self) { scan in + HStack { + ForEach(scan.uiImages, id: \.self) { image in + Image(uiImage: image) + .resizable() + .scaledToFit() + .frame(width: 100, height: 100) + .padding() + + } } } } .navigationTitle("Just Scan It!") - .sheet(isPresented: $isShowingVNDocumentCameraView) { + .sheet(isPresented: $isShowingVNDocumentCameraView, onDismiss: saveImages) { VNDocumentCameraViewControllerRepresentable(scanResult: $scannedImages) } .toolbar { @@ -57,12 +67,19 @@ struct ContentView: View { } private func showVNDocumentCameraView() { - Task { - guard await isAuthorized else { return } - } + Task { guard await isAuthorized else { return } } isShowingVNDocumentCameraView = true } + + private func saveImages() { + let newScan = Scan(images: scannedImages) + + ctx.insert(newScan) + try? ctx.save() + + scannedImages = [] + } } #Preview { diff --git a/JustScanIt/JustScanItApp.swift b/JustScanIt/JustScanItApp.swift index 8e86122..3ce24ca 100644 --- a/JustScanIt/JustScanItApp.swift +++ b/JustScanIt/JustScanItApp.swift @@ -6,12 +6,26 @@ // import SwiftUI +import SwiftData @main struct JustScanItApp: App { + var sharedModelContainer: ModelContainer = { + let schema = Schema([ Scan.self ]) + + let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) + + do { + return try ModelContainer(for: schema, configurations: [modelConfiguration]) + } catch { + fatalError("Could not create ModelContainer: \(error)") + } + }() + var body: some Scene { WindowGroup { ContentView() } + .modelContainer(sharedModelContainer) } } diff --git a/JustScanIt/Model/Scan.swift b/JustScanIt/Model/Scan.swift new file mode 100644 index 0000000..8fb578d --- /dev/null +++ b/JustScanIt/Model/Scan.swift @@ -0,0 +1,37 @@ +// +// Scan.swift +// JustScanIt +// +// Created by Pradyun Setti on 03/07/2024. +// + +import Foundation +import SwiftData +import UIKit + +@Model +final class Scan { + let timestamp: Date + var images: [Data] + + var uiImages: [UIImage] { + self.images.map { UIImage(data: $0) ?? UIImage(systemName: "exclamationmark.questionmark")! } + } + + init() { + self.timestamp = Date() + self.images = [] + } + + init(images: [Data]) { + self.timestamp = Date() + self.images = images + } + + init(images: [UIImage]) { + self.timestamp = Date() + + self.images = images.map{ $0.pngData() ?? Data() } + } + +}