diff --git a/OwnYourData.xcodeproj/project.pbxproj b/OwnYourData.xcodeproj/project.pbxproj index 4677db3..21b0b17 100644 --- a/OwnYourData.xcodeproj/project.pbxproj +++ b/OwnYourData.xcodeproj/project.pbxproj @@ -24,10 +24,8 @@ 2F6025CD29BBE92B0045459E /* FHIRMockDataStorageProvider in Frameworks */ = {isa = PBXBuildFile; productRef = 2F6025CC29BBE92B0045459E /* FHIRMockDataStorageProvider */; }; 2F6025D029BBEC610045459E /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 2F6025CF29BBEC610045459E /* FirebaseAuth */; }; 2FA2023329CBCC0C0039C21A /* DocumentScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA2023229CBCC0C0039C21A /* DocumentScanner.swift */; }; - 2FB2943829CBA29900EE91A0 /* HealthRecordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2943229CBA29900EE91A0 /* HealthRecordView.swift */; }; 2FB2943929CBA29900EE91A0 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2943329CBA29900EE91A0 /* ProfileView.swift */; }; 2FB2943A29CBA29900EE91A0 /* AddDataView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2943429CBA29900EE91A0 /* AddDataView.swift */; }; - 2FB2943B29CBA29900EE91A0 /* HomeTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2943529CBA29900EE91A0 /* HomeTabView.swift */; }; 2FB2943C29CBA29900EE91A0 /* ShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2943629CBA29900EE91A0 /* ShareView.swift */; }; 2FB2943D29CBA29900EE91A0 /* ClinicalTrialsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2943729CBA29900EE91A0 /* ClinicalTrialsView.swift */; }; 2FB2944029CBA4AE00EE91A0 /* ImageSource in Frameworks */ = {isa = PBXBuildFile; productRef = 2FB2943F29CBA4AE00EE91A0 /* ImageSource */; }; @@ -45,10 +43,16 @@ 2FB2FCD329CBDDC00027D85A /* TemplateLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2FCC829CBDDC00027D85A /* TemplateLogin.swift */; }; 2FB2FCD429CBDDC00027D85A /* String+ModuleLocalized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2FCC929CBDDC00027D85A /* String+ModuleLocalized.swift */; }; 2FB2FCD529CBDDC00027D85A /* OnboardingFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2FCCA29CBDDC00027D85A /* OnboardingFlow.swift */; }; - 2FB2FCD629CBDDC00027D85A /* HealthKitPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2FCCB29CBDDC00027D85A /* HealthKitPermissions.swift */; }; 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 */; }; + 2FC975A82978F11A00BA99FE /* OwnYourDataTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FC975A72978F11A00BA99FE /* OwnYourDataTabView.swift */; }; + 2FCDD17729CE505D0097D6D2 /* OwnYourDataSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCDD17629CE505D0097D6D2 /* OwnYourDataSection.swift */; }; + 2FCDD17929CE50660097D6D2 /* OwnYourDataButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCDD17829CE50660097D6D2 /* OwnYourDataButton.swift */; }; + 2FCDD17A29CE51C30097D6D2 /* Home.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB2943529CBA29900EE91A0 /* Home.swift */; }; + 2FCDD17F29CE603B0097D6D2 /* OpenAppleHealthApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCDD17E29CE603B0097D6D2 /* OpenAppleHealthApp.swift */; }; + 2FCDD18129CE60EB0097D6D2 /* Instructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCDD18029CE60EB0097D6D2 /* Instructions.swift */; }; + 2FCDD18329CE64BE0097D6D2 /* InstructionsStep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCDD18229CE64BE0097D6D2 /* InstructionsStep.swift */; }; + 2FCDD18529CE6A3E0097D6D2 /* HowItWorks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCDD18429CE6A3E0097D6D2 /* HowItWorks.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 */; }; @@ -64,7 +68,7 @@ 653A255528338800005D4D48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 653A255428338800005D4D48 /* Assets.xcassets */; }; 653A256228338800005D4D48 /* TemplateApplicationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A256128338800005D4D48 /* TemplateApplicationTests.swift */; }; FC024B5729CD9B1F00AFEFDF /* ViewRecordsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC024B5629CD9B1F00AFEFDF /* ViewRecordsView.swift */; }; - FC1294D329CC1B760008FF21 /* DocumentGalleryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1294D229CC1B760008FF21 /* DocumentGalleryView.swift */; }; + FC1294D329CC1B760008FF21 /* DocumentGallery.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1294D229CC1B760008FF21 /* DocumentGallery.swift */; }; FCD3FFB729CD0C31004D1E0E /* LogoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD3FFB629CD0C31004D1E0E /* LogoView.swift */; }; FCD3FFB929CD1A49004D1E0E /* RecordInstructView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD3FFB829CD1A49004D1E0E /* RecordInstructView.swift */; }; FCD3FFBB29CD898D004D1E0E /* AddRecordInstructView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD3FFBA29CD898D004D1E0E /* AddRecordInstructView.swift */; }; @@ -95,10 +99,9 @@ 2F6025CA29BBE70F0045459E /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 2FA2023229CBCC0C0039C21A /* DocumentScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentScanner.swift; sourceTree = ""; }; 2FAEC07F297F583900C11C42 /* TemplateApplication.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TemplateApplication.entitlements; sourceTree = ""; }; - 2FB2943229CBA29900EE91A0 /* HealthRecordView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HealthRecordView.swift; sourceTree = ""; }; 2FB2943329CBA29900EE91A0 /* ProfileView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; 2FB2943429CBA29900EE91A0 /* AddDataView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddDataView.swift; sourceTree = ""; }; - 2FB2943529CBA29900EE91A0 /* HomeTabView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeTabView.swift; sourceTree = ""; }; + 2FB2943529CBA29900EE91A0 /* Home.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Home.swift; sourceTree = ""; }; 2FB2943629CBA29900EE91A0 /* ShareView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareView.swift; sourceTree = ""; }; 2FB2943729CBA29900EE91A0 /* ClinicalTrialsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClinicalTrialsView.swift; sourceTree = ""; }; 2FB2FCB329CBDC0E0027D85A /* CodableArray+RawRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CodableArray+RawRepresentable.swift"; sourceTree = ""; }; @@ -115,11 +118,16 @@ 2FB2FCC829CBDDC00027D85A /* TemplateLogin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TemplateLogin.swift; sourceTree = ""; }; 2FB2FCC929CBDDC00027D85A /* String+ModuleLocalized.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "String+ModuleLocalized.swift"; path = "TemplateApplication/Onboarding/String+ModuleLocalized.swift"; sourceTree = SOURCE_ROOT; }; 2FB2FCCA29CBDDC00027D85A /* OnboardingFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OnboardingFlow.swift; path = TemplateApplication/Onboarding/OnboardingFlow.swift; sourceTree = SOURCE_ROOT; }; - 2FB2FCCB29CBDDC00027D85A /* HealthKitPermissions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HealthKitPermissions.swift; path = TemplateApplication/Onboarding/HealthKitPermissions.swift; sourceTree = SOURCE_ROOT; }; 2FB2FCCC29CBDDC00027D85A /* Consent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Consent.swift; path = TemplateApplication/Onboarding/Consent.swift; sourceTree = SOURCE_ROOT; }; 2FC94CD4298B0A1D009C8209 /* TemplateApplication.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TemplateApplication.xctestplan; sourceTree = ""; }; 2FC9759E2978E39600BA99FE /* Localizable.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = ""; }; - 2FC975A72978F11A00BA99FE /* Home.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Home.swift; sourceTree = ""; }; + 2FC975A72978F11A00BA99FE /* OwnYourDataTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OwnYourDataTabView.swift; sourceTree = ""; }; + 2FCDD17629CE505D0097D6D2 /* OwnYourDataSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OwnYourDataSection.swift; sourceTree = ""; }; + 2FCDD17829CE50660097D6D2 /* OwnYourDataButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OwnYourDataButton.swift; sourceTree = ""; }; + 2FCDD17E29CE603B0097D6D2 /* OpenAppleHealthApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenAppleHealthApp.swift; sourceTree = ""; }; + 2FCDD18029CE60EB0097D6D2 /* Instructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instructions.swift; sourceTree = ""; }; + 2FCDD18229CE64BE0097D6D2 /* InstructionsStep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstructionsStep.swift; sourceTree = ""; }; + 2FCDD18429CE6A3E0097D6D2 /* HowItWorks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HowItWorks.swift; sourceTree = ""; }; 2FE573A229CD4617008EBBD4 /* PDFDocument+Transferable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PDFDocument+Transferable.swift"; sourceTree = ""; }; 2FE573A429CD464F008EBBD4 /* PDFListDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDFListDetailView.swift; sourceTree = ""; }; 2FE573A629CD4672008EBBD4 /* PDFView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDFView.swift; sourceTree = ""; }; @@ -133,7 +141,7 @@ 653A256728338800005D4D48 /* OwnYourDataUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OwnYourDataUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 653A258928339462005D4D48 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; FC024B5629CD9B1F00AFEFDF /* ViewRecordsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewRecordsView.swift; sourceTree = ""; }; - FC1294D229CC1B760008FF21 /* DocumentGalleryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentGalleryView.swift; sourceTree = ""; }; + FC1294D229CC1B760008FF21 /* DocumentGallery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentGallery.swift; sourceTree = ""; }; FCD3FFB629CD0C31004D1E0E /* LogoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoView.swift; sourceTree = ""; }; FCD3FFB829CD1A49004D1E0E /* RecordInstructView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordInstructView.swift; sourceTree = ""; }; FCD3FFBA29CD898D004D1E0E /* AddRecordInstructView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddRecordInstructView.swift; sourceTree = ""; }; @@ -200,7 +208,6 @@ children = ( 2FB2FCC329CBDDC00027D85A /* AccountSetup */, 2FB2FCCC29CBDDC00027D85A /* Consent.swift */, - 2FB2FCCB29CBDDC00027D85A /* HealthKitPermissions.swift */, 2FB2FCC129CBDDBF0027D85A /* InterestingModules.swift */, 2FB2FCCA29CBDDC00027D85A /* OnboardingFlow.swift */, 2FB2FCC929CBDDC00027D85A /* String+ModuleLocalized.swift */, @@ -234,6 +241,51 @@ path = "Supporting Files"; sourceTree = ""; }; + 2FCDD17529CE50540097D6D2 /* ReusableViews */ = { + isa = PBXGroup; + children = ( + FCD3FFB629CD0C31004D1E0E /* LogoView.swift */, + 2FCDD17629CE505D0097D6D2 /* OwnYourDataSection.swift */, + 2FCDD17829CE50660097D6D2 /* OwnYourDataButton.swift */, + ); + path = ReusableViews; + sourceTree = ""; + }; + 2FCDD17B29CE57F30097D6D2 /* Tabs */ = { + isa = PBXGroup; + children = ( + 2FC975A72978F11A00BA99FE /* OwnYourDataTabView.swift */, + 2FB2943529CBA29900EE91A0 /* Home.swift */, + 2FB2943429CBA29900EE91A0 /* AddDataView.swift */, + 2FB2943629CBA29900EE91A0 /* ShareView.swift */, + 2FB2943329CBA29900EE91A0 /* ProfileView.swift */, + ); + path = Tabs; + sourceTree = ""; + }; + 2FCDD17C29CE58210097D6D2 /* ClinicalTrials */ = { + isa = PBXGroup; + children = ( + 2FB2943729CBA29900EE91A0 /* ClinicalTrialsView.swift */, + 27DD24A329CCE56300A6EEBC /* WebView.swift */, + ); + path = ClinicalTrials; + sourceTree = ""; + }; + 2FCDD17D29CE58550097D6D2 /* Instructions */ = { + isa = PBXGroup; + children = ( + FCD3FFB829CD1A49004D1E0E /* RecordInstructView.swift */, + FC024B5629CD9B1F00AFEFDF /* ViewRecordsView.swift */, + FCD3FFBA29CD898D004D1E0E /* AddRecordInstructView.swift */, + 2FCDD18429CE6A3E0097D6D2 /* HowItWorks.swift */, + 2FCDD18029CE60EB0097D6D2 /* Instructions.swift */, + 2FCDD18229CE64BE0097D6D2 /* InstructionsStep.swift */, + 2FCDD17E29CE603B0097D6D2 /* OpenAppleHealthApp.swift */, + ); + path = Instructions; + sourceTree = ""; + }; 2FE573A129CD4600008EBBD4 /* Documents */ = { isa = PBXGroup; children = ( @@ -242,7 +294,8 @@ 2FE573A629CD4672008EBBD4 /* PDFView.swift */, 2FE573A829CD4697008EBBD4 /* PDFListRow.swift */, 2FE573AA29CD46BF008EBBD4 /* DocumentManager.swift */, - FC1294D229CC1B760008FF21 /* DocumentGalleryView.swift */, + 2FA2023229CBCC0C0039C21A /* DocumentScanner.swift */, + FC1294D229CC1B760008FF21 /* DocumentGallery.swift */, ); path = Documents; sourceTree = ""; @@ -273,22 +326,13 @@ isa = PBXGroup; children = ( 653A2550283387FE005D4D48 /* TemplateApplication.swift */, - FCD3FFB629CD0C31004D1E0E /* LogoView.swift */, 2F5E32BC297E05EA003432F8 /* TemplateAppDelegate.swift */, + 2FCDD17B29CE57F30097D6D2 /* Tabs */, 2FB2FCD829CBDDC30027D85A /* Onboarding */, 2FE573A129CD4600008EBBD4 /* Documents */, - 2FC975A72978F11A00BA99FE /* Home.swift */, - 2FB2943429CBA29900EE91A0 /* AddDataView.swift */, - 2FB2943729CBA29900EE91A0 /* ClinicalTrialsView.swift */, - 2FB2943229CBA29900EE91A0 /* HealthRecordView.swift */, - 2FA2023229CBCC0C0039C21A /* DocumentScanner.swift */, - 2FB2943529CBA29900EE91A0 /* HomeTabView.swift */, - FCD3FFB829CD1A49004D1E0E /* RecordInstructView.swift */, - FC024B5629CD9B1F00AFEFDF /* ViewRecordsView.swift */, - FCD3FFBA29CD898D004D1E0E /* AddRecordInstructView.swift */, - 2FB2943329CBA29900EE91A0 /* ProfileView.swift */, - 2FB2943629CBA29900EE91A0 /* ShareView.swift */, - 27DD24A329CCE56300A6EEBC /* WebView.swift */, + 2FCDD17529CE50540097D6D2 /* ReusableViews */, + 2FCDD17C29CE58210097D6D2 /* ClinicalTrials */, + 2FCDD17D29CE58550097D6D2 /* Instructions */, 2FB2FCD929CBDE540027D85A /* Extensions & Infrastructure */, 2FC9759D2978E30800BA99FE /* Supporting Files */, ); @@ -504,30 +548,35 @@ 2FB2FCD229CBDDC00027D85A /* AccountSetup.swift in Sources */, 2FB2FCB829CBDC0E0027D85A /* StorageKeys.swift in Sources */, 2FB2FCD429CBDDC00027D85A /* String+ModuleLocalized.swift in Sources */, + 2FCDD17729CE505D0097D6D2 /* OwnYourDataSection.swift in Sources */, 2FE573A929CD4697008EBBD4 /* PDFListRow.swift in Sources */, 2FE573AB29CD46BF008EBBD4 /* DocumentManager.swift in Sources */, + 2FCDD18529CE6A3E0097D6D2 /* HowItWorks.swift in Sources */, + 2FCDD17F29CE603B0097D6D2 /* OpenAppleHealthApp.swift in Sources */, + 2FCDD18129CE60EB0097D6D2 /* Instructions.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 */, + 2FC975A82978F11A00BA99FE /* OwnYourDataTabView.swift in Sources */, 2FE573A329CD4617008EBBD4 /* PDFDocument+Transferable.swift in Sources */, 2F4E23832989D51F0013F3D9 /* TemplateAppTestingSetup.swift in Sources */, 2F5E32BD297E05EA003432F8 /* TemplateAppDelegate.swift in Sources */, 2FB2FCD129CBDDC00027D85A /* UserView.swift in Sources */, 2FB2FCCE29CBDDC00027D85A /* Welcome.swift in Sources */, + 2FCDD17A29CE51C30097D6D2 /* Home.swift in Sources */, 2FB2FCB929CBDC0E0027D85A /* FeatureFlags.swift in Sources */, 2FB2FCBA29CBDC0E0027D85A /* CodableArray+RawRepresentable.swift in Sources */, 2FB2FCCD29CBDDC00027D85A /* InterestingModules.swift in Sources */, 2FB2FCB729CBDC0E0027D85A /* Binding+Negate.swift in Sources */, 2FB2943D29CBA29900EE91A0 /* ClinicalTrialsView.swift in Sources */, + 2FCDD18329CE64BE0097D6D2 /* InstructionsStep.swift in Sources */, 2FB2943929CBA29900EE91A0 /* ProfileView.swift in Sources */, FCD3FFB929CD1A49004D1E0E /* RecordInstructView.swift in Sources */, 2FE573A529CD464F008EBBD4 /* PDFListDetailView.swift in Sources */, - 2FB2FCD629CBDDC00027D85A /* HealthKitPermissions.swift in Sources */, + 2FCDD17929CE50660097D6D2 /* OwnYourDataButton.swift in Sources */, 2FB2FCD529CBDDC00027D85A /* OnboardingFlow.swift in Sources */, 2FB2FCCF29CBDDC00027D85A /* IconView.swift in Sources */, FC024B5729CD9B1F00AFEFDF /* ViewRecordsView.swift in Sources */, @@ -536,8 +585,7 @@ 27DD24A429CCE56400A6EEBC /* WebView.swift in Sources */, FCD3FFBB29CD898D004D1E0E /* AddRecordInstructView.swift in Sources */, 2FB2943A29CBA29900EE91A0 /* AddDataView.swift in Sources */, - FC1294D329CC1B760008FF21 /* DocumentGalleryView.swift in Sources */, - 2FB2943B29CBA29900EE91A0 /* HomeTabView.swift in Sources */, + FC1294D329CC1B760008FF21 /* DocumentGallery.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -654,7 +702,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 637867499T; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "TemplateApplication/Supporting Files/Info.plist"; @@ -846,7 +894,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 637867499T; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "TemplateApplication/Supporting Files/Info.plist"; diff --git a/TemplateApplication/AddDataView.swift b/TemplateApplication/AddDataView.swift deleted file mode 100644 index 2bbbdfc..0000000 --- a/TemplateApplication/AddDataView.swift +++ /dev/null @@ -1,93 +0,0 @@ -// -// This source file is part of the Stanford CardinalKit Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import CardinalKit -import FHIR -import HealthKitDataSource -import HealthKitToFHIRAdapter -import ImageSource -import PDFKit -import SwiftUI -import UIKit - - -struct AddDataView: View { - @Environment(\.openURL) var openURL - @State var showingPicker = false - - - var body: some View { - NavigationView { - VStack { - LogoView() - Spacer() - Text("Connect to \nHealth System") - .font(.largeTitle) - .foregroundColor(Color.accentColor) - .fontWeight(.medium) - .multilineTextAlignment(.center) - // Button(action: { - // guard let url = URL(string: "x-apple-health://") else { - // fatalError("Could not create a Health App URL") - // } - // openURL(url) - // }) { - NavigationLink(destination: AddRecordInstructView()) { - Text("Select Health System") - .font(.headline) - .fontWeight(.bold) - .padding() - .frame(maxWidth: .infinity) - .foregroundColor(Color.white) - .background(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .cornerRadius(10) - .padding(.leading) - .padding(.trailing) - } - - Spacer().frame(height: 40) - - VStack { - Text("Take a Photo \nof Document") - .font(.largeTitle) - .foregroundColor(Color.accentColor) - .fontWeight(.medium) - .multilineTextAlignment(.center) - Button(action: { - self.showingPicker.toggle() - }) { - Text("Go to Camera") - .font(.headline) - .fontWeight(.bold) - .padding() - .frame(maxWidth: .infinity) - .foregroundColor(Color.white) - .background(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .cornerRadius(10) - .padding(.leading) - .padding(.trailing) - } - } - .padding(.bottom, 30) - .fullScreenCover(isPresented: $showingPicker) { - DocumentScanner() - .background { - Color.black.ignoresSafeArea() - } - } - } - } - } -} - - -struct AddDataView_Previews: PreviewProvider { - static var previews: some View { - AddDataView() - } -} diff --git a/TemplateApplication/AddRecordInstructView.swift b/TemplateApplication/AddRecordInstructView.swift deleted file mode 100644 index 3d9702c..0000000 --- a/TemplateApplication/AddRecordInstructView.swift +++ /dev/null @@ -1,127 +0,0 @@ -// -// This source file is part of the Stanford CardinalKit Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import CardinalKit -import FHIR -import HealthKitDataSource -import HealthKitToFHIRAdapter -import ImageSource -import SwiftUI -import UIKit - - -struct AddRecordInstructView: View { - @Environment(\.openURL) var openURL - - - var body: some View { - VStack(alignment: .leading) { - HStack { - Text("How It Works") - .font(.largeTitle) - .bold() - .foregroundColor(Color.accentColor) - .padding(.leading, 90) - } - Spacer() - HStack { - Image(systemName: "1.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Open the Apple Health App") - .foregroundColor(Color.accentColor) - .font(.title3) - Spacer() - Image("AppleHealthAppImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Apple Health App")) - .foregroundColor(Color.accentColor) - .frame(width: 90, height: 90) - .padding(.trailing, 18) - } - HStack { - Image(systemName: "2.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Go to the \"Browse\" Tab") - .foregroundColor(Color.accentColor) - .font(.title3) - Spacer() - Image("BrowseTabImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Apple Health App")) - .foregroundColor(Color.accentColor) - .frame(width: 120, height: 120) - .padding(.trailing, 0) - } - HStack { - Image(systemName: "3.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Tap \"Add Account\" to select Health System") - .foregroundColor(Color.accentColor) - .font(.title3) -// .padding(.trailing, 0) - Image("AddAccountImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Apple Health App")) - .foregroundColor(Color.accentColor) - .frame(width: 120, height: 120) - .padding(.leading, 45) - .padding(.trailing, 10) - } - HStack { - Image(systemName: "4.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Log into your health system and provide permission to \ndownload your health data to your phone") - .foregroundColor(Color.accentColor) - .font(.title3) - .padding(.trailing, 50) - } - Spacer() - HStack { - Text("Tap Health App \nto get started!") - .foregroundColor(Color.accentColor) - .font(.system(size: 30)) - .bold() - .padding(.leading, 40) - .padding(.trailing, 10) - .padding(.bottom, 30) - - Image("AppleHealthAppImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Apple Health App")) - .foregroundColor(Color.accentColor) - .frame(width: 90, height: 90) - .padding(.bottom, 30) - .onTapGesture { - guard let url = URL(string: "x-apple-health://") else { - fatalError("Could not create a Health App URL") - } - openURL(url) - } - } - } - } -} - - -struct AddREcordInstructView_Previews: PreviewProvider { - static var previews: some View { - RecordInstructView() - } -} diff --git a/TemplateApplication/ClinicalTrialsView.swift b/TemplateApplication/ClinicalTrials/ClinicalTrialsView.swift similarity index 99% rename from TemplateApplication/ClinicalTrialsView.swift rename to TemplateApplication/ClinicalTrials/ClinicalTrialsView.swift index 20c41d5..c4730dc 100644 --- a/TemplateApplication/ClinicalTrialsView.swift +++ b/TemplateApplication/ClinicalTrials/ClinicalTrialsView.swift @@ -8,6 +8,7 @@ import SwiftUI + struct ClinicalTrialsView: View { var body: some View { if let url = URL(string: "https://www.cancer.gov/about-cancer/treatment/clinical-trials/search") { diff --git a/TemplateApplication/ClinicalTrials/WebView.swift b/TemplateApplication/ClinicalTrials/WebView.swift new file mode 100644 index 0000000..0c40a5c --- /dev/null +++ b/TemplateApplication/ClinicalTrials/WebView.swift @@ -0,0 +1,22 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SafariServices +import SwiftUI + + +struct WebView: UIViewControllerRepresentable { + var url: URL + + + func makeUIViewController(context: Context) -> SFSafariViewController { + SFSafariViewController(url: url) + } + + func updateUIViewController(_ safariViewController: SFSafariViewController, context: Context) {} +} diff --git a/TemplateApplication/Documents/DocumentGalleryView.swift b/TemplateApplication/Documents/DocumentGallery.swift similarity index 95% rename from TemplateApplication/Documents/DocumentGalleryView.swift rename to TemplateApplication/Documents/DocumentGallery.swift index 1b483d8..fb3c264 100644 --- a/TemplateApplication/Documents/DocumentGalleryView.swift +++ b/TemplateApplication/Documents/DocumentGallery.swift @@ -10,7 +10,7 @@ import PDFKit import SwiftUI -struct DocumentGalleryView: View { +struct DocumentGallery: View { @EnvironmentObject var documentManager: DocumentManager @State var documentScanner = false @@ -49,6 +49,6 @@ struct DocumentGalleryView: View { struct DocumentGalleryView_Previews: PreviewProvider { static var previews: some View { - DocumentGalleryView() + DocumentGallery() } } diff --git a/TemplateApplication/Documents/DocumentManager.swift b/TemplateApplication/Documents/DocumentManager.swift index 23385c5..7443c9e 100644 --- a/TemplateApplication/Documents/DocumentManager.swift +++ b/TemplateApplication/Documents/DocumentManager.swift @@ -16,26 +16,19 @@ class DocumentManager: ObservableObject { } } - - init() { + var documentURLs: [URL] { guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { - return + 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 + return (try? FileManager.default.contentsOfDirectory(at: ownYourDataDirectory, includingPropertiesForKeys: nil)) ?? [] + } + + + init() { + self.documents = documentURLs.compactMap { documentURL in + PDFDocument(url: documentURL) } } @@ -76,4 +69,10 @@ class DocumentManager: ObservableObject { } } } + + func removeAllDocuments() { + for documentURL in documentURLs { + try? FileManager.default.removeItem(at: documentURL) + } + } } diff --git a/TemplateApplication/DocumentScanner.swift b/TemplateApplication/Documents/DocumentScanner.swift similarity index 100% rename from TemplateApplication/DocumentScanner.swift rename to TemplateApplication/Documents/DocumentScanner.swift diff --git a/TemplateApplication/Extensions & Infrastructure/StorageKeys.swift b/TemplateApplication/Extensions & Infrastructure/StorageKeys.swift index 5f900bc..e629302 100644 --- a/TemplateApplication/Extensions & Infrastructure/StorageKeys.swift +++ b/TemplateApplication/Extensions & Infrastructure/StorageKeys.swift @@ -21,6 +21,10 @@ public enum StorageKeys { // MARK: - Name - /// The name of the currently signed in user - public static let userName = "user.name" + /// The first name of the currently signed in user + public static let firstName = "user.firstName" + /// The laste name of the currently signed in user + public static let lastName = "user.lastName" + /// The email of the currently signed in user + public static let email = "user.email" } diff --git a/TemplateApplication/HealthRecordView.swift b/TemplateApplication/HealthRecordView.swift deleted file mode 100644 index 08c02a5..0000000 --- a/TemplateApplication/HealthRecordView.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// This source file is part of the Stanford CardinalKit Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import FirebaseAccount -import FirebaseAuth -import SwiftUI - - -// Replace the following placeholder views with the actual implementation for each data element category -struct ConditionsView: View { var body: some View { Text("Conditions View") } } -struct MedicationRecordsView: View { var body: some View { Text("Medication Records View") } } -struct AllergiesView: View { var body: some View { Text("Allergies View") } } -struct ImmunizationsView: View { var body: some View { Text("Immunizations View") } } -struct ClinicalVitalsView: View { var body: some View { Text("Clinical Vitals View") } } -struct LabResultsView: View { var body: some View { Text("Lab Results View") } } -struct ProceduresView: View { var body: some View { Text("Procedures View") } } -struct OtherDocumentsGallery: View { var body: some View { Text("Other Documents Gallery") } } - -struct HealthRecordView: View { - var body: some View { - VStack { - HStack { - healthRecordButton(label: "Conditions", destination: ConditionsView()) - healthRecordButton(label: "Medication Records", destination: MedicationRecordsView()) - } - HStack { - healthRecordButton(label: "Allergies", destination: AllergiesView()) - healthRecordButton(label: "Immunizations", destination: ImmunizationsView()) - } - HStack { - healthRecordButton(label: "Clinical Vitals", destination: ClinicalVitalsView()) - healthRecordButton(label: "Lab Results", destination: LabResultsView()) - } - HStack { - healthRecordButton(label: "Procedures", destination: ProceduresView()) - healthRecordButton(label: "Other Documents", destination: OtherDocumentsGallery()) - } - }.padding() - } - - private func healthRecordButton(label: String, destination: Destination) -> some View { - NavigationLink(destination: destination) { - Text(label) - .foregroundColor(.white) - .frame(minWidth: 0, maxWidth: .infinity) - .padding() - .background(Color.blue) - .cornerRadius(8) - }.padding(.horizontal) - } -} - - -struct HealthRecordView_Previews: PreviewProvider { - static var previews: some View { - HealthRecordView() - } -} diff --git a/TemplateApplication/HomeTabView.swift b/TemplateApplication/HomeTabView.swift deleted file mode 100644 index cf0ad83..0000000 --- a/TemplateApplication/HomeTabView.swift +++ /dev/null @@ -1,106 +0,0 @@ -// -// This source file is part of the Stanford CardinalKit Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import FirebaseAccount -import FirebaseAuth -import SafariServices -import SwiftUI - - -struct HomeTabView: View { - @AppStorage(StorageKeys.userName) var appStorageUserName = "" - @State private var userName: String = "" - - - var body: some View { - NavigationStack { - VStack { - LogoView() - Text("Welcome,") - .font(Font.system(size: 60)) - .foregroundColor(Color.accentColor) - .fontWeight(.semibold) - .padding(.bottom, 1) - - Text("\(userName).") - .font(Font.system(size: 60)) - .foregroundColor(Color.accentColor) - .fontWeight(.semibold) - - Spacer() - - VStack { - NavigationLink(destination: ViewRecordsView()) { - Text("Records") - .font(.headline) - .fontWeight(.bold) - .padding() - .frame(maxWidth: .infinity) - .foregroundColor(Color.white) - .background(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .cornerRadius(10) - .padding(.leading) - .padding(.trailing) - } - .padding(.bottom, 20) - - NavigationLink(destination: DocumentGalleryView()) { - Text("Scanned Documents") - .font(.headline) - .fontWeight(.bold) - .padding() - .frame(maxWidth: .infinity) - .foregroundColor(.white) - .background(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .cornerRadius(10) - .padding(.leading) - .padding(.trailing) - } - .padding(.bottom, 20) - - NavigationLink(destination: ClinicalTrialsView()) { - Text("Find Clinical Trials") - .font(.headline) - .fontWeight(.bold) - .padding() - .frame(maxWidth: .infinity) - .foregroundColor(.white) - .background(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .cornerRadius(10) - .padding(.leading) - .padding(.trailing) - } - } - } - .padding(.bottom, 30) - .onAppear { - getUserName() - } - } - } - - func getUserName() { - userName = appStorageUserName.split(separator: " ").first.map(String.init) ?? "" - if let user = Auth.auth().currentUser { - user.reload { error in - if let error = error { - print("Error reloading user: \(error.localizedDescription)") - } else { - userName = user.displayName?.split(separator: " ").first.map(String.init) ?? "User" - } - } - } - } -} - - -struct HomeTabView_Previews: PreviewProvider { - static var previews: some View { - HomeTabView() - } -} diff --git a/TemplateApplication/Instructions/AddRecordInstructView.swift b/TemplateApplication/Instructions/AddRecordInstructView.swift new file mode 100644 index 0000000..5dbc96d --- /dev/null +++ b/TemplateApplication/Instructions/AddRecordInstructView.swift @@ -0,0 +1,48 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import CardinalKit +import FHIR +import HealthKitDataSource +import HealthKitToFHIRAdapter +import ImageSource +import SwiftUI +import UIKit + + +struct AddRecordInstructView: View { + @Environment(\.openURL) var openURL + + + var body: some View { + HowItWorks( + steps: [ + InstructionsStep.openHealthApp, + InstructionsStep.browseTab, + InstructionsStep(title: "Tap \"Add Account\" to select Health System") { + Image("AddAccountImage") + .resizable() + .scaledToFit() + .accessibilityLabel(Text("Add an account in the Apple Health app.")) + .foregroundColor(Color.accentColor) + .frame(width: 120, height: 120) + .shadow(color: .gray, radius: 4) + .padding(.leading, 16) + }, + InstructionsStep(title: "Log into your health system and provide permission to \ndownload your health data to your phone") + ] + ) + } +} + + +struct AddREcordInstructView_Previews: PreviewProvider { + static var previews: some View { + RecordInstructView() + } +} diff --git a/TemplateApplication/Instructions/HowItWorks.swift b/TemplateApplication/Instructions/HowItWorks.swift new file mode 100644 index 0000000..f7881f1 --- /dev/null +++ b/TemplateApplication/Instructions/HowItWorks.swift @@ -0,0 +1,48 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + +struct HowItWorks: View { + private let steps: [AnyView] + + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 8) { + HStack { + Text("How It Works") + .font(.largeTitle) + .bold() + .foregroundColor(Color.accentColor) + .padding(.leading, 90) + } + Spacer() + Instructions(steps: steps) + Spacer() + OpenAppleHealthApp() + } + } + } + + + init(steps: [AnyView]) { + self.steps = steps + } + + init(steps: [V]) { + self.steps = steps.map { AnyView($0) } + } +} + + +struct HowItWorks_Previews: PreviewProvider { + static var previews: some View { + HowItWorks(steps: []) + } +} diff --git a/TemplateApplication/Instructions/Instructions.swift b/TemplateApplication/Instructions/Instructions.swift new file mode 100644 index 0000000..d841327 --- /dev/null +++ b/TemplateApplication/Instructions/Instructions.swift @@ -0,0 +1,50 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +struct Instructions: View { + let steps: [(offset: Int, element: AnyView)] + + + var body: some View { + ForEach(steps, id: \.offset) { step in + HStack { + Image(systemName: "\(step.offset + 1).circle.fill") + .foregroundColor(Color("ButtonColor_light")) + .font(.system(size: 45)) + .frame(minHeight: 90) + .padding(.trailing, 10) + step.element + } + } + .padding(.horizontal) + } + + + init(steps: [AnyView]) { + self.steps = Array(steps.enumerated()) + } + + init(steps: [V]) { + self.steps = Array( + steps + .map { + AnyView($0) + } + .enumerated() + ) + } +} + +struct Instructions_Previews: PreviewProvider { + static var previews: some View { + Instructions(steps: []) + } +} diff --git a/TemplateApplication/Instructions/InstructionsStep.swift b/TemplateApplication/Instructions/InstructionsStep.swift new file mode 100644 index 0000000..4349729 --- /dev/null +++ b/TemplateApplication/Instructions/InstructionsStep.swift @@ -0,0 +1,74 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + +struct InstructionsStep: View { + let title: String + let content: AnyView + + + var body: some View { + HStack { + Text(title) + .foregroundColor(.accentColor) + .font(.title3) + Spacer() + content + } + } + + + init(title: String, @ViewBuilder content: () -> (StepContent)) { + self.title = title + self.content = AnyView(content()) + } + + init(title: String) { + self.title = title + self.content = AnyView(EmptyView()) + } +} + + +extension InstructionsStep { + static var openHealthApp: InstructionsStep { + InstructionsStep(title: "Open the Apple Health App") { + Image("AppleHealthAppImage") + .resizable() + .scaledToFit() + .accessibilityLabel(Text("Open the Apple Health app.")) + .foregroundColor(.accentColor) + .frame(width: 90, height: 90) + .shadow(color: .gray, radius: 4) + .padding(.trailing, 16) + } + } + + static var browseTab: InstructionsStep { + InstructionsStep(title: "Go to the \"Browse\" Tab") { + Image("BrowseTabImage") + .resizable() + .scaledToFit() + .accessibilityLabel(Text("Navigate to the Browse tab.")) + .foregroundColor(Color.accentColor) + .frame(width: 85, height: 85) + .shadow(color: .gray, radius: 4) + .padding(.trailing, 16) + } + } +} + + +struct InstructionsStep_Previews: PreviewProvider { + static var previews: some View { + InstructionsStep(title: "Instruction") { + Text("Step Content ...") + } + } +} diff --git a/TemplateApplication/Instructions/OpenAppleHealthApp.swift b/TemplateApplication/Instructions/OpenAppleHealthApp.swift new file mode 100644 index 0000000..9dc11ee --- /dev/null +++ b/TemplateApplication/Instructions/OpenAppleHealthApp.swift @@ -0,0 +1,46 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +struct OpenAppleHealthApp: View { + @Environment(\.openURL) private var openURL + + + var body: some View { + HStack(spacing: 16) { + Text("Tap Health App \nto get started!") + .foregroundColor(.accentColor) + .font(.system(size: 30).weight(.bold)) + Image("AppleHealthAppImage") + .resizable() + .scaledToFit() + .foregroundColor(Color.accentColor) + .accessibilityLabel(Text("Apple Health App")) + .frame(width: 90, height: 90) + .shadow(color: .gray, radius: 4) + } + .padding(.horizontal, 32) + .padding(.bottom, 32) + .contentShape(Rectangle()) + .onTapGesture { + guard let url = URL(string: "x-apple-health://") else { + fatalError("Could not create a Health App URL") + } + openURL(url) + } + } +} + + +struct OpenAppleHealthApp_Previews: PreviewProvider { + static var previews: some View { + OpenAppleHealthApp() + } +} diff --git a/TemplateApplication/Instructions/RecordInstructView.swift b/TemplateApplication/Instructions/RecordInstructView.swift new file mode 100644 index 0000000..2c89b12 --- /dev/null +++ b/TemplateApplication/Instructions/RecordInstructView.swift @@ -0,0 +1,47 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import CardinalKit +import FHIR +import HealthKitDataSource +import HealthKitToFHIRAdapter +import ImageSource +import SwiftUI +import UIKit + + +struct RecordInstructView: View { + @Environment(\.openURL) var openURL + + + var body: some View { + HowItWorks( + steps: [ + InstructionsStep.openHealthApp, + InstructionsStep.browseTab, + InstructionsStep(title: "Scroll and select Health Records to share"), + InstructionsStep(title: "Tap \"Export PDF\" on the top right to share PDF") { + Text("Export PDF") + .foregroundColor(.blue) + .frame(width: 120, height: 50) + .background { + Rectangle() + .foregroundColor(Color(uiColor: .systemBackground)) + .shadow(color: .gray, radius: 4) + } + .padding(.trailing, 10) + } + ] + ) + } +} +struct RecordInstructView_Previews: PreviewProvider { + static var previews: some View { + RecordInstructView() + } +} diff --git a/TemplateApplication/Instructions/ViewRecordsView.swift b/TemplateApplication/Instructions/ViewRecordsView.swift new file mode 100644 index 0000000..5acb76a --- /dev/null +++ b/TemplateApplication/Instructions/ViewRecordsView.swift @@ -0,0 +1,38 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import CardinalKit +import FHIR +import HealthKitDataSource +import HealthKitToFHIRAdapter +import ImageSource +import SwiftUI +import UIKit + + +struct ViewRecordsView: View { + @Environment(\.openURL) var openURL + + + var body: some View { + HowItWorks( + steps: [ + InstructionsStep.openHealthApp, + InstructionsStep.browseTab, + InstructionsStep(title: "Select the records you would like to view!") + ] + ) + } +} + + +struct ViewRecordsView_Previews: PreviewProvider { + static var previews: some View { + RecordInstructView() + } +} diff --git a/TemplateApplication/Onboarding/AccountSetup/AccountSetup.swift b/TemplateApplication/Onboarding/AccountSetup/AccountSetup.swift index 6a95aca..cacba76 100644 --- a/TemplateApplication/Onboarding/AccountSetup/AccountSetup.swift +++ b/TemplateApplication/Onboarding/AccountSetup/AccountSetup.swift @@ -16,7 +16,11 @@ import SwiftUI struct AccountSetup: View { - @AppStorage(StorageKeys.userName) var username = "" + @AppStorage(StorageKeys.onboardingFlowComplete) var completedOnboardingFlow = false + @AppStorage(StorageKeys.firstName) var firstName = "" + @AppStorage(StorageKeys.lastName) var lastName = "" + @AppStorage(StorageKeys.email) var email = "" + @Binding private var onboardingSteps: [OnboardingFlow.Step] @EnvironmentObject var account: Account @@ -40,44 +44,33 @@ struct AccountSetup: View { ) .onReceive(account.objectWillChange) { if account.signedIn { - if onboardingSteps.contains(where: { $0 == .signUp }) { - guard let user = Auth.auth().currentUser else { - return - } - - let fullName = user.displayName?.components(separatedBy: " ") - let firstName = fullName?[0] ?? "" - let lastName = fullName?[1] ?? "" - let email = user.email ?? "" - - let userData: [String: Any] = [ - "firstName": firstName, - "lastName": lastName, - "email": email, - "signUpDate": Timestamp() - ] - - Firestore.firestore().collection("users").document(user.uid).setData(userData) { err in - if let err { - print("Error uploading user data: \(err)") - } - } - - self.username = "\(firstName) \(lastName)" + guard let user = Auth.auth().currentUser else { + return } - onboardingSteps.append(.healthKitPermissions) - // Unfortunately, SwiftUI currently animates changes in the navigation path that do not change - // the current top view. Therefore we need to do the following async procedure to remove the - // `.login` and `.signUp` steps while disabling the animations before and re-enabling them - // after the elements have been changed. - Task { @MainActor in - try? await Task.sleep(for: .seconds(1.0)) - UIView.setAnimationsEnabled(false) - onboardingSteps.removeAll(where: { $0 == .login || $0 == .signUp }) - try? await Task.sleep(for: .seconds(1.0)) - UIView.setAnimationsEnabled(true) + let fullName = user.displayName?.components(separatedBy: " ") + let firstName = fullName?[0] ?? "" + let lastName = fullName?[1] ?? "" + let email = user.email ?? "" + + let userData: [String: Any] = [ + "firstName": firstName, + "lastName": lastName, + "email": email, + "signUpDate": Timestamp() + ] + + Firestore.firestore().collection("users").document(user.uid).setData(userData) { err in + if let err { + print("Error uploading user data: \(err)") + } } + + self.firstName = firstName + self.lastName = lastName + self.email = email + + completedOnboardingFlow = true } } } @@ -123,7 +116,7 @@ struct AccountSetup: View { OnboardingActionsView( "ACCOUNT_NEXT".moduleLocalized, action: { - onboardingSteps.append(.healthKitPermissions) + completedOnboardingFlow = true } ) } else { diff --git a/TemplateApplication/Onboarding/Consent.swift b/TemplateApplication/Onboarding/Consent.swift index 6247c59..bc97196 100644 --- a/TemplateApplication/Onboarding/Consent.swift +++ b/TemplateApplication/Onboarding/Consent.swift @@ -12,6 +12,7 @@ import SwiftUI struct Consent: View { @Binding private var onboardingSteps: [OnboardingFlow.Step] + @AppStorage(StorageKeys.onboardingFlowComplete) var completedOnboardingFlow = false private var consentDocument: Data { @@ -37,7 +38,7 @@ struct Consent: View { if !FeatureFlags.disableFirebase { onboardingSteps.append(.accountSetup) } else { - onboardingSteps.append(.healthKitPermissions) + completedOnboardingFlow = true } } ) diff --git a/TemplateApplication/Onboarding/HealthKitPermissions.swift b/TemplateApplication/Onboarding/HealthKitPermissions.swift deleted file mode 100644 index 7f0c500..0000000 --- a/TemplateApplication/Onboarding/HealthKitPermissions.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// This source file is part of the Stanford CardinalKit Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import FHIR -import HealthKitDataSource -import Onboarding -import SwiftUI - - -struct HealthKitPermissions: View { - @EnvironmentObject var healthKitDataSource: HealthKit - @AppStorage(StorageKeys.onboardingFlowComplete) var completedOnboardingFlow = false - @State var healthKitProcessing = false - - - var body: some View { - OnboardingView( - contentView: { - VStack { - OnboardingTitleView( - title: "HEALTHKIT_PERMISSIONS_TITLE".moduleLocalized, - subtitle: "HEALTHKIT_PERMISSIONS_SUBTITLE".moduleLocalized - ) - Spacer() - Image(systemName: "heart.text.square.fill") - .font(.system(size: 150)) - .foregroundColor(.accentColor) - Text("HEALTHKIT_PERMISSIONS_DESCRIPTION") - .multilineTextAlignment(.center) - .padding(.vertical, 16) - Spacer() - } - }, actionView: { - OnboardingActionsView( - "HEALTHKIT_PERMISSIONS_BUTTON".moduleLocalized, - action: { - do { - healthKitProcessing = true - // HealthKit is not available in the preview simulator. - if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" { - try await _Concurrency.Task.sleep(for: .seconds(5)) - } else { - try await healthKitDataSource.askForAuthorization() - } - } catch { - print("Could not request HealthKit permissions.") - } - completedOnboardingFlow = true - healthKitProcessing = false - } - ) - } - ) - .navigationBarBackButtonHidden(healthKitProcessing) - } -} - - -#if DEBUG -struct HealthKitPermissions_Previews: PreviewProvider { - static var previews: some View { - HealthKitPermissions() - } -} -#endif diff --git a/TemplateApplication/Onboarding/OnboardingFlow.swift b/TemplateApplication/Onboarding/OnboardingFlow.swift index 6dbd231..48fd5f1 100644 --- a/TemplateApplication/Onboarding/OnboardingFlow.swift +++ b/TemplateApplication/Onboarding/OnboardingFlow.swift @@ -17,7 +17,6 @@ public struct OnboardingFlow: View { case accountSetup case login case signUp - case healthKitPermissions } @SceneStorage(StorageKeys.onboardingFlowStep) private var onboardingSteps: [Step] = [] @@ -39,8 +38,6 @@ public struct OnboardingFlow: View { TemplateLogin() case .signUp: TemplateSignUp() - case .healthKitPermissions: - HealthKitPermissions() } } .navigationBarTitleDisplayMode(.inline) diff --git a/TemplateApplication/RecordInstructView.swift b/TemplateApplication/RecordInstructView.swift deleted file mode 100644 index 1a3eb6b..0000000 --- a/TemplateApplication/RecordInstructView.swift +++ /dev/null @@ -1,125 +0,0 @@ -// -// This source file is part of the Stanford CardinalKit Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import CardinalKit -import FHIR -import HealthKitDataSource -import HealthKitToFHIRAdapter -import ImageSource -import SwiftUI -import UIKit - - -struct RecordInstructView: View { - @Environment(\.openURL) var openURL - - - var body: some View { - VStack(alignment: .leading) { - HStack { - Text("How It Works") - .font(.largeTitle) - .bold() - .foregroundColor(Color.accentColor) - .padding(.leading, 90) - } - Spacer() - HStack { - Image(systemName: "1.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Open the Apple Health App") - .foregroundColor(Color.accentColor) - .font(.title3) - Spacer() - Image("AppleHealthAppImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Apple Health App")) - .foregroundColor(Color.accentColor) - .frame(width: 90, height: 90) - .padding(.trailing, 20) - } - HStack { - Image(systemName: "2.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Go to the \"Browse\" Tab") - .foregroundColor(Color.accentColor) - .font(.title3) - Spacer() - Image("BrowseTabImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Apple Health App")) - .foregroundColor(Color.accentColor) - .frame(width: 120, height: 120) - .padding(.trailing, 0) - } - HStack { - Image(systemName: "3.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Scroll and select Health Records to share") - .foregroundColor(Color.accentColor) - .font(.title3) - .padding(.trailing, 150) - } - HStack { - Image(systemName: "4.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Tap \"Export PDF\" on the top right to share PDF") - .foregroundColor(Color.accentColor) - .font(.title3) - .padding(.trailing, 10) - Spacer() - Image("ExportIconImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Apple Health App")) - .foregroundColor(Color.accentColor) - .frame(width: 90, height: 90) - .padding(.trailing, 10) - } - Spacer() - HStack { - Text("Tap Health App \nto get started!") - .foregroundColor(Color.accentColor) - .font(.system(size: 30)) - .bold() - .padding(.leading, 40) - .padding(.trailing, 10) - .padding(.bottom, 30) - - Image("AppleHealthAppImage") - .resizable() - .scaledToFit() - .foregroundColor(Color.accentColor) - .accessibilityLabel(Text("Apple Health App")) - .frame(width: 90, height: 90) - .padding(.bottom, 30) - .onTapGesture { - guard let url = URL(string: "x-apple-health://") else { - fatalError("Could not create a Health App URL") - } - openURL(url) - } - } - } - } -} -struct RecordInstructView_Previews: PreviewProvider { - static var previews: some View { - RecordInstructView() - } -} diff --git a/TemplateApplication/LogoView.swift b/TemplateApplication/ReusableViews/LogoView.swift similarity index 76% rename from TemplateApplication/LogoView.swift rename to TemplateApplication/ReusableViews/LogoView.swift index edbea4b..f4eb7c2 100644 --- a/TemplateApplication/LogoView.swift +++ b/TemplateApplication/ReusableViews/LogoView.swift @@ -8,18 +8,19 @@ import SwiftUI + struct LogoView: View { var body: some View { Image("Logo") .resizable() .scaledToFit() - .foregroundColor(Color.accentColor) + .foregroundColor(.accentColor) .accessibilityLabel(Text("The OwnYourData App Icon")) - .frame(width: 240, height: 240) // Make it twice as large - . padding(.vertical, -40) + .frame(width: 100, height: 100) } } + struct LogoView_Previews: PreviewProvider { static var previews: some View { LogoView() diff --git a/TemplateApplication/ReusableViews/OwnYourDataButton.swift b/TemplateApplication/ReusableViews/OwnYourDataButton.swift new file mode 100644 index 0000000..14a37b5 --- /dev/null +++ b/TemplateApplication/ReusableViews/OwnYourDataButton.swift @@ -0,0 +1,61 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +struct OwnYourDataButton: View { + enum ButtonAction { + case action(() -> Void) + case destination(AnyView) + } + + private let title: String + private let action: ButtonAction + + + var body: some View { + switch action { + case let .action(action): + Button(action: action) { + text + } + case let .destination(destination): + NavigationLink(destination: destination) { + text + } + } + } + + private var text: some View { + Text(title) + .font(.headline.weight(.bold)) + .padding() + .frame(maxWidth: .infinity) + .foregroundColor(.white) + .background(Color("ButtonColor_light")) + .cornerRadius(10) + .padding(.horizontal) + } + + + init(title: String, buttonAction: ButtonAction) { + self.title = title + self.action = buttonAction + } + + init(title: String, action: @escaping () -> Void) { + self.title = title + self.action = .action(action) + } + + init(title: String, destination: V) { + self.title = title + self.action = .destination(AnyView(destination)) + } +} diff --git a/TemplateApplication/ReusableViews/OwnYourDataSection.swift b/TemplateApplication/ReusableViews/OwnYourDataSection.swift new file mode 100644 index 0000000..3e0a613 --- /dev/null +++ b/TemplateApplication/ReusableViews/OwnYourDataSection.swift @@ -0,0 +1,49 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +struct OwnYourDataSection: View { + private let title: String + private let buttonTitle: String + private let buttonAction: OwnYourDataButton.ButtonAction + + + var body: some View { + VStack { + Text(title) + .font(.largeTitle.weight(.medium)) + .foregroundColor(.accentColor) + .multilineTextAlignment(.center) + OwnYourDataButton( + title: buttonTitle, + buttonAction: buttonAction + ) + } + } + + + init(title: String, buttonTitle: String, buttonAction: OwnYourDataButton.ButtonAction) { + self.title = title + self.buttonTitle = buttonTitle + self.buttonAction = buttonAction + } + + init(title: String, buttonTitle: String, action: @escaping () -> Void) { + self.title = title + self.buttonTitle = buttonTitle + self.buttonAction = .action(action) + } + + init(title: String, buttonTitle: String, destination: V) { + self.title = title + self.buttonTitle = buttonTitle + self.buttonAction = .destination(AnyView(destination)) + } +} diff --git a/TemplateApplication/ShareView.swift b/TemplateApplication/ShareView.swift deleted file mode 100644 index e63a0a9..0000000 --- a/TemplateApplication/ShareView.swift +++ /dev/null @@ -1,94 +0,0 @@ -// -// This source file is part of the Stanford CardinalKit Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import CardinalKit -import FHIR -import HealthKitDataSource -import HealthKitToFHIRAdapter -import SwiftUI -import UIKit - - -struct ShareView: View { - @Environment(\.openURL) var openURL - - var body: some View { - NavigationView { - VStack { - LogoView() - Spacer() - Text("Share \nHealth Records") - .font(.largeTitle) - .foregroundColor(Color.accentColor) - .fontWeight(.medium) - .multilineTextAlignment(.center) - - NavigationLink(destination: RecordInstructView()) { - Text("Open Health App") - .font(.headline) - .fontWeight(.bold) - .padding() - .frame(maxWidth: .infinity) - .foregroundColor(Color.white) - .background(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .cornerRadius(10) - .padding(.leading) - .padding(.trailing) - } - - Spacer().frame(height: 40) - - VStack { - Text("Share \nDocuments") - .font(.largeTitle) - .foregroundColor(Color.accentColor) - .fontWeight(.medium) - .multilineTextAlignment(.center) - NavigationLink(destination: DocumentGalleryView()) { - Text("Scanned Documents") - .font(.headline) - .fontWeight(.bold) - .padding() - .frame(maxWidth: .infinity) - .foregroundColor(.white) - .background(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .cornerRadius(10) - .padding(.leading) - .padding(.trailing) - } - .padding(.bottom, 20) - Button(action: { - guard let url = URL(string: "x-apple-health://") else { - fatalError("Could not create a Health App URL") - } - openURL(url) - }) { - Text("Apple Health Documents") - .font(.headline) - .fontWeight(.bold) - .padding() - .frame(maxWidth: .infinity) - .foregroundColor(Color.white) - .background(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .cornerRadius(10) - .padding(.leading) - .padding(.trailing) - } - } - .padding(.bottom, 30) - } - } - } -} - - -struct ShareView_Previews: PreviewProvider { - static var previews: some View { - AddDataView() - } -} diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/AddAccountImage.png b/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/AddAccountImage.png index 4f176a0..7ff0f51 100644 Binary files a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/AddAccountImage.png and b/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/AddAccountImage.png differ diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/AddAccountImageDark.png b/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/AddAccountImageDark.png new file mode 100644 index 0000000..4e29183 Binary files /dev/null and b/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/AddAccountImageDark.png differ diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/AddAccountsImage.png.license b/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/AddAccountImageDark.png.license similarity index 100% rename from TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/AddAccountsImage.png.license rename to TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/AddAccountImageDark.png.license diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/Contents.json b/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/Contents.json index eb356cf..a2c7045 100644 --- a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/Contents.json +++ b/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage.imageset/Contents.json @@ -3,6 +3,16 @@ { "filename" : "AddAccountImage.png", "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "AddAccountImageDark.png", + "idiom" : "universal" } ], "info" : { diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/AddAccountsImage.png b/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/AddAccountsImage.png deleted file mode 100644 index 7c65c1c..0000000 Binary files a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/AddAccountsImage.png and /dev/null differ diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/Contents.json b/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/Contents.json deleted file mode 100644 index 7d5899d..0000000 --- a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "AddAccountsImage.png", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/BrowseTabImage.png b/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/BrowseTabImage.png index 761915c..1dffd71 100644 Binary files a/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/BrowseTabImage.png and b/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/BrowseTabImage.png differ diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/BrowseTabImageDark.png b/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/BrowseTabImageDark.png new file mode 100644 index 0000000..5cd265f Binary files /dev/null and b/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/BrowseTabImageDark.png differ diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/Contents.json.license b/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/BrowseTabImageDark.png.license similarity index 100% rename from TemplateApplication/Supporting Files/Assets.xcassets/AddAccountImage1.imageset/Contents.json.license rename to TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/BrowseTabImageDark.png.license diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/Contents.json b/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/Contents.json index cd6b8ea..178a89a 100644 --- a/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/Contents.json +++ b/TemplateApplication/Supporting Files/Assets.xcassets/BrowseTabImage.imageset/Contents.json @@ -3,6 +3,16 @@ { "filename" : "BrowseTabImage.png", "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "BrowseTabImageDark.png", + "idiom" : "universal" } ], "info" : { diff --git a/TemplateApplication/Supporting Files/Assets.xcassets/Logo.imageset/OwnYourData.png b/TemplateApplication/Supporting Files/Assets.xcassets/Logo.imageset/OwnYourData.png index 738ee5d..c473f22 100644 Binary files a/TemplateApplication/Supporting Files/Assets.xcassets/Logo.imageset/OwnYourData.png and b/TemplateApplication/Supporting Files/Assets.xcassets/Logo.imageset/OwnYourData.png differ diff --git a/TemplateApplication/Tabs/AddDataView.swift b/TemplateApplication/Tabs/AddDataView.swift new file mode 100644 index 0000000..ab1fa76 --- /dev/null +++ b/TemplateApplication/Tabs/AddDataView.swift @@ -0,0 +1,50 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +struct AddDataView: View { + @State private var showDocumentScanner = false + + + var body: some View { + NavigationView { + VStack(spacing: 20) { + LogoView() + Spacer() + OwnYourDataSection( + title: "Connect to \nHealth System", + buttonTitle: "Select Health System", + destination: AddRecordInstructView() + ) + OwnYourDataSection( + title: "Take a Photo \nof Document", + buttonTitle: "Go to Camera", + action: { + self.showDocumentScanner.toggle() + } + ) + } + .padding(.bottom, 30) + .fullScreenCover(isPresented: $showDocumentScanner) { + DocumentScanner() + .background { + Color.black.ignoresSafeArea() + } + } + } + } +} + + +struct AddDataView_Previews: PreviewProvider { + static var previews: some View { + AddDataView() + } +} diff --git a/TemplateApplication/Tabs/Home.swift b/TemplateApplication/Tabs/Home.swift new file mode 100644 index 0000000..d99e87a --- /dev/null +++ b/TemplateApplication/Tabs/Home.swift @@ -0,0 +1,73 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import FirebaseAccount +import FirebaseAuth +import SwiftUI + + +struct Home: View { + @AppStorage(StorageKeys.firstName) private var firstName = "" + @State private var showClinicalTrialsView = false + + + var body: some View { + NavigationStack { + VStack(spacing: 20) { + LogoView() + Text("Welcome,\n\(firstName)") + .font(.system(size: 60).weight(.semibold)) + .foregroundColor(.accentColor) + .multilineTextAlignment(.center) + Spacer() + OwnYourDataButton( + title: "Records", + destination: ViewRecordsView() + ) + OwnYourDataButton( + title: "Scanned Documents", + destination: DocumentGallery() + ) + OwnYourDataButton( + title: "Find Clinical Trials", + action: { + showClinicalTrialsView = true + } + ) + } + .padding(.bottom, 30) + .sheet(isPresented: $showClinicalTrialsView) { + ClinicalTrialsView() + .edgesIgnoringSafeArea(.all) + } + .task { + getUserName() + } + } + } + + + private func getUserName() { + if let user = Auth.auth().currentUser { + user.reload { error in + if let error = error { + print("Error reloading user: \(error.localizedDescription)") + } else { + firstName = user.displayName?.split(separator: " ").first.map(String.init) ?? "User" + } + } + } + } +} + + +struct HomeTabView_Previews: PreviewProvider { + static var previews: some View { + Home() + } +} diff --git a/TemplateApplication/Home.swift b/TemplateApplication/Tabs/OwnYourDataTabView.swift similarity index 85% rename from TemplateApplication/Home.swift rename to TemplateApplication/Tabs/OwnYourDataTabView.swift index 02192f7..5a59545 100644 --- a/TemplateApplication/Home.swift +++ b/TemplateApplication/Tabs/OwnYourDataTabView.swift @@ -10,25 +10,22 @@ import FHIRMockDataStorageProvider import SwiftUI -struct HomeView: View { +struct OwnYourDataTabView: View { enum Tabs: String { - case schedule - case contact - case mockUpload - case profileView - case homeTabView + case home case addDataView case shareView + case profileView } - @AppStorage(StorageKeys.homeTabSelection) var selectedTab = Tabs.schedule + @AppStorage(StorageKeys.homeTabSelection) var selectedTab = Tabs.home var body: some View { TabView(selection: $selectedTab) { - HomeTabView() - .tag(Tabs.schedule) + Home() + .tag(Tabs.home) .tabItem { Label("HOME_TAB_VIEW_TITLE", systemImage: "house") } @@ -55,7 +52,7 @@ struct HomeView: View { #if DEBUG struct MainView_Previews: PreviewProvider { static var previews: some View { - HomeView() + OwnYourDataTabView() } } #endif diff --git a/TemplateApplication/ProfileView.swift b/TemplateApplication/Tabs/ProfileView.swift similarity index 53% rename from TemplateApplication/ProfileView.swift rename to TemplateApplication/Tabs/ProfileView.swift index e47be99..f0019d3 100644 --- a/TemplateApplication/ProfileView.swift +++ b/TemplateApplication/Tabs/ProfileView.swift @@ -13,53 +13,52 @@ import SwiftUI struct ProfileView: View { - let user = Auth.auth().currentUser - @AppStorage(StorageKeys.userName) var appStorageUserName = "" - @State private var userName = "" - @State private var email = "" + @AppStorage(StorageKeys.firstName) var firstName = "" + @AppStorage(StorageKeys.lastName) var lastName = "" + @AppStorage(StorageKeys.email) var email = "" + @AppStorage(StorageKeys.onboardingFlowComplete) var completedOnboardingFlow = false + + @EnvironmentObject var documentManager: DocumentManager var body: some View { VStack { Image(systemName: "person.circle.fill") .resizable() - .foregroundColor(Color(UIColor(named: "ButtonColor_dark") ?? .gray)) .scaledToFit() - .frame(width: 120, height: 120) .accessibility(label: Text("profile image")) + .foregroundColor(Color("ButtonColor_dark")) + .frame(width: 120, height: 120) .padding(.top, 80) - VStack(spacing: 10) { - Text("\(userName)") + Text("\(firstName) \(lastName)") .font(.title2) Text("Email: \(email)") .font(.subheadline) } - Spacer() - - Button(action: { - let auth = Auth.auth() - do { - try auth.signOut() - print("Logged out.") - } catch let signOutError as NSError { - print("Error signing out: %@", signOutError) + OwnYourDataButton( + title: "Log Out", + action: { + do { + try Auth.auth().signOut() + + firstName = "" + lastName = "" + email = "" + + completedOnboardingFlow = false + + documentManager.removeAllDocuments() + + print("Logged out.") + } catch { + print("Error signing out: \(error)") + } } - }) { - Text("Log Out") - .font(.headline) - .fontWeight(.bold) - .padding() - .frame(maxWidth: .infinity) - .background(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .foregroundColor(.white) - .cornerRadius(10) - .padding(.leading) - .padding(.trailing) - } - .padding(.bottom, 30) + ) } + .padding(.bottom, 30) .task { fetchUserData() } @@ -67,15 +66,14 @@ struct ProfileView: View { private func fetchUserData() { - self.userName = appStorageUserName - - if let currentUser = user { + if let currentUser = Auth.auth().currentUser { let docRef = Firestore.firestore().collection("users").document(currentUser.uid) docRef.getDocument { document, _ in if let document = document, document.exists { let data = document.data() - self.userName = "\(data?["firstName"] as? String ?? "") \(data?["lastName"] as? String ?? "")" - self.appStorageUserName = self.userName + + self.firstName = data?["firstName"] as? String ?? "" + self.lastName = data?["lastName"] as? String ?? "" self.email = currentUser.email ?? "" } else { print("Document does not exist") @@ -85,6 +83,7 @@ struct ProfileView: View { } } + struct ProfileView_Previews: PreviewProvider { static var previews: some View { ProfileView() diff --git a/TemplateApplication/Tabs/ShareView.swift b/TemplateApplication/Tabs/ShareView.swift new file mode 100644 index 0000000..419b9eb --- /dev/null +++ b/TemplateApplication/Tabs/ShareView.swift @@ -0,0 +1,50 @@ +// +// This source file is part of the Stanford CardinalKit Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +struct ShareView: View { + @Environment(\.openURL) var openURL + + var body: some View { + NavigationView { + VStack(spacing: 20) { + LogoView() + Spacer() + OwnYourDataSection( + title: "Share \nHealth Records", + buttonTitle: "Open Health App", + destination: RecordInstructView() + ) + OwnYourDataSection( + title: "Share \nDocuments", + buttonTitle: "Scanned Documents", + destination: DocumentGallery() + ) + OwnYourDataButton( + title: "Apple Health Documents", + action: { + guard let url = URL(string: "x-apple-health://") else { + fatalError("Could not create a Health App URL") + } + openURL(url) + } + ) + } + .padding(.bottom, 30) + } + } +} + + +struct ShareView_Previews: PreviewProvider { + static var previews: some View { + AddDataView() + } +} diff --git a/TemplateApplication/TemplateAppDelegate.swift b/TemplateApplication/TemplateAppDelegate.swift index adf887e..42103de 100644 --- a/TemplateApplication/TemplateAppDelegate.swift +++ b/TemplateApplication/TemplateAppDelegate.swift @@ -35,9 +35,6 @@ class TemplateAppDelegate: CardinalKitAppDelegate { firestore } FirebaseAccountConfiguration() - if HKHealthStore.isHealthDataAvailable() { - healthKit - } } } @@ -58,16 +55,4 @@ class TemplateAppDelegate: CardinalKitAppDelegate { settings: settings ) } - - - private var healthKit: HealthKit { - HealthKit { - CollectSample( - HKQuantityType(.stepCount), - deliverySetting: .anchorQuery(.afterAuthorizationAndApplicationWillLaunch) - ) - } adapter: { - HealthKitToFHIRAdapter() - } - } } diff --git a/TemplateApplication/TemplateApplication.swift b/TemplateApplication/TemplateApplication.swift index f414cce..9b9b42e 100644 --- a/TemplateApplication/TemplateApplication.swift +++ b/TemplateApplication/TemplateApplication.swift @@ -18,7 +18,7 @@ struct TemplateApplication: App { var body: some Scene { WindowGroup { - HomeView() + OwnYourDataTabView() .sheet(isPresented: !$completedOnboardingFlow) { OnboardingFlow() } diff --git a/TemplateApplication/ViewRecordsView.swift b/TemplateApplication/ViewRecordsView.swift deleted file mode 100644 index ecd41cb..0000000 --- a/TemplateApplication/ViewRecordsView.swift +++ /dev/null @@ -1,107 +0,0 @@ -// -// This source file is part of the Stanford CardinalKit Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import CardinalKit -import FHIR -import HealthKitDataSource -import HealthKitToFHIRAdapter -import ImageSource -import SwiftUI -import UIKit - - -struct ViewRecordsView: View { - @Environment(\.openURL) var openURL - - - var body: some View { - VStack(alignment: .leading) { - HStack { - Text("How It Works") - .font(.largeTitle) - .bold() - .foregroundColor(Color.accentColor) - .padding(.leading, 90) - } - Spacer() - HStack { - Image(systemName: "1.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Open the Apple Health App") - .foregroundColor(Color.accentColor) - .font(.title3) - Spacer() - Image("AppleHealthAppImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Apple Health App")) - .foregroundColor(Color.accentColor) - .frame(width: 90, height: 90) - .padding(.trailing, 20) - } - HStack { - Image(systemName: "2.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Go to the \"Browse\" Tab") - .foregroundColor(Color.accentColor) - .font(.title3) - Spacer() - Image("BrowseTabImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Browse Tab")) - .foregroundColor(Color.accentColor) - .frame(width: 120, height: 120) - .padding(.trailing, 0) - } - HStack { - Image(systemName: "3.circle.fill") - .foregroundColor(Color(UIColor(named: "ButtonColor_light") ?? .gray)) - .font(.title) - .frame(width: 90, height: 90) - Text("Select the records you would like to view!") - .foregroundColor(Color.accentColor) - .font(.title3) - .padding(.trailing, 50) - } - Spacer() - HStack { - Text("Tap Health App \nto get started!") - .foregroundColor(Color.accentColor) - .font(.system(size: 30)) - .bold() - .padding(.leading, 40) - .padding(.trailing, 10) - .padding(.bottom, 30) - - Image("AppleHealthAppImage") - .resizable() - .scaledToFit() - .accessibilityLabel(Text("Apple Health App")) - .foregroundColor(Color.accentColor) - .frame(width: 90, height: 90) - .padding(.bottom, 30) - .onTapGesture { - guard let url = URL(string: "x-apple-health://") else { - fatalError("Could not create a Health App URL") - } - openURL(url) - } - } - } - } -} -struct ViewRecordsView_Previews: PreviewProvider { - static var previews: some View { - RecordInstructView() - } -} diff --git a/TemplateApplication/WebView.swift b/TemplateApplication/WebView.swift deleted file mode 100644 index 73f7d08..0000000 --- a/TemplateApplication/WebView.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// This source file is part of the Stanford CardinalKit Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import SwiftUI -import WebKit - - -struct WebView: UIViewRepresentable { - var url: URL - - func makeUIView(context: Context) -> WKWebView { - WKWebView() - } - - func updateUIView(_ webView: WKWebView, context: Context) { - let request = URLRequest(url: url) - webView.load(request) - } -}