From 2c7e44a07f3aa7d71156e34ef923993cb5f3a4da Mon Sep 17 00:00:00 2001 From: Vishnu Ravi Date: Sun, 26 May 2024 23:58:58 -0400 Subject: [PATCH 1/8] Update consent form --- StrokeCog.xcodeproj/project.pbxproj | 8 +-- StrokeCog/Resources/ConsentDocument.md | 68 +++++++------------------- 2 files changed, 22 insertions(+), 54 deletions(-) diff --git a/StrokeCog.xcodeproj/project.pbxproj b/StrokeCog.xcodeproj/project.pbxproj index 67c6a6e..3227106 100644 --- a/StrokeCog.xcodeproj/project.pbxproj +++ b/StrokeCog.xcodeproj/project.pbxproj @@ -758,7 +758,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = B2Q3T3P8HP; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "StrokeCog/Supporting Files/Info.plist"; @@ -961,7 +961,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = B2Q3T3P8HP; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "StrokeCog/Supporting Files/Info.plist"; @@ -1009,7 +1009,7 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 637867499T; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = B2Q3T3P8HP; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "StrokeCog/Supporting Files/Info.plist"; @@ -1035,7 +1035,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.odden.strokecog; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = StrokeCog; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "StrokeCog Distribution Profile"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; diff --git a/StrokeCog/Resources/ConsentDocument.md b/StrokeCog/Resources/ConsentDocument.md index 543b262..878bd00 100644 --- a/StrokeCog/Resources/ConsentDocument.md +++ b/StrokeCog/Resources/ConsentDocument.md @@ -1,62 +1,30 @@ -You are invited to participate in a research study on life space, or the space within which people live, work, and recreate. Based on a custom iPhone Life Space application, we will develop individual life space maps (geographic footprint). We will sample Google Street View images from the life space and extract features using computer learning in order to evaluate the association of built environment features with health and well-being. This research study is looking for X participants to be enrolled. Stanford University expects to enroll X research study participants. +*FOR QUESTIONS ABOUT THE STUDY, CONTACT:* +(Michelle C. Odden, PhD, 1701 Page Mill Rd., Palo Alto, CA 94304, (650) 721-0230, modden@stanford.edu -To participate in this study, you will download the StrokeCog App and complete the consent form. The StrokeCog App will passively capture your location for two weeks. Each evening, you will complete a brief survey of three questions. At the end of the data collection period, you will be sent an anonymous survey asking about your experiences using the app. +*DESCRIPTION:* +You are invited to participate in a research study on life space, or the space within which people live, work, and recreate. Based on a custom iPhone Life Space application, we will develop individual life space maps (geographic footprint) in order to evaluate the association of aspects of environmental features with health and well-being. This research study is looking for 120 StrokeCog participants to be enrolled. Stanford University expects to enroll 120 research study participants. -**Risks and Benefits** +To participate in this study, you will download the LifeSpace App and complete the consent form. As a part of this research study, you will be asked to sign in using your AppleID. To do this, you will have to review and agree to the LifeSpace App Privacy Policy. This document is separate from this consent form. -The primary risk associated with this study is a potential loss of privacy, and we have taken all measures to minimize this risk. If for any reason you do not wish to have your location recorded temporarily, you can toggle the “Track My Location” button and the app will stop recording until you start it again. Your data are stored securely, and your name and Apple ID will be removed from your data when it is downloaded. +The LifeSpace App will passively capture your location for two weeks. Each evening, you will complete a brief survey of four questions on the app. -We cannot and do not guarantee or promise that you will receive any benefits from this study. +*RISKS AND BENEFITS:* +The primary risk associated with this study is a potential loss of privacy, and we have taken all measures to minimize this risk. If for any reason you do not wish to have your location recorded temporarily, you can toggle the “Track My Location” button and the app will stop recording until you start it again. Your data are stored securely, and your name and Apple ID will be removed from your data when it is downloaded. +We cannot and do not guarantee or promise that you will receive any benefits from this study. The long-term goal of this research is to better understand the role of the physical environment in contributing to cognitive trajectory after stroke. +Your decision whether or not to participate in this study will not affect your medical care. -**Time Involvement** +*TIME INVOLVEMENT:* +Our LifeSpace App will passively capture location for a period of two weeks. Each evening, you will be asked to complete a brief survey of three questions (1-2 minutes). -Our StrokeCog App will passively capture location for a period of two weeks. Each evening, you will be asked to complete a brief survey of three questions (1-2 minutes). At the end of the data collection period, you will be sent a survey asking about your experiences using the app; this survey will take less than 10 minutes to complete. +*PAYMENTS:* +You will not receive payment for your participation. -**Payment** - -You can receive up to $100 for your participation. You will receive $4/day for every day that you complete the survey for up to 14 days of participation and a bonus of $14 if you participate all 14 days. You will receive $30 for completion of the close out survey. - -**Privacy and Data Use** - -The information in this study will be used only for research purposes. This study is not anonymous. Your name will be shared with the investigators at the Coordinating Center so they know that you are participating in this study and they will send us a study specific ID to be used only for this study. Your location data and data from the evening survey will deidentified and coded with this ID and stored at Stanford. Summary level data about your life space (such as the area in km2) will be shared with the Coordinating Center using the study specific ID. These summary data will not contain any specific location data nor geographic identifiers. The summary level data will be linked to the other health data collected at the Coordinating Center, and shared with Stanford. At no point will your location data or other personal identifiers be linked with your health data. - -**Future Use of Private Information** - -Research using private information is an important way to try to understand human health. You are being given this information because the investigators want to save private information for future research. - -Identifiers will be removed from identifiable private information and, after such removal, the information could be used for future research studies or distributed to another investigator for future research studies without additional informed consent from you. - -**Participant's Rights** - -If you have read this form and have decided to participate in this project, please understand your participation is voluntary and you have the right to withdraw your consent or discontinue participation at any time without penalty or loss of benefits to which you are otherwise entitled. - -Your decision whether or not to participate in this study will not affect your participation in the REGARDS study. - -You have the right to refuse to answer particular questions. - -The alternative to participating in this study is not to participate. +*PARTICIPANT’S RIGHTS:* +If you have read this form and have decided to participate in this project, please understand your participation is voluntary and you have the right to withdraw your consent or discontinue participation at any time without penalty or loss of benefits to which you are otherwise entitled. The results of this research study may be presented at scientific or professional meetings or published in scientific journals. However, your identity will not be disclosed. -**Withdraw from Study** - -If you first agree to participate and then you change your mind, you are free to withdraw your consent and discontinue your participation at any time. - -If you decide to withdraw your consent to participate in this study, you should contact the research team by phone at (650) 721-0230 or email to lifespace@stanford.edu. - -If you decide to withdraw from the study, you can delete the LifeSpace App from your phone. - -The Protocol Director may also withdraw you from the study without your consent for one or more of the following reasons: - -- Failure to follow the instructions of the Protocol Director and study staff. -- Unanticipated circumstances. - -**Sponsor** - -Stanford University is providing financial support and/or material for this study. - -**Contact Information** +You have the right to refuse to answer particular questions. -Questions, Concerns, or Complaints: If you have any questions, concerns or complaints about this research study, its procedures, risks and benefits, you should ask the Protocol Director, Michelle Odden, (650) 721-0230 or lifespace@stanford.edu. You should also contact her at any time if you feel you have been hurt by being a part of this study. +Your decision whether or not to participate in this study will not affect your participation in the StrokeCog study. -Independent Contact: If you are not satisfied with how this study is being conducted, or if you have any concerns, complaints, or general questions about the research or your rights as a participant, please contact the Stanford Institutional Review Board (IRB) to speak to someone independent of the research team at (650)-723-5244 or toll free at 1-866-680-2906. You can also write to the Stanford IRB, Stanford University, 1705 El Camino Real, Palo Alto, CA 94306. From f32b7e064abf9cafbe8bc4d58f83456b38576901 Mon Sep 17 00:00:00 2001 From: Vishnu Ravi Date: Mon, 27 May 2024 00:03:15 -0400 Subject: [PATCH 2/8] Add additional text --- StrokeCog/Resources/ConsentDocument.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/StrokeCog/Resources/ConsentDocument.md b/StrokeCog/Resources/ConsentDocument.md index 878bd00..f269677 100644 --- a/StrokeCog/Resources/ConsentDocument.md +++ b/StrokeCog/Resources/ConsentDocument.md @@ -28,3 +28,20 @@ You have the right to refuse to answer particular questions. Your decision whether or not to participate in this study will not affect your participation in the StrokeCog study. +*WITHDRAWAL FROM STUDY:* +If you first agree to participate and then you change your mind, you are free to withdraw your consent and discontinue your participation at any time. +If you decide to withdraw your consent to participate in this study, you should notify the LifeSpace study team (lifespace@stanford.edu) or Michelle Odden (650-721-0230, modden@stanford.edu). + +If you decide to withdraw from the study, you can delete the LifeSpace App from your phone. + +The Protocol Director may also withdraw you from the study without your consent for one or more of the following reasons: + +• Failure to follow the instructions of the Protocol Director and study staff. +• Unanticipated circumstances. + +*CONTACT INFORMATION:* +Questions, Concerns, or Complaints: If you have any questions, concerns or complaints about this research study, its procedures, risks and benefits, you should ask the Protocol Director, Michelle Odden, (650) 721-0230. You should also contact her at any time if you feel you have been hurt by being a part of this study. + +Independent Contact: If you are not satisfied with how this study is being conducted, or if you have any concerns, complaints, or general questions about the research or your rights as a participant, please contact the Stanford Institutional Review Board (IRB) to speak to someone independent of the research team at 650-723-5244 or toll free at 1-866-680-2906. You can also write to the Stanford IRB, Stanford University, 1705 El Camino Real, Palo Alto, CA 94306. + +A copy of this form is saved in your profile in the LifeSpace App – please print or save this locally to your iPhone. If you agree to participate in this research, please sign here. From f0b58a34e3b350e17b016b12f733c7f3a302e244 Mon Sep 17 00:00:00 2001 From: Vishnu Ravi Date: Mon, 27 May 2024 23:54:27 -0400 Subject: [PATCH 3/8] Add study ID to documents --- StrokeCog/Onboarding/StudyIDView.swift | 1 + StrokeCog/SharedContext/StorageKeys.swift | 2 ++ StrokeCog/StrokeCogStandard.swift | 6 ++++-- StrokeCog/Survey/DailySurveyResponse.swift | 4 ++++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/StrokeCog/Onboarding/StudyIDView.swift b/StrokeCog/Onboarding/StudyIDView.swift index 4986076..b845d1b 100644 --- a/StrokeCog/Onboarding/StudyIDView.swift +++ b/StrokeCog/Onboarding/StudyIDView.swift @@ -37,6 +37,7 @@ struct StudyIDView: View { } if verify(id: studyID) { + UserDefaults.standard.set(studyID, forKey: StorageKeys.studyID) onboardingNavigationPath.nextStep() } else { showInvalidIDAlert = true diff --git a/StrokeCog/SharedContext/StorageKeys.swift b/StrokeCog/SharedContext/StorageKeys.swift index 4cad30f..4d7f953 100644 --- a/StrokeCog/SharedContext/StorageKeys.swift +++ b/StrokeCog/SharedContext/StorageKeys.swift @@ -13,6 +13,8 @@ enum StorageKeys { static let onboardingFlowComplete = "onboardingFlow.complete" /// A `Step` flag indicating the current step in the onboarding process. static let onboardingFlowStep = "onboardingFlow.step" + /// The user's study ID + static let studyID = "studyID" // MARK: - Home diff --git a/StrokeCog/StrokeCogStandard.swift b/StrokeCog/StrokeCogStandard.swift index 4c4cb2a..94f4ae8 100644 --- a/StrokeCog/StrokeCogStandard.swift +++ b/StrokeCog/StrokeCogStandard.swift @@ -96,7 +96,9 @@ actor StrokeCogStandard: Standard, EnvironmentAccessible, HealthKitConstraint, O } func add(location: CLLocationCoordinate2D) async throws { - guard let details = await account.details else { + guard let details = await account.details, + let studyID = UserDefaults.standard.string(forKey: StorageKeys.studyID) + else { throw StrokeCogStandardError.userNotAuthenticatedYet } @@ -105,7 +107,7 @@ actor StrokeCogStandard: Standard, EnvironmentAccessible, HealthKitConstraint, O time: Date().timeIntervalSince1970, latitude: location.latitude, longitude: location.longitude, - studyID: details.userId, + studyID: studyID, updatedBy: details.accountId ) diff --git a/StrokeCog/Survey/DailySurveyResponse.swift b/StrokeCog/Survey/DailySurveyResponse.swift index f5bde61..7739b18 100644 --- a/StrokeCog/Survey/DailySurveyResponse.swift +++ b/StrokeCog/Survey/DailySurveyResponse.swift @@ -9,6 +9,10 @@ import Foundation struct DailySurveyResponse: Codable { + var surveyName: String + var studyID: String + var updatedBy: String + var timestamp: Date var socialInteractionQuestion: Int? var leavingTheHouseQuestion: Int? var emotionalWellBeingQuestion: Int? From 0cbceba34f3755df1d441d4758611448950db23b Mon Sep 17 00:00:00 2001 From: Vishnu Ravi Date: Tue, 28 May 2024 00:19:40 -0400 Subject: [PATCH 4/8] Add metadata to survey responses --- StrokeCog.xcodeproj/project.pbxproj | 4 ++-- StrokeCog/Resources/Localizable.xcstrings | 6 ++++++ StrokeCog/StrokeCogStandard.swift | 19 ++++++++++++++++--- .../Supporting Files/GoogleService-Info.plist | 2 +- StrokeCog/Survey/DailySurveyResponse.swift | 8 ++++---- StrokeCog/Survey/DailySurveyTaskView.swift | 2 ++ 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/StrokeCog.xcodeproj/project.pbxproj b/StrokeCog.xcodeproj/project.pbxproj index c6eb1e2..9a6f13f 100644 --- a/StrokeCog.xcodeproj/project.pbxproj +++ b/StrokeCog.xcodeproj/project.pbxproj @@ -762,7 +762,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = B2Q3T3P8HP; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "StrokeCog/Supporting Files/Info.plist"; @@ -965,7 +965,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = B2Q3T3P8HP; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "StrokeCog/Supporting Files/Info.plist"; diff --git a/StrokeCog/Resources/Localizable.xcstrings b/StrokeCog/Resources/Localizable.xcstrings index 04766ac..0e27752 100644 --- a/StrokeCog/Resources/Localizable.xcstrings +++ b/StrokeCog/Resources/Localizable.xcstrings @@ -339,6 +339,12 @@ } } } + }, + "Refresh map" : { + + }, + "Refreshing map" : { + }, "RETRY_BUTTON_LABEL" : { "localizations" : { diff --git a/StrokeCog/StrokeCogStandard.swift b/StrokeCog/StrokeCogStandard.swift index 899899a..85a015b 100644 --- a/StrokeCog/StrokeCogStandard.swift +++ b/StrokeCog/StrokeCogStandard.swift @@ -25,6 +25,7 @@ import SwiftUI actor StrokeCogStandard: Standard, EnvironmentAccessible, HealthKitConstraint, OnboardingConstraint, AccountStorageConstraint { enum StrokeCogStandardError: Error { case userNotAuthenticatedYet + case invalidStudyID } private static var userCollection: CollectionReference { @@ -96,12 +97,14 @@ actor StrokeCogStandard: Standard, EnvironmentAccessible, HealthKitConstraint, O } func add(location: CLLocationCoordinate2D) async throws { - guard let details = await account.details, - let studyID = UserDefaults.standard.string(forKey: StorageKeys.studyID) - else { + guard let details = await account.details else { throw StrokeCogStandardError.userNotAuthenticatedYet } + guard let studyID = UserDefaults.standard.string(forKey: StorageKeys.studyID) else { + throw StrokeCogStandardError.invalidStudyID + } + let dataPoint = LocationDataPoint( currentDate: Date(), time: Date().timeIntervalSince1970, @@ -155,6 +158,16 @@ actor StrokeCogStandard: Standard, EnvironmentAccessible, HealthKitConstraint, O throw StrokeCogStandardError.userNotAuthenticatedYet } + guard let studyID = UserDefaults.standard.string(forKey: StorageKeys.studyID) else { + throw StrokeCogStandardError.invalidStudyID + } + + var response = response + + response.timestamp = Date() + response.studyID = studyID + response.updatedBy = details.accountId + try await userDocumentReference .collection("surveys") .document(UUID().uuidString) diff --git a/StrokeCog/Supporting Files/GoogleService-Info.plist b/StrokeCog/Supporting Files/GoogleService-Info.plist index 9387022..cf20b80 100644 --- a/StrokeCog/Supporting Files/GoogleService-Info.plist +++ b/StrokeCog/Supporting Files/GoogleService-Info.plist @@ -3,7 +3,7 @@ API_KEY - KEY + API_KEY GCM_SENDER_ID 1071663459836 PLIST_VERSION diff --git a/StrokeCog/Survey/DailySurveyResponse.swift b/StrokeCog/Survey/DailySurveyResponse.swift index 7739b18..bed29e8 100644 --- a/StrokeCog/Survey/DailySurveyResponse.swift +++ b/StrokeCog/Survey/DailySurveyResponse.swift @@ -9,10 +9,10 @@ import Foundation struct DailySurveyResponse: Codable { - var surveyName: String - var studyID: String - var updatedBy: String - var timestamp: Date + var surveyName: String? + var studyID: String? + var updatedBy: String? + var timestamp: Date? var socialInteractionQuestion: Int? var leavingTheHouseQuestion: Int? var emotionalWellBeingQuestion: Int? diff --git a/StrokeCog/Survey/DailySurveyTaskView.swift b/StrokeCog/Survey/DailySurveyTaskView.swift index 8aed6e4..0f111d2 100644 --- a/StrokeCog/Survey/DailySurveyTaskView.swift +++ b/StrokeCog/Survey/DailySurveyTaskView.swift @@ -64,6 +64,8 @@ struct DailySurveyTaskView: View { private func saveResponse(taskResult: ORKTaskResult) async { var response = DailySurveyResponse() + response.surveyName = "dailySurveyTask" + if let socialInteractionQuestion = taskResult.stepResult(forStepIdentifier: "SocialInteractionQuestion")?.results { let answer = socialInteractionQuestion[0] as? ORKScaleQuestionResult if let result = answer?.scaleAnswer { From e0fc52b0a588be702985a454b615e1b0190b0dc4 Mon Sep 17 00:00:00 2001 From: Vishnu Ravi Date: Tue, 28 May 2024 00:45:15 -0400 Subject: [PATCH 5/8] Update survey unavailable message --- StrokeCog/Survey/DailySurveyTaskView.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/StrokeCog/Survey/DailySurveyTaskView.swift b/StrokeCog/Survey/DailySurveyTaskView.swift index 0f111d2..582af58 100644 --- a/StrokeCog/Survey/DailySurveyTaskView.swift +++ b/StrokeCog/Survey/DailySurveyTaskView.swift @@ -40,16 +40,20 @@ struct DailySurveyTaskView: View { private var surveyUnavailableView: some View { VStack { + Image(systemName: "clock.fill") + .resizable() + .frame(width: 50, height: 50) + Text("SURVEY_NOT_AVAILABLE_MESSAGE") + .font(.largeTitle) .padding() .multilineTextAlignment(.center) - Button { + Button("CLOSE") { self.showingSurvey.toggle() - } label: { - Text("CLOSE") - .frame(maxWidth: .infinity) } + .buttonStyle(.borderedProminent) + .padding(.top, 20) } } From f7a03ef1278bc0b850df0a371ec63976d643ca34 Mon Sep 17 00:00:00 2001 From: Vishnu Ravi Date: Tue, 28 May 2024 00:54:46 -0400 Subject: [PATCH 6/8] Update onboarding strings to LifeSpace --- StrokeCog/Resources/Localizable.xcstrings | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/StrokeCog/Resources/Localizable.xcstrings b/StrokeCog/Resources/Localizable.xcstrings index 0e27752..fb17f51 100644 --- a/StrokeCog/Resources/Localizable.xcstrings +++ b/StrokeCog/Resources/Localizable.xcstrings @@ -36,7 +36,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "Sign Up or Log In to the StrokeCog Study using Sign In With Apple." + "value" : "Sign Up or Log In to the LifeSpace Study using Sign In With Apple." } } } @@ -121,7 +121,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "The StrokeCog study app will collect activity data from your phone and/or watch while you are enrolled in the study." + "value" : "The LifeSpace app will collect activity data from your phone and/or watch while you are enrolled in the study." } } } @@ -264,7 +264,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "StrokeCog Location" + "value" : "LifeSpace Location" } } } @@ -304,7 +304,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "StrokeCog Notifications" + "value" : "LifeSpace Notifications" } } } @@ -393,7 +393,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "Welcome to the StrokeCog study. Please enter your study ID below." + "value" : "Welcome to the LifeSpace study. Please enter your study ID below." } } } @@ -473,7 +473,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "StrokeCog Daily Survey" + "value" : "LifeSpace Daily Survey" } } } @@ -573,7 +573,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "The StrokeCog Study investigates the relationship between life space and cognitive decline after a stroke." + "value" : "The LifeSpace study investigates the relationship between life space and cognitive decline after a stroke." } } } @@ -584,7 +584,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "StrokeCog Study" + "value" : "LifeSpace Study" } } } From e0d45f0070a1b2ead27fc446ed49d7e9528d125a Mon Sep 17 00:00:00 2001 From: Vishnu Ravi Date: Tue, 28 May 2024 01:30:07 -0400 Subject: [PATCH 7/8] Add study ID to consent file name --- StrokeCog/StrokeCogStandard.swift | 6 ++++-- StrokeCog/Survey/DailySurveyTaskView.swift | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/StrokeCog/StrokeCogStandard.swift b/StrokeCog/StrokeCogStandard.swift index 85a015b..42885af 100644 --- a/StrokeCog/StrokeCogStandard.swift +++ b/StrokeCog/StrokeCogStandard.swift @@ -198,13 +198,15 @@ actor StrokeCogStandard: Standard, EnvironmentAccessible, HealthKitConstraint, O formatter.dateFormat = "yyyy-MM-dd_HHmmss" let dateString = formatter.string(from: Date()) + let studyID = UserDefaults.standard.string(forKey: StorageKeys.studyID) ?? "unknownStudyID" + guard !FeatureFlags.disableFirebase else { guard let basePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { logger.error("Could not create path for writing consent form to user document directory.") return } - let filePath = basePath.appending(path: "consentForm_\(dateString).pdf") + let filePath = basePath.appending(path: "consentForm_\(studyID)_\(dateString).pdf") consent.write(to: filePath) return @@ -218,7 +220,7 @@ actor StrokeCogStandard: Standard, EnvironmentAccessible, HealthKitConstraint, O let metadata = StorageMetadata() metadata.contentType = "application/pdf" - _ = try await userBucketReference.child("consent/\(dateString).pdf").putDataAsync(consentData, metadata: metadata) + _ = try await userBucketReference.child("consent/\(studyID)_\(dateString).pdf").putDataAsync(consentData, metadata: metadata) } catch { logger.error("Could not store consent form: \(error)") } diff --git a/StrokeCog/Survey/DailySurveyTaskView.swift b/StrokeCog/Survey/DailySurveyTaskView.swift index 582af58..f098356 100644 --- a/StrokeCog/Survey/DailySurveyTaskView.swift +++ b/StrokeCog/Survey/DailySurveyTaskView.swift @@ -43,6 +43,7 @@ struct DailySurveyTaskView: View { Image(systemName: "clock.fill") .resizable() .frame(width: 50, height: 50) + .accessibilityLabel("Survey not available.") Text("SURVEY_NOT_AVAILABLE_MESSAGE") .font(.largeTitle) From dbc46d0811848c50733b5f395da01aa44acab83b Mon Sep 17 00:00:00 2001 From: Vishnu Ravi Date: Tue, 28 May 2024 12:24:08 -0400 Subject: [PATCH 8/8] Update bundle identifier --- StrokeCog.xcodeproj/project.pbxproj | 32 +++++++++---------- StrokeCog/Map/StrokeCogMapView.swift | 7 ++++ StrokeCog/Resources/Localizable.xcstrings | 3 ++ StrokeCog/StrokeCogDelegate.swift | 2 +- StrokeCog/StrokeCogStandard.swift | 4 +-- .../Supporting Files/GoogleService-Info.plist | 4 +-- 6 files changed, 31 insertions(+), 21 deletions(-) diff --git a/StrokeCog.xcodeproj/project.pbxproj b/StrokeCog.xcodeproj/project.pbxproj index 9a6f13f..20099c2 100644 --- a/StrokeCog.xcodeproj/project.pbxproj +++ b/StrokeCog.xcodeproj/project.pbxproj @@ -61,9 +61,9 @@ 63497B702BBF6ECE001F8419 /* LocationDataPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63497B6F2BBF6ECE001F8419 /* LocationDataPoint.swift */; }; 63497B732BBF855E001F8419 /* OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63497B722BBF855E001F8419 /* OptionsPanel.swift */; }; 63A28D312C0580310025A1E0 /* RefreshIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63A28D302C0580310025A1E0 /* RefreshIcon.swift */; }; + 63A28D332C062E2E0025A1E0 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 63A28D322C062E2E0025A1E0 /* GoogleService-Info.plist */; }; 63BBF8162BB8993B006890CE /* StudyIDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BBF8152BB8993B006890CE /* StudyIDView.swift */; }; 63BBF8192BB89CF7006890CE /* studyIDs.csv in Resources */ = {isa = PBXBuildFile; fileRef = 63BBF8182BB89CF7006890CE /* studyIDs.csv */; }; - 63E8D2352C043FCC000C7ADF /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 63E8D2342C043FCC000C7ADF /* GoogleService-Info.plist */; }; 63EA5F7B2BC04F8400A48590 /* DailySurveyTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63EA5F7A2BC04F8400A48590 /* DailySurveyTask.swift */; }; 63EA5F892BC78ADD00A48590 /* DailySurveyTaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63EA5F882BC78ADD00A48590 /* DailySurveyTaskView.swift */; }; 63EA5F8C2BC78F8400A48590 /* DailySurveyResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63EA5F8B2BC78F8400A48590 /* DailySurveyResponse.swift */; }; @@ -138,9 +138,9 @@ 63497B6F2BBF6ECE001F8419 /* LocationDataPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationDataPoint.swift; sourceTree = ""; }; 63497B722BBF855E001F8419 /* OptionsPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionsPanel.swift; sourceTree = ""; }; 63A28D302C0580310025A1E0 /* RefreshIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshIcon.swift; sourceTree = ""; }; + 63A28D322C062E2E0025A1E0 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 63BBF8152BB8993B006890CE /* StudyIDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudyIDView.swift; sourceTree = ""; }; 63BBF8182BB89CF7006890CE /* studyIDs.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = studyIDs.csv; sourceTree = ""; }; - 63E8D2342C043FCC000C7ADF /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 63EA5F7A2BC04F8400A48590 /* DailySurveyTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailySurveyTask.swift; sourceTree = ""; }; 63EA5F882BC78ADD00A48590 /* DailySurveyTaskView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailySurveyTaskView.swift; sourceTree = ""; }; 63EA5F8B2BC78F8400A48590 /* DailySurveyResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailySurveyResponse.swift; sourceTree = ""; }; @@ -215,7 +215,7 @@ 2FC9759D2978E30800BA99FE /* Supporting Files */ = { isa = PBXGroup; children = ( - 63E8D2342C043FCC000C7ADF /* GoogleService-Info.plist */, + 63A28D322C062E2E0025A1E0 /* GoogleService-Info.plist */, 2FAEC07F297F583900C11C42 /* StrokeCog.entitlements */, 653A258928339462005D4D48 /* Info.plist */, 2F1AC9DE2B4E840E00C24973 /* StrokeCog.docc */, @@ -558,12 +558,12 @@ buildActionMask = 2147483647; files = ( 63BBF8192BB89CF7006890CE /* studyIDs.csv in Resources */, - 63E8D2352C043FCC000C7ADF /* GoogleService-Info.plist in Resources */, 2FC3439229EE634B002D773C /* ConsentDocument.md in Resources */, 2FC3439129EE6349002D773C /* AppIcon.png in Resources */, 653A255528338800005D4D48 /* Assets.xcassets in Resources */, 2FC3439029EE6346002D773C /* SocialSupportQuestionnaire.json in Resources */, 2FA0BFED2ACC977500E0EF83 /* Localizable.xcstrings in Resources */, + 63A28D332C062E2E0025A1E0 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -766,6 +766,7 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "StrokeCog/Supporting Files/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = LifeSpace; INFOPLIST_KEY_NSCameraUsageDescription = "This message should never appear. Please adjust this when you start using camera information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; INFOPLIST_KEY_NSHealthShareUsageDescription = "The StrokeCog uses the step count to demonstrate Spezi's integration with HealthKit."; INFOPLIST_KEY_NSHealthUpdateUsageDescription = "The StrokeCog uses the step count to demonstrate Spezi's integration with HealthKit."; @@ -784,8 +785,8 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.odden.strokecog; + MARKETING_VERSION = 2.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.odden.lifespace-dev"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -969,6 +970,7 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "StrokeCog/Supporting Files/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = LifeSpace; INFOPLIST_KEY_NSCameraUsageDescription = "This message should never appear. Please adjust this when you start using camera information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; INFOPLIST_KEY_NSHealthShareUsageDescription = "The StrokeCog uses the step count to demonstrate Spezi's integration with HealthKit."; INFOPLIST_KEY_NSHealthUpdateUsageDescription = "The StrokeCog uses the step count to demonstrate Spezi's integration with HealthKit."; @@ -987,8 +989,8 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.odden.strokecog; + MARKETING_VERSION = 2.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.odden.lifespace-dev"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -1008,15 +1010,14 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = "StrokeCog/Supporting Files/StrokeCog.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = B2Q3T3P8HP; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "StrokeCog/Supporting Files/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = LifeSpace; INFOPLIST_KEY_NSCameraUsageDescription = "This message should never appear. Please adjust this when you start using camera information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; INFOPLIST_KEY_NSHealthShareUsageDescription = "The StrokeCog uses the step count to demonstrate Spezi's integration with HealthKit."; INFOPLIST_KEY_NSHealthUpdateUsageDescription = "The StrokeCog uses the step count to demonstrate Spezi's integration with HealthKit."; @@ -1035,11 +1036,10 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.odden.strokecog; + MARKETING_VERSION = 2.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.odden.lifespace-dev"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "StrokeCog Distribution Profile"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1230,8 +1230,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/StanfordSpezi/SpeziQuestionnaire.git"; requirement = { - kind = upToNextMajorVersion; - minimumVersion = 1.0.0; + kind = exactVersion; + version = 1.1.0; }; }; 2FE5DC8829EDD972004B9AB4 /* XCRemoteSwiftPackageReference "SpeziStorage" */ = { diff --git a/StrokeCog/Map/StrokeCogMapView.swift b/StrokeCog/Map/StrokeCogMapView.swift index 0b622fb..579e2ee 100644 --- a/StrokeCog/Map/StrokeCogMapView.swift +++ b/StrokeCog/Map/StrokeCogMapView.swift @@ -10,9 +10,11 @@ import MapboxMaps import SpeziAccount import SwiftUI + struct StrokeCogMapView: View { @AppStorage(StorageKeys.trackingPreference) private var trackingOn = true @Environment(LocationModule.self) private var locationModule + @Environment(\.scenePhase) var scenePhase @State private var presentedContext: EventContext? @Binding private var presentingAccount: Bool @@ -56,6 +58,11 @@ struct StrokeCogMapView: View { } } } + .onChange(of: scenePhase) { _, newPhase in + if newPhase == .active { + refreshMap() + } + } } private var optionsPanelButton: some View { diff --git a/StrokeCog/Resources/Localizable.xcstrings b/StrokeCog/Resources/Localizable.xcstrings index fb17f51..7e2272f 100644 --- a/StrokeCog/Resources/Localizable.xcstrings +++ b/StrokeCog/Resources/Localizable.xcstrings @@ -427,6 +427,9 @@ } } } + }, + "Survey not available." : { + }, "SURVEY_NOT_AVAILABLE_MESSAGE" : { "localizations" : { diff --git a/StrokeCog/StrokeCogDelegate.swift b/StrokeCog/StrokeCogDelegate.swift index 4908750..bc9df9b 100644 --- a/StrokeCog/StrokeCogDelegate.swift +++ b/StrokeCog/StrokeCogDelegate.swift @@ -1,5 +1,5 @@ // -// This source file is part of the StrokeCog based on the Stanford Spezi Template Application project +// This source file is part of the LifeSpace application based on the Stanford Spezi Template Application project // // SPDX-FileCopyrightText: 2023 Stanford University // diff --git a/StrokeCog/StrokeCogStandard.swift b/StrokeCog/StrokeCogStandard.swift index 42885af..2350370 100644 --- a/StrokeCog/StrokeCogStandard.swift +++ b/StrokeCog/StrokeCogStandard.swift @@ -123,7 +123,7 @@ actor StrokeCogStandard: Standard, EnvironmentAccessible, HealthKitConstraint, O func fetchLocations(on date: Date = Date()) async throws -> [CLLocationCoordinate2D] { let calendar = Calendar.current let startOfDay = calendar.startOfDay(for: date) - let endOfDay = calendar.date(byAdding: .day, value: 1, to: startOfDay) + let endOfDay = Date(timeInterval: 24 * 60 * 60, since: startOfDay) var locations = [CLLocationCoordinate2D]() @@ -131,7 +131,7 @@ actor StrokeCogStandard: Standard, EnvironmentAccessible, HealthKitConstraint, O let snapshot = try await userDocumentReference .collection("location_data") .whereField("currentDate", isGreaterThanOrEqualTo: startOfDay) - .whereField("currentDate", isLessThan: endOfDay ?? Date()) + .whereField("currentDate", isLessThan: endOfDay) .getDocuments() for document in snapshot.documents { diff --git a/StrokeCog/Supporting Files/GoogleService-Info.plist b/StrokeCog/Supporting Files/GoogleService-Info.plist index cf20b80..069df9d 100644 --- a/StrokeCog/Supporting Files/GoogleService-Info.plist +++ b/StrokeCog/Supporting Files/GoogleService-Info.plist @@ -9,7 +9,7 @@ PLIST_VERSION 1 BUNDLE_ID - com.odden.strokecog + com.odden.lifespace-dev PROJECT_ID strokecog-9d7a6 STORAGE_BUCKET @@ -25,6 +25,6 @@ IS_SIGNIN_ENABLED GOOGLE_APP_ID - 1:1071663459836:ios:896e9605eaa7d232ef1679 + 1:1071663459836:ios:ff0a281bdf9ec69eef1679