diff --git a/ENGAGEHF.xcodeproj/project.pbxproj b/ENGAGEHF.xcodeproj/project.pbxproj index 32ec1e4e..c37fad88 100644 --- a/ENGAGEHF.xcodeproj/project.pbxproj +++ b/ENGAGEHF.xcodeproj/project.pbxproj @@ -7,12 +7,9 @@ objects = { /* Begin PBXBuildFile section */ - 27FA29902A388E9B009CAC45 /* ModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27FA298F2A388E9B009CAC45 /* ModalView.swift */; }; - 2F3D4ABC2A4E7C290068FB2F /* SpeziScheduler in Frameworks */ = {isa = PBXBuildFile; productRef = 2F3D4ABB2A4E7C290068FB2F /* SpeziScheduler */; }; 2F49B7762980407C00BCB272 /* Spezi in Frameworks */ = {isa = PBXBuildFile; productRef = 2F49B7752980407B00BCB272 /* Spezi */; }; - 2F4E237E2989A2FE0013F3D9 /* ENGAGEHFUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F4E237D2989A2FE0013F3D9 /* ENGAGEHFUITests.swift */; }; + 2F4E237E2989A2FE0013F3D9 /* LaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F4E237D2989A2FE0013F3D9 /* LaunchTests.swift */; }; 2F4E23832989D51F0013F3D9 /* ENGAGEHFTestingSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F4E23822989D51F0013F3D9 /* ENGAGEHFTestingSetup.swift */; }; - 2F4FC8D729EE69D300BFFE26 /* MockUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F4FC8D629EE69D300BFFE26 /* MockUpload.swift */; }; 2F5E32BD297E05EA003432F8 /* ENGAGEHFDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F5E32BC297E05EA003432F8 /* ENGAGEHFDelegate.swift */; }; 2F6025CB29BBE70F0045459E /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2F6025CA29BBE70F0045459E /* GoogleService-Info.plist */; }; 2F65B44E2A3B8B0600A36932 /* NotificationPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F65B44D2A3B8B0600A36932 /* NotificationPermissions.swift */; }; @@ -21,7 +18,6 @@ 2FB099B12A875DF100B20952 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = 2FB099B02A875DF100B20952 /* FirebaseFirestore */; }; 2FB099B32A875DF100B20952 /* FirebaseFirestoreSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 2FB099B22A875DF100B20952 /* FirebaseFirestoreSwift */; }; 2FB099B62A875E2B00B20952 /* HealthKitOnFHIR in Frameworks */ = {isa = PBXBuildFile; productRef = 2FB099B52A875E2B00B20952 /* HealthKitOnFHIR */; }; - 2FBD738C2A3BD150004228E7 /* SpeziScheduler in Frameworks */ = {isa = PBXBuildFile; productRef = 2FBD738B2A3BD150004228E7 /* SpeziScheduler */; }; 2FC3439029EE6346002D773C /* SocialSupportQuestionnaire.json in Resources */ = {isa = PBXBuildFile; fileRef = 2FE5DC5529EDD811004B9AB4 /* SocialSupportQuestionnaire.json */; }; 2FC3439129EE6349002D773C /* AppIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 2FE5DC2A29EDD78D004B9AB4 /* AppIcon.png */; }; 2FC3439229EE634B002D773C /* ConsentDocument.md in Resources */ = {isa = PBXBuildFile; fileRef = 2FE5DC2C29EDD78E004B9AB4 /* ConsentDocument.md */; }; @@ -37,12 +33,6 @@ 2FE5DC4529EDD7F2004B9AB4 /* Binding+Negate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC4229EDD7F2004B9AB4 /* Binding+Negate.swift */; }; 2FE5DC4629EDD7F2004B9AB4 /* Bundle+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC4329EDD7F2004B9AB4 /* Bundle+Image.swift */; }; 2FE5DC4729EDD7F2004B9AB4 /* CodableArray+RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC4429EDD7F2004B9AB4 /* CodableArray+RawRepresentable.swift */; }; - 2FE5DC4E29EDD7FA004B9AB4 /* ScheduleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC4829EDD7FA004B9AB4 /* ScheduleView.swift */; }; - 2FE5DC4F29EDD7FA004B9AB4 /* EventContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC4929EDD7FA004B9AB4 /* EventContext.swift */; }; - 2FE5DC5029EDD7FA004B9AB4 /* EventContextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC4A29EDD7FA004B9AB4 /* EventContextView.swift */; }; - 2FE5DC5129EDD7FA004B9AB4 /* ENGAGEHFTaskContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC4B29EDD7FA004B9AB4 /* ENGAGEHFTaskContext.swift */; }; - 2FE5DC5229EDD7FA004B9AB4 /* ENGAGEHFScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC4C29EDD7FA004B9AB4 /* ENGAGEHFScheduler.swift */; }; - 2FE5DC5329EDD7FA004B9AB4 /* Bundle+Questionnaire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DC4D29EDD7FA004B9AB4 /* Bundle+Questionnaire.swift */; }; 2FE5DC6429EDD883004B9AB4 /* SpeziAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 2FE5DC6329EDD883004B9AB4 /* SpeziAccount */; }; 2FE5DC6729EDD894004B9AB4 /* SpeziContact in Frameworks */ = {isa = PBXBuildFile; productRef = 2FE5DC6629EDD894004B9AB4 /* SpeziContact */; }; 2FE5DC7229EDD8D3004B9AB4 /* SpeziHealthKit in Frameworks */ = {isa = PBXBuildFile; productRef = 2FE5DC7129EDD8D3004B9AB4 /* SpeziHealthKit */; }; @@ -56,8 +46,10 @@ 2FE5DC9929EDD9D9004B9AB4 /* XCTestExtensions in Frameworks */ = {isa = PBXBuildFile; productRef = 2FE5DC9829EDD9D9004B9AB4 /* XCTestExtensions */; }; 2FE5DC9C29EDD9EF004B9AB4 /* XCTHealthKit in Frameworks */ = {isa = PBXBuildFile; productRef = 2FE5DC9B29EDD9EF004B9AB4 /* XCTHealthKit */; }; 2FE5DCB129EE6107004B9AB4 /* AccountOnboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DCAC29EE6107004B9AB4 /* AccountOnboarding.swift */; }; - 2FF53D8B2A8725DE00042B76 /* SpeziMockWebService in Frameworks */ = {isa = PBXBuildFile; productRef = 2FF53D8A2A8725DE00042B76 /* SpeziMockWebService */; }; 2FF53D8D2A8729D600042B76 /* ENGAGEHFStandard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FF53D8C2A8729D600042B76 /* ENGAGEHFStandard.swift */; }; + 4DB025CA2BBE3A59002D2545 /* HomeViewUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DB025C92BBE3A59002D2545 /* HomeViewUITests.swift */; }; + 4DB025D52BBF2E08002D2545 /* Dashboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DB025D42BBF2E08002D2545 /* Dashboard.swift */; }; + 4DB025D82BBF2EEC002D2545 /* Greeting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DB025D72BBF2EEC002D2545 /* Greeting.swift */; }; 56E708352BB06B7100B08F0A /* SpeziLicense in Frameworks */ = {isa = PBXBuildFile; productRef = 56E708342BB06B7100B08F0A /* SpeziLicense */; }; 56E7083B2BB06F6F00B08F0A /* SwiftPackageList in Frameworks */ = {isa = PBXBuildFile; productRef = 56E7083A2BB06F6F00B08F0A /* SwiftPackageList */; }; 653A2551283387FE005D4D48 /* ENGAGEHF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A2550283387FE005D4D48 /* ENGAGEHF.swift */; }; @@ -91,10 +83,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 27FA298F2A388E9B009CAC45 /* ModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalView.swift; sourceTree = ""; }; - 2F4E237D2989A2FE0013F3D9 /* ENGAGEHFUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENGAGEHFUITests.swift; sourceTree = ""; }; + 2F4E237D2989A2FE0013F3D9 /* LaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchTests.swift; sourceTree = ""; }; 2F4E23822989D51F0013F3D9 /* ENGAGEHFTestingSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENGAGEHFTestingSetup.swift; sourceTree = ""; }; - 2F4FC8D629EE69D300BFFE26 /* MockUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockUpload.swift; sourceTree = ""; }; 2F5E32BC297E05EA003432F8 /* ENGAGEHFDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENGAGEHFDelegate.swift; sourceTree = ""; }; 2F6025CA29BBE70F0045459E /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 2F65B44D2A3B8B0600A36932 /* NotificationPermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissions.swift; sourceTree = ""; }; @@ -115,15 +105,12 @@ 2FE5DC4229EDD7F2004B9AB4 /* Binding+Negate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Binding+Negate.swift"; sourceTree = ""; }; 2FE5DC4329EDD7F2004B9AB4 /* Bundle+Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bundle+Image.swift"; sourceTree = ""; }; 2FE5DC4429EDD7F2004B9AB4 /* CodableArray+RawRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CodableArray+RawRepresentable.swift"; sourceTree = ""; }; - 2FE5DC4829EDD7FA004B9AB4 /* ScheduleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduleView.swift; sourceTree = ""; }; - 2FE5DC4929EDD7FA004B9AB4 /* EventContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventContext.swift; sourceTree = ""; }; - 2FE5DC4A29EDD7FA004B9AB4 /* EventContextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventContextView.swift; sourceTree = ""; }; - 2FE5DC4B29EDD7FA004B9AB4 /* ENGAGEHFTaskContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ENGAGEHFTaskContext.swift; sourceTree = ""; }; - 2FE5DC4C29EDD7FA004B9AB4 /* ENGAGEHFScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ENGAGEHFScheduler.swift; sourceTree = ""; }; - 2FE5DC4D29EDD7FA004B9AB4 /* Bundle+Questionnaire.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bundle+Questionnaire.swift"; sourceTree = ""; }; 2FE5DC5529EDD811004B9AB4 /* SocialSupportQuestionnaire.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = SocialSupportQuestionnaire.json; sourceTree = ""; }; 2FE5DCAC29EE6107004B9AB4 /* AccountOnboarding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountOnboarding.swift; sourceTree = ""; }; 2FF53D8C2A8729D600042B76 /* ENGAGEHFStandard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ENGAGEHFStandard.swift; sourceTree = ""; }; + 4DB025C92BBE3A59002D2545 /* HomeViewUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewUITests.swift; sourceTree = ""; }; + 4DB025D42BBF2E08002D2545 /* Dashboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dashboard.swift; sourceTree = ""; }; + 4DB025D72BBF2EEC002D2545 /* Greeting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Greeting.swift; sourceTree = ""; }; 653A254D283387FE005D4D48 /* ENGAGEHF.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ENGAGEHF.app; sourceTree = BUILT_PRODUCTS_DIR; }; 653A2550283387FE005D4D48 /* ENGAGEHF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENGAGEHF.swift; sourceTree = ""; }; 653A255428338800005D4D48 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -158,12 +145,9 @@ 2FE5DC7529EDD8E6004B9AB4 /* SpeziFirebaseAccount in Frameworks */, A92E4DF02BAA001100AC8DE8 /* OrderedCollections in Frameworks */, 9739A0C62AD7B5730084BEA5 /* FirebaseStorage in Frameworks */, - 2FF53D8B2A8725DE00042B76 /* SpeziMockWebService in Frameworks */, 2FE5DC7229EDD8D3004B9AB4 /* SpeziHealthKit in Frameworks */, 2F49B7762980407C00BCB272 /* Spezi in Frameworks */, 2FE5DC8F29EDD980004B9AB4 /* SpeziViews in Frameworks */, - 2F3D4ABC2A4E7C290068FB2F /* SpeziScheduler in Frameworks */, - 2FBD738C2A3BD150004228E7 /* SpeziScheduler in Frameworks */, 2FE5DC7929EDD8E6004B9AB4 /* SpeziFirestore in Frameworks */, 2FE5DC7729EDD8E6004B9AB4 /* SpeziFirebaseConfiguration in Frameworks */, ); @@ -188,14 +172,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 2F4FC8D529EE69BE00BFFE26 /* MockUpload */ = { - isa = PBXGroup; - children = ( - 2F4FC8D629EE69D300BFFE26 /* MockUpload.swift */, - ); - path = MockUpload; - sourceTree = ""; - }; 2FC9759D2978E30800BA99FE /* Supporting Files */ = { isa = PBXGroup; children = ( @@ -240,20 +216,6 @@ path = Resources; sourceTree = ""; }; - 2FE5DC3B29EDD7D0004B9AB4 /* Schedule */ = { - isa = PBXGroup; - children = ( - 2FE5DC4D29EDD7FA004B9AB4 /* Bundle+Questionnaire.swift */, - 2FE5DC4929EDD7FA004B9AB4 /* EventContext.swift */, - 2FE5DC4A29EDD7FA004B9AB4 /* EventContextView.swift */, - 2FE5DC4829EDD7FA004B9AB4 /* ScheduleView.swift */, - 2FE5DC4C29EDD7FA004B9AB4 /* ENGAGEHFScheduler.swift */, - 2FE5DC4B29EDD7FA004B9AB4 /* ENGAGEHFTaskContext.swift */, - 27FA298F2A388E9B009CAC45 /* ModalView.swift */, - ); - path = Schedule; - sourceTree = ""; - }; 2FE5DC3C29EDD7DA004B9AB4 /* SharedContext */ = { isa = PBXGroup; children = ( @@ -273,6 +235,15 @@ path = Helper; sourceTree = ""; }; + 4DB025B52BBDE8EC002D2545 /* Dashboard */ = { + isa = PBXGroup; + children = ( + 4DB025D42BBF2E08002D2545 /* Dashboard.swift */, + 4DB025D72BBF2EEC002D2545 /* Greeting.swift */, + ); + path = Dashboard; + sourceTree = ""; + }; 653A2544283387FE005D4D48 = { isa = PBXGroup; children = ( @@ -303,11 +274,10 @@ 2FF53D8C2A8729D600042B76 /* ENGAGEHFStandard.swift */, 2F4E23822989D51F0013F3D9 /* ENGAGEHFTestingSetup.swift */, 2FC975A72978F11A00BA99FE /* Home.swift */, + 4DB025B52BBDE8EC002D2545 /* Dashboard */, A9720E412ABB68B300872D23 /* Account */, 2FE5DC2829EDD398004B9AB4 /* Onboarding */, - 2FE5DC3B29EDD7D0004B9AB4 /* Schedule */, 2FE5DC2729EDD38D004B9AB4 /* Contacts */, - 2F4FC8D529EE69BE00BFFE26 /* MockUpload */, 2FE5DC3C29EDD7DA004B9AB4 /* SharedContext */, 2FE5DC3D29EDD7E4004B9AB4 /* Helper */, 2FE5DC2D29EDD792004B9AB4 /* Resources */, @@ -327,7 +297,8 @@ 653A256A28338800005D4D48 /* ENGAGEHFUITests */ = { isa = PBXGroup; children = ( - 2F4E237D2989A2FE0013F3D9 /* ENGAGEHFUITests.swift */, + 2F4E237D2989A2FE0013F3D9 /* LaunchTests.swift */, + 4DB025C92BBE3A59002D2545 /* HomeViewUITests.swift */, ); path = ENGAGEHFUITests; sourceTree = ""; @@ -379,10 +350,7 @@ 2FE5DC8929EDD972004B9AB4 /* SpeziLocalStorage */, 2FE5DC8B29EDD972004B9AB4 /* SpeziSecureStorage */, 2FE5DC8E29EDD980004B9AB4 /* SpeziViews */, - 2FBD738B2A3BD150004228E7 /* SpeziScheduler */, - 2F3D4ABB2A4E7C290068FB2F /* SpeziScheduler */, 2FE5DC8029EDD91D004B9AB4 /* SpeziOnboarding */, - 2FF53D8A2A8725DE00042B76 /* SpeziMockWebService */, 2FB099AE2A875DF100B20952 /* FirebaseAuth */, 2FB099B02A875DF100B20952 /* FirebaseFirestore */, 2FB099B22A875DF100B20952 /* FirebaseFirestoreSwift */, @@ -482,9 +450,7 @@ 2FE5DC9029EDD9C3004B9AB4 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, 2FE5DC9729EDD9D9004B9AB4 /* XCRemoteSwiftPackageReference "XCTestExtensions" */, 2FE5DC9A29EDD9EF004B9AB4 /* XCRemoteSwiftPackageReference "XCTHealthKit" */, - 2F3D4ABA2A4E7C290068FB2F /* XCRemoteSwiftPackageReference "SpeziScheduler" */, 97F466E62A76BBEE005DC9B4 /* XCRemoteSwiftPackageReference "SpeziOnboarding" */, - 2FE750CA2A87240100723EAE /* XCRemoteSwiftPackageReference "SpeziMockWebService" */, 2FB099B42A875E2B00B20952 /* XCRemoteSwiftPackageReference "HealthKitOnFHIR" */, 5661551B2AB8384200209B80 /* XCRemoteSwiftPackageReference "swift-package-list" */, A92E4DEE2BAA001100AC8DE8 /* XCRemoteSwiftPackageReference "swift-collections" */, @@ -539,32 +505,26 @@ files = ( 2FE5DC4129EDD7EE004B9AB4 /* StorageKeys.swift in Sources */, 2FE5DCB129EE6107004B9AB4 /* AccountOnboarding.swift in Sources */, - 2F4FC8D729EE69D300BFFE26 /* MockUpload.swift in Sources */, 2FE5DC3A29EDD7CA004B9AB4 /* Welcome.swift in Sources */, 2FE5DC3829EDD7CA004B9AB4 /* InterestingModules.swift in Sources */, 2FE5DC3529EDD7CA004B9AB4 /* Consent.swift in Sources */, 2FE5DC4529EDD7F2004B9AB4 /* Binding+Negate.swift in Sources */, 2FC975A82978F11A00BA99FE /* Home.swift in Sources */, - 2FE5DC4E29EDD7FA004B9AB4 /* ScheduleView.swift in Sources */, + 4DB025D52BBF2E08002D2545 /* Dashboard.swift in Sources */, A9DFE8A92ABE551400428242 /* AccountButton.swift in Sources */, 2FE5DC3729EDD7CA004B9AB4 /* OnboardingFlow.swift in Sources */, 2FF53D8D2A8729D600042B76 /* ENGAGEHFStandard.swift in Sources */, 2FE5DC4729EDD7F2004B9AB4 /* CodableArray+RawRepresentable.swift in Sources */, + 4DB025D82BBF2EEC002D2545 /* Greeting.swift in Sources */, A9720E432ABB68CC00872D23 /* AccountSetupHeader.swift in Sources */, 2FE5DC4029EDD7EE004B9AB4 /* FeatureFlags.swift in Sources */, 2FE5DC4629EDD7F2004B9AB4 /* Bundle+Image.swift in Sources */, - 2FE5DC4F29EDD7FA004B9AB4 /* EventContext.swift in Sources */, - 2FE5DC5029EDD7FA004B9AB4 /* EventContextView.swift in Sources */, 2F4E23832989D51F0013F3D9 /* ENGAGEHFTestingSetup.swift in Sources */, - 2FE5DC5329EDD7FA004B9AB4 /* Bundle+Questionnaire.swift in Sources */, - 2FE5DC5129EDD7FA004B9AB4 /* ENGAGEHFTaskContext.swift in Sources */, 2F5E32BD297E05EA003432F8 /* ENGAGEHFDelegate.swift in Sources */, - 2FE5DC5229EDD7FA004B9AB4 /* ENGAGEHFScheduler.swift in Sources */, A9FE7AD02AA39BAB0077B045 /* AccountSheet.swift in Sources */, 653A2551283387FE005D4D48 /* ENGAGEHF.swift in Sources */, 2FE5DC3629EDD7CA004B9AB4 /* HealthKitPermissions.swift in Sources */, 2F65B44E2A3B8B0600A36932 /* NotificationPermissions.swift in Sources */, - 27FA29902A388E9B009CAC45 /* ModalView.swift in Sources */, 2FE5DC2629EDD38A004B9AB4 /* Contacts.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -581,7 +541,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2F4E237E2989A2FE0013F3D9 /* ENGAGEHFUITests.swift in Sources */, + 2F4E237E2989A2FE0013F3D9 /* LaunchTests.swift in Sources */, + 4DB025CA2BBE3A59002D2545 /* HomeViewUITests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1069,14 +1030,6 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 2F3D4ABA2A4E7C290068FB2F /* XCRemoteSwiftPackageReference "SpeziScheduler" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/StanfordSpezi/SpeziScheduler.git"; - requirement = { - kind = upToNextMinorVersion; - minimumVersion = 0.8.0; - }; - }; 2F49B7742980407B00BCB272 /* XCRemoteSwiftPackageReference "Spezi" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/StanfordSpezi/Spezi"; @@ -1181,14 +1134,6 @@ minimumVersion = 0.3.5; }; }; - 2FE750CA2A87240100723EAE /* XCRemoteSwiftPackageReference "SpeziMockWebService" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/StanfordSpezi/SpeziMockWebService.git"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 1.0.0; - }; - }; 5661551B2AB8384200209B80 /* XCRemoteSwiftPackageReference "swift-package-list" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/FelixHerrmann/swift-package-list"; @@ -1224,11 +1169,6 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 2F3D4ABB2A4E7C290068FB2F /* SpeziScheduler */ = { - isa = XCSwiftPackageProductDependency; - package = 2F3D4ABA2A4E7C290068FB2F /* XCRemoteSwiftPackageReference "SpeziScheduler" */; - productName = SpeziScheduler; - }; 2F49B7752980407B00BCB272 /* Spezi */ = { isa = XCSwiftPackageProductDependency; package = 2F49B7742980407B00BCB272 /* XCRemoteSwiftPackageReference "Spezi" */; @@ -1259,10 +1199,6 @@ package = 2FB099B42A875E2B00B20952 /* XCRemoteSwiftPackageReference "HealthKitOnFHIR" */; productName = HealthKitOnFHIR; }; - 2FBD738B2A3BD150004228E7 /* SpeziScheduler */ = { - isa = XCSwiftPackageProductDependency; - productName = SpeziScheduler; - }; 2FE5DC6329EDD883004B9AB4 /* SpeziAccount */ = { isa = XCSwiftPackageProductDependency; package = 2FE5DC6229EDD883004B9AB4 /* XCRemoteSwiftPackageReference "SpeziAccount" */; @@ -1328,11 +1264,6 @@ package = 2FE5DC9A29EDD9EF004B9AB4 /* XCRemoteSwiftPackageReference "XCTHealthKit" */; productName = XCTHealthKit; }; - 2FF53D8A2A8725DE00042B76 /* SpeziMockWebService */ = { - isa = XCSwiftPackageProductDependency; - package = 2FE750CA2A87240100723EAE /* XCRemoteSwiftPackageReference "SpeziMockWebService" */; - productName = SpeziMockWebService; - }; 56E708342BB06B7100B08F0A /* SpeziLicense */ = { isa = XCSwiftPackageProductDependency; package = 56E708332BB06B7100B08F0A /* XCRemoteSwiftPackageReference "SpeziLicense" */; diff --git a/ENGAGEHF.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ENGAGEHF.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index b4efd2f7..b8e180b2 100644 --- a/ENGAGEHF.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ENGAGEHF.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,13 +1,13 @@ { - "originHash" : "d2097b02aed2e09776146d22c31b71e71570248079de679a782c846c09d0ae6f", + "originHash" : "84060c25a97a757bf3045128a2563021282283c70a9cb6009941a41298deef92", "pins" : [ { "identity" : "abseil-cpp-binary", "kind" : "remoteSourceControl", "location" : "https://github.com/google/abseil-cpp-binary.git", "state" : { - "revision" : "7ce7be095bc3ed3c98b009532fe2d7698c132614", - "version" : "1.2024011601.0" + "revision" : "748c7837511d0e6a507737353af268484e1745e2", + "version" : "1.2024011601.1" } }, { @@ -15,8 +15,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/app-check.git", "state" : { - "revision" : "3e464dad87dad2d29bb29a97836789bf0f8f67d2", - "version" : "10.18.1" + "revision" : "c218c2054299b15ae577e818bbba16084d3eabe6", + "version" : "10.18.2" } }, { @@ -40,7 +40,7 @@ { "identity" : "fhirmodels", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/FHIRModels.git", + "location" : "https://github.com/apple/FHIRModels", "state" : { "revision" : "861afd5816a98d38f86220eab2f812d76cad84a0", "version" : "0.5.0" @@ -87,8 +87,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/grpc-binary.git", "state" : { - "revision" : "67043f6389d0e28b38fa02d1c6952afeb04d807f", - "version" : "1.62.1" + "revision" : "e9fad491d0673bdda7063a0341fb6b47a30c5359", + "version" : "1.62.2" } }, { @@ -105,8 +105,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordBDHG/HealthKitOnFHIR.git", "state" : { - "revision" : "00d64d38a8f0d826ee9e27b6f3ce32314a29fd3e", - "version" : "0.2.6" + "revision" : "d6ceecf11800d73fed0c6ce33717f3dc71a44bd7", + "version" : "0.2.7" } }, { @@ -150,8 +150,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordBDHG/ResearchKit", "state" : { - "revision" : "6b28cdf0d06c3d6e96b5585369968b85deac96e0", - "version" : "2.2.29" + "revision" : "3f70adf898b5985ba15e25d5074d86a9c657d305", + "version" : "2.2.30" } }, { @@ -159,8 +159,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordBDHG/ResearchKitOnFHIR", "state" : { - "revision" : "7c2efdcb17796fc9ee686900304dbbe9dd4aaf85", - "version" : "1.1.2" + "revision" : "7cd02fe3eee061b8cfbb32d272715af8838b978e", + "version" : "1.2.0" } }, { @@ -186,8 +186,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziAccount.git", "state" : { - "revision" : "a7d289ef3be54de62b25dc92e8f7ff1a0f093906", - "version" : "1.2.1" + "revision" : "cb9441e5fe9ca31a17be2507d03817a080e63e9d", + "version" : "1.2.2" } }, { @@ -204,14 +204,14 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziFirebase.git", "state" : { - "revision" : "e05e665b7da39aa399ecd7fba393aab49b8f3034", - "version" : "1.0.1" + "revision" : "16c1c751c14b08ae593eacf9bc2752c2e070fe2f", + "version" : "1.1.0" } }, { "identity" : "spezifoundation", "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziFoundation", + "location" : "https://github.com/StanfordSpezi/SpeziFoundation.git", "state" : { "revision" : "01af5b91a54f30ddd121258e81aff2ddc2a99ff9", "version" : "1.0.4" @@ -232,16 +232,7 @@ "location" : "https://github.com/StanfordSpezi/SpeziLicense", "state" : { "branch" : "dependency-list", - "revision" : "9b1713dd9ac14708c0381cf54ad84e13f3780083" - } - }, - { - "identity" : "spezimockwebservice", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziMockWebService.git", - "state" : { - "revision" : "b18067d3499e630bbd995ef05a296ef8fdd42528", - "version" : "1.0.0" + "revision" : "14e5581aa4dfcaeb2a3301318bc4f05bac9f182b" } }, { @@ -262,15 +253,6 @@ "version" : "1.1.0" } }, - { - "identity" : "spezischeduler", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziScheduler.git", - "state" : { - "revision" : "eed3980f20b01a788720c869010e3fe2fbfcd1fd", - "version" : "0.8.2" - } - }, { "identity" : "spezistorage", "kind" : "remoteSourceControl", diff --git a/ENGAGEHF/MockUpload/MockUpload.swift b/ENGAGEHF/Dashboard/Dashboard.swift similarity index 63% rename from ENGAGEHF/MockUpload/MockUpload.swift rename to ENGAGEHF/Dashboard/Dashboard.swift index 38da83ed..a4090c96 100644 --- a/ENGAGEHF/MockUpload/MockUpload.swift +++ b/ENGAGEHF/Dashboard/Dashboard.swift @@ -6,16 +6,20 @@ // SPDX-License-Identifier: MIT // -import SpeziMockWebService import SwiftUI -struct MockUpload: View { +struct Dashboard: View { @Binding var presentingAccount: Bool + var body: some View { NavigationStack { - RequestList() + VStack { + Greeting() + Spacer() + } + .navigationTitle("Home") .toolbar { if AccountButton.shouldDisplay { AccountButton(isPresented: $presentingAccount) @@ -23,19 +27,9 @@ struct MockUpload: View { } } } - - - init(presentingAccount: Binding) { - self._presentingAccount = presentingAccount - } } -#if DEBUG #Preview { - MockUpload(presentingAccount: .constant(false)) - .previewWith { - MockWebService() - } + Dashboard(presentingAccount: .constant(false)) } -#endif diff --git a/ENGAGEHF/Dashboard/Greeting.swift b/ENGAGEHF/Dashboard/Greeting.swift new file mode 100644 index 00000000..7eb3b4e8 --- /dev/null +++ b/ENGAGEHF/Dashboard/Greeting.swift @@ -0,0 +1,29 @@ +// +// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +struct Greeting: View { + var body: some View { + HStack(alignment: .top) { + Text("Hello, world!") + .font(.title.bold()) + Spacer() + Text(.now, style: .date) + .font(.title3) + .foregroundStyle(.secondary) + } + .padding() + } +} + + +#Preview { + Greeting() +} diff --git a/ENGAGEHF/ENGAGEHFDelegate.swift b/ENGAGEHF/ENGAGEHFDelegate.swift index 170842ab..419332e7 100644 --- a/ENGAGEHF/ENGAGEHFDelegate.swift +++ b/ENGAGEHF/ENGAGEHFDelegate.swift @@ -12,9 +12,7 @@ import SpeziFirebaseAccount import SpeziFirebaseStorage import SpeziFirestore import SpeziHealthKit -import SpeziMockWebService import SpeziOnboarding -import SpeziScheduler import SwiftUI @@ -45,15 +43,12 @@ class ENGAGEHFDelegate: SpeziAppDelegate { } else { FirebaseStorageConfiguration() } - } else { - MockWebService() } if HKHealthStore.isHealthDataAvailable() { healthKit } - ENGAGEHFScheduler() OnboardingDataSource() } } diff --git a/ENGAGEHF/ENGAGEHFStandard.swift b/ENGAGEHF/ENGAGEHFStandard.swift index ba881e9b..ef61daa0 100644 --- a/ENGAGEHF/ENGAGEHFStandard.swift +++ b/ENGAGEHF/ENGAGEHFStandard.swift @@ -16,7 +16,6 @@ import SpeziAccount import SpeziFirebaseAccountStorage import SpeziFirestore import SpeziHealthKit -import SpeziMockWebService import SpeziOnboarding import SpeziQuestionnaire import SwiftUI @@ -31,7 +30,6 @@ actor ENGAGEHFStandard: Standard, EnvironmentAccessible, HealthKitConstraint, On Firestore.firestore().collection("users") } - @Dependency var mockWebService: MockWebService? @Dependency var accountStorage: FirestoreAccountStorage? @AccountReference var account: Account @@ -68,14 +66,6 @@ actor ENGAGEHFStandard: Standard, EnvironmentAccessible, HealthKitConstraint, On func add(sample: HKSample) async { - if let mockWebService { - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes] - let jsonRepresentation = (try? String(data: encoder.encode(sample.resource), encoding: .utf8)) ?? "" - try? await mockWebService.upload(path: "healthkit/\(sample.uuid.uuidString)", body: jsonRepresentation) - return - } - do { try await healthKitDocument(id: sample.id).setData(from: sample.resource) } catch { @@ -84,11 +74,6 @@ actor ENGAGEHFStandard: Standard, EnvironmentAccessible, HealthKitConstraint, On } func remove(sample: HKDeletedObject) async { - if let mockWebService { - try? await mockWebService.remove(path: "healthkit/\(sample.uuid.uuidString)") - return - } - do { try await healthKitDocument(id: sample.uuid).delete() } catch { @@ -99,12 +84,6 @@ actor ENGAGEHFStandard: Standard, EnvironmentAccessible, HealthKitConstraint, On func add(response: ModelsR4.QuestionnaireResponse) async { let id = response.identifier?.value?.value?.string ?? UUID().uuidString - if let mockWebService { - let jsonRepresentation = (try? String(data: JSONEncoder().encode(response), encoding: .utf8)) ?? "" - try? await mockWebService.upload(path: "questionnaireResponse/\(id)", body: jsonRepresentation) - return - } - do { try await userDocumentReference .collection("QuestionnaireResponse") // Add all HealthKit sources in a /QuestionnaireResponse collection. diff --git a/ENGAGEHF/Home.swift b/ENGAGEHF/Home.swift index 8ff21c28..9fad0da8 100644 --- a/ENGAGEHF/Home.swift +++ b/ENGAGEHF/Home.swift @@ -7,15 +7,12 @@ // import SpeziAccount -import SpeziMockWebService import SwiftUI struct HomeView: View { enum Tabs: String { - case schedule - case contact - case mockUpload + case home } static var accountEnabled: Bool { @@ -23,29 +20,17 @@ struct HomeView: View { } - @AppStorage(StorageKeys.homeTabSelection) private var selectedTab = Tabs.schedule + @AppStorage(StorageKeys.homeTabSelection) private var selectedTab = Tabs.home @State private var presentingAccount = false var body: some View { TabView(selection: $selectedTab) { - ScheduleView(presentingAccount: $presentingAccount) - .tag(Tabs.schedule) + Dashboard(presentingAccount: $presentingAccount) + .tag(Tabs.home) .tabItem { - Label("SCHEDULE_TAB_TITLE", systemImage: "list.clipboard") + Label("Home", systemImage: "house") } - Contacts(presentingAccount: $presentingAccount) - .tag(Tabs.contact) - .tabItem { - Label("CONTACTS_TAB_TITLE", systemImage: "person.fill") - } - if FeatureFlags.disableFirebase { - MockUpload(presentingAccount: $presentingAccount) - .tag(Tabs.mockUpload) - .tabItem { - Label("MOCK_WEB_SERVICE_TAB_TITLE", systemImage: "server.rack") - } - } } .sheet(isPresented: $presentingAccount) { AccountSheet() @@ -58,29 +43,12 @@ struct HomeView: View { } -#if DEBUG -#Preview { - let details = AccountDetails.Builder() - .set(\.userId, value: "lelandstanford@stanford.edu") - .set(\.name, value: PersonNameComponents(givenName: "Leland", familyName: "Stanford")) - - return HomeView() - .previewWith(standard: ENGAGEHFStandard()) { - ENGAGEHFScheduler() - MockWebService() - AccountConfiguration(building: details, active: MockUserIdPasswordAccountService()) - } -} - #Preview { - CommandLine.arguments.append("--disableFirebase") // make sure the MockWebService is displayed + CommandLine.arguments.append("--disableFirebase") return HomeView() .previewWith(standard: ENGAGEHFStandard()) { - ENGAGEHFScheduler() - MockWebService() AccountConfiguration { MockUserIdPasswordAccountService() } } } -#endif diff --git a/ENGAGEHF/Onboarding/NotificationPermissions.swift b/ENGAGEHF/Onboarding/NotificationPermissions.swift index 1bec83b6..add920ec 100644 --- a/ENGAGEHF/Onboarding/NotificationPermissions.swift +++ b/ENGAGEHF/Onboarding/NotificationPermissions.swift @@ -7,12 +7,10 @@ // import SpeziOnboarding -import SpeziScheduler import SwiftUI struct NotificationPermissions: View { - @Environment(ENGAGEHFScheduler.self) private var scheduler @Environment(OnboardingNavigationPath.self) private var onboardingNavigationPath @State private var notificationProcessing = false @@ -45,8 +43,6 @@ struct NotificationPermissions: View { // Notification Authorization is not available in the preview simulator. if ProcessInfo.processInfo.isPreviewSimulator { try await _Concurrency.Task.sleep(for: .seconds(5)) - } else { - try await scheduler.requestLocalNotificationAuthorization() } } catch { print("Could not request notification permissions.") @@ -70,8 +66,5 @@ struct NotificationPermissions: View { OnboardingStack { NotificationPermissions() } - .previewWith { - ENGAGEHFScheduler() - } } #endif diff --git a/ENGAGEHF/Onboarding/OnboardingFlow.swift b/ENGAGEHF/Onboarding/OnboardingFlow.swift index e7404a1d..e871564c 100644 --- a/ENGAGEHF/Onboarding/OnboardingFlow.swift +++ b/ENGAGEHF/Onboarding/OnboardingFlow.swift @@ -16,7 +16,6 @@ import SwiftUI /// Displays an multi-step onboarding flow for the ENGAGEHF. struct OnboardingFlow: View { @Environment(HealthKit.self) private var healthKitDataSource - @Environment(ENGAGEHFScheduler.self) private var scheduler @AppStorage(StorageKeys.onboardingFlowComplete) private var completedOnboardingFlow = false @@ -54,9 +53,6 @@ struct OnboardingFlow: View { NotificationPermissions() } } - .task { - localNotificationAuthorization = await scheduler.localNotificationAuthorization - } .interactiveDismissDisabled(!completedOnboardingFlow) } } @@ -72,8 +68,6 @@ struct OnboardingFlow: View { AccountConfiguration { MockUserIdPasswordAccountService() } - - ENGAGEHFScheduler() } } #endif diff --git a/ENGAGEHF/Resources/Assets.xcassets/AccentColor.colorset/Contents.json b/ENGAGEHF/Resources/Assets.xcassets/AccentColor.colorset/Contents.json index eb878970..ecd966b4 100644 --- a/ENGAGEHF/Resources/Assets.xcassets/AccentColor.colorset/Contents.json +++ b/ENGAGEHF/Resources/Assets.xcassets/AccentColor.colorset/Contents.json @@ -1,6 +1,15 @@ { "colors" : [ { + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.373", + "green" : "0.412", + "red" : "0.176" + } + }, "idiom" : "universal" } ], diff --git a/ENGAGEHF/Resources/Localizable.xcstrings b/ENGAGEHF/Resources/Localizable.xcstrings index 9edec4b3..388fe2c0 100644 --- a/ENGAGEHF/Resources/Localizable.xcstrings +++ b/ENGAGEHF/Resources/Localizable.xcstrings @@ -63,16 +63,6 @@ } } }, - "COMPLETED_TASK_LABEL %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Completed Task: %@" - } - } - } - }, "CONSENT_LOADING_ERROR" : { "localizations" : { "en" : { @@ -93,17 +83,6 @@ } } }, - "CONTACTS_TAB_TITLE" : { - "comment" : "MARK: - Contacts", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Contacts" - } - } - } - }, "HEALTHKIT_PERMISSIONS_BUTTON" : { "localizations" : { "en" : { @@ -144,6 +123,12 @@ } } } + }, + "Hello, world!" : { + + }, + "Home" : { + }, "INTERESTING_MODULES_AREA1_DESCRIPTION" : { "localizations" : { @@ -276,17 +261,6 @@ } } }, - "MOCK_WEB_SERVICE_TAB_TITLE" : { - "comment" : "MARK: - Mock Upload Data Storage Provider", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mock Web Service" - } - } - } - }, "NOTIFICATION_PERMISSIONS_BUTTON" : { "localizations" : { "en" : { @@ -328,77 +302,6 @@ } } }, - "SCHEDULE_LIST_TITLE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Schedule" - } - } - } - }, - "SCHEDULE_TAB_TITLE" : { - "comment" : "MARK: - Schedule", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Schedule" - } - } - } - }, - "TASK_CONTEXT_ACTION_QUESTIONNAIRE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Start Questionnaire" - } - } - } - }, - "TASK_CONTEXT_ACTION_TEST" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Start Test" - } - } - } - }, - "TASK_LABEL %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Task: %@" - } - } - } - }, - "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_DESCRIPTION" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Please fill out the Social Support Questionnaire every day." - } - } - } - }, - "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_TITLE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Social Support Questionnaire" - } - } - } - }, "WELCOME_AREA1_DESCRIPTION" : { "localizations" : { "en" : { diff --git a/ENGAGEHF/Schedule/Bundle+Questionnaire.swift b/ENGAGEHF/Schedule/Bundle+Questionnaire.swift deleted file mode 100644 index 6a766924..00000000 --- a/ENGAGEHF/Schedule/Bundle+Questionnaire.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import Foundation -import SpeziQuestionnaire - - -extension Foundation.Bundle { - func questionnaire(withName name: String) -> Questionnaire { - guard let resourceURL = self.url(forResource: name, withExtension: "json") else { - fatalError("Could not find the questionnaire \"\(name).json\" in the bundle.") - } - - do { - let resourceData = try Data(contentsOf: resourceURL) - return try JSONDecoder().decode(Questionnaire.self, from: resourceData) - } catch { - fatalError("Could not decode the FHIR questionnaire named \"\(name).json\": \(error)") - } - } -} diff --git a/ENGAGEHF/Schedule/ENGAGEHFScheduler.swift b/ENGAGEHF/Schedule/ENGAGEHFScheduler.swift deleted file mode 100644 index 5f38b583..00000000 --- a/ENGAGEHF/Schedule/ENGAGEHFScheduler.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import Foundation -import SpeziScheduler - - -/// A `Scheduler` using the ``ENGAGEHFTaskContext`` to schedule and manage tasks and events in the -/// ENGAGEHF. -typealias ENGAGEHFScheduler = Scheduler - - -extension ENGAGEHFScheduler { - static var socialSupportTask: SpeziScheduler.Task { - let dateComponents: DateComponents - if FeatureFlags.testSchedule { - // Adds a task at the current time for UI testing if the `--testSchedule` feature flag is set - dateComponents = DateComponents( - hour: Calendar.current.component(.hour, from: .now), - minute: Calendar.current.component(.minute, from: .now) - ) - } else { - // For the normal app usage, we schedule the task for every day at 8:00 AM - dateComponents = DateComponents(hour: 8, minute: 0) - } - - return Task( - title: String(localized: "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_TITLE"), - description: String(localized: "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_DESCRIPTION"), - schedule: Schedule( - start: Calendar.current.startOfDay(for: Date()), - repetition: .matching(dateComponents), - end: .numberOfEvents(365) - ), - notifications: true, - context: ENGAGEHFTaskContext.questionnaire(Bundle.main.questionnaire(withName: "SocialSupportQuestionnaire")) - ) - } - - /// Creates a default instance of the ``ENGAGEHFScheduler`` by scheduling the tasks listed below. - convenience init() { - self.init(tasks: [Self.socialSupportTask]) - } -} diff --git a/ENGAGEHF/Schedule/ENGAGEHFTaskContext.swift b/ENGAGEHF/Schedule/ENGAGEHFTaskContext.swift deleted file mode 100644 index d0621b3e..00000000 --- a/ENGAGEHF/Schedule/ENGAGEHFTaskContext.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import Foundation -import ModelsR4 - - -/// The context attached to each task in the ENGAGEHF. -/// -/// We currently only support `Questionnaire`s, more cases can be added in the future. -enum ENGAGEHFTaskContext: Codable, Identifiable { - /// The task should display a `Questionnaire`. - case questionnaire(Questionnaire) - /// The task is used for UI testing. - case test(String) - - - var id: FHIRPrimitive? { - switch self { - case let .questionnaire(questionnaire): - return questionnaire.id - case .test: - return FHIRPrimitive(FHIRString(UUID().uuidString)) - } - } - - var actionType: LocalizedStringResource { - switch self { - case .questionnaire: - return LocalizedStringResource("TASK_CONTEXT_ACTION_QUESTIONNAIRE") - case .test: - return LocalizedStringResource("TASK_CONTEXT_ACTION_TEST") - } - } -} diff --git a/ENGAGEHF/Schedule/EventContext.swift b/ENGAGEHF/Schedule/EventContext.swift deleted file mode 100644 index be96cfed..00000000 --- a/ENGAGEHF/Schedule/EventContext.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import SpeziScheduler - - -struct EventContext: Comparable, Identifiable { - let event: Event - let task: Task - - - var id: Event.ID { - event.id - } - - - static func < (lhs: EventContext, rhs: EventContext) -> Bool { - lhs.event.scheduledAt < rhs.event.scheduledAt - } -} diff --git a/ENGAGEHF/Schedule/EventContextView.swift b/ENGAGEHF/Schedule/EventContextView.swift deleted file mode 100644 index 3a5c2551..00000000 --- a/ENGAGEHF/Schedule/EventContextView.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import SpeziScheduler -import SwiftUI - - -struct EventContextView: View { - let eventContext: EventContext - - - var body: some View { - HStack { - VStack(alignment: .leading) { - HStack { - if eventContext.event.complete { - Image(systemName: "checkmark.circle.fill") - .foregroundColor(.accentColor) - .font(.system(size: 30)) - .accessibilityHidden(true) - } - VStack(alignment: .leading, spacing: 8) { - Text(verbatim: eventContext.task.title) - .font(.headline) - .accessibilityLabel( - eventContext.event.complete - ? "COMPLETED_TASK_LABEL \(eventContext.task.title)" - : "TASK_LABEL \(eventContext.task.title)" - ) - Text(verbatim: format(eventDate: eventContext.event.scheduledAt)) - .font(.subheadline) - } - } - Divider() - Text(eventContext.task.description) - .font(.callout) - if !eventContext.event.complete { - Text(eventContext.task.context.actionType) - .frame(maxWidth: .infinity, minHeight: 50) - .foregroundColor(.white) - .background(Color.accentColor) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.top, 8) - } - } - } - .disabled(eventContext.event.complete) - .contentShape(Rectangle()) - } - - - private func format(eventDate: Date) -> String { - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .none - dateFormatter.timeStyle = .short - return dateFormatter.string(from: eventDate) - } -} - - -#if DEBUG -#Preview(traits: .sizeThatFitsLayout) { - let task = ENGAGEHFScheduler.socialSupportTask - - return EventContextView( - eventContext: EventContext( - // We use a force unwrap in the preview as we can not recover from an error here - // and the code will never end up in a production environment. - // swiftlint:disable:next force_unwrapping - event: task.events(from: .now.addingTimeInterval(-60 * 60 * 24)).first!, - task: task - ) - ) - .padding() -} -#endif diff --git a/ENGAGEHF/Schedule/ModalView.swift b/ENGAGEHF/Schedule/ModalView.swift deleted file mode 100644 index 16b826ed..00000000 --- a/ENGAGEHF/Schedule/ModalView.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import SpeziViews -import SwiftUI - - -struct ModalView: View { - @Environment(\.dismiss) private var dismiss - - let text: String - let buttonText: String - let onClose: () async -> Void - - - var body: some View { - VStack { - Spacer() - Text(text) - .padding() - Spacer() - AsyncButton { - self.dismiss() - await self.onClose() - } label: { - Text(buttonText) - .frame(maxWidth: .infinity, minHeight: 38) - } - .padding() - .buttonStyle(.borderedProminent) - } - } -} - - -#if DEBUG -#Preview { - ModalView(text: "Preview Modal", buttonText: "Close") { - print("Preview Modal closed.") - } -} -#endif diff --git a/ENGAGEHF/Schedule/ScheduleView.swift b/ENGAGEHF/Schedule/ScheduleView.swift deleted file mode 100644 index c2f5c343..00000000 --- a/ENGAGEHF/Schedule/ScheduleView.swift +++ /dev/null @@ -1,119 +0,0 @@ -// -// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import OrderedCollections -import SpeziAccount -import SpeziQuestionnaire -import SpeziScheduler -import SwiftUI - - -struct ScheduleView: View { - @Environment(ENGAGEHFStandard.self) private var standard - @Environment(ENGAGEHFScheduler.self) private var scheduler - - @State private var presentedContext: EventContext? - @Binding private var presentingAccount: Bool - - - private var eventContextsByDate: OrderedDictionary { - let eventContexts = scheduler.tasks.flatMap { task in - task - .events( - from: Calendar.current.startOfDay(for: .now), - to: .numberOfEventsOrEndDate(100, .now) - ) - .map { event in - EventContext(event: event, task: task) - } - } - .sorted() - - return OrderedDictionary(grouping: eventContexts) { eventContext in - Calendar.current.startOfDay(for: eventContext.event.scheduledAt) - } - } - - - var body: some View { - NavigationStack { - let eventContextsByDate = eventContextsByDate - List(eventContextsByDate.keys, id: \.timeIntervalSinceNow) { startOfDay in - Section(format(startOfDay: startOfDay)) { - ForEach(eventContextsByDate[startOfDay] ?? [], id: \.event) { eventContext in - EventContextView(eventContext: eventContext) - .onTapGesture { - if !eventContext.event.complete { - presentedContext = eventContext - } - } - } - } - } - .sheet(item: $presentedContext) { presentedContext in - destination(withContext: presentedContext) - } - .toolbar { - if AccountButton.shouldDisplay { - AccountButton(isPresented: $presentingAccount) - } - } - .navigationTitle("SCHEDULE_LIST_TITLE") - } - } - - - init(presentingAccount: Binding) { - self._presentingAccount = presentingAccount - } - - - private func destination(withContext eventContext: EventContext) -> some View { - @ViewBuilder var destination: some View { - switch eventContext.task.context { - case let .questionnaire(questionnaire): - QuestionnaireView(questionnaire: questionnaire) { result in - presentedContext = nil - - guard case let .completed(response) = result else { - return // user cancelled the task - } - - eventContext.event.complete(true) - await standard.add(response: response) - } - case let .test(string): - ModalView(text: string, buttonText: String(localized: "CLOSE")) { - await eventContext.event.complete(true) - } - } - } - return destination - } - - - private func format(startOfDay: Date) -> String { - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .long - dateFormatter.timeStyle = .none - return dateFormatter.string(from: startOfDay) - } -} - - -#if DEBUG -#Preview("ScheduleView") { - ScheduleView(presentingAccount: .constant(false)) - .previewWith(standard: ENGAGEHFStandard()) { - ENGAGEHFScheduler() - AccountConfiguration { - MockUserIdPasswordAccountService() - } - } -} -#endif diff --git a/ENGAGEHFUITests/HomeViewUITests.swift b/ENGAGEHFUITests/HomeViewUITests.swift new file mode 100644 index 00000000..e995aa40 --- /dev/null +++ b/ENGAGEHFUITests/HomeViewUITests.swift @@ -0,0 +1,46 @@ +// This source file is part of the ENGAGE-HF project based on the Stanford Spezi Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import XCTest + + +class HomeViewUITests: XCTestCase { + override func setUpWithError() throws { + try super.setUpWithError() + + continueAfterFailure = false + + let app = XCUIApplication() + app.launchArguments = ["--skipOnboarding"] + app.launch() + } + + // Make sure the Dashboard view UI functions correctly + func testDashboard() throws { + let app = XCUIApplication() + + // Test Home tab button + XCTAssert(app.buttons["Home"].exists) + app.buttons["Home"].tap() + + // Make sure greeting and title appear, indicating we're in the correct view + XCTAssert(app.staticTexts["Hello, world!"].exists) + XCTAssert(app.staticTexts["Home"].exists) + + // Make sure the date appears + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .long + + XCTAssert(app.staticTexts[dateFormatter.string(from: .now)].exists) + + // If it appears, make sure the account button appears and is hittable + if !(app.launchArguments.contains("--disableFirebase")) { + XCTAssert(app.buttons["Your Account"].exists && app.buttons["Your Account"].isHittable) + app.buttons["Your Account"].tap() + } + } +} diff --git a/ENGAGEHFUITests/ENGAGEHFUITests.swift b/ENGAGEHFUITests/LaunchTests.swift similarity index 54% rename from ENGAGEHFUITests/ENGAGEHFUITests.swift rename to ENGAGEHFUITests/LaunchTests.swift index 8005c68a..b2763b48 100644 --- a/ENGAGEHFUITests/ENGAGEHFUITests.swift +++ b/ENGAGEHFUITests/LaunchTests.swift @@ -9,13 +9,19 @@ import XCTest -final class ENGAGEHFUITests: XCTestCase { +// Based off of https://github.com/CS342/2024-Intake/blob/main/IntakeUITests/LaunchTests.swift +final class LaunchTests: XCTestCase { override func setUpWithError() throws { + try super.setUpWithError() + continueAfterFailure = false + + let app = XCUIApplication() + app.launch() } - func testExample() throws { + func testApplicationLaunch() throws { let app = XCUIApplication() - app.launch() + XCTAssertEqual(app.state, .runningForeground) } }