Skip to content

Commit

Permalink
Merge pull request #8 from CS342/feature/documentGallery
Browse files Browse the repository at this point in the history
Add Document Gallery + Sharing
  • Loading branch information
PSchmiedmayer authored Mar 24, 2023
2 parents d9e8101 + 7453d1c commit 64d8152
Show file tree
Hide file tree
Showing 16 changed files with 373 additions and 71 deletions.
30 changes: 29 additions & 1 deletion OwnYourData.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
2FB2FCD729CBDDC00027D85A /* Consent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2FCCC29CBDDC00027D85A /* Consent.swift */; };
2FC9759F2978E39600BA99FE /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2FC9759E2978E39600BA99FE /* Localizable.strings */; };
2FC975A82978F11A00BA99FE /* Home.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FC975A72978F11A00BA99FE /* Home.swift */; };
2FE573A329CD4617008EBBD4 /* PDFDocument+Transferable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE573A229CD4617008EBBD4 /* PDFDocument+Transferable.swift */; };
2FE573A529CD464F008EBBD4 /* PDFListDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE573A429CD464F008EBBD4 /* PDFListDetailView.swift */; };
2FE573A729CD4672008EBBD4 /* PDFView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE573A629CD4672008EBBD4 /* PDFView.swift */; };
2FE573A929CD4697008EBBD4 /* PDFListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE573A829CD4697008EBBD4 /* PDFListRow.swift */; };
2FE573AB29CD46BF008EBBD4 /* DocumentManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE573AA29CD46BF008EBBD4 /* DocumentManager.swift */; };
2FED18F22999AAF400A51A28 /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 2FED18F12999AAF400A51A28 /* Account */; };
2FED18F42999AAF400A51A28 /* FirebaseAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 2FED18F32999AAF400A51A28 /* FirebaseAccount */; };
2FED18FA299A0C7600A51A28 /* FHIRToFirestoreAdapter in Frameworks */ = {isa = PBXBuildFile; productRef = 2FED18F9299A0C7600A51A28 /* FHIRToFirestoreAdapter */; };
Expand Down Expand Up @@ -113,6 +118,11 @@
2FC94CD4298B0A1D009C8209 /* TemplateApplication.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TemplateApplication.xctestplan; sourceTree = "<group>"; };
2FC9759E2978E39600BA99FE /* Localizable.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = "<group>"; };
2FC975A72978F11A00BA99FE /* Home.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Home.swift; sourceTree = "<group>"; };
2FE573A229CD4617008EBBD4 /* PDFDocument+Transferable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PDFDocument+Transferable.swift"; sourceTree = "<group>"; };
2FE573A429CD464F008EBBD4 /* PDFListDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDFListDetailView.swift; sourceTree = "<group>"; };
2FE573A629CD4672008EBBD4 /* PDFView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDFView.swift; sourceTree = "<group>"; };
2FE573A829CD4697008EBBD4 /* PDFListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDFListRow.swift; sourceTree = "<group>"; };
2FE573AA29CD46BF008EBBD4 /* DocumentManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentManager.swift; sourceTree = "<group>"; };
653A254D283387FE005D4D48 /* OwnYourData.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OwnYourData.app; sourceTree = BUILT_PRODUCTS_DIR; };
653A2550283387FE005D4D48 /* TemplateApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateApplication.swift; sourceTree = "<group>"; };
653A255428338800005D4D48 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -220,6 +230,19 @@
path = "Supporting Files";
sourceTree = "<group>";
};
2FE573A129CD4600008EBBD4 /* Documents */ = {
isa = PBXGroup;
children = (
2FE573A229CD4617008EBBD4 /* PDFDocument+Transferable.swift */,
2FE573A429CD464F008EBBD4 /* PDFListDetailView.swift */,
2FE573A629CD4672008EBBD4 /* PDFView.swift */,
2FE573A829CD4697008EBBD4 /* PDFListRow.swift */,
2FE573AA29CD46BF008EBBD4 /* DocumentManager.swift */,
FC1294D229CC1B760008FF21 /* DocumentGalleryView.swift */,
);
path = Documents;
sourceTree = "<group>";
};
653A2544283387FE005D4D48 = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -250,13 +273,13 @@
FCD3FFB629CD0C31004D1E0E /* LogoView.swift */,
2F5E32BC297E05EA003432F8 /* TemplateAppDelegate.swift */,
2FB2FCD829CBDDC30027D85A /* Onboarding */,
2FE573A129CD4600008EBBD4 /* Documents */,
2FC975A72978F11A00BA99FE /* Home.swift */,
2FB2943429CBA29900EE91A0 /* AddDataView.swift */,
2FB2943729CBA29900EE91A0 /* ClinicalTrialsView.swift */,
2FB2943229CBA29900EE91A0 /* HealthRecordView.swift */,
2FA2023229CBCC0C0039C21A /* DocumentScanner.swift */,
2FB2943529CBA29900EE91A0 /* HomeTabView.swift */,
FC1294D229CC1B760008FF21 /* DocumentGalleryView.swift */,
2FB2943329CBA29900EE91A0 /* ProfileView.swift */,
2FB2943629CBA29900EE91A0 /* ShareView.swift */,
27DD24A329CCE56300A6EEBC /* WebView.swift */,
Expand Down Expand Up @@ -475,13 +498,17 @@
2FB2FCD229CBDDC00027D85A /* AccountSetup.swift in Sources */,
2FB2FCB829CBDC0E0027D85A /* StorageKeys.swift in Sources */,
2FB2FCD429CBDDC00027D85A /* String+ModuleLocalized.swift in Sources */,
2FE573A929CD4697008EBBD4 /* PDFListRow.swift in Sources */,
2FE573AB29CD46BF008EBBD4 /* DocumentManager.swift in Sources */,
2FA2023329CBCC0C0039C21A /* DocumentScanner.swift in Sources */,
2FB2943829CBA29900EE91A0 /* HealthRecordView.swift in Sources */,
FCD3FFB729CD0C31004D1E0E /* LogoView.swift in Sources */,
2FB2FCD029CBDDC00027D85A /* TemplateSignUp.swift in Sources */,
2FB2FCD729CBDDC00027D85A /* Consent.swift in Sources */,
2FB2FCD329CBDDC00027D85A /* TemplateLogin.swift in Sources */,
2FE573A729CD4672008EBBD4 /* PDFView.swift in Sources */,
2FC975A82978F11A00BA99FE /* Home.swift in Sources */,
2FE573A329CD4617008EBBD4 /* PDFDocument+Transferable.swift in Sources */,
2F4E23832989D51F0013F3D9 /* TemplateAppTestingSetup.swift in Sources */,
2F5E32BD297E05EA003432F8 /* TemplateAppDelegate.swift in Sources */,
2FB2FCD129CBDDC00027D85A /* UserView.swift in Sources */,
Expand All @@ -493,6 +520,7 @@
2FB2943D29CBA29900EE91A0 /* ClinicalTrialsView.swift in Sources */,
2FB2943929CBA29900EE91A0 /* ProfileView.swift in Sources */,
FCD3FFB929CD1A49004D1E0E /* RecordInstructView.swift in Sources */,
2FE573A529CD464F008EBBD4 /* PDFListDetailView.swift in Sources */,
2FB2FCD629CBDDC00027D85A /* HealthKitPermissions.swift in Sources */,
2FB2FCD529CBDDC00027D85A /* OnboardingFlow.swift in Sources */,
2FB2FCCF29CBDDC00027D85A /* IconView.swift in Sources */,
Expand Down
3 changes: 1 addition & 2 deletions TemplateApplication/AddDataView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import UIKit

