diff --git a/assets/lang/da.json b/assets/lang/da.json index 3f4a7d36..fefc3d9e 100644 --- a/assets/lang/da.json +++ b/assets/lang/da.json @@ -84,9 +84,12 @@ "expired": "udløbet", "completed": "færdig", "cancel": "Anuller", + "install": "Installér", "pages.about.message.read_more": "Tryk for at læse mere", "pages.about.study.website": "Hjemmeside", "pages.about.study.privacy": "Fortrolighedspolitik", + "pages.about.install_health_connect.title": "Health Connect påkrævet", + "pages.about.install_health_connect.description": "Denne app kræver, at Google Connect er installeret. Vil du installere det?", "dialog.location.permission": "Lokaliseringstjeneste", "dialog.location.allow": "Tillad", "pages.ic.need_accept": "Du skal acceptere denne informerede samtykke for at kunne deltage i dette studie.", diff --git a/assets/lang/en.json b/assets/lang/en.json index 414f8008..e793e30f 100644 --- a/assets/lang/en.json +++ b/assets/lang/en.json @@ -84,9 +84,12 @@ "expired": "expired", "completed": "completed", "cancel": "Cancel", + "install": "Install", "pages.about.message.read_more": "Tap to read more", "pages.about.study.website": "Website", "pages.about.study.privacy": "Privacy policy", + "pages.about.install_health_connect.title": "Health Connect Required", + "pages.about.install_health_connect.description": "This app requires Google Health Connect to be installed. Would you like to install it?", "dialog.location.permission": "Permission Required", "dialog.location.allow": "Allow", "pages.ic.need_accept": "You need to accept the informed consent to participate in this study.", diff --git a/lib/blocs/app_bloc.dart b/lib/blocs/app_bloc.dart index 93ee90ca..52be749d 100644 --- a/lib/blocs/app_bloc.dart +++ b/lib/blocs/app_bloc.dart @@ -55,6 +55,7 @@ class StudyAppBLoC extends ChangeNotifier { List _messages = []; final StreamController _messageStreamController = StreamController.broadcast(); + final String _healthConnectPackageName = 'com.google.android.apps.healthdata'; /// The state of this BloC. StudyAppState get state => _state; @@ -84,6 +85,8 @@ class StudyAppBLoC extends ChangeNotifier { GlobalKey get scaffoldKey => _scaffoldKey; State? get scaffoldMessengerState => scaffoldKey.currentState; + String get healthConnectPackageName => _healthConnectPackageName; + /// Create the BLoC for the app. StudyAppBLoC() : super() { const dep = @@ -151,6 +154,10 @@ class StudyAppBLoC extends ChangeNotifier { /// The overall data model for this app CarpStudyAppViewModel get appViewModel => _appViewModel; + final appCheck = AppCheck(); + + List? installedApps; + /// Initialize this BLOC. Called before being used for anything. Future initialize() async { if (isInitialized) return; @@ -178,6 +185,19 @@ class StudyAppBLoC extends ChangeNotifier { element == ConnectivityResult.wifi); } + Future _isHealthConnectInstalled() async { + try { + final apps = await appCheck.getInstalledApps(); + if (apps != null) { + return apps.any((app) => app.packageName == _healthConnectPackageName); + } + } catch (e) { + debug("Error checking Health Connect installation: $e"); + return false; + } + return false; + } + /// Set the active study in the app based on an [invitation]. /// /// If a [context] is provided, the translation for this study is re-loaded diff --git a/lib/main.dart b/lib/main.dart index 759937bd..5786e932 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -27,6 +27,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:open_settings_plus/open_settings_plus.dart'; import 'package:open_settings_plus/core/open_settings_plus.dart'; +import 'package:appcheck/appcheck.dart'; // the CARP packages import 'package:carp_serializable/carp_serializable.dart'; @@ -77,6 +78,7 @@ part 'view_models/user_tasks.dart'; part 'carp_study_app.dart'; part 'ui/pages/informed_consent_page.dart'; part 'ui/pages/home_page.dart'; +part 'ui/pages/home_page.install_health_connect_dialog.dart'; part 'ui/carp_study_style.dart'; part 'ui/colors.dart'; part 'ui/pages/data_visualization_page.dart'; diff --git a/lib/main.g.dart b/lib/main.g.dart index 75aaca78..c71331fe 100644 --- a/lib/main.g.dart +++ b/lib/main.g.dart @@ -12,7 +12,7 @@ WeeklyActivities _$WeeklyActivitiesFromJson(Map json) => (k, e) => MapEntry( $enumDecode(_$ActivityTypeEnumMap, k), (e as Map).map( - (k, e) => MapEntry(int.parse(k), e as int), + (k, e) => MapEntry(int.parse(k), (e as num).toInt()), )), ); @@ -47,9 +47,9 @@ Map _$WeeklyMobilityToJson(WeeklyMobility instance) => DailyMobility _$DailyMobilityFromJson(Map json) => DailyMobility( - json['weekday'] as int, - json['places'] as int, - json['home_stay'] as int, + (json['weekday'] as num).toInt(), + (json['places'] as num).toInt(), + (json['home_stay'] as num).toInt(), (json['distance'] as num).toDouble(), ); @@ -63,7 +63,7 @@ Map _$DailyMobilityToJson(DailyMobility instance) => WeeklySteps _$WeeklyStepsFromJson(Map json) => WeeklySteps() ..weeklySteps = (json['weekly_steps'] as Map).map( - (k, e) => MapEntry(int.parse(k), e as int), + (k, e) => MapEntry(int.parse(k), (e as num).toInt()), ); Map _$WeeklyStepsToJson(WeeklySteps instance) => diff --git a/lib/ui/pages/home_page.dart b/lib/ui/pages/home_page.dart index 3b554a31..8e428d23 100644 --- a/lib/ui/pages/home_page.dart +++ b/lib/ui/pages/home_page.dart @@ -61,6 +61,22 @@ class HomePageState extends State { // - starting sensing askForLocationPermissions(context) .then((_) => bloc.configureStudy().then((_) => bloc.start())); + + if (Platform.isAndroid) { + // Check if HealthConnect is installed + _checkHealthConnectInstallation(); + } + } + + Future _checkHealthConnectInstallation() async { + bool isInstalled = await bloc._isHealthConnectInstalled(); + if (!isInstalled) { + showDialog( + context: context, + barrierDismissible: true, + builder: (context) => InstallHealthConnectDialog(context), + ); + } } @override diff --git a/lib/ui/pages/home_page.install_health_connect_dialog.dart b/lib/ui/pages/home_page.install_health_connect_dialog.dart new file mode 100644 index 00000000..f7cb4929 --- /dev/null +++ b/lib/ui/pages/home_page.install_health_connect_dialog.dart @@ -0,0 +1,46 @@ +part of carp_study_app; + +class InstallHealthConnectDialog extends StatelessWidget { + const InstallHealthConnectDialog(BuildContext context, {super.key}); + + @override + Widget build(BuildContext context) { + RPLocalizations locale = RPLocalizations.of(context)!; + return AlertDialog( + titlePadding: const EdgeInsets.symmetric(vertical: 4), + insetPadding: const EdgeInsets.symmetric(vertical: 24, horizontal: 40), + title: const DialogTitle( + title: "pages.about.install_health_connect.title", + ), + content: Text( + locale.translate('pages.about.install_health_connect.description'), + style: aboutCardContentStyle, + textAlign: TextAlign.justify, + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(locale.translate('cancel')), + ), + TextButton( + child: Text(locale.translate('install')), + onPressed: () async { + _redirectToHealthConnectPlayStore(); + Navigator.of(context).pop(); + }, + ), + ], + ); + } + + void _redirectToHealthConnectPlayStore() async { + final Uri url = Uri.parse( + 'https://play.google.com/store/apps/details?id=${bloc.healthConnectPackageName}'); + var canLaunch = await canLaunchUrl(url); + if (canLaunch) { + await launchUrl(url); + } else { + throw 'Could not launch $url'; + } + } +} diff --git a/pubspec.lock b/pubspec.lock index 43af5039..dda5e9a7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,15 +5,10 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" url: "https://pub.dev" source: hosted - version: "72.0.0" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.2" + version: "67.0.0" air_quality: dependency: transitive description: @@ -26,10 +21,18 @@ packages: dependency: transitive description: name: analyzer - sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" url: "https://pub.dev" source: hosted - version: "6.7.0" + version: "6.4.1" + appcheck: + dependency: "direct main" + description: + name: appcheck + sha256: "0fcbe15b6bba67027c6f94bd177b9b319e019b51e0b49e9cd80486448c4a1909" + url: "https://pub.dev" + source: hosted + version: "1.5.2" archive: dependency: transitive description: @@ -146,18 +149,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: dd09dd4e2b078992f42aac7f1a622f01882a8492fef08486b27ddde929c19f04 + sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7" url: "https://pub.dev" source: hosted - version: "2.4.12" + version: "2.4.11" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe url: "https://pub.dev" source: hosted - version: "7.3.2" + version: "7.3.1" built_collection: dependency: transitive description: @@ -186,10 +189,10 @@ packages: dependency: transitive description: name: camera_android_camerax - sha256: "8bd9cab67551642eb33ceb33ece7acc0890014fc90ddfae637c7e2b683657e65" + sha256: "011be2ab0e5b3e3aa8094413fa890f8c5c5afd7cfdaef353a992047d4dab5780" url: "https://pub.dev" source: hosted - version: "0.6.7+2" + version: "0.6.8+2" camera_avfoundation: dependency: transitive description: @@ -418,10 +421,10 @@ packages: dependency: transitive description: name: coverage - sha256: "576aaab8b1abdd452e0f656c3e73da9ead9d7880e15bdc494189d9c1a1baf0db" + sha256: c1fb2dce3c0085f39dc72668e85f8e0210ec7de05345821ff58530567df345a5 url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.2" cron: dependency: transitive description: @@ -668,10 +671,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "9d98bd47ef9d34e803d438f17fd32b116d31009f534a6fa5ce3a1167f189a6de" + sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda" url: "https://pub.dev" source: hosted - version: "2.0.21" + version: "2.0.22" flutter_secure_storage: dependency: transitive description: @@ -806,10 +809,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: ddc16d34b0d74cb313986918c0f0885a7ba2fc24d8fb8419de75f0015144ccfe + sha256: "2ddb88e9ad56ae15ee144ed10e33886777eb5ca2509a914850a5faa7b52ff459" url: "https://pub.dev" source: hosted - version: "14.2.3" + version: "14.2.7" google_fonts: dependency: "direct main" description: @@ -934,10 +937,10 @@ packages: dependency: transitive description: name: just_audio - sha256: ee50602364ba83fa6308f5512dd560c713ec3e1f2bc75f0db43618f0d82ef71a + sha256: d8e8aaf417d33e345299c17f6457f72bd4ba0c549dc34607abb5183a354edc4d url: "https://pub.dev" source: hosted - version: "0.9.39" + version: "0.9.40" just_audio_platform_interface: dependency: transitive description: @@ -950,10 +953,10 @@ packages: dependency: transitive description: name: just_audio_web - sha256: "0edb481ad4aa1ff38f8c40f1a3576013c3420bf6669b686fe661627d49bc606c" + sha256: b163878529d9b028c53a6972fcd58cae2405bcd11cbfcea620b6fb9f151429d6 url: "https://pub.dev" source: hosted - version: "0.4.11" + version: "0.4.12" jwt_decoder: dependency: transitive description: @@ -1058,14 +1061,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" - macros: - dependency: transitive - description: - name: macros - sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" - url: "https://pub.dev" - source: hosted - version: "0.1.2-main.4" markdown: dependency: transitive description: @@ -1110,10 +1105,10 @@ packages: dependency: transitive description: name: mime - sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" + sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" mobility_features: dependency: transitive description: @@ -1438,10 +1433,10 @@ packages: dependency: transitive description: name: permission_handler_html - sha256: d220eb8476b466d58b161e10b3001d93999010a26228a3fb89c4280db1249546 + sha256: af26edbbb1f2674af65a8f4b56e1a6f526156bc273d0e65dd8075fab51c78851 url: "https://pub.dev" source: hosted - version: "0.1.3+1" + version: "0.1.3+2" permission_handler_platform_interface: dependency: transitive description: @@ -1622,10 +1617,10 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: a7e8467e9181cef109f601e3f65765685786c1a738a83d7fbbde377589c0d974 + sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" shared_preferences_foundation: dependency: transitive description: @@ -1694,10 +1689,10 @@ packages: dependency: transitive description: name: shelf_web_socket - sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "1.0.4" signature: dependency: transitive description: @@ -1747,10 +1742,10 @@ packages: dependency: transitive description: name: source_map_stack_trace - sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" source_maps: dependency: transitive description: @@ -1787,10 +1782,10 @@ packages: dependency: transitive description: name: sqflite_common - sha256: "7b41b6c3507854a159e24ae90a8e3e9cc01eb26a477c118d6dca065b5f55453e" + sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" url: "https://pub.dev" source: hosted - version: "2.5.4+2" + version: "2.5.4" stack_trace: dependency: transitive description: @@ -1843,10 +1838,10 @@ packages: dependency: transitive description: name: synchronized - sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255 + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.1.0+1" system_info2: dependency: transitive description: @@ -2059,10 +2054,10 @@ packages: dependency: transitive description: name: video_player_android - sha256: "4de50df9ee786f5891d3281e1e633d7b142ef1acf47392592eb91cba5d355849" + sha256: e343701aa890b74a863fa460f5c0e628127ed06a975d7d9af6b697133fb25bdf url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.7.1" video_player_avfoundation: dependency: transitive description: @@ -2091,10 +2086,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.4" + version: "14.2.5" watcher: dependency: transitive description: @@ -2119,22 +2114,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" - url: "https://pub.dev" - source: hosted - version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "2.4.5" webkit_inspection_protocol: dependency: transitive description: @@ -2200,5 +2187,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.5.0 <4.0.0" + dart: ">=3.4.0 <4.0.0" flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index 4d1bf293..e3c897d8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: carp_study_app description: The generic CARP study app. publish_to: "none" -version: 2.1.1+30 +version: 2.2.1+32 environment: sdk: ">=3.2.0 <4.0.0" @@ -51,6 +51,7 @@ dependencies: permission_handler: ^11.0.1 connectivity_plus: ^6.0.0 open_settings_plus: ^0.3.0 + appcheck: ^1.5.2 # Overriding carp libraries to use the local copy dependency_overrides: diff --git a/test/heart_rate_data_model_test.mocks.dart b/test/heart_rate_data_model_test.mocks.dart index 6b938e8a..5287673d 100644 --- a/test/heart_rate_data_model_test.mocks.dart +++ b/test/heart_rate_data_model_test.mocks.dart @@ -3,15 +3,16 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i6; -import 'dart:ui' as _i7; +import 'dart:async' as _i7; +import 'dart:ui' as _i8; import 'package:carp_core/carp_core.dart' as _i3; import 'package:carp_mobile_sensing/carp_mobile_sensing.dart' as _i2; -import 'package:carp_polar_package/carp_polar_package.dart' as _i8; +import 'package:carp_polar_package/carp_polar_package.dart' as _i9; import 'package:carp_study_app/main.dart' as _i4; import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i5; +import 'package:mockito/src/dummies.dart' as _i6; +import 'package:permission_handler/permission_handler.dart' as _i5; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -139,6 +140,14 @@ class MockSmartphoneDeploymentController extends _i1.Mock ), ) as _i2.DeviceController); + @override + Map<_i5.Permission, _i5.PermissionStatus> get permissions => + (super.noSuchMethod( + Invocation.getter(#permissions), + returnValue: <_i5.Permission, _i5.PermissionStatus>{}, + returnValueForMissingStub: <_i5.Permission, _i5.PermissionStatus>{}, + ) as Map<_i5.Permission, _i5.PermissionStatus>); + @override _i2.SmartphoneDeploymentExecutor get executor => (super.noSuchMethod( Invocation.getter(#executor), @@ -155,11 +164,11 @@ class MockSmartphoneDeploymentController extends _i1.Mock @override String get privacySchemaName => (super.noSuchMethod( Invocation.getter(#privacySchemaName), - returnValue: _i5.dummyValue( + returnValue: _i6.dummyValue( this, Invocation.getter(#privacySchemaName), ), - returnValueForMissingStub: _i5.dummyValue( + returnValueForMissingStub: _i6.dummyValue( this, Invocation.getter(#privacySchemaName), ), @@ -179,11 +188,11 @@ class MockSmartphoneDeploymentController extends _i1.Mock ) as _i2.DataTransformer); @override - _i6.Stream<_i3.Measurement> get measurements => (super.noSuchMethod( + _i7.Stream<_i3.Measurement> get measurements => (super.noSuchMethod( Invocation.getter(#measurements), - returnValue: _i6.Stream<_i3.Measurement>.empty(), - returnValueForMissingStub: _i6.Stream<_i3.Measurement>.empty(), - ) as _i6.Stream<_i3.Measurement>); + returnValue: _i7.Stream<_i3.Measurement>.empty(), + returnValueForMissingStub: _i7.Stream<_i3.Measurement>.empty(), + ) as _i7.Stream<_i3.Measurement>); @override int get samplingSize => (super.noSuchMethod( @@ -246,11 +255,11 @@ class MockSmartphoneDeploymentController extends _i1.Mock ); @override - _i6.Stream<_i3.StudyStatus> get statusEvents => (super.noSuchMethod( + _i7.Stream<_i3.StudyStatus> get statusEvents => (super.noSuchMethod( Invocation.getter(#statusEvents), - returnValue: _i6.Stream<_i3.StudyStatus>.empty(), - returnValueForMissingStub: _i6.Stream<_i3.StudyStatus>.empty(), - ) as _i6.Stream<_i3.StudyStatus>); + returnValue: _i7.Stream<_i3.StudyStatus>.empty(), + returnValueForMissingStub: _i7.Stream<_i3.StudyStatus>.empty(), + ) as _i7.Stream<_i3.StudyStatus>); @override _i3.StudyStatus get status => (super.noSuchMethod( @@ -299,62 +308,18 @@ class MockSmartphoneDeploymentController extends _i1.Mock ) as List<_i3.DeviceConfiguration<_i3.DeviceRegistration>>); @override - _i6.Stream<_i3.Measurement> measurementsByType(String? type) => + _i7.Stream<_i3.Measurement> measurementsByType(String? type) => (super.noSuchMethod( Invocation.method( #measurementsByType, [type], ), - returnValue: _i6.Stream<_i3.Measurement>.empty(), - returnValueForMissingStub: _i6.Stream<_i3.Measurement>.empty(), - ) as _i6.Stream<_i3.Measurement>); - - @override - _i6.Future<_i3.StudyStatus> tryDeployment({bool? useCached = true}) => - (super.noSuchMethod( - Invocation.method( - #tryDeployment, - [], - {#useCached: useCached}, - ), - returnValue: _i6.Future<_i3.StudyStatus>.value( - _i3.StudyStatus.DeploymentNotStarted), - returnValueForMissingStub: _i6.Future<_i3.StudyStatus>.value( - _i3.StudyStatus.DeploymentNotStarted), - ) as _i6.Future<_i3.StudyStatus>); - - @override - _i6.Future saveDeployment() => (super.noSuchMethod( - Invocation.method( - #saveDeployment, - [], - ), - returnValue: _i6.Future.value(false), - returnValueForMissingStub: _i6.Future.value(false), - ) as _i6.Future); + returnValue: _i7.Stream<_i3.Measurement>.empty(), + returnValueForMissingStub: _i7.Stream<_i3.Measurement>.empty(), + ) as _i7.Stream<_i3.Measurement>); @override - _i6.Future restoreDeployment() => (super.noSuchMethod( - Invocation.method( - #restoreDeployment, - [], - ), - returnValue: _i6.Future.value(false), - returnValueForMissingStub: _i6.Future.value(false), - ) as _i6.Future); - - @override - _i6.Future eraseDeployment() => (super.noSuchMethod( - Invocation.method( - #eraseDeployment, - [], - ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); - - @override - _i6.Future configure({ + _i7.Future configure({ _i2.DataEndPoint? dataEndPoint, _i2.DataTransformer? transformer, }) => @@ -367,9 +332,19 @@ class MockSmartphoneDeploymentController extends _i1.Mock #transformer: transformer, }, ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); + + @override + _i7.Future askForAllPermissions() => (super.noSuchMethod( + Invocation.method( + #askForAllPermissions, + [], + ), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override void initializeDevices() => super.noSuchMethod( @@ -401,45 +376,88 @@ class MockSmartphoneDeploymentController extends _i1.Mock ); @override - _i6.Future connectAllConnectableDevices() => (super.noSuchMethod( + _i7.Future connectAllConnectableDevices() => (super.noSuchMethod( Invocation.method( #connectAllConnectableDevices, [], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future start([bool? start = true]) => (super.noSuchMethod( + _i7.Future<_i3.StudyStatus> tryDeployment({bool? useCached = true}) => + (super.noSuchMethod( Invocation.method( - #start, + #tryDeployment, + [], + {#useCached: useCached}, + ), + returnValue: _i7.Future<_i3.StudyStatus>.value( + _i3.StudyStatus.DeploymentNotStarted), + returnValueForMissingStub: _i7.Future<_i3.StudyStatus>.value( + _i3.StudyStatus.DeploymentNotStarted), + ) as _i7.Future<_i3.StudyStatus>); + + @override + _i7.Future saveDeployment() => (super.noSuchMethod( + Invocation.method( + #saveDeployment, + [], + ), + returnValue: _i7.Future.value(false), + returnValueForMissingStub: _i7.Future.value(false), + ) as _i7.Future); + + @override + _i7.Future restoreDeployment() => (super.noSuchMethod( + Invocation.method( + #restoreDeployment, + [], + ), + returnValue: _i7.Future.value(false), + returnValueForMissingStub: _i7.Future.value(false), + ) as _i7.Future); + + @override + _i7.Future eraseDeployment() => (super.noSuchMethod( + Invocation.method( + #eraseDeployment, [], - {#start: start}, ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); + + @override + _i7.Future start([bool? start = true]) => (super.noSuchMethod( + Invocation.method( + #start, + [start], + ), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future stop() => (super.noSuchMethod( + _i7.Future stop() => (super.noSuchMethod( Invocation.method( #stop, [], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future remove() => (super.noSuchMethod( + _i7.Future remove() => (super.noSuchMethod( Invocation.method( #remove, [], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override void dispose() => super.noSuchMethod( @@ -451,7 +469,7 @@ class MockSmartphoneDeploymentController extends _i1.Mock ); @override - _i6.Future addStudy( + _i7.Future addStudy( _i3.Study? study, _i3.DeviceRegistration? deviceRegistration, ) => @@ -463,44 +481,44 @@ class MockSmartphoneDeploymentController extends _i1.Mock deviceRegistration, ], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future<_i3.StudyDeploymentStatus?> getStudyDeploymentStatus() => + _i7.Future<_i3.StudyDeploymentStatus?> getStudyDeploymentStatus() => (super.noSuchMethod( Invocation.method( #getStudyDeploymentStatus, [], ), - returnValue: _i6.Future<_i3.StudyDeploymentStatus?>.value(), + returnValue: _i7.Future<_i3.StudyDeploymentStatus?>.value(), returnValueForMissingStub: - _i6.Future<_i3.StudyDeploymentStatus?>.value(), - ) as _i6.Future<_i3.StudyDeploymentStatus?>); + _i7.Future<_i3.StudyDeploymentStatus?>.value(), + ) as _i7.Future<_i3.StudyDeploymentStatus?>); @override - _i6.Future tryRegisterConnectedDevice( + _i7.Future tryRegisterConnectedDevice( _i3.DeviceConfiguration<_i3.DeviceRegistration>? device) => (super.noSuchMethod( Invocation.method( #tryRegisterConnectedDevice, [device], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i6.Future tryRegisterRemainingDevicesToRegister() => + _i7.Future tryRegisterRemainingDevicesToRegister() => (super.noSuchMethod( Invocation.method( #tryRegisterRemainingDevicesToRegister, [], ), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), - ) as _i6.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); } /// A class which mocks [HeartRateCardViewModel]. @@ -543,18 +561,18 @@ class MockHeartRateCardViewModel extends _i1.Mock ) as _i4.HourlyHeartRate); @override - _i6.Future get filename => (super.noSuchMethod( + _i7.Future get filename => (super.noSuchMethod( Invocation.getter(#filename), - returnValue: _i6.Future.value(_i5.dummyValue( + returnValue: _i7.Future.value(_i6.dummyValue( this, Invocation.getter(#filename), )), returnValueForMissingStub: - _i6.Future.value(_i5.dummyValue( + _i7.Future.value(_i6.dummyValue( this, Invocation.getter(#filename), )), - ) as _i6.Future); + ) as _i7.Future); @override bool get hasListeners => (super.noSuchMethod( @@ -595,37 +613,46 @@ class MockHeartRateCardViewModel extends _i1.Mock ); @override - _i6.Future save(Map? json) => (super.noSuchMethod( + _i7.Future save(Map? json) => (super.noSuchMethod( Invocation.method( #save, [json], ), - returnValue: _i6.Future.value(false), - returnValueForMissingStub: _i6.Future.value(false), - ) as _i6.Future); + returnValue: _i7.Future.value(false), + returnValueForMissingStub: _i7.Future.value(false), + ) as _i7.Future); @override - _i6.Future dispose() => (super.noSuchMethod( + bool delete() => (super.noSuchMethod( + Invocation.method( + #delete, + [], + ), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + + @override + void dispose() => super.noSuchMethod( Invocation.method( #dispose, [], ), - returnValue: _i6.Future.value(false), - returnValueForMissingStub: _i6.Future.value(false), - ) as _i6.Future); + returnValueForMissingStub: null, + ); @override - _i6.Future<_i4.HourlyHeartRate?> restore() => (super.noSuchMethod( + _i7.Future<_i4.HourlyHeartRate?> restore() => (super.noSuchMethod( Invocation.method( #restore, [], ), - returnValue: _i6.Future<_i4.HourlyHeartRate?>.value(), - returnValueForMissingStub: _i6.Future<_i4.HourlyHeartRate?>.value(), - ) as _i6.Future<_i4.HourlyHeartRate?>); + returnValue: _i7.Future<_i4.HourlyHeartRate?>.value(), + returnValueForMissingStub: _i7.Future<_i4.HourlyHeartRate?>.value(), + ) as _i7.Future<_i4.HourlyHeartRate?>); @override - void addListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i8.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -634,7 +661,7 @@ class MockHeartRateCardViewModel extends _i1.Mock ); @override - void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -817,7 +844,7 @@ class MockHourlyHeartRate extends _i1.Mock implements _i4.HourlyHeartRate { /// A class which mocks [PolarHRSample]. /// /// See the documentation for Mockito's code generation for more information. -class MockPolarHRSample extends _i1.Mock implements _i8.PolarHRSample { +class MockPolarHRSample extends _i1.Mock implements _i9.PolarHRSample { @override int get hr => (super.noSuchMethod( Invocation.getter(#hr), @@ -860,7 +887,7 @@ class MockPolarHRSample extends _i1.Mock implements _i8.PolarHRSample { /// A class which mocks [PolarHR]. /// /// See the documentation for Mockito's code generation for more information. -class MockPolarHR extends _i1.Mock implements _i8.PolarHR { +class MockPolarHR extends _i1.Mock implements _i9.PolarHR { @override Function get fromJsonFunction => (super.noSuchMethod( Invocation.getter(#fromJsonFunction), @@ -871,22 +898,22 @@ class MockPolarHR extends _i1.Mock implements _i8.PolarHR { @override String get jsonType => (super.noSuchMethod( Invocation.getter(#jsonType), - returnValue: _i5.dummyValue( + returnValue: _i6.dummyValue( this, Invocation.getter(#jsonType), ), - returnValueForMissingStub: _i5.dummyValue( + returnValueForMissingStub: _i6.dummyValue( this, Invocation.getter(#jsonType), ), ) as String); @override - List<_i8.PolarHRSample> get samples => (super.noSuchMethod( + List<_i9.PolarHRSample> get samples => (super.noSuchMethod( Invocation.getter(#samples), - returnValue: <_i8.PolarHRSample>[], - returnValueForMissingStub: <_i8.PolarHRSample>[], - ) as List<_i8.PolarHRSample>); + returnValue: <_i9.PolarHRSample>[], + returnValueForMissingStub: <_i9.PolarHRSample>[], + ) as List<_i9.PolarHRSample>); @override set sensorSpecificData(_i3.Data? _sensorSpecificData) => super.noSuchMethod(