From 4b8f981cd579a94de8e08eff1d3d93b138fde57d Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 10 Jul 2024 13:27:25 +0330 Subject: [PATCH 1/5] feat: blueberry bg notifications switches --- .../notifications/notificaitons_page.dart | 235 ++++++++++++++++-- 1 file changed, 208 insertions(+), 27 deletions(-) diff --git a/lib/features/settings/subfeatures/notifications/notificaitons_page.dart b/lib/features/settings/subfeatures/notifications/notificaitons_page.dart index 4b219279..0b010ee1 100644 --- a/lib/features/settings/subfeatures/notifications/notificaitons_page.dart +++ b/lib/features/settings/subfeatures/notifications/notificaitons_page.dart @@ -289,33 +289,214 @@ class NotificationsPage extends HookConsumerWidget { notificationsState .periodicalCallData!.expectedEpochOccurrenceEnabled, ), - // const SizedBox(height: Sizes.spaceXLarge), - // MXCSwitchRowItem( - // title: translate('activity_reminder'), - // value: notificationsState - // .periodicalCallData!.activityReminderEnabled, - // onChanged: notificationsPresenter.changeActivityReminderEnabled, - // enabled: isSettingsChangeEnabled, - // ), - // MXCSwitchRowItem( - // title: translate('sleep_insight'), - // value: - // notificationsState.periodicalCallData!.sleepInsightEnabled, - // onChanged: notificationsPresenter.changeSleepInsightEnabled, - // enabled: isSettingsChangeEnabled, - // ), - // MXCSwitchRowItem( - // title: translate('heart_alert'), - // value: notificationsState.periodicalCallData!.heartAlertEnabled, - // onChanged: notificationsPresenter.changeHeartAlertEnabled, - // enabled: isSettingsChangeEnabled, - // ), - // MXCSwitchRowItem( - // title: translate('low_battery'), - // value: notificationsState.periodicalCallData!.lowBatteryEnabled, - // onChanged: notificationsPresenter.changeLowBatteryEnabled, - // enabled: isSettingsChangeEnabled, - // ), + const SizedBox(height: Sizes.spaceXLarge), + MXCSwitchRowItem( + title: translate('activity_reminder'), + value: notificationsState + .periodicalCallData!.activityReminderEnabled, + onChanged: notificationsPresenter.changeActivityReminderEnabled, + enabled: isSettingsChangeEnabled, + textTrailingWidget: MXCInformationButton( + texts: [ + TextSpan( + text: + FlutterI18n.translate(context, 'experiencing_issues'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate(context, + 'blueberry_background_notifications_requirements_title'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + TextSpan( + text: FlutterI18n.translate(context, + 'blueberry_background_notifications_requirements_text'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + ], + ), + titleStyle: FontTheme.of(context).h6(), + ), + const SizedBox(height: Sizes.spaceXLarge), + MXCSwitchRowItem( + title: translate('sleep_insight'), + value: + notificationsState.periodicalCallData!.sleepInsightEnabled, + onChanged: notificationsPresenter.changeSleepInsightEnabled, + enabled: isSettingsChangeEnabled, + textTrailingWidget: MXCInformationButton( + texts: [ + TextSpan( + text: + FlutterI18n.translate(context, 'experiencing_issues'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_1_title'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_1_text'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_2_title'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_2_text'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'need_further_assistant'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + ], + ), + titleStyle: FontTheme.of(context).h6(), + ), + const SizedBox(height: Sizes.spaceXLarge), + MXCSwitchRowItem( + title: translate('heart_alert'), + value: notificationsState.periodicalCallData!.heartAlertEnabled, + onChanged: notificationsPresenter.changeHeartAlertEnabled, + enabled: isSettingsChangeEnabled, + textTrailingWidget: MXCInformationButton( + texts: [ + TextSpan( + text: + FlutterI18n.translate(context, 'experiencing_issues'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_1_title'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_1_text'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_2_title'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_2_text'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'need_further_assistant'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + ], + ), + titleStyle: FontTheme.of(context).h6(), + ), + const SizedBox(height: Sizes.spaceXLarge), + MXCSwitchRowItem( + title: translate('low_battery'), + value: notificationsState.periodicalCallData!.lowBatteryEnabled, + onChanged: notificationsPresenter.changeLowBatteryEnabled, + enabled: isSettingsChangeEnabled, + textTrailingWidget: MXCInformationButton( + texts: [ + TextSpan( + text: + FlutterI18n.translate(context, 'experiencing_issues'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_1_title'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_1_text'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_2_title'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + TextSpan( + text: FlutterI18n.translate( + context, 'background_service_solution_2_text'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'need_further_assistant'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + ], + ), + titleStyle: FontTheme.of(context).h6(), + ), + const SizedBox(height: Sizes.spaceXLarge), // const SizedBox(height: Sizes.spaceNormal), // MXCSwitchRowItem( // title: translate('daily_earnings'), From b6789a6c31ec16f2e13abf9f4bd100366ad001e4 Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 10 Jul 2024 13:30:59 +0330 Subject: [PATCH 2/5] feat: Add log collector and notif title --- ...rry_ring_background_notifications_use_case.dart | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart index 5cae8bcb..683dec96 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_background_notifications_use_case.dart @@ -5,6 +5,8 @@ import 'package:mxc_logic/mxc_logic.dart'; import 'package:datadashwallet/core/core.dart'; import 'package:datadashwallet/features/settings/subfeatures/chain_configuration/domain/chain_configuration_use_case.dart'; +import '../../../../../../app/logger.dart'; + class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { BlueberryRingBackgroundNotificationsUseCase( this._repository, @@ -25,6 +27,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkActivityReminder() async { final data = await _blueberryRingUseCase.readSteps(); + collectLog('checkActivityReminder:data ${data.map((e) => e.toJson()).toList()}'); // Get spteps data from cache and compare // If steps is below a certain number then show a // Below 5000 @@ -39,7 +42,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { if (isToday && latestData.step < 5000) { AXSNotification().showNotification( - cTranslate('blueberry_ring_inactive_alert_title'), + cTranslate('activity_reminder'), cTranslate('blueberry_ring_inactive_alert_text'), ); } @@ -47,6 +50,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkSleepInsight() async { final data = await _blueberryRingUseCase.readSleep(); + collectLog('checkSleepInsight:data ${data.map((e) => e.toJson()).toList()}'); // If sleeps is below standard level // loop throug all and get average final now = DateTime.now(); @@ -69,7 +73,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { if (!isNormal) { AXSNotification().showNotification( - cTranslate('blueberry_ring_sleep_alert_title'), + cTranslate('sleep_insight'), cTranslate('blueberry_ring_sleep_alert_text'), ); } @@ -77,6 +81,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkHeartAlert() async { final data = await _blueberryRingUseCase.readHeartRate(); + collectLog('checkHeartAlert:data ${data.map((e) => e.toJson()).toList()}'); // If below standard but between person to person different final latestData = data.first; final lastDate = DateTime.fromMillisecondsSinceEpoch( @@ -89,7 +94,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { if (isToday && latestData.value >= 100) { AXSNotification().showNotification( - cTranslate('blueberry_ring_heart_rate_alert_title'), + cTranslate('heart_alert'), cTranslate('blueberry_ring_heart_rate_alert_text'), ); } @@ -97,11 +102,12 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase { Future checkLowBattery() async { final data = await _blueberryRingUseCase.readLevel(); + collectLog('checkLowBattery:data $data'); // What si the low battery level // Is 10 OK if (data < 20) { AXSNotification().showNotification( - cTranslate('blueberry_ring_battery_alert_title'), + cTranslate('low_battery'), cTranslate('blueberry_ring_battery_alert_text'), ); } From 108acaa19b4dc2175b1fe5258ec55861bc758c12 Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 10 Jul 2024 13:51:58 +0330 Subject: [PATCH 3/5] feat: Log collect and improvement --- assets/js/bluetooth/bluetooth.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/assets/js/bluetooth/bluetooth.js b/assets/js/bluetooth/bluetooth.js index 0df91c45..8dd32c29 100644 --- a/assets/js/bluetooth/bluetooth.js +++ b/assets/js/bluetooth/bluetooth.js @@ -125,18 +125,23 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget { ); return response; } + async readValue() { const data = { this: this.uuid, serviceUUID: this.service.uuid }; const response = await window.axs.callHandler( "BluetoothRemoteGATTCharacteristic.readValue", data ); - return response; + + const bytes = new Uint8Array(response); + console.log("Bytes : ", bytes); + const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + selectedCharacteristic.value = dv; + + return dv; } async writeValue(value) { - // We will need to change the value to Base64 for having a standard type to bridge data on that type. - const data = { this: this.uuid, serviceUUID: this.service.uuid, @@ -295,9 +300,10 @@ class AXSBluetooth { } } - updateCharacteristicValue(characteristicUUID, base64String) { - const bytes = new Uint8Array(base64String); + updateCharacteristicValue(characteristicUUID, value) { + const bytes = new Uint8Array(value); console.log("Bytes : ", bytes); + console.log("Bytes type: ", typeof bytes); const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); let selectedCharacteristic = this.getCharacteristicByUUID(characteristicUUID); From fad7b5718c72fb264d6de5bca37d5ce6882a76eb Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 10 Jul 2024 13:55:57 +0330 Subject: [PATCH 4/5] feat: blueberry collect log --- assets/flutter_i18n/en.json | 5 +++- .../domain/blueberry_ring_use_case.dart | 28 ++++++++++++++++--- .../open_dapp/open_dapp_presenter.dart | 11 ++++++-- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/assets/flutter_i18n/en.json b/assets/flutter_i18n/en.json index 21a7f477..27e7fd11 100644 --- a/assets/flutter_i18n/en.json +++ b/assets/flutter_i18n/en.json @@ -430,6 +430,9 @@ "activity_reminder": "Activity reminder", "sleep_insight": "Sleep insight", "heart_alert": "Heart alert", - "low_battery": "Low battery" + "low_battery": "Low battery", + "blueberry_background_notifications_requirements_title": "This service requires: ", + "blueberry_background_notifications_requirements_text_1": "1. Bluetooth to be ON", + "blueberry_background_notifications_requirements_text_2": "2. Blueberry to be reachable" } \ No newline at end of file diff --git a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart index 112fe1a5..b9091042 100644 --- a/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart +++ b/lib/features/common/packages/bluetooth/blueberry_ring/domain/blueberry_ring_use_case.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:typed_data'; +import 'package:datadashwallet/app/logger.dart'; import 'package:datadashwallet/common/common.dart'; import 'package:flutter/material.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; @@ -52,9 +53,9 @@ class BlueberryRingUseCase extends ReactiveUseCase { Future getBlueberryRingBackground() async { // if (bluetoothStatus.value == BluetoothAdapterState.off || bluetoothStatus.value = BluetoothAdapterState.unauthorized) - // TODO: bluetooth should be on before bg notifications _bluetoothUseCase.startScanning( - withServices: [bluetoothServiceUUID], + // withServices: [bluetoothServiceUUID], + withNames: ['Mi Smart Band 4'] ); await Future.delayed(const Duration(seconds: 2), () async { @@ -107,14 +108,18 @@ class BlueberryRingUseCase extends ReactiveUseCase { /// This function will check the blueberry ring, connection Future checkEstablishment(Future Function() func) async { - final isBlueberryRingAvailable = selectedBlueberryRing.value != null; + collectLog('checkEstablishment'); + final isBlueberryRingAvailable = selectedBlueberryRing.hasValue; + collectLog('checkEstablishment:isBlueberryRingAvailable $isBlueberryRingAvailable'); + if (!isBlueberryRingAvailable) { await getBlueberryRingBackground(); } bool isBlueberryRingConnected = selectedBlueberryRing.value?.device.isConnected ?? false; + collectLog('checkEstablishment:isBlueberryRingConnected $isBlueberryRingConnected'); if (!isBlueberryRingConnected) { await selectedBlueberryRing.value?.device.connect(); @@ -126,7 +131,8 @@ class BlueberryRingUseCase extends ReactiveUseCase { } final isBlueberryRingCharacteristicAvailable = - blueberryRingCharacteristic.value != null; + blueberryRingCharacteristic.hasValue; + collectLog('checkEstablishment:isBlueberryRingCharacteristicAvailable $isBlueberryRingCharacteristicAvailable'); if (!isBlueberryRingCharacteristicAvailable) { await getBlueberryRingCharacteristic(); } @@ -138,8 +144,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { return checkEstablishment( () async { final command = BlueberryCommands.readLevel(); + collectLog('readLevel:command $command'); await blueberryRingCharacteristic.value?.write(command); final value = await blueberryRingCharacteristic.value?.read(); + collectLog('readLevel:value $value'); return BlueberryResolves.readLevel(Uint8List.fromList(value!)); }, ); @@ -149,8 +157,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { return checkEstablishment( () async { final command = BlueberryCommands.readVersion(); + collectLog('readVersion:command $command'); await blueberryRingCharacteristic.value?.write(command); final value = await blueberryRingCharacteristic.value?.read(); + collectLog('readVersion:value $value'); return BlueberryResolves.readVersion(Uint8List.fromList(value!)); }, ); @@ -160,8 +170,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { return checkEstablishment( () async { final command = BlueberryCommands.readTime(); + collectLog('readTime:command $command'); await blueberryRingCharacteristic.value?.write(command); final value = await blueberryRingCharacteristic.value?.read(); + collectLog('readTime:value $value'); return BlueberryResolves.readTime(Uint8List.fromList(value!)); }, ); @@ -171,8 +183,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { return checkEstablishment>( () async { final command = BlueberryCommands.readSleep(); + collectLog('readSleep:command $command'); await blueberryRingCharacteristic.value?.write(command); final value = await blueberryRingCharacteristic.value?.read(); + collectLog('readSleep:value $value'); return BlueberryResolves.readSleep(Uint8List.fromList(value!)); }, ); @@ -182,8 +196,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { return checkEstablishment>( () async { final command = BlueberryCommands.readBloodOxygens(); + collectLog('readBloodOxygens:command $command'); await blueberryRingCharacteristic.value?.write(command); final value = await blueberryRingCharacteristic.value?.read(); + collectLog('readBloodOxygens:value $value'); return BlueberryResolves.readBloodOxygens(Uint8List.fromList(value!)); }, ); @@ -193,8 +209,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { return checkEstablishment>( () async { final command = BlueberryCommands.readSteps(); + collectLog('readSteps:command $command'); await blueberryRingCharacteristic.value?.write(command); final value = await blueberryRingCharacteristic.value?.read(); + collectLog('readSteps:value $value'); return BlueberryResolves.readSteps(Uint8List.fromList(value!)); }, ); @@ -204,8 +222,10 @@ class BlueberryRingUseCase extends ReactiveUseCase { return checkEstablishment>( () async { final command = BlueberryCommands.readHeartRates(); + collectLog('readHeartRate:command $command'); await blueberryRingCharacteristic.value?.write(command); final value = await blueberryRingCharacteristic.value?.read(); + collectLog('readHeartRate:value $value'); return BlueberryResolves.readHeartRates(Uint8List.fromList(value!)); }, ); diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index f1680ed4..599bd0b6 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'dart:developer'; import 'package:clipboard/clipboard.dart'; import 'package:collection/collection.dart'; +import 'package:datadashwallet/app/logger.dart'; import 'package:datadashwallet/common/common.dart'; import 'package:datadashwallet/core/core.dart'; import 'package:datadashwallet/features/common/common.dart'; @@ -844,6 +845,7 @@ class OpenDAppPresenter extends CompletePresenter { final value = Uint8List.fromList(List.from(data['value'])); try { + collectLog('handleWrites:value $value'); if (withResponse) { await selectedCharacteristic.write(value); } else { @@ -881,9 +883,11 @@ class OpenDAppPresenter extends CompletePresenter { final value = selectedCharacteristic.lastValue; final uInt8List = Uint8List.fromList(value); - final base64String = base64Encode(uInt8List); - return base64String; + collectLog('characteristicValueStreamSubscription:value $value'); + collectLog('characteristicValueStreamSubscription:uInt8List ${uInt8List.toString()}'); + + return uInt8List; } Timer? characteriticListnerTimer; @@ -901,7 +905,8 @@ class OpenDAppPresenter extends CompletePresenter { characteristic.lastValueStream.listen((event) { final uInt8List = Uint8List.fromList(event); print(uInt8List); - print('lastValueStream'); + collectLog('characteristicValueStreamSubscription:event $event'); + collectLog('characteristicValueStreamSubscription:uInt8List ${uInt8List.toString()}'); final script = ''' navigator.bluetooth.updateCharacteristicValue('${characteristic.uuid.str}', ${uInt8List.toString()},); '''; From b43122d3dc979bbf01f2341e80c78b2fe333801a Mon Sep 17 00:00:00 2001 From: reasje Date: Wed, 10 Jul 2024 13:56:29 +0330 Subject: [PATCH 5/5] feat: notifications page blueberry ring switches --- .../notifications/notificaitons_page.dart | 206 ++++-------------- 1 file changed, 41 insertions(+), 165 deletions(-) diff --git a/lib/features/settings/subfeatures/notifications/notificaitons_page.dart b/lib/features/settings/subfeatures/notifications/notificaitons_page.dart index 0b010ee1..dbc3f776 100644 --- a/lib/features/settings/subfeatures/notifications/notificaitons_page.dart +++ b/lib/features/settings/subfeatures/notifications/notificaitons_page.dart @@ -297,30 +297,7 @@ class NotificationsPage extends HookConsumerWidget { onChanged: notificationsPresenter.changeActivityReminderEnabled, enabled: isSettingsChangeEnabled, textTrailingWidget: MXCInformationButton( - texts: [ - TextSpan( - text: - FlutterI18n.translate(context, 'experiencing_issues'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate(context, - 'blueberry_background_notifications_requirements_title'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - TextSpan( - text: FlutterI18n.translate(context, - 'blueberry_background_notifications_requirements_text'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - ], + texts: getBlueberryRingServiceInfo(context), ), titleStyle: FontTheme.of(context).h6(), ), @@ -332,53 +309,7 @@ class NotificationsPage extends HookConsumerWidget { onChanged: notificationsPresenter.changeSleepInsightEnabled, enabled: isSettingsChangeEnabled, textTrailingWidget: MXCInformationButton( - texts: [ - TextSpan( - text: - FlutterI18n.translate(context, 'experiencing_issues'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_1_title'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_1_text'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_2_title'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_2_text'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate( - context, 'need_further_assistant'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - ], + texts: getBlueberryRingServiceInfo(context), ), titleStyle: FontTheme.of(context).h6(), ), @@ -389,53 +320,7 @@ class NotificationsPage extends HookConsumerWidget { onChanged: notificationsPresenter.changeHeartAlertEnabled, enabled: isSettingsChangeEnabled, textTrailingWidget: MXCInformationButton( - texts: [ - TextSpan( - text: - FlutterI18n.translate(context, 'experiencing_issues'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_1_title'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_1_text'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_2_title'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_2_text'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate( - context, 'need_further_assistant'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - ], + texts: getBlueberryRingServiceInfo(context), ), titleStyle: FontTheme.of(context).h6(), ), @@ -446,53 +331,7 @@ class NotificationsPage extends HookConsumerWidget { onChanged: notificationsPresenter.changeLowBatteryEnabled, enabled: isSettingsChangeEnabled, textTrailingWidget: MXCInformationButton( - texts: [ - TextSpan( - text: - FlutterI18n.translate(context, 'experiencing_issues'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_1_title'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_1_text'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_2_title'), - style: FontTheme.of(context) - .subtitle2() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - TextSpan( - text: FlutterI18n.translate( - context, 'background_service_solution_2_text'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - const TextSpan(text: '\n\n'), - TextSpan( - text: FlutterI18n.translate( - context, 'need_further_assistant'), - style: FontTheme.of(context) - .subtitle1() - .copyWith(color: ColorsTheme.of(context).textPrimary), - ), - ], + texts: getBlueberryRingServiceInfo(context), ), titleStyle: FontTheme.of(context).h6(), ), @@ -522,3 +361,40 @@ class NotificationsPage extends HookConsumerWidget { ); } } + +List getBlueberryRingServiceInfo( + BuildContext context, +) { + return [ + TextSpan( + text: FlutterI18n.translate(context, 'experiencing_issues'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'blueberry_background_notifications_requirements_title'), + style: FontTheme.of(context) + .subtitle2() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'blueberry_background_notifications_requirements_text_1'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + const TextSpan(text: '\n\n'), + TextSpan( + text: FlutterI18n.translate( + context, 'blueberry_background_notifications_requirements_text_2'), + style: FontTheme.of(context) + .subtitle1() + .copyWith(color: ColorsTheme.of(context).textPrimary), + ), + ]; +}