diff --git a/CHANGELOG.md b/CHANGELOG.md
index 14f37a94..9270a9be 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
+## [2.9.19] - 2021-03-12
+### Changed
+- Disable Accept/Revoke buttons initially in Pending Family Members popup.
+- Changed permission request buttons to "Continue" [#560](https://github.com/rokwire/safer-illinois-app/issues/560)
+- Apply WWCL.Disclaimers in Safer app [#562](https://github.com/rokwire/safer-illinois-app/issues/562)
+- Maine health history change [#563](https://github.com/rokwire/safer-illinois-app/issues/563)
+
+### Fixed
+- Health rules file. [#567](https://github.com/rokwire/safer-illinois-app/issues/567)
+
## [2.9.18] - 2021-03-09
### Added
- Fire Analytics events in Pending Family Members popup.
diff --git a/assets/health.rules.json b/assets/health.rules.json
index 014d6862..254dc203 100644
--- a/assets/health.rules.json
+++ b/assets/health.rules.json
@@ -14,11 +14,11 @@
},
"statuses": {
- "PCR.xpositive": {
- "health_status": "red",
- "priority": 11,
- "next_step_html": "positive.step.html"
- },
+ "PCR.xpositive": {
+ "health_status": "red",
+ "priority": 11,
+ "next_step_html": "positive.step.html"
+ },
"PCR.positive": {
"condition": "timeout",
"params": {
@@ -42,7 +42,7 @@
"next_step_html": "positive.step.html"
}
},
-
+
"PCR.positive-IP": {
"condition": "timeout",
"params": {
@@ -166,7 +166,7 @@
},
"PCR.negative": "test-monitor",
-
+
"PCR.invalid": {
"condition": "require-test",
"params": {
@@ -257,7 +257,7 @@
}
}
},
-
+
"force-test": {
"condition": "require-test",
"params": {
@@ -296,7 +296,7 @@
"reason": "test.required.reason"
}
},
-
+
"symptoms-match": {
"health_status": "orange",
"priority": 1,
@@ -330,7 +330,7 @@
"reason": "exposure.reason"
}
},
-
+
"quarantine-on": {
"health_status": "orange",
"priority": 10,
@@ -355,7 +355,7 @@
"next_step": "test.resume.step",
"next_step_interval": "UserTestMonitorInterval",
"warning": "test.future.warning"
- },
+ },
"fail": {
"health_status": "orange",
"priority": -1,
@@ -380,7 +380,7 @@
"next_step": "test.resume.step",
"next_step_interval": "UndergraduateTestMonitorInterval",
"warning": "test.future.warning"
- },
+ },
"fail": {
"health_status": "orange",
"priority": -1,
@@ -408,7 +408,7 @@
}
}
}
- },
+ },
"out-of-test-compliance": {
"condition": "require-test",
@@ -430,12 +430,12 @@
}
},
- "release": {
- "health_status": "orange",
- "priority": -1,
- "next_step": "release.step",
- "reason": "release.reason"
- }
+ "release": {
+ "health_status": "orange",
+ "priority": -1,
+ "next_step": "release.step",
+ "reason": "release.reason"
+ }
},
"tests" : {
@@ -495,36 +495,43 @@
{
"result": "POSITIVE",
"category": "PCR.positive",
+ "disclaimer_html": null,
"status": "PCR.positive"
},
{
"result": "POSITIVE-IP",
"category": "PCR.positive",
+ "disclaimer_html": null,
"status": "PCR.positive-IP"
},
{
"result": "POSITIVE-NIP",
"category": "PCR.negative",
+ "disclaimer_html": null,
"status": "PCR.positive-NIP"
},
{
"result": "NEGATIVE",
"category": "PCR.negative",
+ "disclaimer_html": null,
"status": "PCR.negative"
},
{
"result": "INVALID",
"category": "PCR.invalid",
+ "disclaimer_html": null,
"status": "PCR.invalid"
},
{
"result": "INCONCLUSIVE",
"category": "PCR.invalid",
+ "disclaimer_html": null,
"status": "PCR.invalid"
},
{
"result": "REJECTED",
"category": "PCR.invalid",
+ "disclaimer_html": null,
"status": "PCR.invalid"
}
]
@@ -646,7 +653,7 @@
}
]
},
-
+
"symptoms": {
"rules": [
{
@@ -662,7 +669,7 @@
"status": "symptoms-match"
}
],
-
+
"groups": [
{
"id": null,
@@ -765,7 +772,7 @@
}
]
},
-
+
"contact_trace": {
"rules": [
{
@@ -774,7 +781,7 @@
}
]
},
-
+
"actions": {
"rules": [
{
@@ -823,15 +830,15 @@
"test.resume.step": "Resume testing on your assigned days",
"test.future.warning": "You will turn orange/access denied if no negative test by {next_step_date}.",
"test.past.reason": "Your status changed to Orange because you are past due for another test.",
- "test.multiple.step.html": "
You must take two on-campus tests by Jan. 25.
- Separate the tests by three days of quarantine: if the first test is on day one, the second test will be on day five.
- Limit yourself to essential activities until you get the second negative result.
- Your building access will change to Granted (Yellow) with the second negative test result.
See testing schedule and rules.
",
+ "test.multiple.step.html": "You must take two on-campus tests by Jan. 25.
- Separate the tests by three days of quarantine: if the first test is on day one, the second test will be on day five.
- Limit yourself to essential activities until you get the second negative result.
- Your building access will change to Granted (Yellow) with the second negative test result.
See testing schedule and rules.
",
"symptoms.step": "Take a COVID-19 test now",
"symptoms.reason": "Your status changed to Orange because you self-reported symptoms consistent with the virus.",
"exposure.step.html": "You have likely been exposed to a person who is infected with COVID-19.
- You must quarantine yourself immediately.
- Stay home. Do not go to work, school, or public areas.
- Separate yourself from others in your home.
- Contact covidwellness@illinois.edu for guidance.
- Get tested after {next_step_date} to see if you have developed the disease.
- More Info: Quarantine and Isolation
",
"exposure.reason": "Your status changed to Orange because you received an exposure notification.",
"quarantine-on.step": "Stay at home and avoid contacts",
"quarantine-on.reason": "Your status changed to Orange because the Public Health department placed you in Quarantine.",
- "release.step": "Take a SHIELD Saliva Test",
- "release.reason": "Your status changed to Orange because the Public Health department requires you to take a test.",
+ "release.step": "Take a SHIELD Saliva Test",
+ "release.reason": "Your status changed to Orange because the Public Health department requires you to take a test.",
"symptoms.no-symptoms": "No symptoms",
"symptoms.fever": "Fever",
"symptoms.chills": "Chills",
@@ -850,7 +857,12 @@
"symptoms.sore-throat": "Sore Throat",
"symptoms.congestion-or-runny-nose": "Congestion or runny nose",
"symptoms.nausea-or-vomiting": "Nausea or vomiting",
- "symptoms.diarrhea":"Diarrhea"
+ "symptoms.diarrhea":"Diarrhea",
+ "disclaimers.covid-19_pcr.positive.html": "",
+ "disclaimers.covid-19_pcr.negative.html": "",
+ "disclaimers.covid-19_pcr.invalid.html": "",
+ "disclaimers.covid-19_pcr.inconclusive.html": "",
+ "disclaimers.covid-19_pcr.rejected.html": ""
},
"es": {
"default.step": "Realice una prueba de saliva SHIELD cuando regrese al campus.",
@@ -870,15 +882,15 @@
"test.resume.step": "Reanudar las pruebas en los días asignados",
"test.future.warning": "Se volverá naranja / acceso denegado si no hay una prueba negativa antes del {next_step_date}.",
"test.past.reason": "Su estado cambió a Naranja porque está atrasado para otro examen.",
- "test.multiple.step.html": "Debes de tomar dos pruebas en el campus antes del 25 de enero.
- Separe las pruebas con tres días de cuarentena: si la primera prueba es el día uno, la segunda prueba será el día cinco.
- Limítese a las actividades esenciales hasta que obtenga el segundo resultado negativo.
- El acceso al edificio cambiará a Concedido (amarillo) con el segundo resultado negativo de la prueba.
Ver el calendario y las reglas de las pruebas.
",
+ "test.multiple.step.html": "Debes de tomar dos pruebas en el campus antes del 25 de enero.
- Separe las pruebas con tres días de cuarentena: si la primera prueba es el día uno, la segunda prueba será el día cinco.
- Limítese a las actividades esenciales hasta que obtenga el segundo resultado negativo.
- El acceso al edificio cambiará a Concedido (amarillo) con el segundo resultado negativo de la prueba.
Ver el calendario y las reglas de las pruebas.
",
"symptoms.step": "Realice una prueba de COVID-19 ahora",
"symptoms.reason": "Su estado cambió a Naranja porque usted mismo informó de síntomas consistentes con el virus.",
"exposure.step.html": "Es probable que haya estado expuesto a una persona infectada con COVID-19.
- Debe ponerse en cuarentena inmediatamente.
- Quedarse en casa. No vaya al trabajo, la escuela o áreas públicas.
- Sepárate de las demás en tu casa.
- Póngase en contacto con covidwellness@illinois.edu para obtener orientación.
- Hágase la prueba después del {next_step_date} para ver si ha desarrollado la enfermedad.
- Más información: Cuarentena y aislamiento
",
"exposure.reason": "Su estado cambió a Naranja porque recibió una notificación de exposición.",
"quarantine-on.step": "Quédese en casa y evite los contactos",
"quarantine-on.reason": "Su estado cambió a Orange porque el departamento de Salud Pública lo puso en cuarentena.",
- "release.step": "Realice una prueba de saliva SHIELD",
- "release.reason": "Su estado cambió a Orange porque el departamento de Salud Pública requiere que tome una prueba.",
+ "release.step": "Realice una prueba de saliva SHIELD",
+ "release.reason": "Su estado cambió a Orange porque el departamento de Salud Pública requiere que tome una prueba.",
"symptoms.no-symptoms": "Sin síntomas",
"symptoms.fever": "Fiebre",
"symptoms.chills": "Resfriado",
@@ -897,7 +909,12 @@
"symptoms.sore-throat": "Dolor de garganta",
"symptoms.congestion-or-runny-nose": "Congestión o secreción nasal",
"symptoms.nausea-or-vomiting": "Náuseas o vómitos",
- "symptoms.diarrhea": "Diarrea"
+ "symptoms.diarrhea": "Diarrea",
+ "disclaimers.covid-19_pcr.positive.html": "",
+ "disclaimers.covid-19_pcr.negative.html": "",
+ "disclaimers.covid-19_pcr.invalid.html": "",
+ "disclaimers.covid-19_pcr.inconclusive.html": "",
+ "disclaimers.covid-19_pcr.rejected.html": ""
},
"zh": {
"default.step": "返回校園後,請參加SHIELD唾液測試。",
@@ -944,7 +961,12 @@
"symptoms.sore-throat": "咽喉痛",
"symptoms.congestion-or-runny-nose": "充血或流鼻涕",
"symptoms.nausea-or-vomiting": "噁心或嘔吐",
- "symptoms.diarrhea":"腹瀉"
+ "symptoms.diarrhea":"腹瀉",
+ "disclaimers.covid-19_pcr.positive.html": "",
+ "disclaimers.covid-19_pcr.negative.html": "",
+ "disclaimers.covid-19_pcr.invalid.html": "",
+ "disclaimers.covid-19_pcr.inconclusive.html": "",
+ "disclaimers.covid-19_pcr.rejected.html": ""
}
}
}
diff --git a/assets/strings.en.json b/assets/strings.en.json
index 596d5126..788f9a09 100644
--- a/assets/strings.en.json
+++ b/assets/strings.en.json
@@ -60,7 +60,7 @@
"panel.onboarding.location.label.title": "Turn on Location Services",
"panel.onboarding.location.label.title.hint": "Header 1",
"panel.onboarding.location.label.description": "Background location is required for Bluetooth-based exposure notification to work on your phone",
- "panel.onboarding.location.button.allow.title": "Enable Location Services",
+ "panel.onboarding.location.button.allow.title": "Continue",
"panel.onboarding.location.button.allow.hint": "",
"panel.onboarding.location.button.dont_allow.title": "Not right now",
"panel.onboarding.location.button.dont_allow.hint": "Skip sharing location",
@@ -70,7 +70,7 @@
"panel.onboarding.bluetooth.label.title": "Enable Bluetooth",
"panel.onboarding.bluetooth.label.title.hint": "Header 1",
"panel.onboarding.bluetooth.label.description": "Use Bluetooth to alert you to potential exposure to COVID-19.",
- "panel.onboarding.bluetooth.button.allow.title": "Enable Bluetooth",
+ "panel.onboarding.bluetooth.button.allow.title": "Continue",
"panel.onboarding.bluetooth.button.allow.hint": "",
"panel.onboarding.bluetooth.button.dont_allow.title": "Not right now",
"panel.onboarding.bluetooth.button.dont_allow.hint": "Skip enabling Bluetooth",
@@ -81,7 +81,7 @@
"panel.onboarding.notifications.label.title.hint": "Header 1",
"panel.onboarding.notifications.label.description1": "Get notified about COVID-19 info",
"panel.onboarding.notifications.label.description2": "This is required for Exposure Notifications to work in background on your phone",
- "panel.onboarding.notifications.button.allow.title": "Enable Notifications",
+ "panel.onboarding.notifications.button.allow.title": "Continue",
"panel.onboarding.notifications.button.allow.hint": "",
"panel.onboarding.notifications.button.dont_allow.title": "Not right now",
"panel.onboarding.notifications.button.dont_allow.hint": "Skip receiving notifications",
@@ -588,7 +588,7 @@
"panel.health.covid19.history.label.contact_trace.details": "contact trace: ",
"panel.health.covid19.history.label.action.title": "Action Required",
"panel.health.covid19.history.label.action.details": "action: ",
- "panel.health.covid19.history.label.result.title": "Result: ",
+ "panel.health.covid19.history.label.result.title": "Result",
"panel.health.covid19.history.label.location.title": "Test Location",
"panel.health.covid19.history.label.technician_name.title": "Technician Name",
"panel.health.covid19.history.label.technician_id.title": "Technician ID",
diff --git a/assets/strings.es.json b/assets/strings.es.json
index 48418613..03ed2fc4 100644
--- a/assets/strings.es.json
+++ b/assets/strings.es.json
@@ -60,7 +60,7 @@
"panel.onboarding.location.label.title": "Activar los servicios de ubicación",
"panel.onboarding.location.label.hint": "Encabezado 1",
"panel.onboarding.location.label.description": "Se requiere una ubicación en segundo plano para que la notificación de exposición basada en Bluetooth funcione en su teléfono ",
- "panel.onboarding.location.button.allow.title": "Servicio de localización activado",
+ "panel.onboarding.location.button.allow.title": "Comenzar",
"panel.onboarding.location.button.allow.hint": "",
"panel.onboarding.location.button.dont_allow.title": "No en este momento",
"panel.onboarding.location.button.dont_allow.hint": "Omitir ubicación para compartir",
@@ -70,7 +70,7 @@
"panel.onboarding.bluetooth.label.title": "Habilitar Bluetooth",
"panel.onboarding.bluetooth.label.title.hint": "Encabezado 1",
"panel.onboarding.bluetooth.label.description": "Usar Bluetooth para alertarlo sobre la posible exposición al COVID-19.",
- "panel.onboarding.bluetooth.button.allow.title": "Habilitar Bluetooth",
+ "panel.onboarding.bluetooth.button.allow.title": "Comenzar",
"panel.onboarding.bluetooth.button.allow.hint": "",
"panel.onboarding.bluetooth.button.dont_allow.title": "No en este momento",
"panel.onboarding.bluetooth.button.dont_allow.hint": "Omitir habilitar Bluetooth",
@@ -81,7 +81,7 @@
"panel.onboarding.notifications.label.hint": "Encabezado 1",
"panel.onboarding.notifications.label.description1": "Reciba notificaciones sobre la información de COVID-19",
"panel.onboarding.notifications.label.description2": "Esto es necesario para que las notificaciones de exposición funcionen en segundo plano en su teléfono",
- "panel.onboarding.notifications.button.allow.title": "Permitir notificaciones",
+ "panel.onboarding.notifications.button.allow.title": "Comenzar",
"panel.onboarding.notifications.button.allow.hint": "",
"panel.onboarding.notifications.button.dont_allow.title": "No en este momento",
"panel.onboarding.notifications.button.dont_allow.hint": "Omitir recibir notificaciones",
@@ -587,7 +587,7 @@
"panel.health.covid19.history.label.contact_trace.details": "seguimiento de contacto: ",
"panel.health.covid19.history.label.action.title": "Acción requerida",
"panel.health.covid19.history.label.action.details": "acción: ",
- "panel.health.covid19.history.label.result.title": "Resultado: ",
+ "panel.health.covid19.history.label.result.title": "Resultado",
"panel.health.covid19.history.label.location.title": "Lugar de prueba",
"panel.health.covid19.history.label.technician_name.title": "Nombre del técnico",
"panel.health.covid19.history.label.technician_id.title": "ID del técnico",
diff --git a/assets/strings.zh.json b/assets/strings.zh.json
index 9be432ed..614c1bf0 100644
--- a/assets/strings.zh.json
+++ b/assets/strings.zh.json
@@ -60,7 +60,7 @@
"panel.onboarding.location.label.title": "打开位置服务",
"panel.onboarding.location.label.title.hint": "标题1",
"panel.onboarding.location.label.description": "要在手機上使用基於藍牙的曝光通知,需要背景位置",
- "panel.onboarding.location.button.allow.title": "啟用位置服務",
+ "panel.onboarding.location.button.allow.title": "继续",
"panel.onboarding.location.button.allow.hint": "",
"panel.onboarding.location.button.dont_allow.title": "暂时不",
"panel.onboarding.location.button.dont_allow.hint": "跳过共享位置",
@@ -70,7 +70,7 @@
"panel.onboarding.bluetooth.label.title": "启用蓝牙",
"panel.onboarding.bluetooth.label.title.hint": "标题1",
"panel.onboarding.bluetooth.label.description": "使用藍牙提醒您可能接觸到COVID-19.",
- "panel.onboarding.bluetooth.button.allow.title": "启用蓝牙",
+ "panel.onboarding.bluetooth.button.allow.title": "继续",
"panel.onboarding.bluetooth.button.allow.hint": "",
"panel.onboarding.bluetooth.button.dont_allow.title": "不是现在",
"panel.onboarding.bluetooth.button.dont_allow.hint": "跳过启用蓝牙",
@@ -81,7 +81,7 @@
"panel.onboarding.notifications.label.hint": "标题1",
"panel.onboarding.notifications.label.description1": "您將收到COVID-19信息",
"panel.onboarding.notifications.label.description2": "這是曝光通知在手機上後台運行所必需的",
- "panel.onboarding.notifications.button.allow.title": "啟用通知",
+ "panel.onboarding.notifications.button.allow.title": "继续",
"panel.onboarding.notifications.button.allow.hint": "",
"panel.onboarding.notifications.button.dont_allow.title": "暂时不",
"panel.onboarding.notifications.button.dont_allow.hint": "跳过接收通知",
@@ -587,7 +587,7 @@
"panel.health.covid19.history.label.contact_trace.details": "接触者追踪: ",
"panel.health.covid19.history.label.action.title": "需要採取的行動",
"panel.health.covid19.history.label.action.details": "行動:",
- "panel.health.covid19.history.label.result.title": "结果: ",
+ "panel.health.covid19.history.label.result.title": "结果",
"panel.health.covid19.history.label.location.title": "测试位置",
"panel.health.covid19.history.label.technician_name.title": "技术人员姓名",
"panel.health.covid19.history.label.technician_id.title": "技术人员 ID",
diff --git a/lib/model/Health.dart b/lib/model/Health.dart
index cfafab47..91984355 100644
--- a/lib/model/Health.dart
+++ b/lib/model/Health.dart
@@ -401,15 +401,16 @@ class Covid19History {
(this.blob?.provider == event?.provider) &&
(this.blob?.providerId == event?.providerId) &&
(this.blob?.testType == event?.blob?.testType) &&
- (this.blob?.testResult == event?.blob?.testResult);
+ (this.blob?.testResult == event?.blob?.testResult) &&
+ ListEquality().equals(this.blob.extras, event.blob.extras);
}
else if (event.isAction) {
return this.isAction &&
(this.dateUtc == event?.blob?.dateUtc) &&
(this.blob?.actionType == event?.blob?.actionType) &&
- ((this.blob?.actionText == event?.blob?.actionText) ||
- ((this.blob?.actionText is Map) && (event?.blob?.actionText is Map) && DeepCollectionEquality().equals(this.blob?.actionText, event?.blob?.actionText))
- );
+ (DeepCollectionEquality().equals(this.blob?.actionTitle, event?.blob?.actionTitle)) &&
+ (DeepCollectionEquality().equals(this.blob?.actionText, event?.blob?.actionText)) &&
+ ListEquality().equals(this.blob.extras, event.blob.extras);
}
else {
return false;
@@ -539,13 +540,17 @@ class Covid19HistoryBlob {
final String traceTEK;
final String actionType;
+ final dynamic actionTitle;
final dynamic actionText;
+ final List extras;
+
Covid19HistoryBlob({
this.provider, this.providerId, this.location, this.locationId, this.countyId, this.testType, this.testResult,
this.symptoms,
this.traceDuration, this.traceTEK,
- this.actionType, this.actionText,
+ this.actionType, this.actionTitle, this.actionText,
+ this.extras,
});
factory Covid19HistoryBlob.fromJson(Map json) {
@@ -564,7 +569,10 @@ class Covid19HistoryBlob {
traceTEK: json['trace_tek'],
actionType: json['action_type'],
+ actionTitle: json['action_title'],
actionText: json['action_text'],
+
+ extras: Covid19EventExtra.listFromJson(json['extra']),
) : null;
}
@@ -584,7 +592,10 @@ class Covid19HistoryBlob {
'trace_tek': traceTEK,
'action_type': actionType,
+ 'action_title': actionTitle,
'action_text': actionText,
+
+ 'extra': Covid19EventExtra.listToJson(extras),
};
}
@@ -601,7 +612,7 @@ class Covid19HistoryBlob {
}
bool get isAction {
- return (actionType != null);
+ return (actionType != null) || (actionTitle != null) || (actionText != null);
}
Set get symptomsIds {
@@ -655,12 +666,12 @@ class Covid19HistoryBlob {
return null;
}
- String get localeActionText {
- return Localization().localeString(actionText) ?? actionText;
+ String get localeActionTitle {
+ return Localization().localeString(actionTitle) ?? actionTitle;
}
- String get actionDisplayString {
- return localeActionText ?? actionType;
+ String get localeActionText {
+ return Localization().localeString(actionText) ?? actionText;
}
}
@@ -799,9 +810,12 @@ class Covid19EventBlob {
final String testResult;
final String actionType;
+ final dynamic actionTitle;
final dynamic actionText;
- Covid19EventBlob({this.dateUtc, this.testType, this.testResult, this.actionType, this.actionText});
+ final List extras;
+
+ Covid19EventBlob({this.dateUtc, this.testType, this.testResult, this.actionType, this.actionTitle, this.actionText, this.extras});
factory Covid19EventBlob.fromJson(Map json) {
return (json != null) ? Covid19EventBlob(
@@ -809,7 +823,9 @@ class Covid19EventBlob {
testType: AppJson.stringValue(json['TestName']),
testResult: AppJson.stringValue(json['Result']),
actionType: AppJson.stringValue(json['ActionType']),
+ actionTitle: json['ActionTitle'],
actionText: json['ActionText'],
+ extras: Covid19EventExtra.listFromJson(AppJson.listValue(json['Extra'])),
) : null;
}
@@ -819,18 +835,22 @@ class Covid19EventBlob {
'Date': healthDateTimeToString(dateUtc),
'TestName': testType,
'Result': testResult,
+ 'Extra': Covid19EventExtra.listToJson(extras),
};
}
- else if ((actionType != null) || (actionText != null)) {
+ else if ((actionType != null) || (actionTitle != null) || (actionText != null)) {
return {
'Date': healthDateTimeToString(dateUtc),
'ActionType': actionType,
+ 'ActionTitle': actionTitle,
'ActionText': actionText,
+ 'Extra': Covid19EventExtra.listToJson(extras),
};
}
else {
return {
'Date': healthDateTimeToString(dateUtc),
+ 'Extra': Covid19EventExtra.listToJson(extras),
};
}
}
@@ -840,15 +860,100 @@ class Covid19EventBlob {
}
bool get isAction {
- return AppString.isStringNotEmpty(actionType);
+ return AppString.isStringNotEmpty(actionType) || AppString.isStringNotEmpty(defaultLocaleActionTitle) || AppString.isStringNotEmpty(defaultLocaleActionText);
}
+ String get defaultLocaleActionTitle {
+ return Localization().defaultLocaleString(actionTitle) ?? actionTitle;
+ }
+
String get defaultLocaleActionText {
return Localization().defaultLocaleString(actionText) ?? actionText;
}
}
+///////////////////////////////
+// Covid19EventExtra
+
+class Covid19EventExtra {
+ final dynamic displayName;
+ final dynamic displayValue;
+
+ Covid19EventExtra({this.displayName, this.displayValue});
+
+ factory Covid19EventExtra.fromJson(Map json) {
+ return (json != null) ? Covid19EventExtra(
+ displayName: json['display_name'],
+ displayValue: json['display_value'],
+ ) : null;
+ }
+
+ Map toJson() {
+ return {
+ 'display_name': displayName,
+ 'display_value': displayValue,
+ };
+ }
+
+ bool operator ==(o) =>
+ (o is Covid19EventExtra) &&
+ DeepCollectionEquality().equals(o.displayName, displayName) &&
+ DeepCollectionEquality().equals(o.displayValue, displayValue);
+
+ int get hashCode =>
+ (DeepCollectionEquality().hash(displayName) ?? 0) ^
+ (DeepCollectionEquality().hash(displayValue) ?? 0);
+
+ bool get isVisible {
+ return (0 < (localeDisplayName?.length ?? 0));
+ }
+
+ String get localeDisplayName {
+ return Localization().localeString(displayName) ?? displayName;
+ }
+
+ String get localeDisplayValue {
+ return Localization().localeString(displayValue) ?? displayValue;
+ }
+
+ static List listFromJson(List json) {
+ List values;
+ if (json != null) {
+ values = [];
+ for (dynamic entry in json) {
+ Covid19EventExtra value;
+ try { value = Covid19EventExtra.fromJson((entry as Map)?.cast()); }
+ catch(e) { print(e?.toString()); }
+ values.add(value);
+ }
+ }
+ return values;
+ }
+
+ static List listToJson(List values) {
+ List json;
+ if (values != null) {
+ json = [];
+ for (Covid19EventExtra value in values) {
+ json.add(value?.toJson());
+ }
+ }
+ return json;
+ }
+
+ static bool listHasVisible(List values) {
+ if (values != null) {
+ for (Covid19EventExtra value in values) {
+ if (value?.isVisible ?? false) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
+
///////////////////////////////
// Covid19OSFTest
@@ -1431,7 +1536,7 @@ class HealthTestType {
}
///////////////////////////////
-// HealthTestRuleResult
+// HealthTestTypeResult
class HealthTestTypeResult {
String id;
@@ -2017,6 +2122,10 @@ class HealthRulesSet {
return Localization().localeString(entry) ?? entry;
}
+
+ String localeDisclaimerHtml(Covid19HistoryBlob blob) {
+ return localeString(tests?.matchRuleResult(blob: blob, rules: this)?.disclaimerHtml);
+ }
}
///////////////////////////////
@@ -2050,7 +2159,7 @@ class HealthTestRulesSet {
}
HealthTestRuleResult matchRuleResult({ Covid19HistoryBlob blob, HealthRulesSet rules }) {
- if ((_rules != null) && (blob != null)) {
+ if ((_rules != null) && (blob != null) && (blob.testType != null) && (blob.testResult != null)) {
for (HealthTestRule rule in _rules) {
if ((rule?.testType != null) && (rule?.testType?.toLowerCase() == blob?.testType?.toLowerCase()) && (rule.results != null)) {
for (HealthTestRuleResult ruleResult in rule.results) {
@@ -2103,14 +2212,16 @@ class HealthTestRule {
class HealthTestRuleResult {
final String testResult;
final String category;
+ final String disclaimerHtml;
final _HealthRuleStatus status;
- HealthTestRuleResult({this.testResult, this.category, this.status});
+ HealthTestRuleResult({this.testResult, this.category, this.status, this.disclaimerHtml});
factory HealthTestRuleResult.fromJson(Map json) {
return (json != null) ? HealthTestRuleResult(
testResult: json['result'],
category: json['category'],
+ disclaimerHtml: json['disclaimer_html'],
status: _HealthRuleStatus.fromJson(json['status']),
) : null;
}
diff --git a/lib/service/Analytics.dart b/lib/service/Analytics.dart
index af5efdb9..2b90bf78 100644
--- a/lib/service/Analytics.dart
+++ b/lib/service/Analytics.dart
@@ -210,6 +210,7 @@ class Analytics with Service implements NotificationsListener {
static const String LogHealthDurationName = "duration";
static const String LogHealthExposureTimestampName = "exposure_timestamp";
static const String LogHealthActionTypeName = "action_type";
+ static const String LogHealthActionTitleName = "action_title";
static const String LogHealthActionTextName = "action_text";
static const String LogHealthActionTimestampName = "action_timestamp";
static const String LogHealthExposureScore = "exposure_score";
diff --git a/lib/service/Health.dart b/lib/service/Health.dart
index 35b79c05..c46bcfc1 100644
--- a/lib/service/Health.dart
+++ b/lib/service/Health.dart
@@ -927,6 +927,7 @@ class Health with Service implements NotificationsListener {
prevStatus: prevStatus,
attributes: {
Analytics.LogHealthActionTypeName: event.blob?.actionType,
+ Analytics.LogHealthActionTitleName: event.blob?.defaultLocaleActionTitle,
Analytics.LogHealthActionTextName: event.blob?.defaultLocaleActionText,
});
}
@@ -1014,6 +1015,7 @@ class Health with Service implements NotificationsListener {
providerId: event?.providerId,
testType: event?.blob?.testType,
testResult: event?.blob?.testResult,
+ extras: event?.blob?.extras
),
publicKey: _user?.publicKey
));
@@ -1024,7 +1026,9 @@ class Health with Service implements NotificationsListener {
type: Covid19HistoryType.action,
blob: Covid19HistoryBlob(
actionType: event?.blob?.actionType,
+ actionTitle: event?.blob?.actionTitle,
actionText: event?.blob?.actionText,
+ extras: event?.blob?.extras
),
publicKey: _user?.publicKey
));
@@ -1178,7 +1182,9 @@ class Health with Service implements NotificationsListener {
"type": "health.covid19.action",
"health.covid19.action.date": "2020-07-30T21:23:47Z",
"health.covid19.action.type": "require-test-48",
+ "health.covid19.action.title": "Test Required",
"health.covid19.action.text": "You must take a COVID-19 test in next 48 hours",
+ "health.covid19.action.extra": [...],
}*/
if (action != null) {
@@ -1187,15 +1193,19 @@ class Health with Service implements NotificationsListener {
dateUtc = DateTime.now().toUtc();
}
String actionType = AppJson.stringValue(action['health.covid19.action.type']);
+ dynamic actionTitle = AppJson.stringValue(action['health.covid19.action.title']);
dynamic actionText = action['health.covid19.action.text'];
+ List extras = Covid19EventExtra.listFromJson(AppJson.listValue(action['health.covid19.action.extra']));
- if ((actionType != null) || (actionText != null)) {
+ if ((actionType != null) || (actionText != null) || (actionTitle != null)) {
Covid19History history = await _addCovid19History(await Covid19History.encryptedFromBlob(
dateUtc: dateUtc,
type: Covid19HistoryType.action,
blob: Covid19HistoryBlob(
actionType: actionType,
+ actionTitle: actionTitle,
actionText: actionText,
+ extras: extras
),
publicKey: _user?.publicKey
));
@@ -1216,6 +1226,7 @@ class Health with Service implements NotificationsListener {
prevStatus: lastHealthStatus,
attributes: {
Analytics.LogHealthActionTypeName: actionType,
+ Analytics.LogHealthActionTitleName: actionTitle,
Analytics.LogHealthActionTextName: actionText,
Analytics.LogHealthActionTimestampName: dateUtc?.toIso8601String(),
});
diff --git a/lib/ui/health/Covid19HistoryPanel.dart b/lib/ui/health/Covid19HistoryPanel.dart
index 4d6c61ef..c5e5866a 100644
--- a/lib/ui/health/Covid19HistoryPanel.dart
+++ b/lib/ui/health/Covid19HistoryPanel.dart
@@ -17,6 +17,8 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';
+import 'package:flutter_html/flutter_html.dart';
+import 'package:flutter_html/style.dart';
import 'package:illinois/model/Health.dart';
import 'package:illinois/service/Analytics.dart';
import 'package:illinois/service/Organizations.dart';
@@ -30,7 +32,7 @@ import 'package:illinois/service/Styles.dart';
import 'package:illinois/ui/widgets/PopupDialog.dart';
import 'package:illinois/ui/widgets/RoundedButton.dart';
import 'package:illinois/utils/Utils.dart';
-import 'package:sprintf/sprintf.dart';
+import 'package:url_launcher/url_launcher.dart';
class Covid19HistoryPanel extends StatefulWidget {
@override
@@ -468,7 +470,7 @@ class _Covid19HistoryEntryState extends State<_Covid19HistoryEntry> with SingleT
bool _expanded = false;
AnimationController _controller;
- bool _isLoading = false;
+ bool _isLoadingLocation = false;
@override
void initState() {
@@ -483,12 +485,26 @@ class _Covid19HistoryEntryState extends State<_Covid19HistoryEntry> with SingleT
content.add(Container(height: 16,));
content.add(_buildCommonInfo(),);
- if (widget.history?.isTestVerified ?? false) {
- content.addAll([
- _buildMoreButton(),
- _buildResult(),
- _buildAdditionalInfo(),
- ]);
+ if ((widget.history?.isTestVerified ?? false) || Covid19EventExtra.listHasVisible(widget.history?.blob?.extras)) {
+ content.add(_buildMoreButton());
+
+ if (_expanded) {
+
+ Widget testResult = ((widget.history?.isTestVerified ?? false) && (widget.history?.blob?.testResult != null)) ? _buildTestResult() : null;
+ Widget additionalInfo = _buildAdditionalInfo();
+
+ if (testResult != null) {
+ content.add(testResult);
+ }
+
+ if ((testResult != null) && (additionalInfo != null)) {
+ content.add(_buildSplitter());
+ }
+
+ if (additionalInfo != null) {
+ content.add(additionalInfo);
+ }
+ }
}
content.add(Container(height: 16,));
@@ -498,142 +514,164 @@ class _Covid19HistoryEntryState extends State<_Covid19HistoryEntry> with SingleT
child: Column(children: content,),
);
}
+
Widget _buildCommonInfo(){
String title;
- Widget details;
- bool isVerifiedTest = false;
- bool isTest = false;
- String dateFormat = kReleaseMode ? 'MMMM d, yyyy' : 'MMMM d, yyyy HH:mm:ss';
+ Widget detailWidget;
+ String dateFormat = 'MMMM d, yyyy H:mm a';
if (widget.history != null) {
if (widget.history.isTest) {
- isTest = true;
bool isManualTest = widget.history?.isManualTest ?? false;
- isVerifiedTest = widget.history?.isTestVerified ?? false;
title = widget.history?.blob?.testType ?? Localization().getStringEx("app.common.label.other", "Other");
- details = Row(children: [
- Image.asset(isManualTest? "images/u.png": "images/provider.png", excludeFromSemantics: true,),
+ detailWidget = Row(children: [
+ Image.asset(isManualTest? "images/u.png": "images/provider.png", color: Styles().colors.fillColorSecondary, excludeFromSemantics: true,),
Container(width: 11,),
- Expanded(child:
- Semantics(label: Localization().getStringEx("panel.health.covid19.history.label.provider.hint", "provider: "), child:
- Text( isManualTest? Localization().getStringEx("panel.health.covid19.history.label.provider.self_reported", "Self reported"):
- (widget.history?.blob?.provider ?? Localization().getStringEx("app.common.label.other", "Other")),
- style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textSurface,))
- ))
+ Semantics(label: Localization().getStringEx("panel.health.covid19.history.label.provider.hint", "provider: "), child:
+ Text(isManualTest ? Localization().getStringEx("panel.health.covid19.history.label.provider.self_reported", "Self reported"):
+ (widget.history?.blob?.provider ?? Localization().getStringEx("app.common.label.other", "Other")),
+ style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textSurface,))
+ )
],);
}
else if (widget.history.isSymptoms) {
title = Localization().getStringEx("panel.health.covid19.history.label.self_reported.title","Self Reported Symptoms");
- details =
- Row(children: [
- Expanded(child:
- Semantics(label: Localization().getStringEx("panel.health.covid19.history.label.self_reported.symptoms","symptoms: "), child:
- Text(widget.history.blob?.symptomsDisplayString(rules: widget.rules) ?? '', style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textBackground,))
- )
- )
- ],);
+ detailWidget = Semantics(label: Localization().getStringEx("panel.health.covid19.history.label.self_reported.symptoms","symptoms: "), child:
+ Text(widget.history.blob?.symptomsDisplayString(rules: widget.rules) ?? '', style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textBackground,))
+ );
}
else if (widget.history.isContactTrace) {
+ dateFormat = 'MMMM d, yyyy';
title = Localization().getStringEx("panel.health.covid19.history.label.contact_trace.title","Contact Trace");
- details =
- Row(children: [
- Expanded(child:
- Semantics(label: Localization().getStringEx("panel.health.covid19.history.label.contact_trace.details","contact trace: "), child:
- Text(widget.history.blob?.traceDurationDisplayString ?? '', style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textBackground,))
- ))]);
+ detailWidget = Semantics(label: Localization().getStringEx("panel.health.covid19.history.label.contact_trace.details","contact trace: "), child:
+ Text(widget.history.blob?.traceDurationDisplayString ?? '', style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textBackground,))
+ );
}
else if (widget.history.isAction) {
- title = Localization().getStringEx("panel.health.covid19.history.label.action.title","Action Required");
- details = Semantics(label: Localization().getStringEx("panel.health.covid19.history.label.action.details","action: "), child:
- Text(widget.history.blob?.actionDisplayString ?? '', style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textBackground,))
- );
+ title = widget.history.blob?.localeActionTitle ?? Localization().getStringEx("panel.health.covid19.history.label.action.title", "Action Required");
+ detailWidget = Semantics(label: Localization().getStringEx("panel.health.covid19.history.label.action.details","action: "), child:
+ Text(widget.history.blob?.localeActionText ?? '', style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textBackground,))
+ );
}
}
- return
- Semantics(
- sortKey: OrdinalSortKey(1),
- container: true,
- child: Container(color: Styles().colors.white,
- padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(AppDateTime.formatDateTime(widget.history?.dateUtc?.toLocal(), format:dateFormat, locale: Localization().currentLocale?.languageCode) ?? '',style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textSurface,)),
- Container(height: 4,),
- Row(children: [
- Expanded(child:
- Text(title ?? '', style:TextStyle(fontSize: 20, fontFamily: Styles().fontFamilies.extraBold, color: Styles().colors.fillColorPrimary,)),
- )]),
- Container(height: 9,),
- details ?? Container(),
- !isTest? Container():
- Container(height: 9,),
- !isTest? Container():
- Row(children: [
- Image.asset(isVerifiedTest? "images/certified-copy.png": "images/pending.png"),
- Container(width: 10,),
- Expanded(child: isVerifiedTest?
- Text(Localization().getStringEx("panel.health.covid19.history.label.verified","Verified"),style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textSurface,)):
- Text(Localization().getStringEx("panel.health.covid19.history.label.verification_pending","Verification Pending"),style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textSurface,)),
- )
- ],),
- ],
- )
- ));
+ List contentList = [
+ Padding(padding: EdgeInsets.only(bottom: 4), child: Text(AppDateTime.formatDateTime(widget.history?.dateUtc?.toLocal(), format: dateFormat, locale: Localization().currentLocale?.languageCode) ?? '',style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textSurface,)),),
+ Padding(padding: EdgeInsets.only(), child: Text(title ?? '', style:TextStyle(fontSize: 20, fontFamily: Styles().fontFamilies.extraBold, color: Styles().colors.fillColorPrimary,))),
+ ];
+
+ if (detailWidget != null) {
+ contentList.add(Padding(padding: EdgeInsets.only(top: 9), child: detailWidget));
+ }
+
+ if (widget.history?.isTest ?? false) {
+ bool isVerifiedTest = widget.history?.isTestVerified ?? false;
+ contentList.add(
+ Padding(padding: EdgeInsets.only(top: 9), child:
+ Row(children: [
+ Image.asset(isVerifiedTest ? "images/certified-copy.png": "images/pending.png", excludeFromSemantics: true,),
+ Container(width: 10,),
+ Expanded(child: isVerifiedTest ?
+ Text(Localization().getStringEx("panel.health.covid19.history.label.verified", "Verified"), style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textSurface,)):
+ Text(Localization().getStringEx("panel.health.covid19.history.label.verification_pending", "Verification Pending"), style:TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.regular, color: Styles().colors.textSurface,)),
+ )
+ ],),
+ ),
+ );
+ }
+
+ return Semantics(sortKey: OrdinalSortKey(1), container: true, child:
+ Container(color: Styles().colors.white, padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), child:
+ Row(children: [
+ Expanded(child:
+ Column(crossAxisAlignment: CrossAxisAlignment.start, children: contentList,)
+ ),
+ ]),
+ ),
+ );
}
- Widget _buildResult(){
- return !_expanded || widget.history?.blob?.testResult==null? Container():
- Semantics(
- sortKey: OrdinalSortKey(3),
- container: true,
- child:
- Container(color: Styles().colors.white,
- padding: EdgeInsets.symmetric(horizontal: 16),
- child:
- Column(children: [
- Container(height: 14,),
- Row(
- children: [
- Image.asset("images/selected-black.png",excludeFromSemantics: true,),
- Container(width: 6,),
- Text(Localization().getStringEx("panel.health.covid19.history.label.result.title","Result: "),
- style: TextStyle(color: Styles().colors.textBackground,fontSize: 14, fontFamily: Styles().fontFamilies.bold,),
- ),
- Expanded(child:Container()),
- Text(widget.history.blob?.testResult,
- style: TextStyle(color: Styles().colors.textBackground,fontSize: 14, fontFamily: Styles().fontFamilies.regular,),
- )
- ],
- ),
- Container(height: 14,),
- Container(height:1, color: Styles().colors.surfaceAccent,)
- ],)
- )
+ Widget _buildTestResult() {
+ bool hasDisclaimer = AppString.isStringNotEmpty(widget.rules?.localeDisclaimerHtml(widget.history?.blob));
+ Widget contentData = Row(children: [
+ Padding(padding: EdgeInsets.only(left: 16), child:
+ Image.asset("images/selected-black.png",excludeFromSemantics: true,),
+ ),
+ Container(width: 6,),
+ Text(Localization().getStringEx("panel.health.covid19.history.label.result.title", "Result"),
+ style: TextStyle(color: Styles().colors.textBackground,fontSize: 14, fontFamily: Styles().fontFamilies.bold,),
+ ),
+ Expanded(child:Container(height: 48)),
+ Padding(padding: EdgeInsets.only(right: hasDisclaimer ? 36: 16), child:
+ Text(widget.history.blob?.testResult,
+ style: TextStyle(color: Styles().colors.textBackground,fontSize: 14, fontFamily: Styles().fontFamilies.regular,),
+ ),
+ ),
+ ]);
+
+ Widget contentLine = hasDisclaimer ?
+ Stack(children: [
+ contentData,
+ Container(alignment: Alignment.topRight, child:
+ InkWell(onTap: _onTapDisclaimer, child:
+ Container(/*color: Color(0x20000000),*/ width: 48, height: 48, alignment: Alignment.center, child:
+ Image.asset('images/icon-info-orange.png')
+ ),
+ ),
+ ),
+ ],) :
+ contentData;
+
+ return Semantics(sortKey: OrdinalSortKey(3), container: true, child:
+ Container(color: Styles().colors.white, child:
+ Column(children: [
+ contentLine,
+ ],)
+ ),
);
}
- Widget _buildAdditionalInfo(){
- return
- !_expanded ? Container():
- Semantics(
- sortKey: OrdinalSortKey(4),
- container: true,
- child:
- Container(color: Styles().colors.white,
- padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
- child: Column(
- children: [
- (_isLoading == true) ? Center(child: SizedBox(height: 24, width: 24, child:CircularProgressIndicator(strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Styles().colors.fillColorSecondary),))):
- widget.history?.blob?.location==null? Container():
- _buildDetail(Localization().getStringEx("panel.health.covid19.history.label.location.title","Test Location"), widget.history?.blob?.location, onTapData: (widget.history?.blob?.location != null) ? (){ _onTapLocation(); } : null, onTapHint: "Double tap to show location"),
+ Widget _buildSplitter() {
+ return Container(color: Styles().colors.white, child:
+ Column(children: [
+ Padding(padding: EdgeInsets.symmetric(horizontal: 16), child:
+ Container(height:1, color: Styles().colors.surfaceAccent,)
+ ),
+ ],)
+ );
+ }
- //_buildDetail(Localization().getStringEx("panel.health.covid19.history.label.technician_name.title","Technician Name"), widget.history?.technician),
- //_buildDetail(Localization().getStringEx("panel.health.covid19.history.label.technician_id.title","Technician ID"), widget.history?.technicianId),
- ],
+ Widget _buildAdditionalInfo() {
+ List content = [];
+ if (_isLoadingLocation == true) {
+ content.add(Center(child: SizedBox(height: 24, width: 24, child: CircularProgressIndicator(strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Styles().colors.fillColorSecondary),))));
+ }
+ else if (widget.history?.blob?.location != null) {
+ content.add(_buildDetail(
+ Localization().getStringEx("panel.health.covid19.history.label.location.title", "Test Location"),
+ widget.history?.blob?.location,
+ onTapData: _onTapLocation,
+ onTapHint: "Double tap to show location"));
+ }
+
+ if (AppCollection.isCollectionNotEmpty(widget.history?.blob?.extras)) {
+ for (Covid19EventExtra extra in widget.history?.blob?.extras) {
+ if (extra.isVisible) {
+ content.add(_buildDetail(
+ extra.localeDisplayName,
+ extra.localeDisplayValue ?? '-'));
+ }
+ }
+ }
+
+ //content.add(_buildDetail(Localization().getStringEx("panel.health.covid19.history.label.technician_name.title","Technician Name"), widget.history?.technician)),
+ //content.add(_buildDetail(Localization().getStringEx("panel.health.covid19.history.label.technician_id.title","Technician ID"), widget.history?.technicianId)),
+
+ return (0 < content.length) ? Semantics(sortKey: OrdinalSortKey(4), container: true, child:
+ Container(color: Styles().colors.white, padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6), child:
+ Column(children: content,
)
)
- );
+ ) : null;
}
Widget _buildMoreButton(){
@@ -668,7 +706,7 @@ class _Covid19HistoryEntryState extends State<_Covid19HistoryEntry> with SingleT
Container(width: 4,),
RotationTransition(
turns: _iconTurns,
- child: Image.asset("images/icon-down-orange.png")),
+ child: Image.asset("images/icon-down-orange.png", color: Styles().colors.fillColorSecondary, excludeFromSemantics: true,)),
],)
)));
@@ -693,7 +731,7 @@ class _Covid19HistoryEntryState extends State<_Covid19HistoryEntry> with SingleT
Row(crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(padding: EdgeInsets.symmetric(vertical: 4), child:
- Text(sprintf("%s: ",[title],),
+ Text(title,
style: TextStyle(fontSize: 14, fontFamily: Styles().fontFamilies.bold, color: Styles().colors.textBackground),
),
),
@@ -707,9 +745,9 @@ class _Covid19HistoryEntryState extends State<_Covid19HistoryEntry> with SingleT
Analytics().logSelect(target: widget.history?.blob?.locationId);
String locationId = widget.history?.blob?.locationId;
if(locationId!=null){
- setState(() => _isLoading = true);
+ setState(() => _isLoadingLocation = true);
Health().loadHealthServiceLocation(locationId: locationId).then((location){
- setState(() => _isLoading = false);
+ setState(() => _isLoadingLocation = false);
if(location!=null){
NativeCommunicator().launchMap(
target: {
@@ -734,4 +772,33 @@ class _Covid19HistoryEntryState extends State<_Covid19HistoryEntry> with SingleT
AppToast.show("Missing location id");
}
}
+
+ void _onTapDisclaimer() {
+ Analytics.instance.logSelect(target: "Disclaimer");
+ String disclaimerHtml = widget.rules?.localeDisclaimerHtml(widget.history?.blob);
+ if (AppString.isStringNotEmpty(disclaimerHtml)) {
+ showDialog(context: context, builder: (context) => _buildDisclaimerDialog(context, disclaimerHtml));
+ }
+ }
+
+ Widget _buildDisclaimerDialog(BuildContext context, String htmlContent) {
+ Style htmlStyle = Style(color: Styles().colors.fillColorPrimary, fontFamily: Styles().fontFamilies.bold, fontSize: FontSize(16));
+ return ClipRRect(borderRadius: BorderRadius.all(Radius.circular(8)), child:
+ Dialog(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8),), child:
+ Stack(children: [
+ Padding(padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), child:
+ SingleChildScrollView(child:
+ Html(data: htmlContent, style: { 'body': htmlStyle }, onLinkTap: (url) => launch(url)),
+ ),
+ ),
+ Container(alignment: Alignment.topRight, height: 42, child: InkWell(onTap: _onCloseDisclaimerDialog, child: Container(width: 42, height: 42, alignment: Alignment.center, child: Image.asset('images/close-orange.png')))),
+ ],),
+ ),
+ );
+ }
+
+ void _onCloseDisclaimerDialog() {
+ Analytics.instance.logSelect(target: "Close Disclaimer");
+ Navigator.of(context).pop();
+ }
}
diff --git a/lib/ui/health/Covid19InfoCenterPanel.dart b/lib/ui/health/Covid19InfoCenterPanel.dart
index ec5c99c0..c14bd631 100644
--- a/lib/ui/health/Covid19InfoCenterPanel.dart
+++ b/lib/ui/health/Covid19InfoCenterPanel.dart
@@ -332,8 +332,8 @@ class _Covid19InfoCenterPanelState extends State impleme
info = isManualTest? Localization().getStringEx("panel.covid19home.label.provider.self_reported", "Self reported"):
(blob?.provider ?? Localization().getStringEx("app.common.label.other", "Other"));
} else if(blob.isAction){
- historyTitle = Localization().getStringEx("panel.covid19home.label.action_required.title", "Action Required");
- info = blob.actionDisplayString?? "";
+ historyTitle = blob.localeActionTitle ?? Localization().getStringEx("panel.covid19home.label.action_required.title", "Action Required");
+ info = blob.localeActionText ?? "";
} else if(blob.isContactTrace){
historyTitle = Localization().getStringEx("panel.covid19home.label.contact_trace.title", "Contact Trace");
info = blob.traceDurationDisplayString;
diff --git a/lib/ui/health/Covid19StatusUpdatePanel.dart b/lib/ui/health/Covid19StatusUpdatePanel.dart
index 3e137ec6..708c920e 100644
--- a/lib/ui/health/Covid19StatusUpdatePanel.dart
+++ b/lib/ui/health/Covid19StatusUpdatePanel.dart
@@ -258,9 +258,9 @@ class _Covid19StatusUpdatePanelState extends State {
children: [
Image.asset("images/icon-selected.png",excludeFromSemantics: true,),
Container(width: 7,),
- Text(Localization().getStringEx("panel.health.status_update.label.reason.action.detail", "Action Required: "), style: TextStyle(color: Colors.white, fontSize: 12, fontFamily: Styles().fontFamilies.bold)),
+ Text(reasonHistory.localeActionTitle ?? Localization().getStringEx("panel.health.status_update.label.reason.action.detail", "Action Required: "), style: TextStyle(color: Colors.white, fontSize: 12, fontFamily: Styles().fontFamilies.bold)),
],),
- Text(reasonHistory.actionDisplayString ?? "", style: TextStyle(color: Colors.white, fontSize: 12, fontFamily: Styles().fontFamilies.regular)),
+ Text(reasonHistory.localeActionText ?? "", style: TextStyle(color: Colors.white, fontSize: 12, fontFamily: Styles().fontFamilies.regular)),
],);
diff --git a/lib/ui/health/debug/Covid19DebugCreateEventPanel.dart b/lib/ui/health/debug/Covid19DebugCreateEventPanel.dart
index e4026ff4..8983c0b9 100644
--- a/lib/ui/health/debug/Covid19DebugCreateEventPanel.dart
+++ b/lib/ui/health/debug/Covid19DebugCreateEventPanel.dart
@@ -15,6 +15,7 @@
*/
import 'dart:collection';
+import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@@ -32,6 +33,7 @@ import 'package:illinois/ui/widgets/RoundedButton.dart';
import 'package:illinois/utils/Crypt.dart';
import 'package:illinois/utils/Utils.dart';
import 'package:illinois/service/Styles.dart';
+import 'package:intl/intl.dart';
import "package:pointycastle/export.dart" as PointyCastle;
class Covid19DebugCreateEventPanel extends StatefulWidget {
@@ -425,43 +427,101 @@ class _Covid19DebugCreateEventPanelState extends State[
ScalableRoundedButton(
- label: Localization().getStringEx('panel.onboarding.notifications.button.allow.title', 'Enable Notifications'),
+ label: Localization().getStringEx('panel.onboarding.notifications.button.allow.title', 'Continue'),
hint: Localization().getStringEx('panel.onboarding.notifications.button.allow.hint', ''),
borderColor: Styles().colors.fillColorSecondary,
backgroundColor: Styles().colors.background,
diff --git a/lib/ui/settings/SettingsPendingFamilyMemberPanel.dart b/lib/ui/settings/SettingsPendingFamilyMemberPanel.dart
index c8d44b4a..fad2ced9 100644
--- a/lib/ui/settings/SettingsPendingFamilyMemberPanel.dart
+++ b/lib/ui/settings/SettingsPendingFamilyMemberPanel.dart
@@ -24,7 +24,7 @@ class SettingsPendingFamilyMemberPanel extends StatefulWidget {
class _SettingsPendingFamilyMemberPanelState extends State {
bool _hasProgress = false;
- bool _buttonsEnabled = true;
+ bool _buttonsEnabled = false;
bool _termsAccepted = false;
String _errorMessage;
HealthRulesSet _rules;
diff --git a/lib/utils/Utils.dart b/lib/utils/Utils.dart
index 43107bea..74da4382 100644
--- a/lib/utils/Utils.dart
+++ b/lib/utils/Utils.dart
@@ -288,6 +288,22 @@ class AppJson {
return null;
}
}
+
+ static List listValue (dynamic value) {
+ if (value is List) {
+ try { return value.cast(); }
+ catch(e) { print(e?.toString()); }
+ }
+ return null;
+ }
+
+ static Map mapValue (dynamic value) {
+ if (value is Map) {
+ try { return value.cast(); }
+ catch(e) { print(e?.toString()); }
+ }
+ return null;
+ }
}
class AppFile {
diff --git a/pubspec.yaml b/pubspec.yaml
index d338f866..b966855d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -11,7 +11,7 @@ description: Illinois client application.
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
-version: 2.9.18+918
+version: 2.9.19+919
environment:
sdk: ">=2.2.0 <3.0.0"
diff --git a/scripts/build.sh b/scripts/build.sh
index 130532e8..7af06938 100755
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -83,6 +83,8 @@ if [ "$PLATFORM" = "all" ] || [ "$PLATFORM" = "android" ]; then
cp $APK_BUILD_PATH $APK_OUT_PATH
echo "Copy to $APK_OUT_PATH"
fi
+
+ aws s3 cp $APK_OUT_PATH s3://rokwire-ios-beta/Installs/
fi
if [ "$PLATFORM" = "all" ] || [ "$PLATFORM" = "ios" ]; then
@@ -104,7 +106,11 @@ if [ "$PLATFORM" = "all" ] || [ "$PLATFORM" = "ios" ]; then
xcodebuild -exportArchive -archivePath ../build/_output/tmp/Runner.xcarchive -exportPath ../build/_output/tmp/ -exportOptionsPlist ../build/_output/$BRAND-$VERSION-$ENV.plist
cd ..
cp ./build/_output/tmp/Runner.ipa ./build/_output/$BRAND-$VERSION-$ENV.ipa
- rm -rf ./build/_output/tmp/
+ #rm -rf ./build/_output/tmp/
+
+ aws s3 cp $QR_BUILD_PATH s3://rokwire-ios-beta/Installs/
+ aws s3 cp $PLIST_BUILD_PATH s3://rokwire-ios-beta/Installs/
+ aws s3 cp ./build/_output/$BRAND-$VERSION-$ENV.ipa s3://rokwire-ios-beta/Installs/
fi