struct AddDataView: View {
@Environment(\.openURL) var openURL
@State var document: PDFDocument?
@State var showingPicker = false


Expand Down Expand Up @@ -72,7 +71,7 @@ struct AddDataView: View {
}
.padding(.bottom, 30)
.fullScreenCover(isPresented: $showingPicker) {
DocumentScanner(document: $document)
DocumentScanner()
.background {
Color.black.ignoresSafeArea()
}
Expand Down
21 changes: 0 additions & 21 deletions TemplateApplication/DocumentGalleryView.swift

This file was deleted.

15 changes: 8 additions & 7 deletions TemplateApplication/DocumentScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ import VisionKit

struct DocumentScanner: UIViewControllerRepresentable {
class Coordinator: NSObject, VNDocumentCameraViewControllerDelegate {
@Binding var document: PDFDocument?
let documentManager: DocumentManager


init(document: Binding<PDFDocument?>) {
self._document = document
init(documentManager: DocumentManager) {
self.documentManager = documentManager
}


func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
let pdfDocument = self.document ?? PDFDocument()
let pdfDocument = PDFDocument()

if pdfDocument.documentAttributes == nil {
pdfDocument.documentAttributes = [:]
Expand All @@ -40,13 +40,14 @@ struct DocumentScanner: UIViewControllerRepresentable {
pdfDocument.insert(pdfPage, at: pdfDocument.pageCount)
}

document = pdfDocument
documentManager.store(document: pdfDocument, title: scan.title)

controller.dismiss(animated: true)
}
}


@Binding var document: PDFDocument?
@EnvironmentObject var documentManager: DocumentManager


func makeUIViewController(context: Context) -> some VNDocumentCameraViewController {
Expand All @@ -56,7 +57,7 @@ struct DocumentScanner: UIViewControllerRepresentable {
}

func makeCoordinator() -> Coordinator {
Coordinator(document: $document)
Coordinator(documentManager: documentManager)
}

func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
Expand Down
54 changes: 54 additions & 0 deletions TemplateApplication/Documents/DocumentGalleryView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// This source file is part of the Stanford CardinalKit Template Application project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

import PDFKit
import SwiftUI


struct DocumentGalleryView: View {
@EnvironmentObject var documentManager: DocumentManager
@State var documentScanner = false


var body: some View {
Group {
if documentManager.documents.isEmpty {
Text("No Documents")
} else {
List(documentManager.documents, id: \.documentURL) { document in
PDFListRow(document: document)
}
}
}
.toolbar {
ToolbarItem {
Button(
action: {
documentScanner = true
},
label: {
Image(systemName: "plus")
}
)
}
}
.fullScreenCover(isPresented: $documentScanner) {
DocumentScanner()
.background {
Color.black.ignoresSafeArea()
}
}
.navigationTitle("Documents")
}
}

struct DocumentGalleryView_Previews: PreviewProvider {
static var previews: some View {
DocumentGalleryView()
}
}
79 changes: 79 additions & 0 deletions TemplateApplication/Documents/DocumentManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//
// This source file is part of the Stanford CardinalKit Template Application project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

import PDFKit


class DocumentManager: ObservableObject {
var documents: [PDFDocument] = [] {
willSet {
self.objectWillChange.send()
}
}


init() {
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return
}

let ownYourDataDirectory = documentDirectory.appending(path: "OwnYourData")


var documents: [PDFDocument] = []
do {
let items = try FileManager.default.contentsOfDirectory(at: ownYourDataDirectory, includingPropertiesForKeys: nil)
for item in items {
if let document = PDFDocument(url: item) {
documents.append(document)
}
}
self.documents = documents
} catch {
return
}
}


func store(document: PDFDocument, title: String) {
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return
}

try? FileManager.default.createDirectory(at: documentDirectory.appending(path: "OwnYourData"), withIntermediateDirectories: true)

let documentBaseName: String
if title.isEmpty {
documentBaseName = "Document"
} else {
documentBaseName = title
}

var documentName = documentBaseName

for index in 1...Int.max {
if !FileManager.default.fileExists(atPath: documentDirectory.appending(path: "OwnYourData/\(documentName).pdf").path()) {
break
}
documentName = documentBaseName + "\(index)"
}

let documentPath = documentDirectory.appending(path: "OwnYourData/\(documentName).pdf")

let documentSaved = document.write(to: documentPath)

print("Saved the document \(documentSaved) to \(documentPath)")

if let loadedFromURLDocument = PDFDocument(url: documentPath) {
self.documents.append(loadedFromURLDocument)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.objectWillChange.send()
}
}
}
}
33 changes: 33 additions & 0 deletions TemplateApplication/Documents/PDFDocument+Transferable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// This source file is part of the Stanford CardinalKit Template Application project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

import PDFKit
import SwiftUI


extension PDFDocument: Transferable {
public static var transferRepresentation: some TransferRepresentation {
DataRepresentation(
contentType: .pdf,
exporting: { pdf in
if let data = pdf.dataRepresentation() {
return data
} else {
return Data()
}
},
importing: { data in
if let pdf = PDFDocument(data: data) {
return pdf
} else {
return PDFDocument()
}
}
)
}
}
24 changes: 24 additions & 0 deletions TemplateApplication/Documents/PDFListDetailView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// This source file is part of the Stanford CardinalKit Template Application project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

import PDFKit
import SwiftUI


struct PDFListDetailView: View {
let document: PDFDocument

var body: some View {
PDFView(document)
.toolbar {
ToolbarItem {
ShareLink(item: document, preview: SharePreview("PDF"))
}
}
}
}
Loading

0 comments on commit 64d8152

Please sign in to comment.