From 64a066fb2a3b7d0e0187954abed7f44ed838d228 Mon Sep 17 00:00:00 2001 From: breadone Date: Wed, 3 Jul 2024 20:21:12 +1200 Subject: [PATCH] completely overhauled the scan item view --- JustScanIt.xcodeproj/project.pbxproj | 8 +++ JustScanIt/Model/Scan.swift | 5 ++ JustScanIt/View/MainView.swift | 22 +++--- JustScanIt/View/ScanItemView.swift | 104 +++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 12 deletions(-) create mode 100644 JustScanIt/View/ScanItemView.swift diff --git a/JustScanIt.xcodeproj/project.pbxproj b/JustScanIt.xcodeproj/project.pbxproj index 46c13a7..cbcf239 100644 --- a/JustScanIt.xcodeproj/project.pbxproj +++ b/JustScanIt.xcodeproj/project.pbxproj @@ -13,6 +13,8 @@ 466989D62C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989D52C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift */; }; 466989D92C35206E009884D1 /* Scan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989D82C35206E009884D1 /* Scan.swift */; }; 466989DB2C352776009884D1 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989C82C34DC7A009884D1 /* MainView.swift */; }; + 466989DD2C35299D009884D1 /* ScanItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989DC2C35299D009884D1 /* ScanItemView.swift */; }; + 466989DF2C353FEC009884D1 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989DE2C353FEC009884D1 /* SettingsView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -23,6 +25,8 @@ 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 = ""; }; + 466989DC2C35299D009884D1 /* ScanItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanItemView.swift; sourceTree = ""; }; + 466989DE2C353FEC009884D1 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -93,6 +97,8 @@ isa = PBXGroup; children = ( 466989C82C34DC7A009884D1 /* MainView.swift */, + 466989DC2C35299D009884D1 /* ScanItemView.swift */, + 466989DE2C353FEC009884D1 /* SettingsView.swift */, ); path = View; sourceTree = ""; @@ -170,7 +176,9 @@ 466989C72C34DC7A009884D1 /* JustScanItApp.swift in Sources */, 466989DB2C352776009884D1 /* MainView.swift in Sources */, 466989D92C35206E009884D1 /* Scan.swift in Sources */, + 466989DF2C353FEC009884D1 /* SettingsView.swift in Sources */, 466989D62C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift in Sources */, + 466989DD2C35299D009884D1 /* ScanItemView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JustScanIt/Model/Scan.swift b/JustScanIt/Model/Scan.swift index 8fb578d..573aae5 100644 --- a/JustScanIt/Model/Scan.swift +++ b/JustScanIt/Model/Scan.swift @@ -8,6 +8,7 @@ import Foundation import SwiftData import UIKit +import SwiftUI @Model final class Scan { @@ -17,6 +18,10 @@ final class Scan { var uiImages: [UIImage] { self.images.map { UIImage(data: $0) ?? UIImage(systemName: "exclamationmark.questionmark")! } } + + var suiImages: [Image] { + self.images.map { Image(uiImage: UIImage(data: $0) ?? UIImage(systemName: "exclamationmark.questionmark")!) } + } init() { self.timestamp = Date() diff --git a/JustScanIt/View/MainView.swift b/JustScanIt/View/MainView.swift index e612414..538c2d9 100644 --- a/JustScanIt/View/MainView.swift +++ b/JustScanIt/View/MainView.swift @@ -40,16 +40,7 @@ struct MainView: View { NavigationView { 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() - - } - } + ScanItemView(scan) } } .navigationTitle("Just Scan It!") @@ -57,6 +48,9 @@ struct MainView: View { VNDocumentCameraViewControllerRepresentable(scanResult: $scannedImages) } .toolbar { + ToolbarItem(placement: .topBarLeading) { + Button("clear") { try? ctx.delete(model: Scan.self) } + } ToolbarItem { Button(action: showVNDocumentCameraView) { Image(systemName: "scanner") @@ -73,10 +67,14 @@ struct MainView: View { } private func saveImages() { + guard !scannedImages.isEmpty else { return } + let newScan = Scan(images: scannedImages) - ctx.insert(newScan) - try? ctx.save() + withAnimation(.easeIn) { + ctx.insert(newScan) + try? ctx.save() + } scannedImages = [] } diff --git a/JustScanIt/View/ScanItemView.swift b/JustScanIt/View/ScanItemView.swift new file mode 100644 index 0000000..6997377 --- /dev/null +++ b/JustScanIt/View/ScanItemView.swift @@ -0,0 +1,104 @@ +// +// ScanItemView.swift +// JustScanIt +// +// Created by Pradyun Setti on 03/07/2024. +// + +import SwiftUI + +struct ScanItemView: View { + @Environment(\.modelContext) var ctx + + let scan: Scan + private let translucentColour = Color(red: 1, green: 1, blue: 1, opacity: 0.4) + + init(_ scan: Scan) { + self.scan = scan + } + + var body: some View { + HStack { + Image(uiImage: scan.uiImages.first ?? UIImage(systemName: "questionmark")!) + .resizable() + .scaledToFit() + .frame(maxWidth: 70, maxHeight: 70) + .padding(4) + .background(translucentColour) + .clipShape(RoundedRectangle(cornerRadius: 12)) + + VStack(alignment: .leading) { + Text("\(scan.uiImages.count) \(scan.uiImages.count == 1 ? "Page" : "Pages")") + .font(.title3) + Text("\(scan.timestamp.formatted())") + .font(.footnote) + } + .foregroundStyle(.white) + Spacer() + + if scan.images.count == 1 { + Button { copy() } label: { + Image(systemName: "doc.on.doc.fill").tint(.white) + .padding(8) + .background(Color(red: 1, green: 1, blue: 1, opacity: 0.4)) + .clipShape(Circle()) + } + } + + ShareLink(items: scan.suiImages, preview: { _ in SharePreview("Scan", image: scan.suiImages.first!)} ) { + Image(systemName: "square.and.arrow.up").tint(.white) + .padding(8) + .background(Color(red: 1, green: 1, blue: 1, opacity: 0.4)) + .offset(y: -2) + .clipShape(Circle()) + } + + Button { delete() } label: { + Image(systemName: "trash.fill").tint(.red) + .padding(8) + .background(Color(red: 1, green: 1, blue: 1, opacity: 0.4)) + .clipShape(Circle()) + } + .contextMenu(menuItems: { + Button("Delete All Scans", role: .destructive) { + deleteAll() + } + }) + + } + .padding() + .background(Color.accentColor) + .clipShape(RoundedRectangle(cornerRadius: 12)) + .padding(.horizontal, 12) + } + + func copy() { + UIPasteboard.general.images = scan.uiImages + } + + func delete() { + withAnimation(.easeOut) { + ctx.delete(scan) + try? ctx.save() + } + } + + func deleteAll() { + withAnimation(.easeOut) { + try? ctx.delete(model: Scan.self) + try? ctx.save() + } + } +} + +#Preview { + let scan = Scan(images: Array(repeating: UIImage(systemName: "book.fill")!, count: 5)) + + return NavigationView { + ScrollView { + ForEach(Array(repeating: scan, count: 10)) { s in + ScanItemView(s) + } + } + } +}