From 8eeeb146f3189b70fc42113eca06fb54a2d0477c Mon Sep 17 00:00:00 2001 From: Pauline Date: Wed, 11 Dec 2024 00:47:29 +0000 Subject: [PATCH 01/29] Add reset for schemas and converters --- .../kafka/converters/converter-factory.service..ts | 13 +++++++++++-- .../services/kafka/converters/converter.service.ts | 6 ++++++ src/app/core/services/kafka/schema.service.ts | 6 +++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/app/core/services/kafka/converters/converter-factory.service..ts b/src/app/core/services/kafka/converters/converter-factory.service..ts index 938594b08..f933da405 100644 --- a/src/app/core/services/kafka/converters/converter-factory.service..ts +++ b/src/app/core/services/kafka/converters/converter-factory.service..ts @@ -18,9 +18,9 @@ export class ConverterFactoryService { private completionLogConverter: CompletionLogConverterService, private timzoneConverter: TimezoneConverterService, private keyConverter: KeyConverterService - ) {} + ) { } - init() {} + init() { } getConverter(type) { switch (this.classify(type)) { @@ -45,4 +45,13 @@ export class ConverterFactoryService { if (type.includes(SchemaType.HEALTHKIT)) return SchemaType.HEALTHKIT else return type } + + reset() { + this.healthkitConverter.reset() + this.assessmentConverter.reset() + this.completionLogConverter.reset() + this.timzoneConverter.reset() + this.appEventConverter.reset() + this.assessmentConverter.reset() + } } diff --git a/src/app/core/services/kafka/converters/converter.service.ts b/src/app/core/services/kafka/converters/converter.service.ts index ca4239d77..f5aeda51a 100644 --- a/src/app/core/services/kafka/converters/converter.service.ts +++ b/src/app/core/services/kafka/converters/converter.service.ts @@ -132,4 +132,10 @@ export abstract class ConverterService { return false } } + + reset() { + this.BASE_URI = null + this.specifications = null + this.schemas = {} + } } diff --git a/src/app/core/services/kafka/schema.service.ts b/src/app/core/services/kafka/schema.service.ts index 7593e6ec7..aba8788a5 100644 --- a/src/app/core/services/kafka/schema.service.ts +++ b/src/app/core/services/kafka/schema.service.ts @@ -13,7 +13,7 @@ export class SchemaService { constructor( private converterFactory: ConverterFactoryService, private subjectConfig: SubjectConfigService - ) {} + ) { } getKafkaObjectKey() { return this.subjectConfig @@ -59,4 +59,8 @@ export class SchemaService { }) ) } + + reset() { + return this.converterFactory.reset() + } } From 8817457d9dee87777d37b31c2eef569e2c61837f Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 3 Feb 2025 13:07:57 +0000 Subject: [PATCH 02/29] Allow task info to be hidden --- .../home/containers/home-page.component.html | 2 +- .../pages/home/containers/home-page.component.ts | 2 ++ src/app/pages/home/services/tasks.service.ts | 15 ++++++++++++++- src/app/shared/enums/config.ts | 2 +- src/assets/data/defaultConfig.ts | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/app/pages/home/containers/home-page.component.html b/src/app/pages/home/containers/home-page.component.html index 597a43879..58d7c9a73 100755 --- a/src/app/pages/home/containers/home-page.component.html +++ b/src/app/pages/home/containers/home-page.component.html @@ -75,7 +75,7 @@
isTaskCalendarTaskNameShown: Promise + isTaskInfoShown: Promise currentDate: number APP_CREDITS = '© RADAR-Base' @@ -112,6 +113,7 @@ export class HomePageComponent implements OnInit, OnDestroy { this.title = this.tasksService.getPlatformInstanceName() this.isTaskCalendarTaskNameShown = this.tasksService.getIsTaskCalendarTaskNameShown() + this.isTaskInfoShown = this.tasksService.getIsTaskInfoShown() this.onDemandIcon = this.tasksService.getOnDemandAssessmentIcon() this.showMiscTasksButton = this.getShowMiscTasksButton() } diff --git a/src/app/pages/home/services/tasks.service.ts b/src/app/pages/home/services/tasks.service.ts index 644b9645b..526aaa3e9 100644 --- a/src/app/pages/home/services/tasks.service.ts +++ b/src/app/pages/home/services/tasks.service.ts @@ -5,7 +5,8 @@ import { DefaultAppCreditsTitle, DefaultOnDemandAssessmentIcon, DefaultPlatformInstance, - DefaultShowTaskCalendarName + DefaultShowTaskCalendarName, + DefaultShowTaskInfo } from '../../../../assets/data/defaultConfig' import { QuestionnaireService } from '../../../core/services/config/questionnaire.service' import { RemoteConfigService } from '../../../core/services/config/remote-config.service' @@ -197,4 +198,16 @@ export class TasksService { ) .then(res => JSON.parse(res)) } + + getIsTaskInfoShown() { + return this.remoteConfig + .read() + .then(config => + config.getOrDefault( + ConfigKeys.SHOW_TASK_INFO, + DefaultShowTaskInfo + ) + ) + .then(res => JSON.parse(res)) + } } diff --git a/src/app/shared/enums/config.ts b/src/app/shared/enums/config.ts index 8e61a578b..7ef9c5209 100644 --- a/src/app/shared/enums/config.ts +++ b/src/app/shared/enums/config.ts @@ -39,8 +39,8 @@ export class ConfigKeys { static TOPIC_CACHE_TIMEOUT = new ConfigKeys('topic_cache_timeout') static SHOW_TASK_CALENDAR_NAME = new ConfigKeys('show_task_calendar_name') - static SHOW_TASK_PROGRESS_COUNT = new ConfigKeys('show_task_progress_count') + static SHOW_TASK_INFO = new ConfigKeys('show_task_info') static AUDIO_SAMPLING_RATE = new ConfigKeys('audio_sampling_rate') diff --git a/src/assets/data/defaultConfig.ts b/src/assets/data/defaultConfig.ts index c21b28d50..3fa082972 100755 --- a/src/assets/data/defaultConfig.ts +++ b/src/assets/data/defaultConfig.ts @@ -63,8 +63,8 @@ export const DefaultAppCreditsBody = JSON.stringify( ) export const DefaultShowTaskCalendarName = 'false' - export const DefaultShowTaskProgressCount = 'false' +export const DefaultShowTaskInfo = 'true' // DEFAULT URI From 3a273b166183e1c877ca955160a25366a98b7ddc Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 3 Feb 2025 13:29:58 +0000 Subject: [PATCH 03/29] Allow slider to be a matrix type --- .../components/question/question.component.ts | 15 +++++---------- .../containers/questions-page.component.html | 1 + .../containers/questions-page.component.ts | 9 +++++++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/app/pages/questions/components/question/question.component.ts b/src/app/pages/questions/components/question/question.component.ts index 505151fdf..816343d26 100755 --- a/src/app/pages/questions/components/question/question.component.ts +++ b/src/app/pages/questions/components/question/question.component.ts @@ -41,9 +41,10 @@ export class QuestionComponent implements OnInit, OnChanges { task: Task @Input() isSectionHeaderHidden: boolean - // isNextAutomatic: automatically slide to next upon answer @Input() - isNextAutomatic: boolean + isNextAutomatic: boolean // Automatically slide to next upon answer + @Input() + isMatrix = false @Output() answer: EventEmitter = new EventEmitter() @Output() @@ -59,7 +60,6 @@ export class QuestionComponent implements OnInit, OnChanges { keyboardScrollPadding = 200 keyboardInputOffset = 0 inputHeight = 0 - isMatrix = false isAutoHeight = false showScrollButton = false defaultYesNoResponse: Response[] = [ @@ -80,10 +80,6 @@ export class QuestionComponent implements OnInit, OnChanges { QuestionType.audio, QuestionType.descriptive ]) - MATRIX_INPUT_SET: Set = new Set([ - QuestionType.matrix_radio, - QuestionType.health - ]) // Input set where height is set to auto AUTO_HEIGHT_INPUT_SET: Set = new Set([ @@ -111,7 +107,6 @@ export class QuestionComponent implements OnInit, OnChanges { this.isFieldLabelHidden = this.HIDE_FIELD_LABEL_SET.has( this.question.field_type ) - this.isMatrix = this.MATRIX_INPUT_SET.has(this.question.field_type) this.isAutoHeight = this.isMatrix || this.AUTO_HEIGHT_INPUT_SET.has(this.question.field_type) setTimeout(() => { @@ -205,7 +200,7 @@ export class QuestionComponent implements OnInit, OnChanges { return ( this.SCROLLBAR_VISIBLE_SET.has(this.question.field_type) && this.inputEl.nativeElement.scrollHeight > - this.inputEl.nativeElement.clientHeight + this.inputEl.nativeElement.clientHeight ) } @@ -215,7 +210,7 @@ export class QuestionComponent implements OnInit, OnChanges { this.showScrollButton && event && event.target.scrollTop >= - (event.target.scrollHeight - event.target.clientHeight) * 0.1 + (event.target.scrollHeight - event.target.clientHeight) * 0.1 ) { this.showScrollButton = false } diff --git a/src/app/pages/questions/containers/questions-page.component.html b/src/app/pages/questions/containers/questions-page.component.html index 29bc87966..2637e1694 100755 --- a/src/app/pages/questions/containers/questions-page.component.html +++ b/src/app/pages/questions/containers/questions-page.component.html @@ -31,6 +31,7 @@ [task]="task" [currentIndex]="currentQuestionGroupId" [isSectionHeaderHidden]="j != currentQuestionIndices[0]" + [isMatrix]="item.value.length > 1" (answer)="onAnswer($event)" (nextAction)="nextAction($event)" > diff --git a/src/app/pages/questions/containers/questions-page.component.ts b/src/app/pages/questions/containers/questions-page.component.ts index 601ee311f..eb68da60d 100644 --- a/src/app/pages/questions/containers/questions-page.component.ts +++ b/src/app/pages/questions/containers/questions-page.component.ts @@ -70,6 +70,12 @@ export class QuestionsPageComponent implements OnInit { ]) MATRIX_FIELD_NAME = 'matrix' HEALTH_FIELD_NAME = 'health' + MATRIX_INPUT_SET: Set = new Set([ + QuestionType.matrix_radio, + QuestionType.healthkit, + QuestionType.slider + ]) + backButtonListener: Subscription showProgressCount: Promise @@ -151,8 +157,7 @@ export class QuestionsPageComponent implements OnInit { const groupedQuestions = new Map() questions.forEach(q => { const key = - q.field_type.includes(this.MATRIX_FIELD_NAME) || - q.field_type.includes(this.HEALTH_FIELD_NAME) + this.MATRIX_INPUT_SET.has(q.field_type) ? q.matrix_group_name : q.field_name const entry = groupedQuestions.get(key) ? groupedQuestions.get(key) : [] From c1426f67bbc4bbdd116dcd5d24fc7a98599d302b Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 14 Feb 2025 02:24:22 +0000 Subject: [PATCH 04/29] Add healthkit to QuestionType --- src/app/shared/models/question.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/shared/models/question.ts b/src/app/shared/models/question.ts index 30f4227fd..830d69a60 100755 --- a/src/app/shared/models/question.ts +++ b/src/app/shared/models/question.ts @@ -59,6 +59,7 @@ export class QuestionType { static descriptive = 'descriptive' static matrix_radio = 'matrix-radio' static health = 'health' + static healthkit = 'healthkit' } export interface Response { @@ -98,4 +99,4 @@ export interface QuestionPosition { export enum WebInputType { NHS = 'nhs' -} \ No newline at end of file +} From 4dc75447f2a9894bc8b37b3114120219fdb9e8c6 Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 6 Feb 2025 13:52:18 +0000 Subject: [PATCH 05/29] Check matrix group name exists before grouping --- src/app/pages/questions/containers/questions-page.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/pages/questions/containers/questions-page.component.ts b/src/app/pages/questions/containers/questions-page.component.ts index eb68da60d..3d1083b3a 100644 --- a/src/app/pages/questions/containers/questions-page.component.ts +++ b/src/app/pages/questions/containers/questions-page.component.ts @@ -157,7 +157,7 @@ export class QuestionsPageComponent implements OnInit { const groupedQuestions = new Map() questions.forEach(q => { const key = - this.MATRIX_INPUT_SET.has(q.field_type) + this.MATRIX_INPUT_SET.has(q.field_type) && q.matrix_group_name ? q.matrix_group_name : q.field_name const entry = groupedQuestions.get(key) ? groupedQuestions.get(key) : [] From 2cfda7cde6de3c0efefaa8a29f07018aa3495d50 Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 6 Feb 2025 13:55:08 +0000 Subject: [PATCH 06/29] Check all questions are answered in matrix --- .../pages/questions/containers/questions-page.component.ts | 2 +- src/app/pages/questions/services/questions.service.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/pages/questions/containers/questions-page.component.ts b/src/app/pages/questions/containers/questions-page.component.ts index 3d1083b3a..e16f1ed22 100644 --- a/src/app/pages/questions/containers/questions-page.component.ts +++ b/src/app/pages/questions/containers/questions-page.component.ts @@ -286,7 +286,7 @@ export class QuestionsPageComponent implements OnInit { const currentQs = this.getCurrentQuestions() if (!currentQs) return this.isRightButtonDisabled = - !this.questionsService.isAnyAnswered(currentQs) && + !this.questionsService.areAllAnswered(currentQs) && !this.questionsService.getIsAnyNextEnabled(currentQs) this.isLeftButtonDisabled = this.questionsService.getIsAnyPreviousEnabled(currentQs) diff --git a/src/app/pages/questions/services/questions.service.ts b/src/app/pages/questions/services/questions.service.ts index 9b5c3d4a2..07d128427 100644 --- a/src/app/pages/questions/services/questions.service.ts +++ b/src/app/pages/questions/services/questions.service.ts @@ -158,8 +158,8 @@ export class QuestionsService { return this.answerService.check(id) } - isAnyAnswered(questions: Question[]) { - return questions.some(q => this.isAnswered(q)) + areAllAnswered(questions: Question[]) { + return questions.every(q => this.isAnswered(q)) } getNextQuestion(groupedQuestions, currentQuestionId): QuestionPosition { From 0ec29c93b1baf943586643fa7438dd78e6d6f6af Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 10 Feb 2025 21:39:32 +0000 Subject: [PATCH 07/29] Allow yesno input to be a matrix question --- src/app/pages/questions/containers/questions-page.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/pages/questions/containers/questions-page.component.ts b/src/app/pages/questions/containers/questions-page.component.ts index e16f1ed22..394c57e25 100644 --- a/src/app/pages/questions/containers/questions-page.component.ts +++ b/src/app/pages/questions/containers/questions-page.component.ts @@ -73,7 +73,8 @@ export class QuestionsPageComponent implements OnInit { MATRIX_INPUT_SET: Set = new Set([ QuestionType.matrix_radio, QuestionType.healthkit, - QuestionType.slider + QuestionType.slider, + QuestionType.yesno ]) backButtonListener: Subscription From d1d1d470054147139dd33fdd725bce7f9c99ce6a Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 10 Feb 2025 21:40:26 +0000 Subject: [PATCH 08/29] Update date input to use dd/mm/yyyy format --- .../text-input/text-input.component.ts | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/src/app/pages/questions/components/question/text-input/text-input.component.ts b/src/app/pages/questions/components/question/text-input/text-input.component.ts index 278a20706..481c13751 100644 --- a/src/app/pages/questions/components/question/text-input/text-input.component.ts +++ b/src/app/pages/questions/components/question/text-input/text-input.component.ts @@ -53,13 +53,13 @@ export class TextInputComponent implements OnInit { ampm: 'AM/PM' } textValue = '' - value = {} + DEFAULT_DATE_FORMAT = 'DD/MM/YYYY' constructor( private localization: LocalizationService, public modalCtrl: ModalController - ) {} + ) { } ngOnInit() { if (this.type.length) { @@ -80,36 +80,33 @@ export class TextInputComponent implements OnInit { } initDates() { - const moment = this.localization.moment(Date.now()) - const locale = moment.localeData() - const formatL = locale.longDateFormat('L') + const momentInstance = this.localization.moment(Date.now()) // Use a local instance this.datePickerObj = { - // User the user's locale format as output format - dateFormat: formatL, + dateFormat: this.DEFAULT_DATE_FORMAT, btnProperties: { - expand: 'block', // Default 'block' - fill: 'outline', // Default 'solid' - size: 'small', // Default 'default' - disabled: '', // Default false - strong: 'true', // Default false - color: 'secondary' // Default '' + expand: 'block', + fill: 'outline', + size: 'small', + disabled: '', + strong: 'true', + color: 'secondary' }, closeOnSelect: 'true' } - const month = locale.monthsShort() + const month = moment.monthsShort() const day = this.addLeadingZero(Array.from(Array(32).keys()).slice(1, 32)) const year = Array.from(Array(31).keys()).map(d => String(d + 2000)) this.datePickerValues = { day, month, year } this.defaultDatePickerValue = { - day: moment.format('DD'), - month: moment.format('MMM'), - year: moment.format('YYYY') + day: momentInstance.format('DD'), + month: momentInstance.format('MMM'), + year: momentInstance.format('YYYY') } this.emitAnswer(this.defaultDatePickerValue) } initTime() { - const moment = this.localization.moment(Date.now()) + const momentInstance = this.localization.moment(Date.now()) const hour = this.addLeadingZero(Array.from(Array(13).keys()).slice(1, 13)) const minute = this.addLeadingZero(Array.from(Array(60).keys())) const second = minute @@ -117,10 +114,10 @@ export class TextInputComponent implements OnInit { this.timePickerValues = { hour, minute, ampm } if (this.showSeconds) this.timePickerValues = { hour, minute, second, ampm } this.defaultTimePickerValue = { - hour: moment.format('hh'), - minute: moment.format('mm'), - second: this.showSeconds ? moment.format('ss') : '00', - ampm: moment.format('A') + hour: momentInstance.format('hh'), + minute: momentInstance.format('mm'), + second: this.showSeconds ? momentInstance.format('ss') : '00', + ampm: momentInstance.format('A') } } @@ -136,7 +133,7 @@ export class TextInputComponent implements OnInit { } datePickerObj: any = {} - selectedDate: string = this.localization.moment(Date.now()).format('L') + selectedDate: string = this.localization.moment(Date.now()).format(this.DEFAULT_DATE_FORMAT) async openDatePicker() { const datePickerModal = await this.modalCtrl.create({ @@ -150,11 +147,9 @@ export class TextInputComponent implements OnInit { await datePickerModal.present() datePickerModal.onDidDismiss().then(data => { - let date = moment(data.data.date) - date = date.isValid() ? date : this.localization.moment(this.selectedDate) - this.selectedDate = date.format('L') + let date = moment(data.data.date, this.DEFAULT_DATE_FORMAT) + this.selectedDate = date.isValid() ? date.format(this.DEFAULT_DATE_FORMAT) : this.selectedDate - // Transfer local date format all to US format to easily parse the data this.defaultDatePickerValue = { year: date.format('YYYY'), month: date.format('M'), From 2944ebb08f98f9ee6c4639ee380705dd3b46e26e Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 10 Feb 2025 21:53:50 +0000 Subject: [PATCH 09/29] Update task service --- src/app/pages/home/services/tasks.service.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/pages/home/services/tasks.service.ts b/src/app/pages/home/services/tasks.service.ts index 526aaa3e9..f3f13e9a8 100644 --- a/src/app/pages/home/services/tasks.service.ts +++ b/src/app/pages/home/services/tasks.service.ts @@ -66,7 +66,7 @@ export class TasksService { .getTasksForDate(new Date(), AssessmentType.SCHEDULED) .then(tasks => tasks.filter( - t => !this.isTaskExpired(t) || this.wasTaskCompletedToday(t) + t => !this.isTaskExpired(t) || this.wasTaskCompletedToday(t) || this.wasTaskValidToday(t) ) ) } @@ -128,6 +128,10 @@ export class TasksService { return task.completed && this.isToday(task.timeCompleted) } + wasTaskValidToday(task) { + return this.isToday(task.timestamp) + } + /** * This function Retrieves the most current next task from a list of tasks. * @param tasks : list of tasks to retrieve the next task from. From 49bce109c78f6b4f6605313dae19c8a808bec507 Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 10 Feb 2025 22:29:31 +0000 Subject: [PATCH 10/29] Update xcode project file --- ios/App/App.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 0878601f7..fc4538dbb 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -9,7 +9,7 @@ /* Begin PBXBuildFile section */ 2DCC4441ECB6AE53462C7302 /* Pods_RADAR_Active_RMT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3FBB3316FEBE50D0F3BCBA4C /* Pods_RADAR_Active_RMT.framework */; }; 2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; }; - 4C4FF1572BEBFDF000B0D335 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4C4FF1562BEBFDF000B0D335 /* GoogleService-Info.plist */; }; + 4CAE23452D50FE9900E2E2EC /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4CAE23442D50FE9900E2E2EC /* GoogleService-Info.plist */; }; 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; 504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; 504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; @@ -22,8 +22,8 @@ 0066ED161F09C0B9FCA0716A /* Pods-RADAR Active RMT.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RADAR Active RMT.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RADAR Active RMT/Pods-RADAR Active RMT.debug.xcconfig"; sourceTree = ""; }; 2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = ""; }; 3FBB3316FEBE50D0F3BCBA4C /* Pods_RADAR_Active_RMT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RADAR_Active_RMT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C4FF1562BEBFDF000B0D335 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../GoogleService-Info.plist"; sourceTree = ""; }; 4C4FF1592BEC015000B0D335 /* RADAR Questionnaire.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RADAR Questionnaire.entitlements"; sourceTree = ""; }; + 4CAE23442D50FE9900E2E2EC /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../../../Downloads/GoogleService-Info.plist"; sourceTree = ""; }; 50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = ""; }; 504EC3041FED79650016851F /* RADAR Active RMT.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "RADAR Active RMT.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -81,10 +81,10 @@ 504EC3061FED79650016851F /* App */ = { isa = PBXGroup; children = ( + 4CAE23442D50FE9900E2E2EC /* GoogleService-Info.plist */, 50379B222058CBB4000EE86E /* capacitor.config.json */, 504EC3071FED79650016851F /* AppDelegate.swift */, 504EC30B1FED79650016851F /* Main.storyboard */, - 4C4FF1562BEBFDF000B0D335 /* GoogleService-Info.plist */, 504EC30E1FED79650016851F /* Assets.xcassets */, 504EC3101FED79650016851F /* LaunchScreen.storyboard */, 504EC3131FED79650016851F /* Info.plist */, @@ -174,7 +174,7 @@ 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */, 504EC30D1FED79650016851F /* Main.storyboard in Resources */, 2FAD9763203C412B000D30F8 /* config.xml in Resources */, - 4C4FF1572BEBFDF000B0D335 /* GoogleService-Info.plist in Resources */, + 4CAE23452D50FE9900E2E2EC /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 7ca0f2a70ece6f12abeb9429fcaf44d59a675a53 Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 13 Feb 2025 01:47:08 +0000 Subject: [PATCH 11/29] Update enrolment page change detection --- .../containers/enrolment-page.component.html | 5 ++ .../containers/enrolment-page.component.scss | 9 +++ .../containers/enrolment-page.component.ts | 73 ++++++++++--------- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/src/app/pages/auth/containers/enrolment-page.component.html b/src/app/pages/auth/containers/enrolment-page.component.html index 754473952..e99ede398 100755 --- a/src/app/pages/auth/containers/enrolment-page.component.html +++ b/src/app/pages/auth/containers/enrolment-page.component.html @@ -22,6 +22,11 @@
+
+
+ {{ outcomeStatus }} +
+
{{ 'BTN_START' | translate }} diff --git a/src/app/pages/auth/containers/enrolment-page.component.scss b/src/app/pages/auth/containers/enrolment-page.component.scss index f39694adc..0c172d9d0 100755 --- a/src/app/pages/auth/containers/enrolment-page.component.scss +++ b/src/app/pages/auth/containers/enrolment-page.component.scss @@ -55,6 +55,15 @@ text-align: center; } +.initial-status { + margin-top: 48px; + padding: auto; + flex: 1 0 100%; + width: 100%; + height: auto; + text-align: center; +} + #outcome { padding: 5px; background-color: var(--cl-danger-40); diff --git a/src/app/pages/auth/containers/enrolment-page.component.ts b/src/app/pages/auth/containers/enrolment-page.component.ts index f010e6161..f472fda97 100755 --- a/src/app/pages/auth/containers/enrolment-page.component.ts +++ b/src/app/pages/auth/containers/enrolment-page.component.ts @@ -1,4 +1,4 @@ -import { Component, ElementRef, ViewChild } from '@angular/core' +import { ChangeDetectorRef, Component, ElementRef, ViewChild } from '@angular/core' import { App } from '@capacitor/app' import { Browser } from '@capacitor/browser' import { Device } from '@capacitor/device' @@ -51,7 +51,8 @@ export class EnrolmentPageComponent { private localization: LocalizationService, private alertService: AlertService, private usage: UsageService, - private logger: LogService + private logger: LogService, + private cdr: ChangeDetectorRef ) { this.init() } @@ -91,18 +92,16 @@ export class EnrolmentPageComponent { // Attempt to slide to the next slide with a delay for stability setTimeout(() => { - this.slides.nativeElement.swiper - .slideTo(nextIndex, 500) - .then(() => { - // Disable sliding after moving to the next slide - this.slides.nativeElement.swiper.allowSlideNext = false - this.slides.nativeElement.swiper.allowSlidePrev = false - }) - .catch(error => { - console.warn('Slide transition failed:', error) - // Retry the slide transition if it fails - this.retrySlideTransition(nextIndex) - }) + try { + this.slides.nativeElement.swiper.slideTo(nextIndex, 500) + // Disable sliding after moving to the next slide + this.slides.nativeElement.swiper.allowSlideNext = false + this.slides.nativeElement.swiper.allowSlidePrev = false + } catch (error) { + console.warn('Slide transition failed:', error) + // Retry the slide transition if it fails + this.retrySlideTransition(nextIndex) + } }, 100) // Adjust delay as necessary } else { console.warn('Swiper instance not ready, retrying...') @@ -120,9 +119,8 @@ export class EnrolmentPageComponent { const slideIndex = this.findSlideIndexById(id) if (slideIndex !== -1) { this.slides.nativeElement.swiper.allowSlideNext = true - this.slides.nativeElement.swiper - .slideTo(slideIndex, 500) - .then(() => (this.slides.nativeElement.swiper.allowSlideNext = false)) + this.slides.nativeElement.swiper.slideTo(slideIndex, 500) + this.slides.nativeElement.swiper.allowSlideNext = false } } @@ -145,16 +143,10 @@ export class EnrolmentPageComponent { this.slides.nativeElement.swiper ) { this.slides.nativeElement.swiper.update() // Ensure swiper is updated - this.slides.nativeElement.swiper - .slideTo(targetIndex, 500) - .then(() => { - // Disable sliding after moving to the target slide - this.slides.nativeElement.swiper.allowSlideNext = false - this.slides.nativeElement.swiper.allowSlidePrev = false - }) - .catch(error => - console.warn('Retry failed for slide transition:', error) - ) + this.slides.nativeElement.swiper.slideTo(targetIndex, 500) + // Disable sliding after moving to the target slide + this.slides.nativeElement.swiper.allowSlideNext = false + this.slides.nativeElement.swiper.allowSlidePrev = false } } @@ -165,6 +157,7 @@ export class EnrolmentPageComponent { authenticate(authObj) { this.loading.next(true) + this.cdr.detectChanges() this.clearStatus() return this.auth .authenticate(authObj) @@ -173,14 +166,18 @@ export class EnrolmentPageComponent { }) .then(() => this.handleAuthenticationSuccess()) .catch(e => this.handleAuthenticationError(e)) - .then(() => this.loading.next(false)) + .then(() => { + this.loading.next(false) + this.cdr.detectChanges() + }) } handleAuthenticationSuccess() { return this.auth.initSubjectInformation().then(() => { this.usage.sendGeneralEvent(EnrolmentEventType.SUCCESS) this.removeSlideById('qr-registration-choice') - return this.removeSlideById('qr-registration') + this.removeSlideById('qr-registration') + return this.goToSlideById('privacy-policy') }) } @@ -191,13 +188,16 @@ export class EnrolmentPageComponent { handleError(e) { this.logger.error('Failed to log in', e) + setTimeout(() => this.logger.error('Failed to log in', e), 10000) this.showStatus() this.outcomeStatus = - e.error && e.error.message - ? e.error.message - : e.status - ? e.statusText + ' (' + e.status + ')' - : e + e.error && e.error.error_description + ? e.error.error_description + : e.error && e.error.message + ? e.error.message + : e.status + ? e.statusText + ' (' + e.status + ')' + : e this.usage.sendGeneralEvent( e.status == 409 ? EnrolmentEventType.ERROR : EnrolmentEventType.FAIL, false, @@ -212,7 +212,10 @@ export class EnrolmentPageComponent { } showStatus() { - setTimeout(() => (this.showOutcomeStatus = true), 500) + setTimeout(() => { + (this.showOutcomeStatus = true) + this.cdr.detectChanges() + }, 500) } navigateToSplash() { From 6fcfde2f4eacbb25a3b69f50ff1c86d245d4f156 Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 13 Feb 2025 16:58:12 +0000 Subject: [PATCH 12/29] Ensure storage service is ready before init --- src/app/core/services/storage/storage.service.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/core/services/storage/storage.service.ts b/src/app/core/services/storage/storage.service.ts index 5df193514..16ef64fc5 100755 --- a/src/app/core/services/storage/storage.service.ts +++ b/src/app/core/services/storage/storage.service.ts @@ -21,14 +21,14 @@ export class StorageService { ) { this.keyUpdates = new Subject() this.platform.ready().then(() => { - this.prepare().then(() => + this.getStorageState().then(() => this.logger.log('Global configuration', this.global) ) }) } - getStorageState() { - return this.storage.ready() + getStorageState(): Promise { + return this.storage.ready().then(() => this.prepare()) } set(key: StorageKeys, value: any): Promise { @@ -107,8 +107,8 @@ export class StorageService { const errMsg = error.message ? error.message : error.status - ? `${error.status} - ${error.statusText}` - : 'error' + ? `${error.status} - ${error.statusText}` + : 'error' return observableThrowError(errMsg) } } From e6f7b6fc197cd082ba4c8905a53a587c79bc9d0e Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 14 Feb 2025 02:27:10 +0000 Subject: [PATCH 13/29] Cleanup --- src/app/pages/auth/containers/enrolment-page.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/pages/auth/containers/enrolment-page.component.ts b/src/app/pages/auth/containers/enrolment-page.component.ts index f472fda97..610c1f6b2 100755 --- a/src/app/pages/auth/containers/enrolment-page.component.ts +++ b/src/app/pages/auth/containers/enrolment-page.component.ts @@ -188,7 +188,6 @@ export class EnrolmentPageComponent { handleError(e) { this.logger.error('Failed to log in', e) - setTimeout(() => this.logger.error('Failed to log in', e), 10000) this.showStatus() this.outcomeStatus = e.error && e.error.error_description From 02b69e01764c619b96bc04fdd6fdc91c689c49ab Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 6 Dec 2024 17:22:49 +0000 Subject: [PATCH 14/29] Decode iat in token if not present in response --- src/app/core/services/token/token.service.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/core/services/token/token.service.ts b/src/app/core/services/token/token.service.ts index 28d193ce5..ac94f7a18 100644 --- a/src/app/core/services/token/token.service.ts +++ b/src/app/core/services/token/token.service.ts @@ -103,11 +103,18 @@ export class TokenService { .post(uri, refreshBody, { headers: headers }) .toPromise() }) - .then(res => this.setTokens(res).then(() => res)) + .then((res: any) => { + if (!res.iat) + res.iat = this.jwtHelper.decodeToken(res.access_token)['iat'] + this.setTokens(res) + return res + }) } refresh(): Promise { + console.log('Refreshing tokenn...') return this.getTokens().then(tokens => { + console.log(tokens) if (!tokens) { throw new Error('No tokens are available to refresh') } From cc0a05e36c5d6c7a51567a1838196bb5f538d316 Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 14 Feb 2025 12:38:01 +0000 Subject: [PATCH 15/29] Cleanup --- src/app/core/services/token/token.service.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/core/services/token/token.service.ts b/src/app/core/services/token/token.service.ts index ac94f7a18..fc98326e0 100644 --- a/src/app/core/services/token/token.service.ts +++ b/src/app/core/services/token/token.service.ts @@ -112,9 +112,7 @@ export class TokenService { } refresh(): Promise { - console.log('Refreshing tokenn...') return this.getTokens().then(tokens => { - console.log(tokens) if (!tokens) { throw new Error('No tokens are available to refresh') } From 065214fd98e76974217bec7cea524727f5453b16 Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 14 Feb 2025 12:48:39 +0000 Subject: [PATCH 16/29] Enrolment page improvements --- src/app/pages/auth/components/qr-form/qr-form.component.ts | 5 +++-- src/app/pages/auth/containers/enrolment-page.component.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/pages/auth/components/qr-form/qr-form.component.ts b/src/app/pages/auth/components/qr-form/qr-form.component.ts index bed8f5db4..32b50adac 100755 --- a/src/app/pages/auth/components/qr-form/qr-form.component.ts +++ b/src/app/pages/auth/components/qr-form/qr-form.component.ts @@ -15,9 +15,10 @@ export class QRFormComponent { @Output() data: EventEmitter = new EventEmitter() - constructor(private usage: UsageService) {} + constructor(private usage: UsageService) { } async scanQRHandler() { + this.loading = true document.querySelector('body').classList.add('scanner-active') // Check camera permission // This is just a simple example, check out the better checks below @@ -29,7 +30,7 @@ export class QRFormComponent { async result => { await listener.remove() this.data.emit(result.barcode.rawValue) - + this.loading = false // Removes the class after the scan (workaround for the camera not closing) document.querySelector('body').classList.remove('scanner-active') } diff --git a/src/app/pages/auth/containers/enrolment-page.component.ts b/src/app/pages/auth/containers/enrolment-page.component.ts index 610c1f6b2..4e278e9e4 100755 --- a/src/app/pages/auth/containers/enrolment-page.component.ts +++ b/src/app/pages/auth/containers/enrolment-page.component.ts @@ -54,6 +54,7 @@ export class EnrolmentPageComponent { private logger: LogService, private cdr: ChangeDetectorRef ) { + this.initializeDeepLinking() this.init() } @@ -64,7 +65,6 @@ export class EnrolmentPageComponent { let lang = this.languagesSelectable.find(a => a.value == tag) this.language = lang ? lang : this.language this.localization.setLanguage(this.language) - this.initializeDeepLinking() } ionViewDidEnter() { From ab7aedd6bf257f8cb38abf66aced2e523d9caab6 Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 14 Feb 2025 14:49:38 +0000 Subject: [PATCH 17/29] Add explicit check for changes in participant attributes --- .../core/services/config/config.service.ts | 24 +++++++++++++++++-- .../core/services/config/protocol.service.ts | 19 +++++---------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/app/core/services/config/config.service.ts b/src/app/core/services/config/config.service.ts index a7a76fc24..9ee5075d0 100755 --- a/src/app/core/services/config/config.service.ts +++ b/src/app/core/services/config/config.service.ts @@ -59,7 +59,8 @@ export class ConfigService { this.hasAppVersionChanged(), this.hasTimezoneChanged(), this.hasNotificationsExpired(), - this.hasNotificationMessagingTypeChanged() + this.hasNotificationMessagingTypeChanged(), + this.hasParticipantAttributesChanged() ]) .then( ([ @@ -67,8 +68,11 @@ export class ConfigService { newAppVersion, newTimezone, newNotifications, - newMessagingType + newMessagingType, + newAttributes ]) => { + if (newAttributes) + return this.fetchConfigState(true) if (newProtocol && newAppVersion && newTimezone) this.subjectConfig .getEnrolmentDate() @@ -96,6 +100,22 @@ export class ConfigService { }) } + hasParticipantAttributesChanged() { + return Promise.all([ + this.subjectConfig.getParticipantAttributes(), + this.subjectConfig.pullSubjectInformation(), + ]) + .then(([attributes, user]) => { + const hasChanged = JSON.stringify(attributes) !== JSON.stringify(user.attributes) + const newAttributes = hasChanged ? user.attributes : attributes + if (hasChanged) { + this.subjectConfig.setParticipantAttributes(newAttributes) + this.analytics.setUserProperties(newAttributes) + } + return hasChanged + }) + } + hasProtocolChanged(force?) { return Promise.all([ this.appConfig.getScheduleHashUrl(), diff --git a/src/app/core/services/config/protocol.service.ts b/src/app/core/services/config/protocol.service.ts index 32e5fcaac..6f23722f2 100644 --- a/src/app/core/services/config/protocol.service.ts +++ b/src/app/core/services/config/protocol.service.ts @@ -36,7 +36,7 @@ export class ProtocolService { private logger: LogService, private analytics: AnalyticsService, private util: Utility - ) {} + ) { } pull(): Promise { return Promise.all([this.getProjectTree(), this.getParticipantAttributes()]) @@ -176,20 +176,13 @@ export class ProtocolService { .then(cfg => Promise.all([ this.config.getParticipantAttributes(), - this.config.pullSubjectInformation(), this.getParticipantAttributeOrder(cfg) ]) ) - .then(([attributes, user, order]) => { - const newAttributes = - JSON.stringify(attributes) == JSON.stringify(user.attributes) - ? attributes - : user.attributes - this.config.setParticipantAttributes(newAttributes) - this.analytics.setUserProperties(newAttributes) + .then(([attributes, order]) => { return sortObject( - newAttributes, - this.formatAttributeOrder(newAttributes, order) + attributes, + this.formatAttributeOrder(attributes, order) ) }) } @@ -201,8 +194,8 @@ export class ProtocolService { const orderWithoutNull = {} Object.keys(attributes).map( k => - (orderWithoutNull[k] = - order[k] != null ? order[k] : this.DEFAULT_ATTRIBUTE_ORDER) + (orderWithoutNull[k] = + order[k] != null ? order[k] : this.DEFAULT_ATTRIBUTE_ORDER) ) return orderWithoutNull } From 0b251a705f0439d384932b076a6d5da191d2c6f5 Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 14 Feb 2025 14:58:35 +0000 Subject: [PATCH 18/29] Remove unnecessary check in participant attributes --- src/app/core/services/config/config.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/services/config/config.service.ts b/src/app/core/services/config/config.service.ts index 9ee5075d0..153c3b5c4 100755 --- a/src/app/core/services/config/config.service.ts +++ b/src/app/core/services/config/config.service.ts @@ -106,8 +106,8 @@ export class ConfigService { this.subjectConfig.pullSubjectInformation(), ]) .then(([attributes, user]) => { + const newAttributes = user.attributes const hasChanged = JSON.stringify(attributes) !== JSON.stringify(user.attributes) - const newAttributes = hasChanged ? user.attributes : attributes if (hasChanged) { this.subjectConfig.setParticipantAttributes(newAttributes) this.analytics.setUserProperties(newAttributes) From e6014657faea2294972eaf4f3c82ad8614fafe0a Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 14 Feb 2025 15:09:53 +0000 Subject: [PATCH 19/29] Bump versions --- android/app/build.gradle | 4 ++-- ios/App/App.xcodeproj/project.pbxproj | 4 ++-- ios/App/App/Info.plist | 2 +- package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index ca580d75a..12498070d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "org.phidatalab.radar_armt" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 592 - versionName "3.3.3-alpha" + versionCode 593 + versionName "3.3.4-alpha" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index fc4538dbb..bf78699f4 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -366,7 +366,7 @@ INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 3.3.3; + MARKETING_VERSION = 3.3.4; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = "org.phidatalab.radar-armt"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -388,7 +388,7 @@ INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 3.3.3; + MARKETING_VERSION = 3.3.4; PRODUCT_BUNDLE_IDENTIFIER = "org.phidatalab.radar-armt"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist index 1510729da..968b3ce9f 100644 --- a/ios/App/App/Info.plist +++ b/ios/App/App/Info.plist @@ -21,7 +21,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 3.3.3 + 3.3.4 CFBundleURLTypes diff --git a/package.json b/package.json index c318a5f07..ce63618f4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "radar-questionnaire", "description": "An application that collects active data for research.", - "version": "3.3.3", + "version": "3.3.4", "author": "RADAR Base", "homepage": "http://www.radar-base.org/", "scripts": { From 8dc2e68acea7eeb17f25f6022fc83ac8088dfc94 Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 17 Feb 2025 17:41:32 +0000 Subject: [PATCH 20/29] Fix matrix radio input --- .../matrix-radio-input/matrix-radio-input.component.html | 3 +-- .../matrix-radio-input/matrix-radio-input.component.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/pages/questions/components/question/matrix-radio-input/matrix-radio-input.component.html b/src/app/pages/questions/components/question/matrix-radio-input/matrix-radio-input.component.html index ebf425530..265868034 100755 --- a/src/app/pages/questions/components/question/matrix-radio-input/matrix-radio-input.component.html +++ b/src/app/pages/questions/components/question/matrix-radio-input/matrix-radio-input.component.html @@ -1,4 +1,4 @@ - + @@ -8,7 +8,6 @@ diff --git a/src/app/pages/questions/components/question/matrix-radio-input/matrix-radio-input.component.ts b/src/app/pages/questions/components/question/matrix-radio-input/matrix-radio-input.component.ts index 9d682c580..3453ed8ef 100755 --- a/src/app/pages/questions/components/question/matrix-radio-input/matrix-radio-input.component.ts +++ b/src/app/pages/questions/components/question/matrix-radio-input/matrix-radio-input.component.ts @@ -48,6 +48,6 @@ export class MatrixRadioInputComponent implements OnInit, OnChanges { } onInputChange(event) { - this.valueChange.emit(event) + this.valueChange.emit(event.detail.value) } } From 5aecd14455fb86276038396b8250a3adb7a4c662 Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 17 Feb 2025 17:41:42 +0000 Subject: [PATCH 21/29] Update ios Info.plist --- ios/App/App/Info.plist | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist index 968b3ce9f..40d56fc99 100644 --- a/ios/App/App/Info.plist +++ b/ios/App/App/Info.plist @@ -83,5 +83,10 @@ UIViewControllerBasedStatusBarAppearance + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + From 265d22b69998730880a0fe7a552afb2896e418f4 Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 18 Feb 2025 14:32:29 +0000 Subject: [PATCH 22/29] Remove unnecessary loading var update --- src/app/pages/auth/components/qr-form/qr-form.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/pages/auth/components/qr-form/qr-form.component.ts b/src/app/pages/auth/components/qr-form/qr-form.component.ts index 32b50adac..b5b836a7a 100755 --- a/src/app/pages/auth/components/qr-form/qr-form.component.ts +++ b/src/app/pages/auth/components/qr-form/qr-form.component.ts @@ -30,7 +30,6 @@ export class QRFormComponent { async result => { await listener.remove() this.data.emit(result.barcode.rawValue) - this.loading = false // Removes the class after the scan (workaround for the camera not closing) document.querySelector('body').classList.remove('scanner-active') } From 60da91e1bfdc0801ed0b8ba63df983b5404d91eb Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 18 Feb 2025 14:34:50 +0000 Subject: [PATCH 23/29] Bump deprecated actions --- .github/workflows/main.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c15e186f8..84cec247a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/checkout@v2 - name: Cache - uses: actions/cache@v2.0.0 + uses: actions/cache@v3.0.0 with: # Cache gradle directories path: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f54cf93d8..32062cfe8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,7 +30,7 @@ jobs: - uses: actions/checkout@v2 - name: Cache - uses: actions/cache@v2.0.0 + uses: actions/cache@v3.0.0 with: # Cache gradle directories path: | From 6be293a00922aea6ab2d4d9bbb33e02e997c1dba Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 18 Feb 2025 14:38:42 +0000 Subject: [PATCH 24/29] Bump deprecated actions --- .github/workflows/main.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 84cec247a..ddae7d656 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/checkout@v2 - name: Cache - uses: actions/cache@v3.0.0 + uses: actions/cache@v4 with: # Cache gradle directories path: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 32062cfe8..1b2e6b112 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,7 +30,7 @@ jobs: - uses: actions/checkout@v2 - name: Cache - uses: actions/cache@v3.0.0 + uses: actions/cache@v4 with: # Cache gradle directories path: | From a2031c92094cec625137c989ebd76c1db9cabb2e Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 18 Feb 2025 15:42:11 +0000 Subject: [PATCH 25/29] Update Info.plist --- ios/App/App/Info.plist | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist index 40d56fc99..968b3ce9f 100644 --- a/ios/App/App/Info.plist +++ b/ios/App/App/Info.plist @@ -83,10 +83,5 @@ UIViewControllerBasedStatusBarAppearance - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - From 70846f76008b99afd54500b46549cf59f56e2652 Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 18 Feb 2025 16:07:03 +0000 Subject: [PATCH 26/29] Add iOS privacy manifest --- ios/App/App/PrivacyInfo.xcprivacy | 114 ++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 ios/App/App/PrivacyInfo.xcprivacy diff --git a/ios/App/App/PrivacyInfo.xcprivacy b/ios/App/App/PrivacyInfo.xcprivacy new file mode 100644 index 000000000..effad41c0 --- /dev/null +++ b/ios/App/App/PrivacyInfo.xcprivacy @@ -0,0 +1,114 @@ + + + + NSPrivacyTracking + + NSPrivacyAccessedAPITypes + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryScreen + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryAnalytics + NSPrivacyAccessedAPITypeReasons + + CA92.2 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryPushNotifications + NSPrivacyAccessedAPITypeReasons + + CA92.3 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryConfiguration + NSPrivacyAccessedAPITypeReasons + + CA92.4 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryCamera + NSPrivacyAccessedAPITypeReasons + + CA92.5 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryDevice + NSPrivacyAccessedAPITypeReasons + + CA92.6 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileSystem + NSPrivacyAccessedAPITypeReasons + + CA92.7 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserInteraction + NSPrivacyAccessedAPITypeReasons + + CA92.8 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileSystem + NSPrivacyAccessedAPITypeReasons + + CA92.9 + + + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryOther + NSPrivacyAccessedAPITypeReasons + + CA92.10 + + + + + + NSPrivacyTrackingDomains + + + From 828f6957c9846e593f2a2e558a08af3859b0acf0 Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 18 Feb 2025 16:45:48 +0000 Subject: [PATCH 27/29] Update privacy manifest: remove duplicates --- ios/App/App/PrivacyInfo.xcprivacy | 90 +++---------------------------- 1 file changed, 7 insertions(+), 83 deletions(-) diff --git a/ios/App/App/PrivacyInfo.xcprivacy b/ios/App/App/PrivacyInfo.xcprivacy index effad41c0..768b2cc14 100644 --- a/ios/App/App/PrivacyInfo.xcprivacy +++ b/ios/App/App/PrivacyInfo.xcprivacy @@ -6,103 +6,27 @@ NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryScreen - NSPrivacyAccessedAPITypeReasons - - CA92.1 - - - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryAnalytics - NSPrivacyAccessedAPITypeReasons - - CA92.2 - - - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryPushNotifications - NSPrivacyAccessedAPITypeReasons - - CA92.3 - - - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryConfiguration - NSPrivacyAccessedAPITypeReasons - - CA92.4 - - - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryCamera - NSPrivacyAccessedAPITypeReasons - - CA92.5 - - - + + - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryDevice - NSPrivacyAccessedAPITypeReasons - - CA92.6 - - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileSystem - NSPrivacyAccessedAPITypeReasons - - CA92.7 - - - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserInteraction - NSPrivacyAccessedAPITypeReasons - - CA92.8 - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileSystem + NSPrivacyAccessedAPICategoryDiskSpace NSPrivacyAccessedAPITypeReasons - CA92.9 + E174.1 - + NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryOther + NSPrivacyAccessedAPICategoryUserDefaults NSPrivacyAccessedAPITypeReasons - CA92.10 + CA92.1 From 06272442c962c99709088639c53f0ca304184a61 Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 18 Feb 2025 23:01:53 +0000 Subject: [PATCH 28/29] Update privacy manifest --- ios/App/{App => }/PrivacyInfo.xcprivacy | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) rename ios/App/{App => }/PrivacyInfo.xcprivacy (57%) diff --git a/ios/App/App/PrivacyInfo.xcprivacy b/ios/App/PrivacyInfo.xcprivacy similarity index 57% rename from ios/App/App/PrivacyInfo.xcprivacy rename to ios/App/PrivacyInfo.xcprivacy index 768b2cc14..ed9f35761 100644 --- a/ios/App/App/PrivacyInfo.xcprivacy +++ b/ios/App/PrivacyInfo.xcprivacy @@ -1,38 +1,29 @@ + NSPrivacyTracking NSPrivacyAccessedAPITypes - - - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryDiskSpace + NSPrivacyAccessedAPICategoryFileTimestamp NSPrivacyAccessedAPITypeReasons - E174.1 + C617.1 - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPICategoryDiskSpace NSPrivacyAccessedAPITypeReasons - CA92.1 + E174.1 - - - NSPrivacyTrackingDomains + NSPrivacyCollectedDataTypes - + \ No newline at end of file From 098d7bdc6b63c3dfa41786faeebabe42fc24296f Mon Sep 17 00:00:00 2001 From: Pauline Date: Wed, 19 Feb 2025 11:25:22 +0000 Subject: [PATCH 29/29] Bump versions and update ios files --- ios/App/App.xcodeproj/project.pbxproj | 17 +++++++++++++++-- ios/App/Podfile.lock | 12 ++++++------ package.json | 10 +++++----- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index bf78699f4..7537a286c 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; }; 50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; }; + F5307CDA0B504AB59720284B /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3EEFC32190254FBBA57F3349 /* PrivacyInfo.xcprivacy */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -37,6 +38,7 @@ A4424794DED16B074B2B4CA9 /* Pods-RADAR Active RMT.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RADAR Active RMT.release.xcconfig"; path = "Pods/Target Support Files/Pods-RADAR Active RMT/Pods-RADAR Active RMT.release.xcconfig"; sourceTree = ""; }; AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = ""; }; FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = ""; }; + 3EEFC32190254FBBA57F3349 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; name = "PrivacyInfo.xcprivacy"; path = "PrivacyInfo.xcprivacy"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -67,6 +69,7 @@ 504EC3051FED79650016851F /* Products */, 7F8756D8B27F46E3366F6CEA /* Pods */, 27E2DDA53C4D2A4D1A88CE4A /* Frameworks */, + 3EEFC32190254FBBA57F3349 /* Resources */, ); sourceTree = ""; }; @@ -107,6 +110,15 @@ name = Pods; sourceTree = ""; }; + 68FC8506249F495CBBFC6201 /* Resources */ = { + isa = PBXGroup; + children = ( + 3EEFC32190254FBBA57F3349 /* PrivacyInfo.xcprivacy */, + ); + name = Resources; + path = undefined; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -135,8 +147,8 @@ 504EC2FC1FED79650016851F /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0920; + LastSwiftUpdateCheck = 920; + LastUpgradeCheck = 920; TargetAttributes = { 504EC3031FED79650016851F = { CreatedOnToolsVersion = 9.2; @@ -175,6 +187,7 @@ 504EC30D1FED79650016851F /* Main.storyboard in Resources */, 2FAD9763203C412B000D30F8 /* config.xml in Resources */, 4CAE23452D50FE9900E2E2EC /* GoogleService-Info.plist in Resources */, + F5307CDA0B504AB59720284B /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock index 070102ca4..149bd5227 100644 --- a/ios/App/Podfile.lock +++ b/ios/App/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - Capacitor (5.7.0): + - Capacitor (5.7.4): - CapacitorCordova - CapacitorApp (5.0.7): - Capacitor @@ -9,7 +9,7 @@ PODS: - Capacitor - CapacitorCommunityKeepAwake (4.0.0): - Capacitor - - CapacitorCordova (5.7.0) + - CapacitorCordova (5.7.4) - CapacitorDevice (5.0.7): - Capacitor - CapacitorDialog (5.0.7): @@ -49,7 +49,7 @@ PODS: - Capacitor - CapacitorVoiceRecorder (6.0.3): - Capacitor - - CordovaPlugins (5.7.0): + - CordovaPlugins (5.7.4): - CapacitorCordova - Firebase/CoreOnly (10.21.0): - FirebaseCore (= 10.21.0) @@ -304,12 +304,12 @@ EXTERNAL SOURCES: :path: "../../node_modules/@perfood/capacitor-healthkit" SPEC CHECKSUMS: - Capacitor: fc155ee2ee45a2093d716f13cf5aa5a865e2d85a + Capacitor: 4fe9adf012caceb4c71ffea2f1f4d005cdcbeea7 CapacitorApp: 17fecd0e6cb23feafac7eb0939417389038b0979 CapacitorAppLauncher: 7b2705481a74cbe322441bd374f56194de59ab1a CapacitorBrowser: a6deae9e5bf87f62b62a753cff7992c5def9e771 CapacitorCommunityKeepAwake: f3442e3e9b666dd0162522fbd053da1fe81ede20 - CapacitorCordova: e825fce1a2e14e4b5730641c7e098dccf74397b7 + CapacitorCordova: a6e87fccc0307dee7aec1560ec9398485f2b0ce7 CapacitorDevice: fc91bdb484dc0e70755e9b621cd557afe642613a CapacitorDialog: ea1beaccb7f825191aa18b72cba8981b881b3b2d CapacitorFilesystem: 9f3e3c7fea2fff12f46dd5b07a2914f2103e4cfc @@ -325,7 +325,7 @@ SPEC CHECKSUMS: CapacitorStatusBar: f390fbb49b82ffb754ea4b3cf71dc8b048baf3e7 CapacitorTextZoom: 69814a62b1d0f23a899cca06ea9838c38de187ff CapacitorVoiceRecorder: d44c1da901cc3918eb9c92c24834d8dc90f071f4 - CordovaPlugins: a707edf6d79ba00bd300f341fe9e1ada032d211f + CordovaPlugins: a17fcaee819862ac7aca195699992de19cf191d4 Firebase: 4453b799f72f625384dc23f412d3be92b0e3b2a0 FirebaseABTesting: 40774deef367dcc7b736b6c26dd59ce0fab42f41 FirebaseAnalytics: d275f288881d4417f780115dd52c05fa9752d530 diff --git a/package.json b/package.json index ce63618f4..ef22902ff 100644 --- a/package.json +++ b/package.json @@ -53,16 +53,16 @@ "@capacitor-firebase/messaging": "^5.0.0", "@capacitor-firebase/remote-config": "^5.0.0", "@capacitor-mlkit/barcode-scanning": "^5.4.0", - "@capacitor/android": "^5.0.3", + "@capacitor/android": "5.7.4", "@capacitor/app": "5.0.7", "@capacitor/app-launcher": "^5.0.7", "@capacitor/browser": "^5.2.0", - "@capacitor/core": "5.7.0", + "@capacitor/core": "5.7.4", "@capacitor/device": "^5.0.2", "@capacitor/dialog": "^5.0.2", "@capacitor/filesystem": "^5.0.2", "@capacitor/haptics": "5.0.7", - "@capacitor/ios": "^5.0.3", + "@capacitor/ios": "5.7.4", "@capacitor/keyboard": "^5.0.8", "@capacitor/local-notifications": "^5.0.2", "@capacitor/splash-screen": "^5.0.2", @@ -117,7 +117,7 @@ "@angular/compiler-cli": "~14.3.0", "@angular/language-service": "~14.3.0", "@angular/platform-server": "~14.3.0", - "@capacitor/cli": "5.7.0", + "@capacitor/cli": "5.7.4", "@ionic/angular-toolkit": "^7.0.0", "@types/jasmine": "~3.6.0", "@types/jasminewd2": "~2.0.3", @@ -174,7 +174,7 @@ "loader-utils": "2.0.4", "nth-check": "2.0.1", "webpack": "5.76.0", - "@capacitor/core": "5.7.0", + "@capacitor/core": "5.7.4", "undici": "6.6.1" }, "ionic_enable_lint": false