From db813e656e50c56ede58bb52e6afc3962e3d1518 Mon Sep 17 00:00:00 2001
From: nriedman <108841122+nriedman@users.noreply.github.com>
Date: Mon, 8 Apr 2024 11:54:12 -0700
Subject: [PATCH] Enhancement/customize home (#2)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
# Customize Landing Page
## :recycle: Current situation & Problem
Currently, the app is a direct copy of the Spezi Template Application,
with general views unrelated to ENGAGE-HF.
## :gear: Release Notes
- Developed the Home tab to have basic navigation structure, including
title, account button, and a greeting that includes the current date
## :books: Documentation
The landing page now appears like this:
## :white_check_mark: Testing
Implemented UI tests for the Tab buttons and Static Text fields. Further
testing will be implemented after authentication is integrated into the
app.
### Code of Conduct & Contributing Guidelines
By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md):
- [X] I agree to follow the [Code of Conduct]
---------
Co-authored-by: Paul Schmiedmayer
---
ENGAGEHF.xcodeproj/project.pbxproj | 117 ++++-------------
.../xcshareddata/swiftpm/Package.resolved | 58 +++------
.../Dashboard.swift} | 22 ++--
ENGAGEHF/Dashboard/Greeting.swift | 29 +++++
ENGAGEHF/ENGAGEHFDelegate.swift | 5 -
ENGAGEHF/ENGAGEHFStandard.swift | 21 ----
ENGAGEHF/Home.swift | 44 +------
.../Onboarding/NotificationPermissions.swift | 7 --
ENGAGEHF/Onboarding/OnboardingFlow.swift | 6 -
.../AccentColor.colorset/Contents.json | 9 ++
ENGAGEHF/Resources/Localizable.xcstrings | 109 +---------------
ENGAGEHF/Schedule/Bundle+Questionnaire.swift | 26 ----
ENGAGEHF/Schedule/ENGAGEHFScheduler.swift | 49 --------
ENGAGEHF/Schedule/ENGAGEHFTaskContext.swift | 40 ------
ENGAGEHF/Schedule/EventContext.swift | 25 ----
ENGAGEHF/Schedule/EventContextView.swift | 81 ------------
ENGAGEHF/Schedule/ModalView.swift | 47 -------
ENGAGEHF/Schedule/ScheduleView.swift | 119 ------------------
ENGAGEHFUITests/HomeViewUITests.swift | 46 +++++++
...NGAGEHFUITests.swift => LaunchTests.swift} | 12 +-
20 files changed, 157 insertions(+), 715 deletions(-)
rename ENGAGEHF/{MockUpload/MockUpload.swift => Dashboard/Dashboard.swift} (63%)
create mode 100644 ENGAGEHF/Dashboard/Greeting.swift
delete mode 100644 ENGAGEHF/Schedule/Bundle+Questionnaire.swift
delete mode 100644 ENGAGEHF/Schedule/ENGAGEHFScheduler.swift
delete mode 100644 ENGAGEHF/Schedule/ENGAGEHFTaskContext.swift
delete mode 100644 ENGAGEHF/Schedule/EventContext.swift
delete mode 100644 ENGAGEHF/Schedule/EventContextView.swift
delete mode 100644 ENGAGEHF/Schedule/ModalView.swift
delete mode 100644 ENGAGEHF/Schedule/ScheduleView.swift
create mode 100644 ENGAGEHFUITests/HomeViewUITests.swift
rename ENGAGEHFUITests/{ENGAGEHFUITests.swift => LaunchTests.swift} (54%)
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)
}
}