diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e42569e..bca39487 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ jobs: run: flutter pub get - name: Verify formatting - run: dart format --output=none --set-exit-if-changed lib/** test/** + run: dart format --line-length 120 --output=none --set-exit-if-changed lib/** test/** - name: Analyze project source run: flutter analyze --no-fatal-infos --no-fatal-warnings lib/ test/ diff --git a/analysis_options.yaml b/analysis_options.yaml index b449163e..6a7acd6c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -3,6 +3,9 @@ include: package:lints/recommended.yaml +formatter: + page_width: 120 + analyzer: exclude: [build/**] language: diff --git a/lib/blocs/app_bloc.dart b/lib/blocs/app_bloc.dart index 0619564f..7f368397 100644 --- a/lib/blocs/app_bloc.dart +++ b/lib/blocs/app_bloc.dart @@ -53,8 +53,7 @@ class StudyAppBLoC extends ChangeNotifier { final CarpBackend _backend = CarpBackend(); final CarpStudyAppViewModel _appViewModel = CarpStudyAppViewModel(); List _messages = []; - final StreamController _messageStreamController = - StreamController.broadcast(); + final StreamController _messageStreamController = StreamController.broadcast(); /// The state of this BloC. StudyAppState get state => _state; @@ -86,14 +85,11 @@ class StudyAppBLoC extends ChangeNotifier { /// Create the BLoC for the app. StudyAppBLoC() : super() { - const dep = - String.fromEnvironment('deployment-mode', defaultValue: 'production'); - deploymentMode = - DeploymentMode.values.where((element) => element.name == dep).first; + const dep = String.fromEnvironment('deployment-mode', defaultValue: 'production'); + deploymentMode = DeploymentMode.values.where((element) => element.name == dep).first; const deb = String.fromEnvironment('debug-level', defaultValue: 'info'); - debugLevel = - DebugLevel.values.where((element) => element.name == deb).first; + debugLevel = DebugLevel.values.where((element) => element.name == deb).first; info('$runtimeType created. ' 'DeploymentMode: ${deploymentMode.name}, ' @@ -101,28 +97,22 @@ class StudyAppBLoC extends ChangeNotifier { } LocalizationManager get localizationManager => - (deploymentMode == DeploymentMode.local - ? LocalResourceManager() - : CarpResourceManager()) as LocalizationManager; + (deploymentMode == DeploymentMode.local ? LocalResourceManager() : CarpResourceManager()) as LocalizationManager; LocalizationLoader get localizationLoader { debug('$runtimeType - using localizationManager: $localizationManager'); return ResourceLocalizationLoader(localizationManager); } - MessageManager get messageManager => (deploymentMode == DeploymentMode.local - ? LocalResourceManager() - : CarpResourceManager()) as MessageManager; + MessageManager get messageManager => + (deploymentMode == DeploymentMode.local ? LocalResourceManager() : CarpResourceManager()) as MessageManager; InformedConsentManager get informedConsentManager => - (bloc.deploymentMode == DeploymentMode.local - ? LocalResourceManager() - : CarpResourceManager()) as InformedConsentManager; + (bloc.deploymentMode == DeploymentMode.local ? LocalResourceManager() : CarpResourceManager()) + as InformedConsentManager; ParticipationService get participationService => - (bloc.deploymentMode == DeploymentMode.local - ? LocalParticipationService() - : CarpParticipationService()); + (bloc.deploymentMode == DeploymentMode.local ? LocalParticipationService() : CarpParticipationService()); CarpBackend get backend => _backend; @@ -138,13 +128,11 @@ class StudyAppBLoC extends ChangeNotifier { /// The deployment running on this phone. SmartphoneDeployment? get deployment => Sensing().controller?.deployment; - Set get expectedParticipantData => - deployment?.expectedParticipantData ?? {}; + Set get expectedParticipantData => deployment?.expectedParticipantData ?? {}; /// Get the status for the current study deployment. /// Returns null if the study is not yet deployed on this phone. - Future get studyDeploymentStatus async => - await Sensing().getStudyDeploymentStatus(); + Future get studyDeploymentStatus async => await Sensing().getStudyDeploymentStatus(); /// When was this study deployed on this phone. DateTime? get studyStartTimestamp => deployment?.deployed; @@ -185,12 +173,9 @@ class StudyAppBLoC extends ChangeNotifier { /// Is the phone connected to the internet either via wifi or mobile network? Future checkConnectivity() async { - final List results = - await (Connectivity().checkConnectivity()); + final List results = await (Connectivity().checkConnectivity()); - return results.any((element) => - element == ConnectivityResult.mobile || - element == ConnectivityResult.wifi); + return results.any((element) => element == ConnectivityResult.mobile || element == ConnectivityResult.wifi); } /// Check if the Health database is installed on this phone. @@ -202,8 +187,7 @@ class StudyAppBLoC extends ChangeNotifier { try { final apps = await appCheck.getInstalledApps() ?? []; - return apps.any( - (app) => app.packageName == LocalSettings.healthConnectPackageName); + return apps.any((app) => app.packageName == LocalSettings.healthConnectPackageName); } catch (e) { debug("$runtimeType - Error checking Health Connect installation: $e"); return false; @@ -243,8 +227,7 @@ class StudyAppBLoC extends ChangeNotifier { var protocol = await LocalResourceManager().getStudyProtocol(''); // Deploy this protocol using the on-phone deployment service. - final status = - await SmartphoneDeploymentService().createStudyDeployment(protocol!); + final status = await SmartphoneDeploymentService().createStudyDeployment(protocol!); // Save the participant and study on the phone for use across app restart. var participant = Participant( @@ -326,10 +309,7 @@ class StudyAppBLoC extends ChangeNotifier { } Future> getParticipantDataListFromDeployment() async => - (deployment == null) - ? [] - : await participationService - .getParticipantDataList([deployment!.studyDeploymentId]); + (deployment == null) ? [] : await participationService.getParticipantDataList([deployment!.studyDeploymentId]); /// Set the participant data for this study. void setParticipantData( @@ -352,9 +332,7 @@ class StudyAppBLoC extends ChangeNotifier { /// Has the informed consent been accepted by the user? bool get hasInformedConsentBeenAccepted => - backend.getInformedConsentByRole( - study!.studyDeploymentId, study!.participantRoleName) != - null; + backend.getInformedConsentByRole(study!.studyDeploymentId, study!.participantRoleName) != null; set hasInformedConsentBeenAccepted(bool accepted) { var participant = LocalSettings().participant; @@ -406,11 +384,10 @@ class StudyAppBLoC extends ChangeNotifier { /// Does this [deployment] have any measures? bool hasMeasures() => (deployment == null) ? false - : (deployment!.measures.any((measure) => - (measure.type != SurveyUserTask.VIDEO_TYPE && - measure.type != SurveyUserTask.IMAGE_TYPE && - measure.type != SurveyUserTask.AUDIO_TYPE && - measure.type != SurveyUserTask.SURVEY_TYPE))); + : (deployment!.measures.any((measure) => (measure.type != SurveyUserTask.VIDEO_TYPE && + measure.type != SurveyUserTask.IMAGE_TYPE && + measure.type != SurveyUserTask.AUDIO_TYPE && + measure.type != SurveyUserTask.SURVEY_TYPE))); /// Does this [deployment] have the measure of type [type]? bool hasMeasure(String type) { @@ -426,21 +403,16 @@ class StudyAppBLoC extends ChangeNotifier { } /// Does this [deployment] have any user tasks? - bool hasUserTasks() => (deployment == null) - ? false - : deployment!.tasks.whereType().isNotEmpty; + bool hasUserTasks() => (deployment == null) ? false : deployment!.tasks.whereType().isNotEmpty; /// Does this [deployment] have any connected devices? - bool hasDevices() => - (deployment == null) ? false : deployment!.connectedDevices.isNotEmpty; + bool hasDevices() => (deployment == null) ? false : deployment!.connectedDevices.isNotEmpty; /// Is sensing running, i.e. has the study executor been resumed? bool get isRunning => Sensing().isRunning; /// the list of running - i.e. used - probes in this study. - List get runningProbes => (Sensing().controller != null) - ? Sensing().controller!.executor.probes - : []; + List get runningProbes => (Sensing().controller != null) ? Sensing().controller!.executor.probes : []; DeploymentService get deploymentService => Sensing().deploymentService; @@ -450,8 +422,7 @@ class StudyAppBLoC extends ChangeNotifier { /// Start sensing. Future start() async { - assert(Sensing().controller != null, - 'No Study Controller - the study has not been deployed.'); + assert(Sensing().controller != null, 'No Study Controller - the study has not been deployed.'); if (!Sensing().isRunning) Sensing().controller?.start(); } @@ -466,12 +437,10 @@ class StudyAppBLoC extends ChangeNotifier { } /// Add [measurement] to the stream of collected measurements. - void addMeasurement(Measurement measurement) => - Sensing().controller?.executor.addMeasurement(measurement); + void addMeasurement(Measurement measurement) => Sensing().controller?.executor.addMeasurement(measurement); /// Add [error] to the stream of measurements. - void addError(Object error, [StackTrace? stacktrace]) => - Sensing().controller?.executor.addError(error, stacktrace); + void addError(Object error, [StackTrace? stacktrace]) => Sensing().controller?.executor.addError(error, stacktrace); /// Leave the study deployed on this phone. /// diff --git a/lib/blocs/sensing.dart b/lib/blocs/sensing.dart index 4ce5d2ba..24022afa 100644 --- a/lib/blocs/sensing.dart +++ b/lib/blocs/sensing.dart @@ -26,9 +26,7 @@ class Sensing { /// The deployment service used in this app. DeploymentService get deploymentService => - bloc.deploymentMode == DeploymentMode.local - ? SmartphoneDeploymentService() - : CarpDeploymentService(); + bloc.deploymentMode == DeploymentMode.local ? SmartphoneDeploymentService() : CarpDeploymentService(); /// The study running on this phone. /// Only available after [addStudy] is called. @@ -51,13 +49,10 @@ class Sensing { SmartphoneDeploymentController? get controller => _controller; /// Is sensing running, i.e. has the study executor been started? - bool get isRunning => - (controller != null) && - controller!.executor.state == ExecutorState.started; + bool get isRunning => (controller != null) && controller!.executor.state == ExecutorState.started; /// The list of running - i.e. used - probes in this study. - List get runningProbes => - (_controller != null) ? _controller!.executor.probes : []; + List get runningProbes => (_controller != null) ? _controller!.executor.probes : []; /// The list of all device managers used in the current deployment. /// @@ -69,8 +64,7 @@ class Sensing { .deviceController .devices .values - .where((manager) => deployment!.devices - .any((element) => element.type == manager.type)) + .where((manager) => deployment!.devices.any((element) => element.type == manager.type)) .toList() : []; @@ -79,8 +73,7 @@ class Sensing { SmartPhoneClientManager().deviceController.smartphoneDeviceManager; /// The list of connected devices. - List? get connectedDevices => - SmartPhoneClientManager().deviceController.connectedDevices; + List? get connectedDevices => SmartPhoneClientManager().deviceController.connectedDevices; /// The singleton sensing instance factory Sensing() => _instance; @@ -131,13 +124,11 @@ class Sensing { Future addStudy() async { assert(SmartPhoneClientManager().isConfigured, 'The client manager is not yet configured. Call SmartPhoneClientManager().configure() before adding a study.'); - assert(bloc.study != null, - 'No study is provided. Cannot start deployment w/o a study.'); + assert(bloc.study != null, 'No study is provided. Cannot start deployment w/o a study.'); // Add the study to the client. _study = await SmartPhoneClientManager().addStudy(bloc.study!); - _controller = - SmartPhoneClientManager().getStudyRuntime(study!.studyDeploymentId); + _controller = SmartPhoneClientManager().getStudyRuntime(study!.studyDeploymentId); // Get the study controller and try to deploy the study. return await tryDeployment(); @@ -150,8 +141,7 @@ class Sensing { /// If not deployed before (i.e., cached) the study deployment will be /// fetched from the deployment service. Future tryDeployment() async { - assert(controller != null, - 'No study or controller is provided. Cannot start deployment w/o a study.'); + assert(controller != null, 'No study or controller is provided. Cannot start deployment w/o a study.'); StudyStatus status = await controller!.tryDeployment(useCached: true); @@ -163,8 +153,7 @@ class Sensing { await controller?.configure(); // Listening on the data stream and print them as json to the debug console - controller?.measurements - .listen((measurement) => debugPrint(toJsonString(measurement))); + controller?.measurements.listen((measurement) => debugPrint(toJsonString(measurement))); info('$runtimeType - Study added, deployment id: $studyDeploymentId'); return status; @@ -184,10 +173,7 @@ class Sensing { /// Get the status for the current study deployment. /// Returns null if the study is not yet deployed on this phone. Future getStudyDeploymentStatus() async => - studyDeploymentId != null - ? _status = await deploymentService - .getStudyDeploymentStatus(studyDeploymentId!) - : null; + studyDeploymentId != null ? _status = await deploymentService.getStudyDeploymentStatus(studyDeploymentId!) : null; /// Translate the title and description of all AppTask in the study protocol /// of the current master deployment. @@ -198,8 +184,7 @@ class Sensing { if (bloc.localization == null) return; // Fast out, if not configured or no protocol - if (controller?.status != StudyStatus.Deployed || - controller?.deployment == null) { + if (controller?.status != StudyStatus.Deployed || controller?.deployment == null) { return; } @@ -210,7 +195,6 @@ class Sensing { } } - info( - "$runtimeType - Study protocol translated to locale '${bloc.localization!.locale}'"); + info("$runtimeType - Study protocol translated to locale '${bloc.localization!.locale}'"); } } diff --git a/lib/blocs/util.dart b/lib/blocs/util.dart index f2c35de1..1713255c 100644 --- a/lib/blocs/util.dart +++ b/lib/blocs/util.dart @@ -1,8 +1,7 @@ part of carp_study_app; extension StringExtension on String { - String truncateTo(int maxLength) => - (length <= maxLength) ? this : '${substring(0, maxLength)}...'; + String truncateTo(int maxLength) => (length <= maxLength) ? this : '${substring(0, maxLength)}...'; } extension Humanize on Duration { diff --git a/lib/carp_study_app.dart b/lib/carp_study_app.dart index 43ac5389..03c24104 100644 --- a/lib/carp_study_app.dart +++ b/lib/carp_study_app.dart @@ -8,8 +8,7 @@ class CarpStudyApp extends StatefulWidget { /// Reload language translations and re-build the entire app. static void reloadLocale(BuildContext context) async { - CarpStudyAppState? state = - context.findAncestorStateOfType(); + CarpStudyAppState? state = context.findAncestorStateOfType(); state?.reloadLocale(); } @@ -34,8 +33,7 @@ class CarpStudyAppState extends State { routes: [ ShellRoute( navigatorKey: _shellNavigatorKey, - builder: (BuildContext context, GoRouterState state, Widget child) => - HomePage(child: child), + builder: (BuildContext context, GoRouterState state, Widget child) => HomePage(child: child), routes: [ // This is the root route, handling the onboarding. // The flow of logic is: @@ -87,8 +85,7 @@ class CarpStudyAppState extends State { path: DataVisualizationPage.route, parentNavigatorKey: _shellNavigatorKey, pageBuilder: (context, state) => CustomTransitionPage( - child: DataVisualizationPage( - bloc.appViewModel.dataVisualizationPageViewModel), + child: DataVisualizationPage(bloc.appViewModel.dataVisualizationPageViewModel), transitionsBuilder: bottomNavigationBarAnimation, ), ), @@ -120,8 +117,7 @@ class CarpStudyAppState extends State { GoRoute( path: ParticipantDataPage.route, parentNavigatorKey: _rootNavigatorKey, - builder: (context, state) => ParticipantDataPage( - model: bloc.appViewModel.participantDataPageViewModel), + builder: (context, state) => ParticipantDataPage(model: bloc.appViewModel.participantDataPageViewModel), ), GoRoute( path: '/task/:taskId', @@ -147,8 +143,7 @@ class CarpStudyAppState extends State { GoRoute( path: '${MessageDetailsPage.route}/:messageId', parentNavigatorKey: _rootNavigatorKey, - builder: (context, state) => MessageDetailsPage( - messageId: state.pathParameters['messageId'] ?? ''), + builder: (context, state) => MessageDetailsPage(messageId: state.pathParameters['messageId'] ?? ''), ), GoRoute( path: '${InvitationDetailsPage.route}/:invitationId', @@ -161,11 +156,9 @@ class CarpStudyAppState extends State { GoRoute( path: InvitationListPage.route, parentNavigatorKey: _rootNavigatorKey, - redirect: (context, state) => bloc.study != null - ? InformedConsentPage.route - : (bloc.user == null ? LoginPage.route : null), - builder: (context, state) => InvitationListPage( - model: bloc.appViewModel.invitationsListViewModel), + redirect: (context, state) => + bloc.study != null ? InformedConsentPage.route : (bloc.user == null ? LoginPage.route : null), + builder: (context, state) => InvitationListPage(model: bloc.appViewModel.invitationsListViewModel), ), ], debugLogDiagnostics: true, @@ -173,8 +166,7 @@ class CarpStudyAppState extends State { /// Research Package translations, incl. both local language assets plus /// translations of informed consent and surveys downloaded from CARP - final RPLocalizationsDelegate rpLocalizationsDelegate = - RPLocalizationsDelegate( + final RPLocalizationsDelegate rpLocalizationsDelegate = RPLocalizationsDelegate( loaders: [ const AssetLocalizationLoader(), bloc.localizationLoader, diff --git a/lib/data/carp_backend.dart b/lib/data/carp_backend.dart index e51e2bd6..2ee5b6be 100644 --- a/lib/data/carp_backend.dart +++ b/lib/data/carp_backend.dart @@ -141,17 +141,14 @@ class CarpBackend { Future> getInvitations() async { CarpParticipationService().configureFrom(CarpService()); - invitations = - await CarpParticipationService().getActiveParticipationInvitations(); + invitations = await CarpParticipationService().getActiveParticipationInvitations(); // Filter the invitations to only include those that // have a smartphone as a device in [ActiveParticipationInvitation.assignedDevices] list // (i.e. the invitation is for a smartphone). // This is done to avoid showing invitations for other devices (e.g. [WebBrowser]). - invitations.removeWhere((invitation) => - invitation.assignedDevices - ?.any((device) => device.device is! Smartphone) ?? - false); + invitations.removeWhere( + (invitation) => invitation.assignedDevices?.any((device) => device.device is! Smartphone) ?? false); return invitations; } @@ -178,8 +175,7 @@ class CarpBackend { return null; } if (participant == null) { - warning( - '$runtimeType - No participant (no invitation has been accepted).'); + warning('$runtimeType - No participant (no invitation has been accepted).'); return null; } @@ -189,8 +185,7 @@ class CarpBackend { (result) => result is RPConsentSignatureResult, ) as RPConsentSignatureResult; } catch (_) { - warning( - '$runtimeType - No signed informed consent found to be uploaded.'); + warning('$runtimeType - No signed informed consent found to be uploaded.'); return null; } @@ -205,24 +200,18 @@ class CarpBackend { ); try { - await CarpParticipationService() - .participation() - .setInformedConsent(uploadedConsent); + await CarpParticipationService().participation().setInformedConsent(uploadedConsent); info('$runtimeType - Informed consent document uploaded successfully for ' 'deployment id: ${bloc.study?.studyDeploymentId}'); } on Exception { - warning( - '$runtimeType - Informed consent upload failed for username: $username'); + warning('$runtimeType - Informed consent upload failed for username: $username'); } return uploadedConsent; } - Future? getInformedConsentByRole( - String studyDeploymentId, String? role) async { - return await CarpParticipationService() - .participation(studyDeploymentId) - .getInformedConsentByRole(role); + Future? getInformedConsentByRole(String studyDeploymentId, String? role) async { + return await CarpParticipationService().participation(studyDeploymentId).getInformedConsentByRole(role); } } diff --git a/lib/data/local_participation_service.dart b/lib/data/local_participation_service.dart index 610ac23b..67c543d2 100644 --- a/lib/data/local_participation_service.dart +++ b/lib/data/local_participation_service.dart @@ -3,8 +3,7 @@ part of carp_study_app; /// A local [ParticipationService] that does not connect to any backend. /// This is used when running in [DeploymentMode.local]. class LocalParticipationService implements ParticipationService { - static final LocalParticipationService _instance = - LocalParticipationService._(); + static final LocalParticipationService _instance = LocalParticipationService._(); LocalParticipationService._(); @@ -12,9 +11,7 @@ class LocalParticipationService implements ParticipationService { factory LocalParticipationService() => _instance; @override - Future> getActiveParticipationInvitations( - [String? accountId]) async => - []; + Future> getActiveParticipationInvitations([String? accountId]) async => []; @override Future getParticipantData(String studyDeploymentId) async => diff --git a/lib/data/local_resource_manager.dart b/lib/data/local_resource_manager.dart index fafdba4b..4afe1432 100644 --- a/lib/data/local_resource_manager.dart +++ b/lib/data/local_resource_manager.dart @@ -17,11 +17,7 @@ part of carp_study_app; /// Note that the 'id' of the protocol in the [getStudyProtocol] method is ignored. /// The 'protocol.json' file is always loaded. class LocalResourceManager - implements - InformedConsentManager, - LocalizationManager, - MessageManager, - StudyProtocolManager { + implements InformedConsentManager, LocalizationManager, MessageManager, StudyProtocolManager { /// The path to the json files to be loaded using this resource manager. static final String basePath = 'assets/carp'; @@ -49,10 +45,8 @@ class LocalResourceManager Future getInformedConsent({bool refresh = false}) async { if (_informedConsent == null) { try { - var jsonString = - await rootBundle.loadString('$basePath/resources/consent.json'); - Map jsonMap = - json.decode(jsonString) as Map; + var jsonString = await rootBundle.loadString('$basePath/resources/consent.json'); + Map jsonMap = json.decode(jsonString) as Map; _informedConsent = RPOrderedTask.fromJson(jsonMap); } catch (error) { warning("$runtimeType - Could not load a local informed consent. " @@ -85,10 +79,8 @@ class LocalResourceManager var path = '$basePath/lang/${locale.languageCode}.json'; var jsonString = await rootBundle.loadString(path); - Map jsonMap = - json.decode(jsonString) as Map; - _translations = - jsonMap.map((key, value) => MapEntry(key, value.toString())); + Map jsonMap = json.decode(jsonString) as Map; + _translations = jsonMap.map((key, value) => MapEntry(key, value.toString())); } return _translations!; } @@ -119,36 +111,28 @@ class LocalResourceManager }) async { if (_messages.isEmpty) { final assetManifest = await AssetManifest.loadFromAssetBundle(rootBundle); - final files = assetManifest - .listAssets() - .where((string) => string.startsWith("$basePath/messages/")) - .toList(); + final files = assetManifest.listAssets().where((string) => string.startsWith("$basePath/messages/")).toList(); for (var file in files) { var jsonString = await rootBundle.loadString(file); - Map jsonMap = - json.decode(jsonString) as Map; + Map jsonMap = json.decode(jsonString) as Map; var message = Message.fromJson(jsonMap); _messages[message.id] = message; } } - return _messages.values - .toList() - .sublist(0, (count! < _messages.length) ? count : _messages.length); + return _messages.values.toList().sublist(0, (count! < _messages.length) ? count : _messages.length); } @override Future getMessage(String messageId) async => _messages[messageId]; @override - Future setMessage(Message message) async => - _messages[message.id] = message; + Future setMessage(Message message) async => _messages[message.id] = message; @override - Future deleteMessage(String messageId) async => - _messages.remove(messageId); + Future deleteMessage(String messageId) async => _messages.remove(messageId); @override Future deleteAllMessages() async => _messages.clear(); @@ -159,11 +143,9 @@ class LocalResourceManager Future getStudyProtocol(String id) async { if (_protocol == null) { try { - var jsonString = - await rootBundle.loadString('$basePath/resources/protocol.json'); + var jsonString = await rootBundle.loadString('$basePath/resources/protocol.json'); - Map jsonMap = - json.decode(jsonString) as Map; + Map jsonMap = json.decode(jsonString) as Map; _protocol = SmartphoneStudyProtocol.fromJson(jsonMap); if (_protocol?.dataEndPoint?.type != null) { diff --git a/lib/data/local_settings.dart b/lib/data/local_settings.dart index a5194c1a..461d8034 100644 --- a/lib/data/local_settings.dart +++ b/lib/data/local_settings.dart @@ -35,9 +35,7 @@ class LocalSettings { if (_user == null) { String? userString = Settings().preferences!.getString(userKey); - _user = (userString != null) - ? CarpUser.fromJson(jsonDecode(userString) as Map) - : null; + _user = (userString != null) ? CarpUser.fromJson(jsonDecode(userString) as Map) : null; } return _user; } @@ -62,9 +60,7 @@ class LocalSettings { Participant? get participant { if (_participant == null) { String? userString = Settings().preferences!.getString(participantKey); - _participant = (userString != null) - ? Participant.fromJson(jsonDecode(userString) as Map) - : null; + _participant = (userString != null) ? Participant.fromJson(jsonDecode(userString) as Map) : null; } return _participant; } @@ -72,9 +68,7 @@ class LocalSettings { set participant(Participant? participant) { _participant = participant; if (participant != null) { - Settings() - .preferences! - .setString(participantKey, jsonEncode(participant.toJson())); + Settings().preferences!.setString(participantKey, jsonEncode(participant.toJson())); } else { Settings().preferences!.remove(participantKey); } @@ -86,10 +80,8 @@ class LocalSettings { SmartphoneStudy? get study { if (_study != null) return _study; var jsonString = Settings().preferences?.getString(studyKey); - return _study = (jsonString == null) - ? null - : _$SmartphoneStudyFromJson( - json.decode(jsonString) as Map); + return _study = + (jsonString == null) ? null : _$SmartphoneStudyFromJson(json.decode(jsonString) as Map); } set study(SmartphoneStudy? study) { @@ -105,10 +97,7 @@ class LocalSettings { } bool get hasSeenBluetoothConnectionInstructions => - Settings() - .preferences - ?.getBool('hasSeenBluetoothConnectionInstructions') ?? - false; + Settings().preferences?.getBool('hasSeenBluetoothConnectionInstructions') ?? false; set hasSeenBluetoothConnectionInstructions(bool seen) { Settings().preferences?.setBool( @@ -117,10 +106,8 @@ class LocalSettings { ); } - bool get isAnonymous => - Settings().preferences!.getBool('isAnonymous') ?? false; - set isAnonymous(bool value) => - Settings().preferences!.setBool('isAnonymous', value); + bool get isAnonymous => Settings().preferences!.getBool('isAnonymous') ?? false; + set isAnonymous(bool value) => Settings().preferences!.setBool('isAnonymous', value); /// The study deployment id for the currently running deployment. String? get studyDeploymentId => _study?.studyDeploymentId; @@ -142,18 +129,15 @@ class LocalSettings { await Settings().preferences!.remove(userKey); } - Future get deploymentBasePath async => (studyDeploymentId == null) - ? null - : await Settings().getDeploymentBasePath(studyDeploymentId!); + Future get deploymentBasePath async => + (studyDeploymentId == null) ? null : await Settings().getDeploymentBasePath(studyDeploymentId!); - Future get cacheBasePath async => (studyDeploymentId == null) - ? null - : await Settings().getCacheBasePath(studyDeploymentId!); + Future get cacheBasePath async => + (studyDeploymentId == null) ? null : await Settings().getCacheBasePath(studyDeploymentId!); } // Need to create our own JSON serializers here, since SmartphoneStudy is not made serializable -Map _$SmartphoneStudyToJson(SmartphoneStudy study) => - { +Map _$SmartphoneStudyToJson(SmartphoneStudy study) => { 'studyId': study.studyId, 'studyDeploymentId': study.studyDeploymentId, 'deviceRoleName': study.deviceRoleName, @@ -161,8 +145,7 @@ Map _$SmartphoneStudyToJson(SmartphoneStudy study) => 'participantRoleName': study.participantRoleName, }; -SmartphoneStudy _$SmartphoneStudyFromJson(Map json) => - SmartphoneStudy( +SmartphoneStudy _$SmartphoneStudyFromJson(Map json) => SmartphoneStudy( studyId: json['studyId'] as String?, studyDeploymentId: json['studyDeploymentId'] as String, deviceRoleName: json['deviceRoleName'] as String, diff --git a/lib/data/localization_loader.dart b/lib/data/localization_loader.dart index 4f7c81e1..5ec67c9b 100644 --- a/lib/data/localization_loader.dart +++ b/lib/data/localization_loader.dart @@ -15,8 +15,7 @@ class ResourceLocalizationLoader implements LocalizationLoader { translations = await localizationManager.getLocalizations(locale) ?? {}; info("$runtimeType - translations for ยด$locale' loaded."); } catch (error) { - warning( - "$runtimeType - could not load translations for '$locale' - $error"); + warning("$runtimeType - could not load translations for '$locale' - $error"); } return translations; diff --git a/lib/data/participant.dart b/lib/data/participant.dart index df71905e..e8f88857 100644 --- a/lib/data/participant.dart +++ b/lib/data/participant.dart @@ -29,11 +29,9 @@ class Participant { studyDeploymentId: invitation.studyDeploymentId, deviceRoleName: invitation.assignedDevices?.first.device.roleName, participantId: invitation.participation.participantId, - participantRoleName: - invitation.participation.assignedRoles.roleNames?.first, + participantRoleName: invitation.participation.assignedRoles.roleNames?.first, ); - factory Participant.fromJson(Map json) => - _$ParticipantFromJson(json); + factory Participant.fromJson(Map json) => _$ParticipantFromJson(json); Map toJson() => _$ParticipantToJson(this); } diff --git a/lib/main.g.dart b/lib/main.g.dart index cb297781..b3cd016d 100644 --- a/lib/main.g.dart +++ b/lib/main.g.dart @@ -12,37 +12,30 @@ Participant _$ParticipantFromJson(Map json) => Participant( deviceRoleName: json['deviceRoleName'] as String?, participantId: json['participantId'] as String?, participantRoleName: json['participantRoleName'] as String?, - hasInformedConsentBeenAccepted: - json['hasInformedConsentBeenAccepted'] as bool? ?? false, + hasInformedConsentBeenAccepted: json['hasInformedConsentBeenAccepted'] as bool? ?? false, ); -Map _$ParticipantToJson(Participant instance) => - { +Map _$ParticipantToJson(Participant instance) => { if (instance.studyId case final value?) 'studyId': value, - if (instance.studyDeploymentId case final value?) - 'studyDeploymentId': value, + if (instance.studyDeploymentId case final value?) 'studyDeploymentId': value, if (instance.deviceRoleName case final value?) 'deviceRoleName': value, if (instance.participantId case final value?) 'participantId': value, - if (instance.participantRoleName case final value?) - 'participantRoleName': value, + if (instance.participantRoleName case final value?) 'participantRoleName': value, 'hasInformedConsentBeenAccepted': instance.hasInformedConsentBeenAccepted, }; -WeeklyActivities _$WeeklyActivitiesFromJson(Map json) => - WeeklyActivities() - ..activities = (json['activities'] as Map).map( - (k, e) => MapEntry( - $enumDecode(_$ActivityTypeEnumMap, k), - (e as Map).map( - (k, e) => MapEntry(int.parse(k), (e as num).toInt()), - )), - ); - -Map _$WeeklyActivitiesToJson(WeeklyActivities instance) => - { - 'activities': instance.activities.map((k, e) => MapEntry( - _$ActivityTypeEnumMap[k]!, - e.map((k, e) => MapEntry(k.toString(), e)))), +WeeklyActivities _$WeeklyActivitiesFromJson(Map json) => WeeklyActivities() + ..activities = (json['activities'] as Map).map( + (k, e) => MapEntry( + $enumDecode(_$ActivityTypeEnumMap, k), + (e as Map).map( + (k, e) => MapEntry(int.parse(k), (e as num).toInt()), + )), + ); + +Map _$WeeklyActivitiesToJson(WeeklyActivities instance) => { + 'activities': instance.activities + .map((k, e) => MapEntry(_$ActivityTypeEnumMap[k]!, e.map((k, e) => MapEntry(k.toString(), e)))), }; const _$ActivityTypeEnumMap = { @@ -54,29 +47,23 @@ const _$ActivityTypeEnumMap = { ActivityType.UNKNOWN: 'UNKNOWN', }; -WeeklyMobility _$WeeklyMobilityFromJson(Map json) => - WeeklyMobility() - ..weekMobility = (json['weekMobility'] as Map).map( - (k, e) => MapEntry( - int.parse(k), DailyMobility.fromJson(e as Map)), - ); - -Map _$WeeklyMobilityToJson(WeeklyMobility instance) => - { - 'weekMobility': - instance.weekMobility.map((k, e) => MapEntry(k.toString(), e)), +WeeklyMobility _$WeeklyMobilityFromJson(Map json) => WeeklyMobility() + ..weekMobility = (json['weekMobility'] as Map).map( + (k, e) => MapEntry(int.parse(k), DailyMobility.fromJson(e as Map)), + ); + +Map _$WeeklyMobilityToJson(WeeklyMobility instance) => { + 'weekMobility': instance.weekMobility.map((k, e) => MapEntry(k.toString(), e)), }; -DailyMobility _$DailyMobilityFromJson(Map json) => - DailyMobility( +DailyMobility _$DailyMobilityFromJson(Map json) => DailyMobility( (json['weekday'] as num).toInt(), (json['places'] as num).toInt(), (json['homeStay'] as num).toInt(), (json['distance'] as num).toDouble(), ); -Map _$DailyMobilityToJson(DailyMobility instance) => - { +Map _$DailyMobilityToJson(DailyMobility instance) => { 'weekday': instance.weekday, 'places': instance.places, 'homeStay': instance.homeStay, @@ -88,41 +75,31 @@ WeeklySteps _$WeeklyStepsFromJson(Map json) => WeeklySteps() (k, e) => MapEntry(int.parse(k), (e as num).toInt()), ); -Map _$WeeklyStepsToJson(WeeklySteps instance) => - { - 'weeklySteps': - instance.weeklySteps.map((k, e) => MapEntry(k.toString(), e)), +Map _$WeeklyStepsToJson(WeeklySteps instance) => { + 'weeklySteps': instance.weeklySteps.map((k, e) => MapEntry(k.toString(), e)), }; -HourlyHeartRate _$HourlyHeartRateFromJson(Map json) => - HourlyHeartRate() - ..hourlyHeartRate = (json['hourlyHeartRate'] as Map).map( - (k, e) => MapEntry(int.parse(k), - HeartRateMinMaxPrHour.fromJson(e as Map)), - ) - ..lastUpdated = DateTime.parse(json['lastUpdated'] as String) - ..maxHeartRate = (json['maxHeartRate'] as num?)?.toDouble() - ..minHeartRate = (json['minHeartRate'] as num?)?.toDouble(); - -Map _$HourlyHeartRateToJson(HourlyHeartRate instance) => - { - 'hourlyHeartRate': - instance.hourlyHeartRate.map((k, e) => MapEntry(k.toString(), e)), +HourlyHeartRate _$HourlyHeartRateFromJson(Map json) => HourlyHeartRate() + ..hourlyHeartRate = (json['hourlyHeartRate'] as Map).map( + (k, e) => MapEntry(int.parse(k), HeartRateMinMaxPrHour.fromJson(e as Map)), + ) + ..lastUpdated = DateTime.parse(json['lastUpdated'] as String) + ..maxHeartRate = (json['maxHeartRate'] as num?)?.toDouble() + ..minHeartRate = (json['minHeartRate'] as num?)?.toDouble(); + +Map _$HourlyHeartRateToJson(HourlyHeartRate instance) => { + 'hourlyHeartRate': instance.hourlyHeartRate.map((k, e) => MapEntry(k.toString(), e)), 'lastUpdated': instance.lastUpdated.toIso8601String(), if (instance.maxHeartRate case final value?) 'maxHeartRate': value, if (instance.minHeartRate case final value?) 'minHeartRate': value, }; -HeartRateMinMaxPrHour _$HeartRateMinMaxPrHourFromJson( - Map json) => - HeartRateMinMaxPrHour( +HeartRateMinMaxPrHour _$HeartRateMinMaxPrHourFromJson(Map json) => HeartRateMinMaxPrHour( (json['min'] as num?)?.toDouble(), (json['max'] as num?)?.toDouble(), ); -Map _$HeartRateMinMaxPrHourToJson( - HeartRateMinMaxPrHour instance) => - { +Map _$HeartRateMinMaxPrHourToJson(HeartRateMinMaxPrHour instance) => { if (instance.min case final value?) 'min': value, if (instance.max case final value?) 'max': value, }; diff --git a/lib/ui/cards/activity_card.dart b/lib/ui/cards/activity_card.dart index 68fe931f..8847b104 100644 --- a/lib/ui/cards/activity_card.dart +++ b/lib/ui/cards/activity_card.dart @@ -3,9 +3,7 @@ part of carp_study_app; class ActivityCard extends StatefulWidget { final ActivityCardViewModel model; final List colors; - const ActivityCard(this.model, - {super.key, - this.colors = const [CACHET.CAQUI, CACHET.OCEAN, CACHET.BLUE_2]}); + const ActivityCard(this.model, {super.key, this.colors = const [CACHET.CAQUI, CACHET.OCEAN, CACHET.BLUE_2]}); @override State createState() => ActivityCardState(); @@ -21,18 +19,14 @@ class ActivityCardState extends State { final betweenSpace = 2.4; - List> activitiesList = List.generate( - 7, (_) => List.generate(4, (index) => index, growable: false), - growable: false); + List> activitiesList = + List.generate(7, (_) => List.generate(4, (index) => index, growable: false), growable: false); @override void initState() { - _walk = - widget.model.activities[ActivityType.WALKING]![DateTime.now().weekday]; - _run = - widget.model.activities[ActivityType.RUNNING]![DateTime.now().weekday]; - _cycle = widget - .model.activities[ActivityType.ON_BICYCLE]![DateTime.now().weekday]; + _walk = widget.model.activities[ActivityType.WALKING]![DateTime.now().weekday]; + _run = widget.model.activities[ActivityType.RUNNING]![DateTime.now().weekday]; + _cycle = widget.model.activities[ActivityType.ON_BICYCLE]![DateTime.now().weekday]; /// Doing some conversions to make the data readable by the chart /// The data is organized in a list of lists, where each list represents a day @@ -125,10 +119,7 @@ class ActivityCardState extends State { padding: const EdgeInsets.all(4.0), child: Text( locale.translate('cards.activity.walking'), - style: fs12fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey800), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey800), ), ), ], @@ -150,10 +141,7 @@ class ActivityCardState extends State { padding: const EdgeInsets.all(4.0), child: Text( locale.translate('cards.activity.running'), - style: fs12fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey800), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey800), ), ), ], @@ -174,9 +162,7 @@ class ActivityCardState extends State { child: Text( locale.translate('cards.activity.cycling'), style: fs12fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey800, + color: Theme.of(context).extension()!.grey800, ), ), ), @@ -216,16 +202,12 @@ class ActivityCardState extends State { enabled: false, touchCallback: (p0, p1) { setState(() { - touchedIndex = (p1?.spot?.touchedBarGroupIndex ?? - DateTime.now().weekday - 1) + - 1; + touchedIndex = (p1?.spot?.touchedBarGroupIndex ?? DateTime.now().weekday - 1) + 1; }); }, ), groupsSpace: 4, - barGroups: activitiesList - .map((e) => generateGroupData(e[0], e[1], e[2], e[3])) - .toList(), + barGroups: activitiesList.map((e) => generateGroupData(e[0], e[1], e[2], e[3])).toList(), maxY: (maxValue) * 1.2, gridData: FlGridData( show: true, @@ -301,9 +283,7 @@ class ActivityCardState extends State { meta: meta, space: 6, child: Text( - value.toInt() % meta.appliedInterval == 0 - ? value.toInt().toString() - : '', + value.toInt() % meta.appliedInterval == 0 ? value.toInt().toString() : '', style: fs14ls1.copyWith( color: Theme.of(context).extension()!.grey600, ), diff --git a/lib/ui/cards/anonymous_card.dart b/lib/ui/cards/anonymous_card.dart index c135d51a..d776831c 100644 --- a/lib/ui/cards/anonymous_card.dart +++ b/lib/ui/cards/anonymous_card.dart @@ -22,15 +22,13 @@ class AnonymousCard extends StatelessWidget { children: [ Expanded( child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, vertical: 22.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 22.0), child: Row( children: [ Column( children: [ Padding( - padding: const EdgeInsets.symmetric( - horizontal: 6.0, vertical: 4), + padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 4), child: CircleAvatar( radius: 18, backgroundColor: CACHET.ANONYMOUS, @@ -56,9 +54,7 @@ class AnonymousCard extends StatelessWidget { child: Text( locale.translate('pages.about.anonymous.message'), style: fs16fw600.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, fontSize: 14, ), ), diff --git a/lib/ui/cards/distance_card.dart b/lib/ui/cards/distance_card.dart index 857ad3ae..e5466e81 100644 --- a/lib/ui/cards/distance_card.dart +++ b/lib/ui/cards/distance_card.dart @@ -4,9 +4,7 @@ class DistanceCard extends StatefulWidget { final List colors; final MobilityCardViewModel model; - const DistanceCard(this.model, - {super.key, - this.colors = const [CACHET.BLUE_1, CACHET.BLUE_2, CACHET.BLUE_3]}); + const DistanceCard(this.model, {super.key, this.colors = const [CACHET.BLUE_1, CACHET.BLUE_2, CACHET.BLUE_3]}); @override State createState() => _DistanceCardState(); @@ -107,9 +105,7 @@ class _DistanceCardState extends State { enabled: false, touchCallback: (p0, p1) { setState(() { - touchedIndex = - (p1?.spot?.touchedBarGroupIndex ?? DateTime.now().weekday - 1) + - 1; + touchedIndex = (p1?.spot?.touchedBarGroupIndex ?? DateTime.now().weekday - 1) + 1; }); }, ), @@ -138,9 +134,7 @@ class _DistanceCardState extends State { } List get barChartsGroups { - return widget.model.weekData.entries - .map((e) => generateGroupData(e.key, e.value.distance)) - .toList(); + return widget.model.weekData.entries.map((e) => generateGroupData(e.key, e.value.distance)).toList(); } BarChartGroupData generateGroupData(int x, double step) { @@ -171,9 +165,7 @@ class _DistanceCardState extends State { meta: meta, space: 6, child: Text( - value.toInt() % meta.appliedInterval == 0 - ? value.toInt().toString() - : '', + value.toInt() % meta.appliedInterval == 0 ? value.toInt().toString() : '', style: fs14ls1.copyWith( color: Theme.of(context).extension()!.grey600, ), diff --git a/lib/ui/cards/heart_rate_card.dart b/lib/ui/cards/heart_rate_card.dart index 570fc7de..5a6879e1 100644 --- a/lib/ui/cards/heart_rate_card.dart +++ b/lib/ui/cards/heart_rate_card.dart @@ -4,15 +4,13 @@ class HeartRateCardWidget extends StatefulWidget { final HeartRateCardViewModel model; const HeartRateCardWidget(this.model, {super.key}); - factory HeartRateCardWidget.withSampleData(HeartRateCardViewModel model) => - HeartRateCardWidget(model); + factory HeartRateCardWidget.withSampleData(HeartRateCardViewModel model) => HeartRateCardWidget(model); @override HeartRateCardWidgetState createState() => HeartRateCardWidgetState(); } -class HeartRateCardWidgetState extends State - with SingleTickerProviderStateMixin { +class HeartRateCardWidgetState extends State with SingleTickerProviderStateMixin { late AnimationController animationController; late Animation animation; @@ -83,18 +81,14 @@ class HeartRateCardWidgetState extends State Container( margin: const EdgeInsets.only(left: 8, right: 4, bottom: 4), child: Text( - min == null || max == null - ? '-' - : '${(min.toInt())} - ${(max.toInt())}', + min == null || max == null ? '-' : '${(min.toInt())} - ${(max.toInt())}', style: fs28fw700, ), ), Padding( padding: const EdgeInsets.only(bottom: 10), child: Text( - min == null || max == null - ? '' - : locale.translate('cards.heartrate.bpm'), + min == null || max == null ? '' : locale.translate('cards.heartrate.bpm'), style: fs10fw700.copyWith( fontSize: 12, color: Theme.of(context).extension()!.grey600, @@ -134,8 +128,7 @@ class HeartRateCardWidgetState extends State children: [ RepaintBoundary( child: ScaleTransition( - scale: Tween(begin: 1, end: 1) - .animate(animationController), + scale: Tween(begin: 1, end: 1).animate(animationController), child: Icon( Icons.favorite, color: CACHET.HEART_RATE_RED, @@ -146,8 +139,7 @@ class HeartRateCardWidgetState extends State Text( locale.translate('cards.heartrate.bpm'), style: fs10fw700.copyWith( - color: - Theme.of(context).extension()!.grey600, + color: Theme.of(context).extension()!.grey600, ), ), ], @@ -177,11 +169,9 @@ class HeartRateCardWidgetState extends State textAlign: TextAlign.start, children: [ TextSpan( - text: - locale.translate('cards.heartrate.range').toUpperCase(), + text: locale.translate('cards.heartrate.range').toUpperCase(), style: TextStyle( - color: - Theme.of(context).primaryTextTheme.bodySmall?.color, + color: Theme.of(context).primaryTextTheme.bodySmall?.color, fontWeight: FontWeight.bold, ), ), @@ -196,16 +186,14 @@ class HeartRateCardWidgetState extends State text: "${locale.translate('cards.heartrate.bpm')}\n", style: TextStyle( fontWeight: FontWeight.bold, - color: - Theme.of(context).primaryTextTheme.bodySmall?.color, + color: Theme.of(context).primaryTextTheme.bodySmall?.color, fontSize: 20, ), ), TextSpan( text: "$groupIndex-${groupIndex + 1} ", style: TextStyle( - color: - Theme.of(context).primaryTextTheme.bodySmall?.color, + color: Theme.of(context).primaryTextTheme.bodySmall?.color, fontWeight: FontWeight.bold, fontSize: 20, ), @@ -248,10 +236,8 @@ class HeartRateCardWidgetState extends State strokeWidth: 1, ), checkToShowHorizontalLine: (value) => value % 100 == 0, - getDrawingVerticalLine: (value) => FlLine( - color: Colors.grey.withValues(alpha: 0.2), - strokeWidth: 1, - dashArray: [3, 2]), + getDrawingVerticalLine: (value) => + FlLine(color: Colors.grey.withValues(alpha: 0.2), strokeWidth: 1, dashArray: [3, 2]), verticalInterval: 1 / 24, checkToShowVerticalLine: (value) { if ((value * 24).round() == 6) return true; @@ -308,9 +294,7 @@ class HeartRateCardWidgetState extends State meta: meta, space: 6, child: Text( - value.toInt() % meta.appliedInterval == 0 - ? value.toInt().toString() - : '', + value.toInt() % meta.appliedInterval == 0 ? value.toInt().toString() : '', style: fs14ls1.copyWith( color: Theme.of(context).extension()!.grey600, ), @@ -319,20 +303,19 @@ class HeartRateCardWidgetState extends State ); } - List getHeartRateBars() => - widget.model.hourlyHeartRate.entries - .map((value) => BarChartGroupData( - x: value.key, - barRods: [ - BarChartRodData( - fromY: value.value.min, - toY: value.value.max ?? 0, - color: CACHET.HEART_RATE_RED, - width: 6, - ), - ], - )) - .toList(); + List getHeartRateBars() => widget.model.hourlyHeartRate.entries + .map((value) => BarChartGroupData( + x: value.key, + barRods: [ + BarChartRodData( + fromY: value.value.min, + toY: value.value.max ?? 0, + color: CACHET.HEART_RATE_RED, + width: 6, + ), + ], + )) + .toList(); } class HeartRateOuterStatefulWidget extends StatefulWidget { @@ -340,12 +323,10 @@ class HeartRateOuterStatefulWidget extends StatefulWidget { const HeartRateOuterStatefulWidget(this.model, {super.key}); @override - HeartRateOuterStatefulWidgetState createState() => - HeartRateOuterStatefulWidgetState(); + HeartRateOuterStatefulWidgetState createState() => HeartRateOuterStatefulWidgetState(); } -class HeartRateOuterStatefulWidgetState - extends State { +class HeartRateOuterStatefulWidgetState extends State { @override Widget build(BuildContext context) { return HeartRateCardWidget.withSampleData(widget.model); diff --git a/lib/ui/cards/media_card.dart b/lib/ui/cards/media_card.dart index c69d3c0f..a8c715e8 100644 --- a/lib/ui/cards/media_card.dart +++ b/lib/ui/cards/media_card.dart @@ -3,8 +3,7 @@ part of carp_study_app; class MediaCardWidget extends StatefulWidget { final List modelsList; final List colors; - const MediaCardWidget(this.modelsList, - {super.key, this.colors = CACHET.COLOR_LIST}); + const MediaCardWidget(this.modelsList, {super.key, this.colors = CACHET.COLOR_LIST}); @override MediaCardWidgetState createState() => MediaCardWidgetState(); } @@ -41,27 +40,20 @@ class MediaCardWidgetState extends State { .entries .map( (entry) => Column( - crossAxisAlignment: - CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 15), Text( '${entry.value.tasksDone} ${locale.translate('cards.${entry.value.taskType}.title')}', - style: - fs16fw400ls1.copyWith(fontSize: 14), + style: fs16fw400ls1.copyWith(fontSize: 14), ), - LayoutBuilder(builder: - (BuildContext context, - BoxConstraints constraints) { + LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { return HorizontalBar( parentWidth: constraints.maxWidth, names: entry.value.taskCount - .map((task) => locale - .translate(task.title)) - .toList(), - values: entry.value.taskCount - .map((task) => task.size) + .map((task) => locale.translate(task.title)) .toList(), + values: entry.value.taskCount.map((task) => task.size).toList(), colors: CACHET.COLOR_LIST, height: 18); }), diff --git a/lib/ui/cards/mobility_card.dart b/lib/ui/cards/mobility_card.dart index 20278945..b2362860 100644 --- a/lib/ui/cards/mobility_card.dart +++ b/lib/ui/cards/mobility_card.dart @@ -4,9 +4,7 @@ class MobilityCard extends StatefulWidget { final List colors; final MobilityCardViewModel model; - const MobilityCard(this.model, - {super.key, - this.colors = const [CACHET.CAQUI, CACHET.ORANGE, CACHET.BLUE_3]}); + const MobilityCard(this.model, {super.key, this.colors = const [CACHET.CAQUI, CACHET.ORANGE, CACHET.BLUE_3]}); @override State createState() => _MobilityCardState(); @@ -48,8 +46,7 @@ class _MobilityCardState extends State { child: Text( "${locale.translate('cards.mobility.homestay')} ${_getDayName(touchedIndex)}", style: fs12fw700.copyWith( - color: - Theme.of(context).extension()!.grey900!, + color: Theme.of(context).extension()!.grey900!, ), ), ), @@ -90,10 +87,7 @@ class _MobilityCardState extends State { padding: const EdgeInsets.all(4.0), child: Text( locale.translate('cards.mobility.places'), - style: fs12fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey800), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey800), ), ), ], @@ -131,9 +125,7 @@ class _MobilityCardState extends State { enabled: false, touchCallback: (p0, p1) { setState(() { - touchedIndex = - (p1?.spot?.touchedBarGroupIndex ?? DateTime.now().weekday - 1) + - 1; + touchedIndex = (p1?.spot?.touchedBarGroupIndex ?? DateTime.now().weekday - 1) + 1; }); }, ), @@ -204,9 +196,7 @@ class _MobilityCardState extends State { meta: meta, space: 6, child: Text( - value.toInt() % meta.appliedInterval == 0 - ? value.toInt().toString() - : '', + value.toInt() % meta.appliedInterval == 0 ? value.toInt().toString() : '', style: fs14ls1.copyWith( color: Theme.of(context).extension()!.grey600, ), @@ -219,9 +209,7 @@ class _MobilityCardState extends State { meta: meta, space: 6, child: Text( - value.toInt() % meta.appliedInterval == 0 - ? value.toInt().toString() - : '', + value.toInt() % meta.appliedInterval == 0 ? value.toInt().toString() : '', style: fs14ls1.copyWith( color: Theme.of(context).extension()!.grey600, ), diff --git a/lib/ui/cards/scoreboard_card.dart b/lib/ui/cards/scoreboard_card.dart index 2b38fc5b..4675357b 100644 --- a/lib/ui/cards/scoreboard_card.dart +++ b/lib/ui/cards/scoreboard_card.dart @@ -29,8 +29,7 @@ class ScoreboardCardState extends State { /// This is used in the [StudyPage] to make the header of the page. /// The delegate should retract from 110px to 40px when scrolling down. /// The animation should be simple and linear. A stretched header does not do anything. -class ScoreboardPersistentHeaderDelegate - extends SliverPersistentHeaderDelegate { +class ScoreboardPersistentHeaderDelegate extends SliverPersistentHeaderDelegate { TaskListPageViewModel model; RPLocalizations locale; @override @@ -46,8 +45,7 @@ class ScoreboardPersistentHeaderDelegate }); @override - Widget build( - BuildContext context, double shrinkOffset, bool overlapsContent) { + Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { double height = 110; double offsetForShrink = 50; @@ -55,40 +53,34 @@ class ScoreboardPersistentHeaderDelegate List childrenDays = [ Text(model.daysInStudy.toString(), style: fs36fw800.copyWith( - fontSize: calculateScrollAwareSizing( - shrinkOffset, fs20fw800.fontSize!, fs36fw800.fontSize!), + fontSize: calculateScrollAwareSizing(shrinkOffset, fs20fw800.fontSize!, fs36fw800.fontSize!), color: Theme.of(context).extension()!.grey900)), if (shrinkOffset < offsetForShrink) Text(locale.translate('cards.scoreboard.days'), - style: fs12fw700.copyWith( - color: Theme.of(context).extension()!.grey900)), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey900)), if (shrinkOffset > offsetForShrink) Padding( padding: const EdgeInsets.only(left: 8.0), child: Text(locale.translate('cards.scoreboard.days-short'), - style: fs12fw700.copyWith( - color: Theme.of(context).extension()!.grey900)), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey900)), ) ]; List childrenTasks = [ Text(model.tasksCompleted.toString(), style: fs36fw800.copyWith( - fontSize: calculateScrollAwareSizing( - shrinkOffset, fs20fw800.fontSize!, fs36fw800.fontSize!), + fontSize: calculateScrollAwareSizing(shrinkOffset, fs20fw800.fontSize!, fs36fw800.fontSize!), color: Theme.of(context).extension()!.primary)), if (shrinkOffset < offsetForShrink) Text(locale.translate('cards.scoreboard.tasks'), - style: fs12fw700.copyWith( - color: Theme.of(context).extension()!.primary)), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.primary)), if (shrinkOffset > offsetForShrink) Expanded( flex: 0, child: Padding( padding: const EdgeInsets.only(left: 8.0), child: Text(locale.translate('cards.scoreboard.tasks-short'), - style: fs12fw700.copyWith( - color: Theme.of(context).extension()!.primary)), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.primary)), ), ) ]; @@ -121,8 +113,7 @@ class ScoreboardPersistentHeaderDelegate Expanded( flex: 0, child: Container( - height: calculateScrollAwareSizing( - shrinkOffset, minExtent * 0.6, maxExtent * 0.6), + height: calculateScrollAwareSizing(shrinkOffset, minExtent * 0.6, maxExtent * 0.6), width: 2, decoration: BoxDecoration( color: Theme.of(context).dividerColor, @@ -150,8 +141,7 @@ class ScoreboardPersistentHeaderDelegate // A simple function that returns the font size from the scoreNumberStyle, but increasingly smaller when scrolling down. // Also used for the size of the divider in the middle - double calculateScrollAwareSizing( - double shrinkOffset, double minSize, double maxSize) { + double calculateScrollAwareSizing(double shrinkOffset, double minSize, double maxSize) { // Calculate the normalized shrinkOffset value in the range [0, 1] double normalizedShrinkOffset = shrinkOffset / maxExtent; @@ -168,13 +158,11 @@ class ScoreboardPersistentHeaderDelegate } @override - FloatingHeaderSnapConfiguration get snapConfiguration => - FloatingHeaderSnapConfiguration( + FloatingHeaderSnapConfiguration get snapConfiguration => FloatingHeaderSnapConfiguration( curve: Curves.linear, duration: const Duration(milliseconds: 100), ); @override - OverScrollHeaderStretchConfiguration get stretchConfiguration => - OverScrollHeaderStretchConfiguration(); + OverScrollHeaderStretchConfiguration get stretchConfiguration => OverScrollHeaderStretchConfiguration(); } diff --git a/lib/ui/cards/steps_card.dart b/lib/ui/cards/steps_card.dart index ffb40e14..681096dc 100644 --- a/lib/ui/cards/steps_card.dart +++ b/lib/ui/cards/steps_card.dart @@ -4,9 +4,7 @@ class StepsCardWidget extends StatefulWidget { final List colors; final StepsCardViewModel model; - const StepsCardWidget(this.model, - {super.key, - this.colors = const [CACHET.ORANGE, CACHET.BLUE_2, CACHET.BLUE_3]}); + const StepsCardWidget(this.model, {super.key, this.colors = const [CACHET.ORANGE, CACHET.BLUE_2, CACHET.BLUE_3]}); @override StepsCardWidgetState createState() => StepsCardWidgetState(); @@ -105,9 +103,7 @@ class StepsCardWidgetState extends State { enabled: false, touchCallback: (p0, p1) { setState(() { - touchedIndex = - (p1?.spot?.touchedBarGroupIndex ?? DateTime.now().weekday - 1) + - 1; + touchedIndex = (p1?.spot?.touchedBarGroupIndex ?? DateTime.now().weekday - 1) + 1; }); }, ), @@ -136,9 +132,7 @@ class StepsCardWidgetState extends State { } List get barChartsGroups { - return widget.model.weeklySteps.entries - .map((e) => generateGroupData(e.key, e.value)) - .toList(); + return widget.model.weeklySteps.entries.map((e) => generateGroupData(e.key, e.value)).toList(); } BarChartGroupData generateGroupData(int x, int step) { @@ -169,9 +163,7 @@ class StepsCardWidgetState extends State { meta: meta, space: 6, child: Text( - value.toInt() % meta.appliedInterval == 0 - ? value.toInt().toString() - : '', + value.toInt() % meta.appliedInterval == 0 ? value.toInt().toString() : '', style: fs14ls1.copyWith( color: Theme.of(context).extension()!.grey600, ), diff --git a/lib/ui/cards/study_progress_card.dart b/lib/ui/cards/study_progress_card.dart index 800b6b46..268b0dea 100644 --- a/lib/ui/cards/study_progress_card.dart +++ b/lib/ui/cards/study_progress_card.dart @@ -5,8 +5,7 @@ class StudyProgressCardWidget extends StatefulWidget { final List colors; const StudyProgressCardWidget(this.model, - {super.key, - this.colors = const [CACHET.BLUE_1, CACHET.RED_1, CACHET.GREY_6]}); + {super.key, this.colors = const [CACHET.BLUE_1, CACHET.RED_1, CACHET.GREY_6]}); @override StudyProgressCardWidgetState createState() => StudyProgressCardWidgetState(); @@ -32,34 +31,29 @@ class StudyProgressCardWidgetState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - Text(locale.translate('cards.study_progress.title'), - style: fs16fw400ls1), + Text(locale.translate('cards.study_progress.title'), style: fs16fw400ls1), ], ), ), SizedBox( height: 130, child: LayoutBuilder( - builder: - (BuildContext context, BoxConstraints constraints) { + builder: (BuildContext context, BoxConstraints constraints) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8.0), + padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: List.generate( widget.model.progress.length, (index) => Padding( - padding: - const EdgeInsets.symmetric(vertical: 4.0), + padding: const EdgeInsets.symmetric(vertical: 4.0), child: Row( children: [ Text( - widget.model.progress[index].value - .toString(), + widget.model.progress[index].value.toString(), style: TextStyle( fontSize: 22, fontWeight: FontWeight.bold, @@ -68,8 +62,7 @@ class StudyProgressCardWidgetState extends State { ), const SizedBox(width: 4), Text( - locale.translate( - widget.model.progress[index].state), + locale.translate(widget.model.progress[index].state), style: const TextStyle(fontSize: 16), ), ], @@ -80,20 +73,15 @@ class StudyProgressCardWidgetState extends State { ), // Circular Progress Representation Padding( - padding: - const EdgeInsets.only(bottom: 18, right: 24.0), + padding: const EdgeInsets.only(bottom: 18, right: 24.0), child: SizedBox( width: 104, height: 104, child: CustomPaint( painter: TaskProgressPainter( - values: widget.model.progress - .map((p) => p.value) - .toList(), + values: widget.model.progress.map((p) => p.value).toList(), colors: widget.colors, - faintColors: widget.colors - .map((c) => c.withValues(alpha: 0.2)) - .toList(), + faintColors: widget.colors.map((c) => c.withValues(alpha: 0.2)).toList(), ), ), ), @@ -118,8 +106,7 @@ class TaskProgressPainter extends CustomPainter { final List faintColors; final double pi = 3.141592; - TaskProgressPainter( - {required this.values, required this.colors, required this.faintColors}); + TaskProgressPainter({required this.values, required this.colors, required this.faintColors}); @override void paint(Canvas canvas, Size size) { diff --git a/lib/ui/cards/survey_card.dart b/lib/ui/cards/survey_card.dart index 579b1b1f..844985de 100644 --- a/lib/ui/cards/survey_card.dart +++ b/lib/ui/cards/survey_card.dart @@ -29,8 +29,7 @@ class _SurveyCardState extends State { children: [ Padding( padding: const EdgeInsets.only(left: 10.0), - child: Text(locale.translate('cards.survey.title').toUpperCase(), - style: fs16fw400ls1), + child: Text(locale.translate('cards.survey.title').toUpperCase(), style: fs16fw400ls1), ), SizedBox( height: 160, @@ -40,8 +39,7 @@ class _SurveyCardState extends State { Expanded( flex: 2, child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10.0, vertical: 8), + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: widget.model.tasksTable.entries.map((entry) { @@ -49,9 +47,7 @@ class _SurveyCardState extends State { width: 10, height: 10, decoration: BoxDecoration( - color: widget.colors[widget.model.tasksTable.keys - .toList() - .indexOf(entry.key)], + color: widget.colors[widget.model.tasksTable.keys.toList().indexOf(entry.key)], shape: BoxShape.circle, ), ); @@ -84,9 +80,7 @@ class _SurveyCardState extends State { Text( '$totalSurveys', style: fs24fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey800, + color: Theme.of(context).extension()!.grey800, ), ) ], @@ -105,8 +99,7 @@ class _SurveyCardState extends State { (entry) { return PieChartSectionData( // Color should be the next color in the list - color: widget - .colors[widget.model.tasksTable.keys.toList().indexOf(entry.key)], + color: widget.colors[widget.model.tasksTable.keys.toList().indexOf(entry.key)], value: entry.value.toDouble(), title: '${entry.value}', showTitle: false, diff --git a/lib/ui/carp_study_style.dart b/lib/ui/carp_study_style.dart index 0ac9bfce..ae555f1a 100644 --- a/lib/ui/carp_study_style.dart +++ b/lib/ui/carp_study_style.dart @@ -151,10 +151,10 @@ ThemeData carpStudyTheme = ThemeData.light().copyWith( fontWeight: FontWeight.w400, fontSize: 16.0, ), - titleMedium: ThemeData.light().textTheme.titleMedium!.copyWith( - fontWeight: FontWeight.w600, - fontSize: 20.0, - color: const Color(0xFF206FA2)), + titleMedium: ThemeData.light() + .textTheme + .titleMedium! + .copyWith(fontWeight: FontWeight.w600, fontSize: 20.0, color: const Color(0xFF206FA2)), titleLarge: ThemeData.light().textTheme.titleLarge!.copyWith( fontWeight: FontWeight.w500, fontSize: 20.0, @@ -163,8 +163,10 @@ ThemeData carpStudyTheme = ThemeData.light().copyWith( fontWeight: FontWeight.w700, fontSize: 30.0, ), - labelLarge: ThemeData.light().textTheme.labelLarge!.copyWith( - fontWeight: FontWeight.w500, fontSize: 16.0, color: Colors.white), + labelLarge: ThemeData.light() + .textTheme + .labelLarge! + .copyWith(fontWeight: FontWeight.w500, fontSize: 16.0, color: Colors.white), ) .apply( fontFamily: 'OpenSans', @@ -234,10 +236,10 @@ ThemeData carpStudyDarkTheme = ThemeData.dark().copyWith( fontWeight: FontWeight.w700, fontSize: 30.0, ), - labelLarge: ThemeData.dark().textTheme.labelLarge!.copyWith( - fontWeight: FontWeight.w500, - fontSize: 16.0, - color: Colors.grey.shade800), + labelLarge: ThemeData.dark() + .textTheme + .labelLarge! + .copyWith(fontWeight: FontWeight.w500, fontSize: 16.0, color: Colors.grey.shade800), ) .apply( fontFamily: 'OpenSans', diff --git a/lib/ui/colors.dart b/lib/ui/colors.dart index 4e04adb8..877216aa 100644 --- a/lib/ui/colors.dart +++ b/lib/ui/colors.dart @@ -57,8 +57,7 @@ class CACHET { static const Color HEART_RATE_RED = Color.fromRGBO(235, 75, 98, 1.0); - static Color pie = - createMaterialColor(const Color.fromRGBO(225, 244, 250, 1)); + static Color pie = createMaterialColor(const Color.fromRGBO(225, 244, 250, 1)); static const List COLOR_LIST = [ Color(0xFF7FC9E3), diff --git a/lib/ui/pages/data_visualization_page.dart b/lib/ui/pages/data_visualization_page.dart index 373b3ca6..73192d16 100644 --- a/lib/ui/pages/data_visualization_page.dart +++ b/lib/ui/pages/data_visualization_page.dart @@ -15,16 +15,14 @@ class _DataVisualizationPageState extends State { Widget build(BuildContext context) { RPLocalizations locale = RPLocalizations.of(context)!; return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), child: const CarpAppBar(hasProfileIcon: true), ), Container( @@ -39,9 +37,7 @@ class _DataVisualizationPageState extends State { children: [ Text(locale.translate('pages.data_viz.title'), style: fs24fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, fontWeight: FontWeight.bold, )), ], @@ -57,13 +53,10 @@ class _DataVisualizationPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( - padding: const EdgeInsets.symmetric( - horizontal: 15, vertical: 24.0), + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 24.0), child: Text(locale.translate('pages.data_viz.thanks'), style: fs16fw600.copyWith( - color: Theme.of(context) - .extension()! - .grey600, + color: Theme.of(context).extension()!.grey600, )), ), ..._dataVizCards, @@ -81,15 +74,12 @@ class _DataVisualizationPageState extends State { // Show user task progress, if study has any tasks. if (bloc.hasUserTasks()) { - widgets.add( - StudyProgressCardWidget(widget.model.studyProgressCardDataModel)); + widgets.add(StudyProgressCardWidget(widget.model.studyProgressCardDataModel)); } // Show HR if there is a POLAR or MOVESENSE device in the study - if (bloc.hasMeasure(PolarSamplingPackage.HR) || - bloc.hasMeasure(MovesenseSamplingPackage.HR)) { - widgets.add( - HeartRateOuterStatefulWidget(widget.model.heartRateCardDataModel)); + if (bloc.hasMeasure(PolarSamplingPackage.HR) || bloc.hasMeasure(MovesenseSamplingPackage.HR)) { + widgets.add(HeartRateOuterStatefulWidget(widget.model.heartRateCardDataModel)); } // check to show surveys stats diff --git a/lib/ui/pages/device_list_page.dart b/lib/ui/pages/device_list_page.dart index 9e563688..e28894ac 100644 --- a/lib/ui/pages/device_list_page.dart +++ b/lib/ui/pages/device_list_page.dart @@ -16,19 +16,16 @@ class DeviceListPageState extends State { StreamSubscription? bluetoothStateStream; BluetoothAdapterState? bluetoothAdapterState; - final List _smartphoneDevice = bloc.deploymentDevices - .where((element) => element.deviceManager is SmartphoneDeviceManager) - .toList(); + final List _smartphoneDevice = + bloc.deploymentDevices.where((element) => element.deviceManager is SmartphoneDeviceManager).toList(); final List _hardwareDevices = bloc.deploymentDevices .where((element) => - element.deviceManager is HardwareDeviceManager && - element.deviceManager is! SmartphoneDeviceManager) + element.deviceManager is HardwareDeviceManager && element.deviceManager is! SmartphoneDeviceManager) .toList(); - final List _onlineServices = bloc.deploymentDevices - .where((element) => element.deviceManager is OnlineServiceManager) - .toList(); + final List _onlineServices = + bloc.deploymentDevices.where((element) => element.deviceManager is OnlineServiceManager).toList(); @override void initState() { @@ -49,16 +46,14 @@ class DeviceListPageState extends State { Widget build(BuildContext context) { RPLocalizations locale = RPLocalizations.of(context)!; return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), child: const CarpAppBar(hasProfileIcon: true), ), Container( @@ -74,9 +69,7 @@ class DeviceListPageState extends State { Text( locale.translate('pages.devices.title'), style: fs24fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, fontWeight: FontWeight.bold, ), ), @@ -97,9 +90,7 @@ class DeviceListPageState extends State { children: [ Text(locale.translate("pages.devices.message"), style: fs16fw600.copyWith( - color: Theme.of(context) - .extension()! - .grey600, + color: Theme.of(context).extension()!.grey600, )), const SizedBox(height: 15), ], @@ -112,10 +103,8 @@ class DeviceListPageState extends State { child: CustomScrollView( slivers: [ ..._smartphoneDeviceList(locale), - if (_hardwareDevices.isNotEmpty) - ..._hardwareDevicesList(locale), - if (_onlineServices.isNotEmpty) - ..._onlineServicesList(locale), + if (_hardwareDevices.isNotEmpty) ..._hardwareDevicesList(locale), + if (_onlineServices.isNotEmpty) ..._onlineServicesList(locale), ], ), ), @@ -135,8 +124,7 @@ class DeviceListPageState extends State { listenable: _smartphoneDevice[index], builder: (BuildContext context, Widget? widget) => Center( child: StudiesMaterial( - backgroundColor: - Theme.of(context).extension()!.grey50!, + backgroundColor: Theme.of(context).extension()!.grey50!, child: _cardListBuilder( leading: _smartphoneDevice[index].icon!, title: ( @@ -167,23 +155,16 @@ class DeviceListPageState extends State { () => _cardListBuilder( enableFeedback: true, leading: device.icon!, - title: ( - locale.translate(device.typeName), - device.batteryLevel ?? 0 - ), + title: (locale.translate(device.typeName), device.batteryLevel ?? 0), subtitle: device.name, onTap: () async => await _hardwareDeviceClicked(device), trailing: device.getDeviceStatusIcon is Icon ? device.getDeviceStatusIcon as Icon : Container( - padding: const EdgeInsets.symmetric( - horizontal: 16, vertical: 8), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( - color: CACHET.DEPLOYMENT_DEPLOYING, - borderRadius: BorderRadius.circular(100)), - child: Text( - locale.translate( - device.getDeviceStatusIcon as String), + color: CACHET.DEPLOYMENT_DEPLOYING, borderRadius: BorderRadius.circular(100)), + child: Text(locale.translate(device.getDeviceStatusIcon as String), style: fs20fw700.copyWith(color: Colors.white)), ), ), @@ -211,14 +192,11 @@ class DeviceListPageState extends State { onTap: () async => await _onlineServiceClicked(service), trailing: service.getServiceStatusIcon is String ? Container( - padding: const EdgeInsets.symmetric( - horizontal: 16, vertical: 8), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( - color: CACHET.DEPLOYMENT_DEPLOYING, - borderRadius: BorderRadius.circular(100)), + color: CACHET.DEPLOYMENT_DEPLOYING, borderRadius: BorderRadius.circular(100)), child: Text( - locale.translate( - service.getServiceStatusIcon as String), + locale.translate(service.getServiceStatusIcon as String), style: fs20fw700.copyWith(color: Colors.white), ), ) @@ -260,8 +238,7 @@ class DeviceListPageState extends State { ), ), SizedBox(width: 6), - if (title.$2 != null && title.$2! > 0) - BatteryPercentage(batteryLevel: title.$2 ?? 0), + if (title.$2 != null && title.$2! > 0) BatteryPercentage(batteryLevel: title.$2 ?? 0), ], ), ), @@ -276,8 +253,7 @@ class DeviceListPageState extends State { child: Text( subtitle, style: fs12fw700.copyWith( - color: - Theme.of(context).extension()!.grey700, + color: Theme.of(context).extension()!.grey700, ), ), ), @@ -311,8 +287,7 @@ class DeviceListPageState extends State { ); Future _onlineServiceClicked(DeviceViewModel service) async { - if (service.status == DeviceStatus.connected || - service.status == DeviceStatus.connecting) { + if (service.status == DeviceStatus.connected || service.status == DeviceStatus.connecting) { return; } @@ -320,8 +295,7 @@ class DeviceListPageState extends State { if (service.type == HealthService.DEVICE_TYPE) { Navigator.push( context, - MaterialPageRoute( - builder: (context) => HealthServiceConnectPage()), + MaterialPageRoute(builder: (context) => HealthServiceConnectPage()), ); } else { await service.deviceManager.requestPermissions(); @@ -338,16 +312,14 @@ class DeviceListPageState extends State { if (Platform.isAndroid) await FlutterBluePlus.turnOn(); if (context.mounted) { - if (bluetoothAdapterState == BluetoothAdapterState.off && - Platform.isIOS) { + if (bluetoothAdapterState == BluetoothAdapterState.off && Platform.isIOS) { await showDialog( context: context, barrierDismissible: true, builder: (context) => EnableBluetoothDialog(device: device), ); } else if (bluetoothAdapterState == BluetoothAdapterState.on) { - if (device.status == DeviceStatus.connected || - device.status == DeviceStatus.connecting) { + if (device.status == DeviceStatus.connected || device.status == DeviceStatus.connecting) { bool disconnect = await showDialog( context: context, barrierDismissible: true, @@ -356,22 +328,18 @@ class DeviceListPageState extends State { false; if (disconnect) await device.disconnectFromDevice(); } else { - final hasSeenInstructions = - LocalSettings().hasSeenBluetoothConnectionInstructions; + final hasSeenInstructions = LocalSettings().hasSeenBluetoothConnectionInstructions; Navigator.push( context, MaterialPageRoute( builder: (context) => BluetoothConnectionPage( - hasSeenInstructions - ? CurrentStep.scan - : CurrentStep.instructions, + hasSeenInstructions ? CurrentStep.scan : CurrentStep.instructions, device: device, ), ), ); } - } else if (bluetoothAdapterState == BluetoothAdapterState.unauthorized && - Platform.isIOS) { + } else if (bluetoothAdapterState == BluetoothAdapterState.unauthorized && Platform.isIOS) { await showDialog( context: context, barrierDismissible: true, diff --git a/lib/ui/pages/devices_page.authorization_dialog.dart b/lib/ui/pages/devices_page.authorization_dialog.dart index f7a6f370..5c5781fb 100644 --- a/lib/ui/pages/devices_page.authorization_dialog.dart +++ b/lib/ui/pages/devices_page.authorization_dialog.dart @@ -20,8 +20,7 @@ class AuthorizationDialog extends StatelessWidget { )); } - Widget authorizationInstructions( - BuildContext context, DeviceViewModel device) { + Widget authorizationInstructions(BuildContext context, DeviceViewModel device) { RPLocalizations locale = RPLocalizations.of(context)!; return Column( children: [ @@ -30,8 +29,7 @@ class AuthorizationDialog extends StatelessWidget { child: Column( children: [ Text( - locale.translate( - "pages.devices.connection.bluetooth_authorization.message"), + locale.translate("pages.devices.connection.bluetooth_authorization.message"), style: fs16fw400, textAlign: TextAlign.justify, ), @@ -55,8 +53,7 @@ class AuthorizationDialog extends StatelessWidget { }, ), TextButton( - child: - Text(locale.translate("pages.devices.connection.settings")), + child: Text(locale.translate("pages.devices.connection.settings")), onPressed: () => OpenSettingsPlusIOS().bluetooth(), ), ], diff --git a/lib/ui/pages/devices_page.bluetooth_connection_page.dart b/lib/ui/pages/devices_page.bluetooth_connection_page.dart index c9be4ac5..715f5566 100644 --- a/lib/ui/pages/devices_page.bluetooth_connection_page.dart +++ b/lib/ui/pages/devices_page.bluetooth_connection_page.dart @@ -6,15 +6,13 @@ enum CurrentStep { scan, instructions, done } class BluetoothConnectionPage extends StatefulWidget { final DeviceViewModel device; - const BluetoothConnectionPage(CurrentStep currentStep, - {super.key, required this.device}) + const BluetoothConnectionPage(CurrentStep currentStep, {super.key, required this.device}) : _currentStep = currentStep; final CurrentStep _currentStep; @override - State createState() => - _BluetoothConnectionPageState(_currentStep); + State createState() => _BluetoothConnectionPageState(_currentStep); } class _BluetoothConnectionPageState extends State { @@ -50,8 +48,7 @@ class _BluetoothConnectionPageState extends State { RPLocalizations locale = RPLocalizations.of(context)!; return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: SafeArea( child: Stack( children: [ @@ -59,8 +56,7 @@ class _BluetoothConnectionPageState extends State { child: Column( children: [ Padding( - padding: const EdgeInsets.symmetric( - vertical: 8.0, horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16), child: const CarpAppBar(hasProfileIcon: true), ), Expanded( @@ -78,8 +74,7 @@ class _BluetoothConnectionPageState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, vertical: 16), + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: _buildActionButtons(locale), @@ -107,13 +102,10 @@ class _BluetoothConnectionPageState extends State { Widget _buildDialogTitle(RPLocalizations locale) { final stepTitleMap = { - CurrentStep.scan: - locale.translate("pages.devices.connection.step.start.title"), - CurrentStep.instructions: - locale.translate("pages.devices.connection.step.how_to.title"), + CurrentStep.scan: locale.translate("pages.devices.connection.step.start.title"), + CurrentStep.instructions: locale.translate("pages.devices.connection.step.how_to.title"), CurrentStep.done: - locale.translate("pages.devices.connection.step.confirm.title") + - (" ${selectedDevice?.platformName} "), + locale.translate("pages.devices.connection.step.confirm.title") + (" ${selectedDevice?.platformName} "), }; return Padding( padding: const EdgeInsets.only(bottom: 16), @@ -148,8 +140,8 @@ class _BluetoothConnectionPageState extends State { } List _buildActionButtons(RPLocalizations locale) { - Widget buildTranslatedButton(String key, VoidCallback onPressed, - bool enabled, ButtonStyle? buttonStyle, TextStyle? buttonTextStyle) { + Widget buildTranslatedButton( + String key, VoidCallback onPressed, bool enabled, ButtonStyle? buttonStyle, TextStyle? buttonTextStyle) { return ElevatedButton( onPressed: enabled ? onPressed : null, child: Text( @@ -180,9 +172,7 @@ class _BluetoothConnectionPageState extends State { ], CurrentStep.instructions: [ buildTranslatedButton("settings", () { - Platform.isAndroid - ? OpenSettingsPlusAndroid().bluetooth() - : OpenSettingsPlusIOS().bluetooth(); + Platform.isAndroid ? OpenSettingsPlusAndroid().bluetooth() : OpenSettingsPlusIOS().bluetooth(); }, true, null, null), buildTranslatedButton( "ok", @@ -264,10 +254,8 @@ class _BluetoothConnectionPageState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text(locale.translate( - "pages.devices.connection.connection_failed.title")), - content: Text(locale.translate( - "pages.devices.connection.connection_failed.message")), + title: Text(locale.translate("pages.devices.connection.connection_failed.title")), + content: Text(locale.translate("pages.devices.connection.connection_failed.message")), actions: [ TextButton( onPressed: () { @@ -323,18 +311,15 @@ class _BluetoothConnectionPageState extends State { padding: const EdgeInsets.only(top: 16), child: Column( children: snapshot.data! - .where((element) => - element.device.platformName.isNotEmpty && - _matchesUuid(element, _filterUuids)) + .where( + (element) => element.device.platformName.isNotEmpty && _matchesUuid(element, _filterUuids)) .toList() .asMap() .entries .map( (bluetoothDevice) => StudiesMaterial( hasBorder: true, - backgroundColor: Theme.of(context) - .extension()! - .grey50!, + backgroundColor: Theme.of(context).extension()!.grey50!, child: InkWell( child: ListTile( selected: bluetoothDevice.key == selected, @@ -344,9 +329,7 @@ class _BluetoothConnectionPageState extends State { fontSize: 20, ), ), - selectedTileColor: Theme.of(context) - .primaryColor - .withValues(alpha: 0.2), + selectedTileColor: Theme.of(context).primaryColor.withValues(alpha: 0.2), ), onTap: () { selectedDevice = bluetoothDevice.value.device; @@ -369,12 +352,10 @@ class _BluetoothConnectionPageState extends State { TextSpan( children: [ TextSpan( - text: locale - .translate("pages.devices.connection.step.start.1"), + text: locale.translate("pages.devices.connection.step.start.1"), ), TextSpan( - text: locale - .translate("pages.devices.connection.instructions"), + text: locale.translate("pages.devices.connection.instructions"), style: TextStyle( color: Theme.of(context).extension()!.primary, decoration: TextDecoration.underline, @@ -392,8 +373,7 @@ class _BluetoothConnectionPageState extends State { ), ], ), - style: fs22fw700.copyWith( - color: Theme.of(context).extension()!.grey900), + style: fs22fw700.copyWith(color: Theme.of(context).extension()!.grey900), textAlign: TextAlign.center, ), ) @@ -437,28 +417,22 @@ class _BluetoothConnectionPageState extends State { switch (device.deviceManager) { case PolarDeviceManager _ when device.type == PolarDevice.DEVICE_TYPE && - (device.polarDeviceType == PolarDeviceType.H10 || - device.polarDeviceType == PolarDeviceType.H9): - assetImage = - AssetImage('assets/instructions/polar_h9_h10_instructions.png'); + (device.polarDeviceType == PolarDeviceType.H10 || device.polarDeviceType == PolarDeviceType.H9): + assetImage = AssetImage('assets/instructions/polar_h9_h10_instructions.png'); break; case PolarDeviceManager _ - when device.type == PolarDevice.DEVICE_TYPE && - device.polarDeviceType == PolarDeviceType.SENSE: - assetImage = - AssetImage('assets/instructions/polar_sense_instructions.png'); + when device.type == PolarDevice.DEVICE_TYPE && device.polarDeviceType == PolarDeviceType.SENSE: + assetImage = AssetImage('assets/instructions/polar_sense_instructions.png'); break; // if device type is not defined in the protocol, show h9, h10 instructions case PolarDeviceManager _: - assetImage = - AssetImage('assets/instructions/polar_h9_h10_instructions.png'); + assetImage = AssetImage('assets/instructions/polar_h9_h10_instructions.png'); break; case MovesenseDeviceManager _: - assetImage = - AssetImage('assets/instructions/movesense_instructions.png'); + assetImage = AssetImage('assets/instructions/movesense_instructions.png'); break; default: diff --git a/lib/ui/pages/devices_page.disconnection_dialog.dart b/lib/ui/pages/devices_page.disconnection_dialog.dart index 0390df0e..90ab9c7d 100644 --- a/lib/ui/pages/devices_page.disconnection_dialog.dart +++ b/lib/ui/pages/devices_page.disconnection_dialog.dart @@ -45,8 +45,7 @@ class DisconnectionDialog extends StatelessWidget { if (context.canPop()) context.pop(true); }, child: Text( - locale.translate( - "pages.devices.connection.disconnect_bluetooth.disconnect"), + locale.translate("pages.devices.connection.disconnect_bluetooth.disconnect"), ), ), ], diff --git a/lib/ui/pages/devices_page.enable_bluetooth_dialog.dart b/lib/ui/pages/devices_page.enable_bluetooth_dialog.dart index 72944dfc..93390b82 100644 --- a/lib/ui/pages/devices_page.enable_bluetooth_dialog.dart +++ b/lib/ui/pages/devices_page.enable_bluetooth_dialog.dart @@ -11,16 +11,14 @@ class EnableBluetoothDialog extends StatelessWidget { scrollable: true, titlePadding: const EdgeInsets.symmetric(vertical: 4), insetPadding: const EdgeInsets.symmetric(vertical: 24, horizontal: 40), - title: const DialogTitle( - title: "pages.devices.connection.enable_bluetooth.title"), + title: const DialogTitle(title: "pages.devices.connection.enable_bluetooth.title"), content: SizedBox( height: MediaQuery.of(context).size.height * 0.45, child: enableBluetoothInstructions(context, device), )); } - Widget enableBluetoothInstructions( - BuildContext context, DeviceViewModel device) { + Widget enableBluetoothInstructions(BuildContext context, DeviceViewModel device) { RPLocalizations locale = RPLocalizations.of(context)!; return Column( children: [ @@ -29,8 +27,7 @@ class EnableBluetoothDialog extends StatelessWidget { child: Column( children: [ Text( - locale.translate( - "pages.devices.connection.enable_bluetooth.message1"), + locale.translate("pages.devices.connection.enable_bluetooth.message1"), style: fs16fw400, textAlign: TextAlign.justify, ), @@ -38,8 +35,7 @@ class EnableBluetoothDialog extends StatelessWidget { padding: EdgeInsets.symmetric(vertical: 16.0), ), Text( - locale.translate( - "pages.devices.connection.enable_bluetooth.message2"), + locale.translate("pages.devices.connection.enable_bluetooth.message2"), style: fs16fw400, textAlign: TextAlign.justify, ), @@ -52,8 +48,7 @@ class EnableBluetoothDialog extends StatelessWidget { ), ), Text( - locale.translate( - "pages.devices.connection.enable_bluetooth.message3"), + locale.translate("pages.devices.connection.enable_bluetooth.message3"), style: fs16fw400, textAlign: TextAlign.justify, ), diff --git a/lib/ui/pages/devices_page.health_service_connect.dart b/lib/ui/pages/devices_page.health_service_connect.dart index 0a35387b..214f486c 100644 --- a/lib/ui/pages/devices_page.health_service_connect.dart +++ b/lib/ui/pages/devices_page.health_service_connect.dart @@ -8,9 +8,7 @@ class HealthServiceConnectPage extends StatelessWidget { RPLocalizations locale = RPLocalizations.of(context)!; DeviceViewModel healthServive = bloc.deploymentDevices - .where((element) => - element.deviceManager is OnlineServiceManager && - element.type == HealthService.DEVICE_TYPE) + .where((element) => element.deviceManager is OnlineServiceManager && element.type == HealthService.DEVICE_TYPE) .first; return Scaffold( @@ -20,8 +18,7 @@ class HealthServiceConnectPage extends StatelessWidget { child: Column( children: [ Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 18), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 18), child: const CarpAppBar(), ), Expanded( @@ -46,51 +43,36 @@ class HealthServiceConnectPage extends StatelessWidget { TextSpan( children: [ TextSpan( - text: - "${locale.translate("pages.devices.type.health.instructions.page2.part1")} ", + text: "${locale.translate("pages.devices.type.health.instructions.page2.part1")} ", style: fs22fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, ), ), TextSpan( text: "${Platform.isAndroid ? locale.translate("pages.devices.type.health.instructions.page2.android.allow_all") : locale.translate("pages.devices.type.health.instructions.page2.ios.turn_on_all")} ", style: fs22fw700.copyWith( - color: Theme.of(context) - .extension()! - .primary, // Change to desired color + color: Theme.of(context).extension()!.primary, // Change to desired color ), ), TextSpan( - text: - "${locale.translate("pages.devices.type.health.instructions.page2.part2")} ", + text: "${locale.translate("pages.devices.type.health.instructions.page2.part2")} ", style: fs22fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, ), ), TextSpan( - text: - "${locale.translate("pages.devices.type.health.instructions.page2.allow")} ", + text: "${locale.translate("pages.devices.type.health.instructions.page2.allow")} ", style: fs22fw700.copyWith( - color: Theme.of(context) - .extension()! - .primary, // Change to desired color + color: Theme.of(context).extension()!.primary, // Change to desired color ), ), TextSpan( text: Platform.isAndroid - ? locale.translate( - "pages.devices.type.health.instructions.page2.part3.android") - : locale.translate( - "pages.devices.type.health.instructions.page2.part3.ios"), + ? locale.translate("pages.devices.type.health.instructions.page2.part3.android") + : locale.translate("pages.devices.type.health.instructions.page2.part3.ios"), style: fs22fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, ), ), ], @@ -125,10 +107,8 @@ class HealthServiceConnectPage extends StatelessWidget { ), ), style: ElevatedButton.styleFrom( - backgroundColor: - Theme.of(context).extension()!.primary, - padding: - const EdgeInsets.symmetric(horizontal: 30, vertical: 12), + backgroundColor: Theme.of(context).extension()!.primary, + padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 12), ), onPressed: () async { await healthServive.deviceManager.requestPermissions(); diff --git a/lib/ui/pages/devices_page.list_title.dart b/lib/ui/pages/devices_page.list_title.dart index 19f57309..97d3fd73 100644 --- a/lib/ui/pages/devices_page.list_title.dart +++ b/lib/ui/pages/devices_page.list_title.dart @@ -21,11 +21,9 @@ class DevicesPageListTitle extends StatelessWidget { return SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 6), - child: Text( - locale.translate("pages.devices.${type.name}.title").toUpperCase(), + child: Text(locale.translate("pages.devices.${type.name}.title").toUpperCase(), style: fs16fw400ls1.copyWith( - color: Theme.of(context).extension()!.grey900, - fontWeight: FontWeight.bold)), + color: Theme.of(context).extension()!.grey900, fontWeight: FontWeight.bold)), ), ); } diff --git a/lib/ui/pages/enable_connection_dialog.dart b/lib/ui/pages/enable_connection_dialog.dart index cf5c7776..e8d7f656 100644 --- a/lib/ui/pages/enable_connection_dialog.dart +++ b/lib/ui/pages/enable_connection_dialog.dart @@ -9,9 +9,7 @@ class EnableInternetConnectionDialog extends StatelessWidget { scrollable: true, titlePadding: const EdgeInsets.symmetric(vertical: 4), insetPadding: const EdgeInsets.symmetric(vertical: 24, horizontal: 40), - title: DialogTitle( - title: - "pages.login.internet_connection.enable_internet_connections.title"), + title: DialogTitle(title: "pages.login.internet_connection.enable_internet_connections.title"), content: SizedBox( height: MediaQuery.of(context).size.height * 0.45, child: (() { @@ -35,16 +33,14 @@ class EnableInternetConnectionDialog extends StatelessWidget { child: Column( children: [ Text( - locale.translate( - "pages.login.internet_connection.enable_internet_connections.general_message"), + locale.translate("pages.login.internet_connection.enable_internet_connections.general_message"), style: fs16fw400, textAlign: TextAlign.justify, ), Padding( padding: EdgeInsets.symmetric(vertical: 16.0), child: Text( - locale.translate( - "pages.login.internet_connection.enable_internet_connections.wifi_message"), + locale.translate("pages.login.internet_connection.enable_internet_connections.wifi_message"), style: fs16fw400, textAlign: TextAlign.justify, )), @@ -58,8 +54,7 @@ class EnableInternetConnectionDialog extends StatelessWidget { Padding( padding: EdgeInsets.symmetric(vertical: 16.0), child: Text( - locale.translate( - "pages.login.internet_connection.enable_internet_connections.mobile_data_message"), + locale.translate("pages.login.internet_connection.enable_internet_connections.mobile_data_message"), style: fs16fw400, textAlign: TextAlign.justify, ), @@ -109,16 +104,14 @@ class EnableInternetConnectionDialog extends StatelessWidget { child: Column( children: [ Text( - locale.translate( - "pages.login.internet_connection.enable_internet_connections.general_message"), + locale.translate("pages.login.internet_connection.enable_internet_connections.general_message"), style: fs16fw400, textAlign: TextAlign.justify, ), Padding( padding: EdgeInsets.symmetric(vertical: 16.0), child: Text( - locale.translate( - "pages.login.internet_connection.enable_internet_connections.wifi_message"), + locale.translate("pages.login.internet_connection.enable_internet_connections.wifi_message"), style: fs16fw400, textAlign: TextAlign.justify, )), @@ -133,8 +126,8 @@ class EnableInternetConnectionDialog extends StatelessWidget { padding: EdgeInsets.symmetric(vertical: 16.0), child: Column(children: [ Text( - locale.translate( - "pages.login.internet_connection.enable_internet_connections.mobile_data_message"), + locale + .translate("pages.login.internet_connection.enable_internet_connections.mobile_data_message"), style: fs16fw400, textAlign: TextAlign.justify, ), diff --git a/lib/ui/pages/home_page.dart b/lib/ui/pages/home_page.dart index 791a9920..d33d7f83 100644 --- a/lib/ui/pages/home_page.dart +++ b/lib/ui/pages/home_page.dart @@ -35,15 +35,13 @@ class HomePageState extends State { barrierDismissible: false, barrierColor: Colors.black38, transitionBuilder: (ctx, anim1, anim2, child) => BackdropFilter( - filter: ui.ImageFilter.blur( - sigmaX: 4 * anim1.value, sigmaY: 4 * anim1.value), + filter: ui.ImageFilter.blur(sigmaX: 4 * anim1.value, sigmaY: 4 * anim1.value), child: FadeTransition( opacity: anim1, child: child, ), ), - pageBuilder: (context, anim1, anim2) => - LocationPermissionPage().build( + pageBuilder: (context, anim1, anim2) => LocationPermissionPage().build( context, "dialog.location.info", )); @@ -61,12 +59,11 @@ class HomePageState extends State { // - configuring the study // - loading localizations // - starting sensing - askForLocationPermissions(context) - .then((_) => bloc.configureStudy().then((_) { - // Load localizations for the current locale and study - CarpStudyApp.reloadLocale(context); - bloc.start(); - })); + askForLocationPermissions(context).then((_) => bloc.configureStudy().then((_) { + // Load localizations for the current locale and study + CarpStudyApp.reloadLocale(context); + bloc.start(); + })); if (Platform.isAndroid) { // Check if HealthConnect is installed @@ -103,8 +100,7 @@ class HomePageState extends State { }); return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: SafeArea( child: widget.child, ), diff --git a/lib/ui/pages/home_page.install_health_connect_dialog.dart b/lib/ui/pages/home_page.install_health_connect_dialog.dart index 2129ece0..7f6e6ea7 100644 --- a/lib/ui/pages/home_page.install_health_connect_dialog.dart +++ b/lib/ui/pages/home_page.install_health_connect_dialog.dart @@ -34,8 +34,8 @@ class InstallHealthConnectDialog extends StatelessWidget { } void _redirectToHealthConnectPlayStore() async { - final Uri url = Uri.parse( - 'https://play.google.com/store/apps/details?id=${LocalSettings.healthConnectPackageName}'); + final Uri url = + Uri.parse('https://play.google.com/store/apps/details?id=${LocalSettings.healthConnectPackageName}'); var canLaunch = await canLaunchUrl(url); if (canLaunch) { await launchUrl(url); diff --git a/lib/ui/pages/invitation_list_page.dart b/lib/ui/pages/invitation_list_page.dart index d6ddbadb..671e523f 100644 --- a/lib/ui/pages/invitation_list_page.dart +++ b/lib/ui/pages/invitation_list_page.dart @@ -9,8 +9,7 @@ class InvitationListPage extends StatelessWidget { Widget build(BuildContext context) { RPLocalizations locale = RPLocalizations.of(context)!; return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: FutureBuilder>( future: bloc.backend.getInvitations(), builder: (context, snapshot) { @@ -38,8 +37,7 @@ class InvitationListPage extends StatelessWidget { return CustomScrollView( slivers: [ SliverAppBar( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, title: const CarpAppBar(), centerTitle: true, pinned: true, @@ -86,8 +84,7 @@ class InvitationListPage extends StatelessWidget { ), SliverToBoxAdapter( child: Padding( - padding: const EdgeInsets.only( - bottom: 8.0, left: 16.0, right: 16.0), + padding: const EdgeInsets.only(bottom: 8.0, left: 16.0, right: 16.0), child: Container( padding: EdgeInsets.all(10.0), child: Text( @@ -128,8 +125,7 @@ class InvitationMaterial extends StatelessWidget { ), child: InkWell( onTap: () { - context.push( - '${InvitationDetailsPage.route}/${invitation.participation.participantId}'); + context.push('${InvitationDetailsPage.route}/${invitation.participation.participantId}'); }, child: Padding( padding: const EdgeInsets.all(16.0), @@ -139,27 +135,22 @@ class InvitationMaterial extends StatelessWidget { Text( invitation.invitation.name, maxLines: 1, - style: fs24fw600.copyWith( - color: CACHET.TASK_COMPLETED_BLUE, - overflow: TextOverflow.ellipsis), + style: fs24fw600.copyWith(color: CACHET.TASK_COMPLETED_BLUE, overflow: TextOverflow.ellipsis), ), Text.rich( TextSpan( children: [ TextSpan( - text: locale.translate( - 'invitation_list.roles_in_the_study.description'), + text: locale.translate('invitation_list.roles_in_the_study.description'), style: fs16fw700.copyWith( - color: - Theme.of(context).extension()!.grey600, + color: Theme.of(context).extension()!.grey600, fontSize: 12, ), ), TextSpan( text: invitation.participantRoleName, style: fs16fw700.copyWith( - color: - Theme.of(context).extension()!.grey600, + color: Theme.of(context).extension()!.grey600, fontSize: 12, ), ), diff --git a/lib/ui/pages/invitation_page.dart b/lib/ui/pages/invitation_page.dart index c7084b18..c77c1a35 100644 --- a/lib/ui/pages/invitation_page.dart +++ b/lib/ui/pages/invitation_page.dart @@ -17,8 +17,7 @@ class InvitationDetailsPage extends StatelessWidget { var invitation = model.getInvitation(invitationId); return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: SafeArea( @@ -59,8 +58,7 @@ class InvitationDetailsPage extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 16.0), child: StudiesMaterial( - backgroundColor: - Theme.of(context).extension()!.white!, + backgroundColor: Theme.of(context).extension()!.white!, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.0), ), @@ -70,8 +68,7 @@ class InvitationDetailsPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - locale - .translate('invitation.roles_in_the_study.title'), + locale.translate('invitation.roles_in_the_study.title'), style: TextStyle( fontWeight: FontWeight.bold, fontSize: 20.0, @@ -93,8 +90,7 @@ class InvitationDetailsPage extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(top: 16.0), child: StudiesMaterial( - backgroundColor: - Theme.of(context).extension()!.white!, + backgroundColor: Theme.of(context).extension()!.white!, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.0), ), @@ -118,14 +114,11 @@ class InvitationDetailsPage extends StatelessWidget { style: TextStyle( fontWeight: FontWeight.bold, fontSize: 22.0, - color: Theme.of(context) - .extension()! - .primary, + color: Theme.of(context).extension()!.primary, ), ), Padding( - padding: const EdgeInsets.only( - top: 8, bottom: 24), + padding: const EdgeInsets.only(top: 8, bottom: 24), child: FittedBox( fit: BoxFit.scaleDown, child: Text( @@ -133,9 +126,7 @@ class InvitationDetailsPage extends StatelessWidget { style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, - color: Theme.of(context) - .extension()! - .grey600, + color: Theme.of(context).extension()!.grey600, ), maxLines: 1, textScaler: TextScaler.linear(0.9), @@ -144,9 +135,7 @@ class InvitationDetailsPage extends StatelessWidget { ), Text( invitation.invitation.description ?? '', - style: const TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.bold), + style: const TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), ), ], ), @@ -173,8 +162,7 @@ class InvitationDetailsPage extends StatelessWidget { }, child: Text( locale.translate("invitation.accept_invite"), - style: - const TextStyle(color: Color(0xffffffff), fontSize: 22), + style: const TextStyle(color: Color(0xffffffff), fontSize: 22), textAlign: TextAlign.center, ), ), diff --git a/lib/ui/pages/message_details_page.dart b/lib/ui/pages/message_details_page.dart index 757cf560..6df370dd 100644 --- a/lib/ui/pages/message_details_page.dart +++ b/lib/ui/pages/message_details_page.dart @@ -13,8 +13,7 @@ class MessageDetailsPage extends StatelessWidget { Widget build(BuildContext context) { RPLocalizations locale = RPLocalizations.of(context)!; - Message message = bloc.messages - .firstWhere((element) => element.id == messageId, orElse: () { + Message message = bloc.messages.firstWhere((element) => element.id == messageId, orElse: () { return Message( id: '0', title: 'Unknown message', @@ -31,15 +30,13 @@ class MessageDetailsPage extends StatelessWidget { child: Column( children: [ Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 18), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 18), child: const CarpAppBar(hasProfileIcon: true), ), Row( children: [ IconButton( - padding: const EdgeInsets.only( - left: 26, right: 10, top: 16, bottom: 16), + padding: const EdgeInsets.only(left: 26, right: 10, top: 16, bottom: 16), icon: Icon( Icons.arrow_back_ios, color: Theme.of(context).extension()!.grey600, @@ -55,10 +52,7 @@ class MessageDetailsPage extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(vertical: 10.0), child: Text(locale.translate(message.title!), - style: fs20fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900)), + style: fs20fw700.copyWith(color: Theme.of(context).extension()!.grey900)), ), Spacer(), Padding( @@ -67,14 +61,8 @@ class MessageDetailsPage extends StatelessWidget { color: CACHET.DEPLOYMENT_DEPLOYING, borderRadius: BorderRadius.circular(100.0), child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, vertical: 6.0), - child: Text( - locale.translate(message.type - .toString() - .split('.') - .last - .toLowerCase()), + padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 6.0), + child: Text(locale.translate(message.type.toString().split('.').last.toLowerCase()), style: fs16fw600.copyWith(color: Colors.white)), ), ), @@ -83,18 +71,13 @@ class MessageDetailsPage extends StatelessWidget { ), Flexible( child: ListView( - padding: - const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), children: [ message.subTitle != null ? Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10.0, vertical: 6.0), + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0), child: Text(locale.translate(message.subTitle!), - style: fs16fw400.copyWith( - color: Theme.of(context) - .extension()! - .grey700)), + style: fs16fw400.copyWith(color: Theme.of(context).extension()!.grey700)), ) : const SizedBox.shrink(), if (message.image != null && message.image!.isNotEmpty) @@ -108,24 +91,19 @@ class MessageDetailsPage extends StatelessWidget { ), child: FittedBox( fit: BoxFit.contain, - child: bloc.appViewModel.studyPageViewModel - .getMessageImage(message.image)), + child: bloc.appViewModel.studyPageViewModel.getMessageImage(message.image)), ); }), // DetailsBanner(message.title ?? '', message.image), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, vertical: 16), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (message.message != null) Text( locale.translate(message.message!), - style: fs16fw400.copyWith( - color: Theme.of(context) - .extension()! - .grey900), + style: fs16fw400.copyWith(color: Theme.of(context).extension()!.grey900), textAlign: TextAlign.justify, ) ], diff --git a/lib/ui/pages/process_message_page.dart b/lib/ui/pages/process_message_page.dart index d9b4b131..cca49cc4 100644 --- a/lib/ui/pages/process_message_page.dart +++ b/lib/ui/pages/process_message_page.dart @@ -41,18 +41,15 @@ class ProcessMessagePage extends StatelessWidget { switch (statusType) { case ProcessStatus.done: image = Image( - image: const AssetImage('assets/icons/done.png'), - height: MediaQuery.of(context).size.height * 0.35); + image: const AssetImage('assets/icons/done.png'), height: MediaQuery.of(context).size.height * 0.35); break; case ProcessStatus.error: image = Image( - image: const AssetImage('assets/icons/error.png'), - height: MediaQuery.of(context).size.height * 0.35); + image: const AssetImage('assets/icons/error.png'), height: MediaQuery.of(context).size.height * 0.35); break; case ProcessStatus.other: image = Image( - image: const AssetImage('assets/icons/info.png'), - height: MediaQuery.of(context).size.height * 0.35); + image: const AssetImage('assets/icons/info.png'), height: MediaQuery.of(context).size.height * 0.35); break; } @@ -88,8 +85,7 @@ class ProcessMessagePage extends StatelessWidget { Navigator.of(context).pop(); }, child: Text(locale.translate('cancel').toUpperCase(), - style: TextStyle( - color: Theme.of(context).primaryColor))), + style: TextStyle(color: Theme.of(context).primaryColor))), const SizedBox(width: 10), ], ) @@ -98,8 +94,7 @@ class ProcessMessagePage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context).primaryColor), + style: ElevatedButton.styleFrom(backgroundColor: Theme.of(context).primaryColor), onPressed: () { actionFunction(); }, diff --git a/lib/ui/pages/profile_page.dart b/lib/ui/pages/profile_page.dart index 4b390de4..9d438717 100644 --- a/lib/ui/pages/profile_page.dart +++ b/lib/ui/pages/profile_page.dart @@ -40,15 +40,12 @@ class ProfilePageState extends State { children: [ TextButton.icon( onPressed: () {}, - icon: Icon(Icons.account_circle, - color: Theme.of(context).primaryColor, size: 30), + icon: Icon(Icons.account_circle, color: Theme.of(context).primaryColor, size: 30), label: Text(locale.translate("pages.profile.title"), - style: fs20fw700.copyWith( - color: Theme.of(context).primaryColor)), + style: fs20fw700.copyWith(color: Theme.of(context).primaryColor)), ), IconButton( - icon: Icon(Icons.close, - color: Theme.of(context).primaryColor, size: 30), + icon: Icon(Icons.close, color: Theme.of(context).primaryColor, size: 30), tooltip: locale.translate('Back'), onPressed: () { Navigator.of(context).pop(); @@ -78,15 +75,13 @@ class ProfilePageState extends State { _buildListTile( locale.translate('pages.profile.full_name'), LocalSettings().isAnonymous - ? locale - .translate('pages.about.anonymous.anonymous') + ? locale.translate('pages.about.anonymous.anonymous') : widget.model.fullName, ), _buildListTile( locale.translate('pages.profile.email'), LocalSettings().isAnonymous - ? locale - .translate('pages.about.anonymous.anonymous') + ? locale.translate('pages.about.anonymous.anonymous') : widget.model.email, ), ], @@ -142,10 +137,8 @@ class ProfilePageState extends State { context, [ _buildActionListTile( - leading: Icon(Icons.mail, - color: Theme.of(context).primaryColor), - trailing: const Icon(Icons.arrow_forward_ios, - color: CACHET.GREY_6), + leading: Icon(Icons.mail, color: Theme.of(context).primaryColor), + trailing: const Icon(Icons.arrow_forward_ios, color: CACHET.GREY_6), title: locale.translate('pages.profile.contact'), onTap: () async { _sendEmailToContactResearcher( @@ -155,10 +148,8 @@ class ProfilePageState extends State { }, ), _buildActionListTile( - leading: Icon(Icons.policy, - color: Theme.of(context).primaryColor), - trailing: const Icon(Icons.arrow_forward_ios, - color: CACHET.GREY_6), + leading: Icon(Icons.policy, color: Theme.of(context).primaryColor), + trailing: const Icon(Icons.arrow_forward_ios, color: CACHET.GREY_6), title: locale.translate('pages.profile.privacy'), onTap: () async { try { @@ -167,10 +158,8 @@ class ProfilePageState extends State { }, ), _buildActionListTile( - leading: Icon(Icons.public, - color: Theme.of(context).primaryColor), - trailing: const Icon(Icons.arrow_forward_ios, - color: CACHET.GREY_6), + leading: Icon(Icons.public, color: Theme.of(context).primaryColor), + trailing: const Icon(Icons.arrow_forward_ios, color: CACHET.GREY_6), title: locale.translate('pages.profile.study_website'), onTap: () async { try { @@ -191,8 +180,7 @@ class ProfilePageState extends State { ]), _buildSectionCard(context, [ _buildActionListTile( - leading: const Icon(Icons.power_settings_new, - color: CACHET.RED_1), + leading: const Icon(Icons.power_settings_new, color: CACHET.RED_1), title: locale.translate('pages.profile.log_out'), onTap: () async { bool isConnected = await bloc.checkConnectivity(); @@ -256,9 +244,7 @@ class ProfilePageState extends State { }) { return ListTile( leading: leading, - title: Text(title, - style: fs16fw600.copyWith( - color: Theme.of(context).extension()!.grey900)), + title: Text(title, style: fs16fw600.copyWith(color: Theme.of(context).extension()!.grey900)), trailing: trailing, onTap: onTap, contentPadding: EdgeInsets.symmetric(vertical: 4, horizontal: 16), @@ -277,12 +263,8 @@ class ProfilePageState extends State { /// Sends and email to the researcher with the name of the study + user id void _sendEmailToContactResearcher(String email, String subject) async { - final url = Uri( - scheme: 'mailto', - path: email, - queryParameters: {'subject': subject}) - .toString() - .replaceAll("+", "%20"); + final url = + Uri(scheme: 'mailto', path: email, queryParameters: {'subject': subject}).toString().replaceAll("+", "%20"); try { await launchUrl(Uri.parse(url)); } finally {} @@ -326,8 +308,7 @@ class ProfilePageState extends State { context: context, builder: (BuildContext builderContext) { return AlertDialog( - title: - Text(locale.translate("pages.profile.leave_study.confirmation")), + title: Text(locale.translate("pages.profile.leave_study.confirmation")), actions: [ TextButton( child: Text(locale.translate("NO")), @@ -371,8 +352,7 @@ class SlidePageRoute extends PageRouteBuilder { var begin = Offset(1.0, 0.0); var end = Offset.zero; var curve = Curves.easeInOut; - var tween = - Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); + var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); var offsetAnimation = animation.drive(tween); return SlideTransition( position: offsetAnimation, diff --git a/lib/ui/pages/qr_scanner.dart b/lib/ui/pages/qr_scanner.dart index b67ec16e..430337aa 100644 --- a/lib/ui/pages/qr_scanner.dart +++ b/lib/ui/pages/qr_scanner.dart @@ -84,21 +84,15 @@ class _QRViewExampleState extends State { Widget _buildQrView(BuildContext context) { // For this example we check how width or tall the device is and change the scanArea and overlay accordingly. - var scanArea = (MediaQuery.of(context).size.width < 400 || - MediaQuery.of(context).size.height < 400) - ? 150.0 - : 300.0; + var scanArea = + (MediaQuery.of(context).size.width < 400 || MediaQuery.of(context).size.height < 400) ? 150.0 : 300.0; // To ensure the Scanner view is properly sizes after rotation // we need to listen for Flutter SizeChanged notification and update controller return qr.QRView( key: qrKey, onQRViewCreated: _onQRViewCreated, overlay: qr.QrScannerOverlayShape( - borderColor: Colors.red, - borderRadius: 10, - borderLength: 30, - borderWidth: 10, - cutOutSize: scanArea), + borderColor: Colors.red, borderRadius: 10, borderLength: 30, borderWidth: 10, cutOutSize: scanArea), onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p), ); } @@ -125,8 +119,7 @@ class _QRViewExampleState extends State { }); } - void _onPermissionSet( - BuildContext context, qr.QRViewController ctrl, bool p) { + void _onPermissionSet(BuildContext context, qr.QRViewController ctrl, bool p) { if (!p) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('no Permission')), diff --git a/lib/ui/pages/study_details_page.dart b/lib/ui/pages/study_details_page.dart index 6f1673fc..da41a976 100644 --- a/lib/ui/pages/study_details_page.dart +++ b/lib/ui/pages/study_details_page.dart @@ -10,23 +10,20 @@ class StudyDetailsPage extends StatelessWidget { RPLocalizations locale = RPLocalizations.of(context)!; return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: SafeArea( child: Container( color: Theme.of(context).extension()!.backgroundGray, child: Column( children: [ Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 18), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 18), child: const CarpAppBar(hasProfileIcon: true), ), Row( children: [ IconButton( - padding: const EdgeInsets.only( - left: 26, right: 10, top: 16, bottom: 16), + padding: const EdgeInsets.only(left: 26, right: 10, top: 16, bottom: 16), icon: Icon( Icons.arrow_back_ios, color: Theme.of(context).extension()!.grey600, @@ -42,17 +39,13 @@ class StudyDetailsPage extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(vertical: 10.0), child: Text(locale.translate(model.title), - style: fs20fw700.copyWith( - color: Theme.of(context) - .extension()! - .primary)), + style: fs20fw700.copyWith(color: Theme.of(context).extension()!.primary)), ), ], ), Flexible( child: ListView( - padding: - const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), @@ -75,12 +68,8 @@ class StudyDetailsPage extends StatelessWidget { [ _buildActionListTile( context: context, - leading: Icon(Icons.mail, - color: Theme.of(context) - .extension()! - .primary), - trailing: const Icon(Icons.arrow_forward_ios, - color: CACHET.GREY_6), + leading: Icon(Icons.mail, color: Theme.of(context).extension()!.primary), + trailing: const Icon(Icons.arrow_forward_ios, color: CACHET.GREY_6), title: locale.translate('pages.profile.contact'), onTap: () async { _sendEmailToContactResearcher( @@ -91,18 +80,12 @@ class StudyDetailsPage extends StatelessWidget { ), _buildActionListTile( context: context, - leading: Icon(Icons.policy, - color: Theme.of(context) - .extension()! - .primary), - trailing: const Icon(Icons.arrow_forward_ios, - color: CACHET.GREY_6), - title: - locale.translate('pages.about.study.privacy'), + leading: Icon(Icons.policy, color: Theme.of(context).extension()!.primary), + trailing: const Icon(Icons.arrow_forward_ios, color: CACHET.GREY_6), + title: locale.translate('pages.about.study.privacy'), onTap: () async { try { - await launchUrl(Uri.parse( - locale.translate(model.privacyPolicyUrl))); + await launchUrl(Uri.parse(locale.translate(model.privacyPolicyUrl))); } catch (error) { warning( "Could not launch study description URL - ${locale.translate(model.privacyPolicyUrl)}"); @@ -110,17 +93,12 @@ class StudyDetailsPage extends StatelessWidget { }), _buildActionListTile( context: context, - leading: Icon(Icons.public, - color: Theme.of(context) - .extension()! - .primary), - trailing: const Icon(Icons.arrow_forward_ios, - color: CACHET.GREY_6), + leading: Icon(Icons.public, color: Theme.of(context).extension()!.primary), + trailing: const Icon(Icons.arrow_forward_ios, color: CACHET.GREY_6), title: locale.translate('pages.about.study.website'), onTap: () async { try { - await launchUrl(Uri.parse( - locale.translate(model.studyDescriptionUrl))); + await launchUrl(Uri.parse(locale.translate(model.studyDescriptionUrl))); } catch (error) { warning( "Could not launch study description URL - ${locale.translate(model.studyDescriptionUrl)}"); @@ -137,54 +115,35 @@ class StudyDetailsPage extends StatelessWidget { children: [ Text( locale.translate('widgets.study_card.responsible'), - style: fs16fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900), + style: fs16fw700.copyWith(color: Theme.of(context).extension()!.grey900), ), Padding( padding: const EdgeInsets.only(top: 4.0, bottom: 8), child: Text( locale.translate(model.responsibleName), - style: fs12fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey700), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey700), ), ), Text( - locale.translate( - 'widgets.study_card.participant_role'), - style: fs16fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900), + locale.translate('widgets.study_card.participant_role'), + style: fs16fw700.copyWith(color: Theme.of(context).extension()!.grey900), ), Padding( padding: const EdgeInsets.only(top: 4.0, bottom: 8), child: Text( locale.translate(model.participantRole), - style: fs12fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey700), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey700), ), ), Text( locale.translate('widgets.study_card.device_role'), - style: fs16fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900), + style: fs16fw700.copyWith(color: Theme.of(context).extension()!.grey900), ), Padding( padding: const EdgeInsets.only(top: 4.0, bottom: 8), child: Text( locale.translate(model.deviceRole), - style: fs12fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey700), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey700), ), ), ], @@ -200,39 +159,25 @@ class StudyDetailsPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - locale.translate( - 'widgets.study_card.study_description'), - style: fs16fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900), + locale.translate('widgets.study_card.study_description'), + style: fs16fw700.copyWith(color: Theme.of(context).extension()!.grey900), ), Padding( padding: const EdgeInsets.only(top: 4.0, bottom: 8), child: Text( locale.translate(model.description), - style: fs12fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey700), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey700), ), ), Text( - locale - .translate('widgets.study_card.study_purpose'), - style: fs16fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900), + locale.translate('widgets.study_card.study_purpose'), + style: fs16fw700.copyWith(color: Theme.of(context).extension()!.grey900), ), Padding( padding: const EdgeInsets.only(top: 4.0, bottom: 8), child: Text( locale.translate(model.purpose), - style: fs12fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey700), + style: fs12fw700.copyWith(color: Theme.of(context).extension()!.grey700), ), ), ], @@ -278,9 +223,7 @@ class StudyDetailsPage extends StatelessWidget { }) { return ListTile( leading: leading, - title: Text(title, - style: fs16fw600.copyWith( - color: Theme.of(context).extension()!.grey900)), + title: Text(title, style: fs16fw600.copyWith(color: Theme.of(context).extension()!.grey900)), trailing: trailing, onTap: onTap, contentPadding: EdgeInsets.symmetric(vertical: 4, horizontal: 16), @@ -289,12 +232,8 @@ class StudyDetailsPage extends StatelessWidget { // Sends and email to the researcher with the name of the study + user id void _sendEmailToContactResearcher(String email, String subject) async { - final url = Uri( - scheme: 'mailto', - path: email, - queryParameters: {'subject': subject}) - .toString() - .replaceAll("+", "%20"); + final url = + Uri(scheme: 'mailto', path: email, queryParameters: {'subject': subject}).toString().replaceAll("+", "%20"); try { await launchUrl(Uri.parse(url)); } finally {} diff --git a/lib/ui/pages/study_page.dart b/lib/ui/pages/study_page.dart index 6b3352b9..3167317a 100644 --- a/lib/ui/pages/study_page.dart +++ b/lib/ui/pages/study_page.dart @@ -13,16 +13,14 @@ class StudyPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), child: const CarpAppBar(hasProfileIcon: true), ), Flexible( @@ -37,8 +35,7 @@ class StudyPageState extends State { if (status == StudyStatus.Deployed) { bloc.start(); } - bloc.deploymentService.getStudyDeploymentStatus( - widget.model.studyDeploymentId); + bloc.deploymentService.getStudyDeploymentStatus(widget.model.studyDeploymentId); }, child: ListView.builder( itemCount: cards.length, @@ -72,8 +69,7 @@ class StudyPageState extends State { if (widget.model.messages.isNotEmpty) { items.add(_buildAnnouncementsTitle(context)); // Show newest announcements first: sort by timestamp descending - final messages = List.from(widget.model.messages) - ..sort((a, b) => b.timestamp.compareTo(a.timestamp)); + final messages = List.from(widget.model.messages)..sort((a, b) => b.timestamp.compareTo(a.timestamp)); items.addAll(messages.map((message) { return _announcementCard(context, message); }).toList()); @@ -88,8 +84,7 @@ class StudyPageState extends State { builder: (context, snapshot) { if (snapshot.data == true) { return StudiesMaterial( - backgroundColor: - Theme.of(context).extension()!.grey50!, + backgroundColor: Theme.of(context).extension()!.grey50!, elevation: 8, child: Padding( padding: const EdgeInsets.only(left: 16.0), @@ -101,9 +96,7 @@ class StudyPageState extends State { child: Text( locale.translate('pages.about.app_update'), style: fs16fw600.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, ), ), ), @@ -177,10 +170,7 @@ class StudyPageState extends State { Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text(locale.translate(message.title!), - style: fs24fw700.copyWith( - color: Theme.of(context) - .extension()! - .primary)), + style: fs24fw700.copyWith(color: Theme.of(context).extension()!.primary)), ), if (message.subTitle != null && message.subTitle!.isNotEmpty) Row( @@ -189,9 +179,7 @@ class StudyPageState extends State { child: Text( locale.translate(message.subTitle!), style: fs16fw400.copyWith( - color: Theme.of(context) - .extension()! - .grey700, + color: Theme.of(context).extension()!.grey700, ), ), ), @@ -202,9 +190,7 @@ class StudyPageState extends State { Expanded( child: Text( "${locale.translate(message.message!).substring(0, (message.message!.length > 150) ? 150 : null)}...", - style: fs16fw400.copyWith( - color: - Theme.of(context).extension()!.grey900), + style: fs16fw400.copyWith(color: Theme.of(context).extension()!.grey900), textAlign: TextAlign.start, )), ]), @@ -265,37 +251,26 @@ class StudyPageState extends State { children: [ Expanded( child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, vertical: 22.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 22.0), child: Row( children: [ Column( children: [ Padding( - padding: const EdgeInsets.symmetric( - horizontal: 6.0, vertical: 4), + padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 4), child: CircleAvatar( radius: 18, - backgroundColor: - studyStatusColors[deploymentStatus], + backgroundColor: studyStatusColors[deploymentStatus], ), ), Padding( - padding: - const EdgeInsets.symmetric(horizontal: 6.0), + padding: const EdgeInsets.symmetric(horizontal: 6.0), child: Text( - deploymentStatus == - StudyDeploymentStatusTypes - .DeployingDevices - ? locale.translate( - 'pages.about.status.deploying_devices') - : deploymentStatus - .toString() - .split('.') - .last, + deploymentStatus == StudyDeploymentStatusTypes.DeployingDevices + ? locale.translate('pages.about.status.deploying_devices') + : deploymentStatus.toString().split('.').last, maxLines: 2, - style: fs16fw600.copyWith( - color: studyStatusColors[deploymentStatus]), + style: fs16fw600.copyWith(color: studyStatusColors[deploymentStatus]), ), ), ], @@ -306,9 +281,7 @@ class StudyPageState extends State { child: Text( getStatusText(locale, deploymentStatus, snapshot), style: fs16fw600.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, fontSize: 14, ), ), @@ -382,15 +355,12 @@ class StudyPageState extends State { children: [ Expanded( child: Padding( - padding: const EdgeInsets.only( - top: 8.0, bottom: 8, right: 8), + padding: const EdgeInsets.only(top: 8.0, bottom: 8, right: 8), child: Text( locale.translate(message.title!), overflow: TextOverflow.ellipsis, style: fs20fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, ), ), ), @@ -409,15 +379,12 @@ class StudyPageState extends State { padding: const EdgeInsets.only(bottom: 12.0), child: Row( children: [ - if (message.subTitle != null && - message.subTitle!.isNotEmpty) + if (message.subTitle != null && message.subTitle!.isNotEmpty) Expanded( child: Text( locale.translate(message.subTitle!), style: fs16fw400.copyWith( - color: Theme.of(context) - .extension()! - .grey700, + color: Theme.of(context).extension()!.grey700, ), ), ), @@ -425,9 +392,7 @@ class StudyPageState extends State { Text( timeago.format(message.timestamp.toLocal()), style: fs10fw600.copyWith( - color: Theme.of(context) - .extension()! - .grey600, + color: Theme.of(context).extension()!.grey600, ), ) ], @@ -458,8 +423,7 @@ class StudyPageState extends State { PackageInfo packageInfo = await PackageInfo.fromPlatform(); Uri url; if (Platform.isAndroid) { - url = Uri.parse( - 'https://play.google.com/store/apps/details?id=${packageInfo.packageName}'); + url = Uri.parse('https://play.google.com/store/apps/details?id=${packageInfo.packageName}'); } else if (Platform.isIOS) { url = Uri.parse('https://apps.apple.com/app/id1569798025'); } else { @@ -480,9 +444,7 @@ class StudyPageState extends State { ) { if (deploymentStatusType == StudyDeploymentStatusTypes.DeployingDevices) { return locale.translate('pages.about.status.deploying_devices.message') + - snapshot.data!.deviceStatusList.first - .remainingDevicesToRegisterBeforeDeployment! - .join(' | '); + snapshot.data!.deviceStatusList.first.remainingDevicesToRegisterBeforeDeployment!.join(' | '); } else { return locale.translate(studyStatusText[deploymentStatusType]!); } @@ -497,8 +459,7 @@ class StudyPageState extends State { static Map studyStatusText = { StudyDeploymentStatusTypes.Invited: 'pages.about.status.invited.message', - StudyDeploymentStatusTypes.DeployingDevices: - 'pages.about.status.deploying_devices.message', + StudyDeploymentStatusTypes.DeployingDevices: 'pages.about.status.deploying_devices.message', StudyDeploymentStatusTypes.Running: 'pages.about.status.running.message', StudyDeploymentStatusTypes.Stopped: 'pages.about.status.stopped.message', }; diff --git a/lib/ui/pages/task_list_page.dart b/lib/ui/pages/task_list_page.dart index 5abea3c3..3b82bef3 100644 --- a/lib/ui/pages/task_list_page.dart +++ b/lib/ui/pages/task_list_page.dart @@ -22,8 +22,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { double get maxExtent => _tabBar.preferredSize.height; @override - Widget build( - BuildContext context, double shrinkOffset, bool overlapsContent) { + Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { return Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 4), @@ -41,8 +40,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { } } -class TaskListPageState extends State - with TickerProviderStateMixin { +class TaskListPageState extends State with TickerProviderStateMixin { late TabController _tabController; bool showParticipantDataCard = false; @@ -68,15 +66,13 @@ class TaskListPageState extends State return DefaultTabController( length: 2, child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), child: const CarpAppBar(hasProfileIcon: true), ), Expanded( @@ -91,16 +87,13 @@ class TaskListPageState extends State slivers: [ SliverToBoxAdapter( child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 16), + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: Align( alignment: Alignment.centerLeft, child: Text( locale.translate('pages.task_list.title'), style: fs24fw700.copyWith( - color: Theme.of(context) - .extension()! - .grey900, + color: Theme.of(context).extension()!.grey900, fontWeight: FontWeight.bold, ), ), @@ -109,49 +102,38 @@ class TaskListPageState extends State ), // Scoreboard showing days in study and tasks completed SliverPadding( - padding: const EdgeInsets.only( - top: 4, bottom: 6, left: 40, right: 40), + padding: const EdgeInsets.only(top: 4, bottom: 6, left: 40, right: 40), sliver: ScoreboardCard(widget.model), ), // Tab holder SliverPadding( - padding: const EdgeInsets.only( - top: 8, bottom: 24, left: 64, right: 64), + padding: const EdgeInsets.only(top: 8, bottom: 24, left: 64, right: 64), sliver: SliverPersistentHeader( pinned: true, delegate: _SliverAppBarDelegate( TabBar( controller: _tabController, - labelPadding: const EdgeInsets.only( - top: 4, bottom: 4, left: 4, right: 4), - labelColor: Theme.of(context) - .extension()! - .grey900, - unselectedLabelColor: Theme.of(context) - .extension()! - .grey900, + labelPadding: const EdgeInsets.only(top: 4, bottom: 4, left: 4, right: 4), + labelColor: Theme.of(context).extension()!.grey900, + unselectedLabelColor: Theme.of(context).extension()!.grey900, dividerColor: Colors.transparent, indicator: ShapeDecoration( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), - color: Theme.of(context) - .extension()! - .white, + color: Theme.of(context).extension()!.white, ), tabs: [ Container( width: double.infinity, child: Tab( - text: locale.translate( - 'pages.task_list.pending'), + text: locale.translate('pages.task_list.pending'), ), ), Container( width: double.infinity, child: Tab( - text: locale.translate( - 'pages.task_list.completed'), + text: locale.translate('pages.task_list.completed'), ), ), ], @@ -169,14 +151,11 @@ class TaskListPageState extends State UserTask userTask = widget.model.tasks[index]; if (_tabController.index == 0) { if (userTask.availableForUser) { - return _buildAvailableTaskCard( - context, userTask); + return _buildAvailableTaskCard(context, userTask); } } else if (_tabController.index == 1) { - if (userTask.state == UserTaskState.done || - userTask.state == UserTaskState.expired) { - return _buildCompletedTaskCard( - context, userTask); + if (userTask.state == UserTaskState.done || userTask.state == UserTaskState.expired) { + return _buildCompletedTaskCard(context, userTask); } } return const SizedBox.shrink(); @@ -229,8 +208,7 @@ class TaskListPageState extends State child: Text( "Input Data", style: TextStyle( - color: - taskTypeColors["ExpectedParticipantData"], + color: taskTypeColors["ExpectedParticipantData"], fontWeight: FontWeight.bold, ), ), @@ -288,10 +266,9 @@ class TaskListPageState extends State right: Radius.circular(8.0), ), ), - backgroundColor: - userTask.expiresIn != null && userTask.expiresIn!.inHours < 24 - ? CACHET.TASK_TO_EXPIRE_BACKGROUND - : Theme.of(context).extension()!.grey50!, + backgroundColor: userTask.expiresIn != null && userTask.expiresIn!.inHours < 24 + ? CACHET.TASK_TO_EXPIRE_BACKGROUND + : Theme.of(context).extension()!.grey50!, child: Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: IntrinsicHeight( @@ -306,15 +283,12 @@ class TaskListPageState extends State children: [ Row( children: [ - if (userTask.state == UserTaskState.started) - CircularProgressIndicator(), - if (userTask.state != UserTaskState.started) - _taskTypeIcon(userTask), + if (userTask.state == UserTaskState.started) CircularProgressIndicator(), + if (userTask.state != UserTaskState.started) _taskTypeIcon(userTask), Padding( padding: const EdgeInsets.only(left: 4.0), child: Text( - userTask.type[0].toUpperCase() + - userTask.type.substring(1), + userTask.type[0].toUpperCase() + userTask.type.substring(1), style: TextStyle( color: taskTypeColors[userTask.type], fontWeight: FontWeight.bold, @@ -325,11 +299,8 @@ class TaskListPageState extends State if (_timeRemainingSubtitle(userTask).isNotEmpty) Icon( Icons.alarm, - color: userTask.expiresIn != null && - userTask.expiresIn!.inHours < 24 - ? Theme.of(context) - .extension()! - .warningColor + color: userTask.expiresIn != null && userTask.expiresIn!.inHours < 24 + ? Theme.of(context).extension()!.warningColor : Colors.grey, ), const SizedBox(width: 4.0), @@ -338,11 +309,8 @@ class TaskListPageState extends State child: Text( _timeRemainingSubtitle(userTask), style: TextStyle( - color: userTask.expiresIn != null && - userTask.expiresIn!.inHours < 24 - ? Theme.of(context) - .extension()! - .warningColor + color: userTask.expiresIn != null && userTask.expiresIn!.inHours < 24 + ? Theme.of(context).extension()!.warningColor : Colors.grey, fontSize: 12.0, ), @@ -401,8 +369,7 @@ class TaskListPageState extends State ), onTap: () { // only start if not already started, done, or expired - if (userTask.state == UserTaskState.enqueued || - userTask.state == UserTaskState.canceled) { + if (userTask.state == UserTaskState.enqueued || userTask.state == UserTaskState.canceled) { userTask.onStart(); if (userTask.hasWidget) { context.push('/task/${userTask.id}'); @@ -410,8 +377,7 @@ class TaskListPageState extends State Timer(const Duration(seconds: 10), () { userTask.onDone(); ScaffoldMessenger.of(context).showSnackBar(SnackBar( - backgroundColor: - Theme.of(context).extension()!.grey700, + backgroundColor: Theme.of(context).extension()!.grey700, content: Text(locale.translate('Done!')), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4), @@ -436,8 +402,7 @@ class TaskListPageState extends State builder: (context, snapshot) { if (taskTypeIcons[userTask.type] != null && userTask.availableForUser) { return originalIcon; - } else if (taskTypeIcons[userTask.type] != null && - userTask.state == UserTaskState.started) { + } else if (taskTypeIcons[userTask.type] != null && userTask.state == UserTaskState.started) { return Padding( padding: const EdgeInsets.all(4), child: SizedBox( @@ -448,12 +413,10 @@ class TaskListPageState extends State width: 14, ), ); - } else if (taskTypeIcons[userTask.type] != null && - userTask.state == UserTaskState.done) { + } else if (taskTypeIcons[userTask.type] != null && userTask.state == UserTaskState.done) { return Icon(originalIcon.icon, color: CACHET.TASK_COMPLETED_BLUE); } else { - return Icon(originalIcon.icon, - color: Theme.of(context).extension()!.grey600); + return Icon(originalIcon.icon, color: Theme.of(context).extension()!.grey600); } }, ); @@ -501,9 +464,7 @@ class TaskListPageState extends State right: Radius.circular(8.0), ), ), - borderColor: (userTask.state == UserTaskState.done) - ? CACHET.TASK_COMPLETED_BLUE - : CACHET.GREY_6, + borderColor: (userTask.state == UserTaskState.done) ? CACHET.TASK_COMPLETED_BLUE : CACHET.GREY_6, child: Padding( padding: const EdgeInsets.only(top: 16, bottom: 16, right: 16), child: IntrinsicHeight( @@ -534,15 +495,11 @@ class TaskListPageState extends State Spacer(), Text( userTask.doneTime != null - ? DateFormat('MMMM dd yyyy') - .format(userTask.doneTime!) + ? DateFormat('MMMM dd yyyy').format(userTask.doneTime!) : 'Done time null', style: TextStyle( - color: userTask.expiresIn != null && - userTask.expiresIn!.inHours < 24 - ? Theme.of(context) - .extension()! - .warningColor + color: userTask.expiresIn != null && userTask.expiresIn!.inHours < 24 + ? Theme.of(context).extension()!.warningColor : Colors.grey, fontSize: 12.0, ), @@ -733,13 +690,10 @@ class TaskListPageState extends State }; static Map get taskStateIcon => { - UserTaskState.initialized: - const Icon(Icons.stream, color: CACHET.YELLOW), - UserTaskState.enqueued: - const Icon(Icons.notifications, color: CACHET.YELLOW), + UserTaskState.initialized: const Icon(Icons.stream, color: CACHET.YELLOW), + UserTaskState.enqueued: const Icon(Icons.notifications, color: CACHET.YELLOW), UserTaskState.dequeued: const Icon(Icons.stop, color: CACHET.YELLOW), - UserTaskState.started: - const Icon(Icons.play_arrow, color: CACHET.GREY_4), + UserTaskState.started: const Icon(Icons.play_arrow, color: CACHET.GREY_4), UserTaskState.canceled: const Icon(Icons.pause, color: CACHET.GREY_4), UserTaskState.done: const Icon(Icons.check, color: CACHET.GREEN), }; diff --git a/lib/ui/tasks/audio_page.dart b/lib/ui/tasks/audio_page.dart index f236941e..f5c526be 100644 --- a/lib/ui/tasks/audio_page.dart +++ b/lib/ui/tasks/audio_page.dart @@ -28,17 +28,14 @@ class AudioPageState extends State { Row( children: [ Padding( - padding: const EdgeInsets.symmetric( - vertical: 8.0, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), child: const CarpAppBar( hasProfileIcon: false, ), ), Spacer(), IconButton( - color: Theme.of(context) - .extension()! - .grey900!, + color: Theme.of(context).extension()!.grey900!, onPressed: () { _showCancelConfirmationDialog(); }, @@ -60,34 +57,26 @@ class AudioPageState extends State { child: Column( children: [ Padding( - padding: - const EdgeInsets.only(bottom: 24), + padding: const EdgeInsets.only(bottom: 24), child: Text( locale.translate( widget.audioUserTask!.title, ), style: fs22fw700.copyWith( - color: Theme.of(context) - .extension()! - .primary, + color: Theme.of(context).extension()!.primary, ), ), ), StudiesMaterial( - backgroundColor: Theme.of(context) - .extension()! - .white!, + backgroundColor: Theme.of(context).extension()!.white!, child: Scrollbar( child: SingleChildScrollView( - scrollDirection: - Axis.vertical, //.horizontal + scrollDirection: Axis.vertical, //.horizontal child: Padding( - padding: - const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8.0), child: Text( locale.translate( - widget.audioUserTask! - .instructions, + widget.audioUserTask!.instructions, ), style: fs16fw600, ), @@ -98,12 +87,9 @@ class AudioPageState extends State { Spacer(), CircleAvatar( radius: 30, - backgroundColor: Theme.of(context) - .extension()! - .primary, + backgroundColor: Theme.of(context).extension()!.primary, child: IconButton( - onPressed: () => widget.audioUserTask! - .onRecordStart(), + onPressed: () => widget.audioUserTask!.onRecordStart(), padding: const EdgeInsets.all(0), icon: const Icon( Icons.mic, @@ -113,11 +99,9 @@ class AudioPageState extends State { ), ), Padding( - padding: const EdgeInsets.only( - top: 8, bottom: 40), + padding: const EdgeInsets.only(top: 8, bottom: 40), child: Text( - locale.translate( - "pages.audio_task.play"), + locale.translate("pages.audio_task.play"), style: fs16fw600, ), ), @@ -129,34 +113,25 @@ class AudioPageState extends State { child: Column( children: [ Padding( - padding: - const EdgeInsets.only(bottom: 24), + padding: const EdgeInsets.only(bottom: 24), child: Text( locale.translate( widget.audioUserTask!.title, ), style: fs22fw700.copyWith( - color: Theme.of(context) - .extension()! - .primary, + color: Theme.of(context).extension()!.primary, ), ), ), StudiesMaterial( - backgroundColor: Theme.of(context) - .extension()! - .white!, + backgroundColor: Theme.of(context).extension()!.white!, child: Scrollbar( child: SingleChildScrollView( - scrollDirection: - Axis.vertical, //.horizontal + scrollDirection: Axis.vertical, //.horizontal child: Padding( - padding: - const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8.0), child: Text( - locale.translate(widget - .audioUserTask! - .instructions), + locale.translate(widget.audioUserTask!.instructions), style: fs16fw600, ), ), @@ -165,16 +140,13 @@ class AudioPageState extends State { ), Spacer(), Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, + mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ CircleAvatar( radius: 30, backgroundColor: CACHET.RED_1, child: IconButton( - onPressed: () => widget - .audioUserTask! - .onRecordStop(), + onPressed: () => widget.audioUserTask!.onRecordStop(), padding: const EdgeInsets.all(0), icon: const Icon( Icons.stop, @@ -191,8 +163,7 @@ class AudioPageState extends State { bottom: 40, ), child: Text( - locale.translate( - "pages.audio_task.recording"), + locale.translate("pages.audio_task.recording"), style: fs22fw700, ), ), @@ -204,24 +175,17 @@ class AudioPageState extends State { child: Column( children: [ Padding( - padding: - const EdgeInsets.only(bottom: 32), + padding: const EdgeInsets.only(bottom: 32), child: Text( - locale.translate( - 'pages.audio_task.done'), + locale.translate('pages.audio_task.done'), style: fs22fw700.copyWith( - color: Theme.of(context) - .extension()! - .primary, + color: Theme.of(context).extension()!.primary, ), ), ), Padding( - padding: - const EdgeInsets.only(bottom: 20), - child: Text( - locale.translate( - 'pages.audio_task.recording_completed'), + padding: const EdgeInsets.only(bottom: 20), + child: Text(locale.translate('pages.audio_task.recording_completed'), style: fs16fw600), ), Spacer(), @@ -233,20 +197,15 @@ class AudioPageState extends State { right: 20, ), child: Row( - crossAxisAlignment: - CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( flex: 1, child: IconButton( - onPressed: () => widget - .audioUserTask! - .onRecordReset(), + onPressed: () => widget.audioUserTask!.onRecordReset(), icon: Icon( Icons.replay, - color: Theme.of(context) - .extension()! - .grey700, + color: Theme.of(context).extension()!.grey700, size: 30, ), ), @@ -261,8 +220,7 @@ class AudioPageState extends State { Navigator.of(context).pop(); Navigator.of(context).pop(); }, - padding: - const EdgeInsets.all(0), + padding: const EdgeInsets.all(0), icon: const Icon( Icons.check_circle_outline, color: Colors.white, diff --git a/lib/ui/tasks/audio_task_page.dart b/lib/ui/tasks/audio_task_page.dart index 46518caa..6e2bb751 100644 --- a/lib/ui/tasks/audio_task_page.dart +++ b/lib/ui/tasks/audio_task_page.dart @@ -25,17 +25,14 @@ class AudioTaskPageState extends State { Row( children: [ Padding( - padding: const EdgeInsets.symmetric( - vertical: 8.0, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), child: const CarpAppBar( hasProfileIcon: false, ), ), Spacer(), IconButton( - color: Theme.of(context) - .extension()! - .grey900!, + color: Theme.of(context).extension()!.grey900!, onPressed: () { _showCancelConfirmationDialog(); }, @@ -48,19 +45,14 @@ class AudioTaskPageState extends State { ), Padding( padding: const EdgeInsets.symmetric(vertical: 30), - child: const Image( - image: AssetImage('assets/icons/audio.png'), - width: 220, - height: 220), + child: const Image(image: AssetImage('assets/icons/audio.png'), width: 220, height: 220), ), Padding( padding: const EdgeInsets.symmetric(vertical: 12), - child: Text(locale.translate(widget.audioUserTask!.title), - style: fs22fw700), + child: Text(locale.translate(widget.audioUserTask!.title), style: fs22fw700), ), Padding( - padding: const EdgeInsets.symmetric( - vertical: 12, horizontal: 20), + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20), child: Text( '${locale.translate(widget.audioUserTask!.description)}\n\n' '${locale.translate('pages.audio_task.play')}', @@ -89,9 +81,7 @@ class AudioTaskPageState extends State { ), ), style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context) - .extension()! - .primary, + backgroundColor: Theme.of(context).extension()!.primary, padding: const EdgeInsets.symmetric( horizontal: 30, vertical: 12, diff --git a/lib/ui/tasks/camera_page.dart b/lib/ui/tasks/camera_page.dart index eaef6e53..4a471aa5 100644 --- a/lib/ui/tasks/camera_page.dart +++ b/lib/ui/tasks/camera_page.dart @@ -109,10 +109,8 @@ class CameraPageState extends State { if (context.mounted) { await Navigator.of(context).push( MaterialPageRoute( - builder: (context) => DisplayPicturePage( - file: video, - isVideo: true, - videoUserTask: widget.videoUserTask)), + builder: (context) => + DisplayPicturePage(file: video, isVideo: true, videoUserTask: widget.videoUserTask)), ); } setState(() { @@ -142,8 +140,7 @@ class CameraPageState extends State { builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return LayoutBuilder( - builder: - (BuildContext context, BoxConstraints constraints) { + builder: (BuildContext context, BoxConstraints constraints) { return SizedBox( width: constraints.maxWidth, height: constraints.maxHeight, @@ -152,10 +149,8 @@ class CameraPageState extends State { child: FittedBox( fit: BoxFit.cover, child: SizedBox( - width: - _cameraController.value.previewSize!.height, - height: - _cameraController.value.previewSize!.width, + width: _cameraController.value.previewSize!.height, + height: _cameraController.value.previewSize!.width, child: CameraPreview(_cameraController), ), ), @@ -221,8 +216,7 @@ class CameraPageState extends State { height: 65, child: CircularProgressIndicator( backgroundColor: Colors.white54, - valueColor: - AlwaysStoppedAnimation(Colors.black54), + valueColor: AlwaysStoppedAnimation(Colors.black54), strokeWidth: 5, ), ), @@ -286,8 +280,7 @@ class CameraPageState extends State { actions: [ TextButton( child: Text(locale.translate("NO")), - onPressed: () => - Navigator.of(context).pop(), // Dismissing the pop-up + onPressed: () => Navigator.of(context).pop(), // Dismissing the pop-up ), TextButton( child: Text(locale.translate("YES")), diff --git a/lib/ui/tasks/camera_task_page.dart b/lib/ui/tasks/camera_task_page.dart index 6d827520..dd0916ea 100644 --- a/lib/ui/tasks/camera_task_page.dart +++ b/lib/ui/tasks/camera_task_page.dart @@ -28,25 +28,21 @@ class CameraTaskPageState extends State { return StreamBuilder( stream: widget.mediaUserTask.stateEvents, initialData: UserTaskState.enqueued, - builder: - (context, AsyncSnapshot snapshot) { + builder: (context, AsyncSnapshot snapshot) { return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( children: [ Padding( - padding: const EdgeInsets.symmetric( - vertical: 8.0, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), child: const CarpAppBar( hasProfileIcon: false, ), ), Spacer(), IconButton( - color: Theme.of(context) - .extension()! - .grey900!, + color: Theme.of(context).extension()!.grey900!, onPressed: () { _showCancelConfirmationDialog(); }, @@ -60,60 +56,46 @@ class CameraTaskPageState extends State { Column( children: [ Padding( - padding: const EdgeInsets.symmetric( - vertical: 30), + padding: const EdgeInsets.symmetric(vertical: 30), child: const Image( - image: AssetImage( - 'assets/icons/camera.png'), - width: 220, - height: 220), + image: AssetImage('assets/icons/camera.png'), width: 220, height: 220), ), Padding( - padding: const EdgeInsets.symmetric( - vertical: 12), + padding: const EdgeInsets.symmetric(vertical: 12), child: Text( - locale.translate( - widget.mediaUserTask.title), + locale.translate(widget.mediaUserTask.title), style: fs22fw700, ), ), Padding( - padding: const EdgeInsets.symmetric( - vertical: 12, horizontal: 20), + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20), child: Text( - locale.translate( - widget.mediaUserTask.description), + locale.translate(widget.mediaUserTask.description), style: fs16fw600, ), ), Padding( - padding: const EdgeInsets.symmetric( - vertical: 30), + padding: const EdgeInsets.symmetric(vertical: 30), child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ OutlinedButton( onPressed: () { Navigator.pop(context); }, - child: - Text(locale.translate("Cancel")), + child: Text(locale.translate("Cancel")), ), ElevatedButton( onPressed: () => Navigator.push( context, MaterialPageRoute( builder: (context) => CameraPage( - videoUserTask: - widget.mediaUserTask, + videoUserTask: widget.mediaUserTask, ), ), ), style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context) - .extension()! - .primary, + backgroundColor: Theme.of(context).extension()!.primary, padding: const EdgeInsets.symmetric( horizontal: 30, vertical: 12, diff --git a/lib/ui/tasks/display_picture_page.dart b/lib/ui/tasks/display_picture_page.dart index 29cff952..d8566af1 100644 --- a/lib/ui/tasks/display_picture_page.dart +++ b/lib/ui/tasks/display_picture_page.dart @@ -5,11 +5,7 @@ class DisplayPicturePage extends StatefulWidget { final bool isVideo; final VideoUserTask videoUserTask; - const DisplayPicturePage( - {super.key, - required this.file, - required this.videoUserTask, - this.isVideo = false}); + const DisplayPicturePage({super.key, required this.file, required this.videoUserTask, this.isVideo = false}); @override State createState() => DisplayPicturePageState(); @@ -52,8 +48,7 @@ class DisplayPicturePageState extends State { Row( children: [ Padding( - padding: - const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), child: const CarpAppBar( hasProfileIcon: false, ), @@ -81,8 +76,7 @@ class DisplayPicturePageState extends State { child: (widget.isVideo && _videoPlayerController != null) ? _videoPlayerController!.value.isInitialized ? AspectRatio( - aspectRatio: - _videoPlayerController!.value.aspectRatio, + aspectRatio: _videoPlayerController!.value.aspectRatio, child: VideoPlayer(_videoPlayerController!)) : const CircularProgressIndicator() : Image.file(File(videoFilePath)), @@ -96,8 +90,7 @@ class DisplayPicturePageState extends State { children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 10), - child: Text(locale.translate('pages.audio_task.done'), - style: fs22fw700), + child: Text(locale.translate('pages.audio_task.done'), style: fs22fw700), ), const SizedBox(height: 40), Padding( @@ -119,8 +112,7 @@ class DisplayPicturePageState extends State { IconButton( onPressed: () => Navigator.of(context).pop(), padding: const EdgeInsets.all(0), - icon: const Icon(Icons.replay, - size: 25, color: CACHET.GREY_5), + icon: const Icon(Icons.replay, size: 25, color: CACHET.GREY_5), ), const SizedBox(width: 20), CircleAvatar( @@ -134,8 +126,7 @@ class DisplayPicturePageState extends State { Navigator.of(context).pop(); }, padding: const EdgeInsets.all(0), - icon: const Icon(Icons.check_circle_outline, - color: Colors.white, size: 30), + icon: const Icon(Icons.check_circle_outline, color: Colors.white, size: 30), ), ), const SizedBox(width: 50), diff --git a/lib/ui/tasks/participant_data_page.dart b/lib/ui/tasks/participant_data_page.dart index 23c1320f..8ed6638f 100644 --- a/lib/ui/tasks/participant_data_page.dart +++ b/lib/ui/tasks/participant_data_page.dart @@ -1,14 +1,6 @@ part of carp_study_app; -enum ParticipantStep { - presentTypes, - address, - diagnosis, - fullName, - phoneNumber, - socialSecurityNumber, - review -} +enum ParticipantStep { presentTypes, address, diagnosis, fullName, phoneNumber, socialSecurityNumber, review } class ParticipantDataPage extends StatefulWidget { static const String route = '/participant_data'; @@ -81,8 +73,7 @@ class ParticipantDataPageState extends State { widget.model._lastNameFocusNode = FocusNode(); for (final key in _stepMap.keys) { - if (widget.model.expectedData.any( - (dataType) => dataType!.attribute!.inputDataType.contains(key))) { + if (widget.model.expectedData.any((dataType) => dataType!.attribute!.inputDataType.contains(key))) { _includedSteps.add(_stepMap[key]!); } } @@ -237,14 +228,13 @@ class ParticipantDataPageState extends State { widget.model._countryController.text.isNotEmpty; break; case ParticipantStep.diagnosis: - _nextEnabled = - widget.model._effectiveDateController.text.isNotEmpty && - widget.model._icd11CodeController.text.isNotEmpty && - widget.model._conclusionController.text.isNotEmpty; + _nextEnabled = widget.model._effectiveDateController.text.isNotEmpty && + widget.model._icd11CodeController.text.isNotEmpty && + widget.model._conclusionController.text.isNotEmpty; break; case ParticipantStep.fullName: - _nextEnabled = widget.model._firstNameController.text.isNotEmpty && - widget.model._lastNameController.text.isNotEmpty; + _nextEnabled = + widget.model._firstNameController.text.isNotEmpty && widget.model._lastNameController.text.isNotEmpty; break; case ParticipantStep.phoneNumber: _nextEnabled = widget.model._phoneNumberController.text.isNotEmpty; @@ -266,8 +256,7 @@ class ParticipantDataPageState extends State { Widget build(BuildContext context) { RPLocalizations locale = RPLocalizations.of(context)!; return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray!, + backgroundColor: Theme.of(context).extension()!.backgroundGray!, body: SafeArea( child: Container( padding: const EdgeInsets.all(16.0), @@ -276,8 +265,7 @@ class ParticipantDataPageState extends State { Row( children: [ Padding( - padding: const EdgeInsets.symmetric( - vertical: 8.0, horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), child: const CarpAppBar( hasProfileIcon: false, ), @@ -306,14 +294,12 @@ class ParticipantDataPageState extends State { child: Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: SizedBox( - child: _buildStepContent( - locale, widget.model.expectedData), + child: _buildStepContent(locale, widget.model.expectedData), ), ), ), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, vertical: 16), + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: _buildActionButtons(locale), @@ -333,20 +319,13 @@ class ParticipantDataPageState extends State { /// Builds the title of the dialog based on the current step. Widget _buildDialogTitle(RPLocalizations locale) { final stepTitleMap = { - ParticipantStep.presentTypes: - locale.translate("tasks.participant_data.present_data.title"), - ParticipantStep.address: - locale.translate("tasks.participant_data.address.title"), - ParticipantStep.diagnosis: - locale.translate("tasks.participant_data.diagnosis.title"), - ParticipantStep.fullName: - locale.translate("tasks.participant_data.full_name.title"), - ParticipantStep.phoneNumber: - locale.translate("tasks.participant_data.phone_number.title"), - ParticipantStep.socialSecurityNumber: - locale.translate("tasks.participant_data.ssn.title"), - ParticipantStep.review: - locale.translate("tasks.participant_data.review.title"), + ParticipantStep.presentTypes: locale.translate("tasks.participant_data.present_data.title"), + ParticipantStep.address: locale.translate("tasks.participant_data.address.title"), + ParticipantStep.diagnosis: locale.translate("tasks.participant_data.diagnosis.title"), + ParticipantStep.fullName: locale.translate("tasks.participant_data.full_name.title"), + ParticipantStep.phoneNumber: locale.translate("tasks.participant_data.phone_number.title"), + ParticipantStep.socialSecurityNumber: locale.translate("tasks.participant_data.ssn.title"), + ParticipantStep.review: locale.translate("tasks.participant_data.review.title"), }; return Padding( padding: const EdgeInsets.only(bottom: 16), @@ -371,16 +350,13 @@ class ParticipantDataPageState extends State { } /// Builds the content of the current step based on the [_includedSteps]. - Widget _buildStepContent( - RPLocalizations locale, Set expectedData) { + Widget _buildStepContent(RPLocalizations locale, Set expectedData) { List fields = []; switch (currentStep) { case ParticipantStep.presentTypes: fields.add(_buildPresentTypes( _includedSteps - .where((step) => - step != ParticipantStep.presentTypes && - step != ParticipantStep.review) + .where((step) => step != ParticipantStep.presentTypes && step != ParticipantStep.review) .map((step) => participantStepDescriptions[step]) .toList(), )); @@ -396,10 +372,8 @@ class ParticipantDataPageState extends State { break; case ParticipantStep.diagnosis: fields.addAll([ - _buildField(locale, widget.model.effectiveDateField, - isDatePicker: true), - _buildField(locale, widget.model.diagnosisDescriptionField, - isOptional: true), + _buildField(locale, widget.model.effectiveDateField, isDatePicker: true), + _buildField(locale, widget.model.diagnosisDescriptionField, isOptional: true), _buildField(locale, widget.model.icd11CodeField), _buildField(locale, widget.model.conclusionField, isThicc: true), ]); @@ -412,8 +386,7 @@ class ParticipantDataPageState extends State { ]); break; case ParticipantStep.phoneNumber: - fields.add(_buildField(locale, widget.model.phoneNumberField, - isPhoneNumber: true)); + fields.add(_buildField(locale, widget.model.phoneNumberField, isPhoneNumber: true)); break; case ParticipantStep.socialSecurityNumber: fields.add(_buildField(locale, widget.model.ssnField, isCPR: true)); @@ -463,14 +436,10 @@ class ParticipantDataPageState extends State { final String field = fields.elementAt(index).title; String input = ""; if (index < fields.length) { - if (fields.elementAt(index).controller == - widget.model._phoneNumberController) { - input = - "${widget.model._phoneNumberCodeController.text} ${fields.elementAt(index).controller.text}"; - } else if (fields.elementAt(index).controller == - widget.model._ssnController) { - input = - "${widget.model._ssnCountryController.text} ${fields.elementAt(index).controller.text}"; + if (fields.elementAt(index).controller == widget.model._phoneNumberController) { + input = "${widget.model._phoneNumberCodeController.text} ${fields.elementAt(index).controller.text}"; + } else if (fields.elementAt(index).controller == widget.model._ssnController) { + input = "${widget.model._ssnCountryController.text} ${fields.elementAt(index).controller.text}"; } else { input = fields.elementAt(index).controller.text; } @@ -520,8 +489,7 @@ class ParticipantDataPageState extends State { if (isPhoneNumber) { return InternationalPhoneNumberInput( onInputChanged: (phoneNumber) { - widget.model._phoneNumberCodeController.text = - phoneNumber.dialCode ?? ''; + widget.model._phoneNumberCodeController.text = phoneNumber.dialCode ?? ''; }, textFieldController: stepField.controller, selectorConfig: SelectorConfig( @@ -533,8 +501,7 @@ class ParticipantDataPageState extends State { autoValidateMode: AutovalidateMode.disabled, selectorTextStyle: TextStyle(color: Colors.black), formatInput: true, - keyboardType: - TextInputType.numberWithOptions(signed: true, decimal: true), + keyboardType: TextInputType.numberWithOptions(signed: true, decimal: true), inputBorder: OutlineInputBorder(), ); } else if (isCPR) { @@ -549,8 +516,7 @@ class ParticipantDataPageState extends State { child: Container( decoration: BoxDecoration( border: Border.all( - color: - Theme.of(context).extension()!.grey600!, + color: Theme.of(context).extension()!.grey600!, width: 1.0, ), borderRadius: BorderRadius.circular(16.0), @@ -558,8 +524,7 @@ class ParticipantDataPageState extends State { child: CountryCodePicker( onChanged: (value) { stepField.controller.clear(); - widget.model._ssnCountryController.text = - value.code ?? ''; + widget.model._ssnCountryController.text = value.code ?? ''; stepField.controller.text = stepField.controller.text; }, initialSelection: 'DK', @@ -567,8 +532,7 @@ class ParticipantDataPageState extends State { showOnlyCountryWhenClosed: true, alignLeft: false, textStyle: fs16fw600.copyWith( - color: - Theme.of(context).extension()!.grey900!, + color: Theme.of(context).extension()!.grey900!, ), ), ), @@ -597,8 +561,7 @@ class ParticipantDataPageState extends State { textInputAction: TextInputAction.next, onFieldSubmitted: (_) { if (stepField.nextFocusNode != null) { - FocusScope.of(context) - .requestFocus(stepField.nextFocusNode); + FocusScope.of(context).requestFocus(stepField.nextFocusNode); } }, onTap: isDatePicker @@ -610,8 +573,7 @@ class ParticipantDataPageState extends State { lastDate: DateTime.now(), ); if (pickedDate != null) { - stepField.controller.text = - "${pickedDate.toLocal()}".split(' ')[0]; + stepField.controller.text = "${pickedDate.toLocal()}".split(' ')[0]; } } : null, @@ -624,8 +586,7 @@ class ParticipantDataPageState extends State { } } - InputDecoration _buildInputDecoration( - RPLocalizations locale, StepField stepField, bool isThicc) { + InputDecoration _buildInputDecoration(RPLocalizations locale, StepField stepField, bool isThicc) { return InputDecoration( labelText: locale.translate(stepField.title), floatingLabelBehavior: FloatingLabelBehavior.always, @@ -641,16 +602,15 @@ class ParticipantDataPageState extends State { borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: Colors.blue, width: 2), ), - contentPadding: - EdgeInsets.symmetric(horizontal: 16, vertical: isThicc ? 70 : 12)); + contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: isThicc ? 70 : 12)); } /// Builds the action buttons at the bottom of the page. /// Includes "Cancel", "Previous", "Next", and "Submit" buttons. /// The "Next" button is enabled only if the required fields for the current step are filled. List _buildActionButtons(RPLocalizations locale) { - Widget buildTranslatedButton(String key, VoidCallback onPressed, - bool enabled, ButtonStyle? buttonStyle, TextStyle? buttonTextStyle) { + Widget buildTranslatedButton( + String key, VoidCallback onPressed, bool enabled, ButtonStyle? buttonStyle, TextStyle? buttonTextStyle) { return ElevatedButton( onPressed: enabled ? onPressed : null, child: Text( @@ -683,10 +643,8 @@ class ParticipantDataPageState extends State { }, _nextEnabled, ElevatedButton.styleFrom( - backgroundColor: - Theme.of(context).extension()!.primary, - padding: - const EdgeInsets.symmetric(horizontal: 30, vertical: 12), + backgroundColor: Theme.of(context).extension()!.primary, + padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 12), ), TextStyle( color: Colors.white, @@ -704,10 +662,8 @@ class ParticipantDataPageState extends State { }, currentStep == ParticipantStep.presentTypes ? true : _nextEnabled, ElevatedButton.styleFrom( - backgroundColor: - Theme.of(context).extension()!.primary, - padding: - const EdgeInsets.symmetric(horizontal: 30, vertical: 12), + backgroundColor: Theme.of(context).extension()!.primary, + padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 12), ), TextStyle( color: Colors.white, @@ -736,8 +692,7 @@ class ParticipantDataPageState extends State { DiagnosisInput.type: DiagnosisInput( effectiveDate: widget.model._effectiveDateController.text.isNotEmpty ? DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") - .parse( - '${widget.model._effectiveDateController.text}T00:00:00Z') + .parse('${widget.model._effectiveDateController.text}T00:00:00Z') .toUtc() : null, diagnosis: widget.model._diagnosisDescriptionController.text, diff --git a/lib/ui/widgets/battery_icon.dart b/lib/ui/widgets/battery_icon.dart index 1a3dae64..bc402ee6 100644 --- a/lib/ui/widgets/battery_icon.dart +++ b/lib/ui/widgets/battery_icon.dart @@ -5,8 +5,7 @@ class BatteryPercentage extends StatelessWidget { super.key, required this.batteryLevel, this.scale = 1.0, - }) : assert(batteryLevel >= 0 && batteryLevel <= 100, - 'Battery level must be between 0 and 100'); + }) : assert(batteryLevel >= 0 && batteryLevel <= 100, 'Battery level must be between 0 and 100'); // Battery level from 0 to 100 final int batteryLevel; @@ -28,8 +27,7 @@ class BatteryPercentage extends StatelessWidget { height: height, child: Row(children: [ SizedBox( - width: - batteryLevel != 0 ? batteryLevel * (width * 0.9 / 100) : 0, + width: batteryLevel != 0 ? batteryLevel * (width * 0.9 / 100) : 0, height: height * 0.75, child: Container(color: Theme.of(context).primaryColor)), ]), diff --git a/lib/ui/widgets/carp_app_bar.dart b/lib/ui/widgets/carp_app_bar.dart index b7598380..8b5b60b3 100644 --- a/lib/ui/widgets/carp_app_bar.dart +++ b/lib/ui/widgets/carp_app_bar.dart @@ -31,10 +31,7 @@ class CarpAppBar extends StatelessWidget { ), tooltip: 'Profile', onPressed: () { - Navigator.push( - context, - SlidePageRoute( - ProfilePage(ProfilePageViewModel()))); + Navigator.push(context, SlidePageRoute(ProfilePage(ProfilePageViewModel()))); }, ), ], diff --git a/lib/ui/widgets/charts_legend.dart b/lib/ui/widgets/charts_legend.dart index 12f0a434..99cc4135 100644 --- a/lib/ui/widgets/charts_legend.dart +++ b/lib/ui/widgets/charts_legend.dart @@ -8,12 +8,7 @@ class ChartsLegend extends StatelessWidget { final List colors; const ChartsLegend( - {super.key, - this.heroTag, - this.iconAssetName, - required this.title, - this.values = const [], - required this.colors}); + {super.key, this.heroTag, this.iconAssetName, required this.title, this.values = const [], required this.colors}); @override Widget build(BuildContext context) { @@ -37,8 +32,7 @@ class ChartsLegend extends StatelessWidget { (entry) => Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Icon(Icons.circle, - color: colors[entry.key], size: 12.0), + Icon(Icons.circle, color: colors[entry.key], size: 12.0), Text(' ${entry.value} ', style: fs12fw400), ], ), diff --git a/lib/ui/widgets/details_banner.dart b/lib/ui/widgets/details_banner.dart index cc070eb2..aa9926ff 100644 --- a/lib/ui/widgets/details_banner.dart +++ b/lib/ui/widgets/details_banner.dart @@ -17,8 +17,7 @@ class DetailsBanner extends StatelessWidget { if (imagePath != null && imagePath!.isNotEmpty) SizedBox( height: 300, - child: - bloc.appViewModel.studyPageViewModel.getMessageImage(imagePath), + child: bloc.appViewModel.studyPageViewModel.getMessageImage(imagePath), ), Padding( padding: const EdgeInsets.all(16), @@ -29,8 +28,7 @@ class DetailsBanner extends StatelessWidget { children: [ Text( locale.translate(title), - style: fs30fw800.copyWith( - fontSize: 30, color: Theme.of(context).primaryColor), + style: fs30fw800.copyWith(fontSize: 30, color: Theme.of(context).primaryColor), ), ], ), diff --git a/lib/ui/widgets/dialog_title.dart b/lib/ui/widgets/dialog_title.dart index 51ed72ac..3c36339b 100644 --- a/lib/ui/widgets/dialog_title.dart +++ b/lib/ui/widgets/dialog_title.dart @@ -5,8 +5,7 @@ class DialogTitle extends StatelessWidget { final String? deviceName; final String? titleEnd; - const DialogTitle( - {super.key, required this.title, this.deviceName, this.titleEnd}); + const DialogTitle({super.key, required this.title, this.deviceName, this.titleEnd}); @override Widget build(BuildContext context) { @@ -14,17 +13,14 @@ class DialogTitle extends StatelessWidget { return _buildDialogTitle(locale, title, context); } - Widget _buildDialogTitle( - RPLocalizations locale, String title, BuildContext context) { + Widget _buildDialogTitle(RPLocalizations locale, String title, BuildContext context) { return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ IconButton( - onPressed: () => Navigator.of(context).canPop() - ? Navigator.of(context).pop() - : null, + onPressed: () => Navigator.of(context).canPop() ? Navigator.of(context).pop() : null, icon: const Icon(Icons.close), padding: const EdgeInsets.only(right: 8), ), @@ -42,12 +38,8 @@ class DialogTitle extends StatelessWidget { locale.translate( title, ) + - (deviceName != null - ? " ${locale.translate(deviceName!)} " - : "") + - (titleEnd != null - ? ' ${locale.translate(titleEnd!)}' - : ""), + (deviceName != null ? " ${locale.translate(deviceName!)} " : "") + + (titleEnd != null ? ' ${locale.translate(titleEnd!)}' : ""), style: fs18fw700.copyWith( color: Theme.of(context).primaryColor, ), diff --git a/lib/ui/widgets/horizontal_bar.dart b/lib/ui/widgets/horizontal_bar.dart index bc3b3aa6..58bc1709 100644 --- a/lib/ui/widgets/horizontal_bar.dart +++ b/lib/ui/widgets/horizontal_bar.dart @@ -23,10 +23,7 @@ class HorizontalBar extends StatelessWidget { List assetList() { List assetList = []; for (int i = 0; i < names.length; i++) { - assetList.add(MyAsset( - size: values.elementAt(i), - color: colors.elementAt(i), - name: names.elementAt(i))); + assetList.add(MyAsset(size: values.elementAt(i), color: colors.elementAt(i), name: names.elementAt(i))); } return assetList; } @@ -42,8 +39,7 @@ class HorizontalBar extends StatelessWidget { child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(height / 2)), child: Container( - decoration: - BoxDecoration(color: Theme.of(context).colorScheme.tertiary), + decoration: BoxDecoration(color: Theme.of(context).colorScheme.tertiary), width: width, height: height, child: const SizedBox.shrink(), @@ -135,9 +131,7 @@ class MyAssetsBar extends StatelessWidget { //single.size : assetsSum = x : width Widget _createSingle(MyAsset singleAsset) { return SizedBox( - width: singleAsset.size! != 0 - ? singleAsset.size! * (width / _getValuesSum()) - : 0, + width: singleAsset.size! != 0 ? singleAsset.size! * (width / _getValuesSum()) : 0, child: Container(color: singleAsset.color), ); } @@ -151,14 +145,12 @@ class MyAssetsBar extends StatelessWidget { .entries .map( (entry) => Padding( - padding: - const EdgeInsets.symmetric(vertical: 4, horizontal: 8), + padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Icon(Icons.circle, color: entry.value.color, size: 12.0), - Text(' ${entry.value.name!} ${entry.value.size}', - style: fs12fw400, textAlign: TextAlign.right), + Text(' ${entry.value.name!} ${entry.value.size}', style: fs12fw400, textAlign: TextAlign.right), ], )), ) @@ -180,19 +172,15 @@ class MyAssetsBar extends StatelessWidget { .entries .map( (entry) => Padding( - padding: - const EdgeInsets.symmetric(vertical: 3, horizontal: 5), + padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 5), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Icon(Icons.circle, color: entry.value.color, size: 12.0), - Text(' ${entry.value.size}', - style: fs12fw400, textAlign: TextAlign.left), + Text(' ${entry.value.size}', style: fs12fw400, textAlign: TextAlign.left), Expanded( child: Text(' ${entry.value.name!}', - style: fs12fw400, - textAlign: TextAlign.left, - overflow: TextOverflow.ellipsis)), + style: fs12fw400, textAlign: TextAlign.left, overflow: TextOverflow.ellipsis)), ], )), ) @@ -217,10 +205,7 @@ class MyAssetsBar extends StatelessWidget { decoration: BoxDecoration(color: background), width: width, height: height, - child: Row( - children: assets - .map((singleAsset) => _createSingle(singleAsset)) - .toList()), + child: Row(children: assets.map((singleAsset) => _createSingle(singleAsset)).toList()), ), ), _labelOrientation(), diff --git a/lib/ui/widgets/location_permission_page.dart b/lib/ui/widgets/location_permission_page.dart index c4fce61a..2cf72ef2 100644 --- a/lib/ui/widgets/location_permission_page.dart +++ b/lib/ui/widgets/location_permission_page.dart @@ -5,8 +5,7 @@ class LocationPermissionPage { RPLocalizations locale = RPLocalizations.of(context)!; return Scaffold( - backgroundColor: - Theme.of(context).extension()!.backgroundGray, + backgroundColor: Theme.of(context).extension()!.backgroundGray, body: Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: SafeArea( @@ -27,8 +26,7 @@ class LocationPermissionPage { child: Padding( padding: const EdgeInsets.only(top: 16.0), child: StudiesMaterial( - backgroundColor: - Theme.of(context).extension()!.white!, + backgroundColor: Theme.of(context).extension()!.white!, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.0), ), @@ -50,26 +48,20 @@ class LocationPermissionPage { Row( children: [ Text( - locale.translate( - 'dialog.location.location_data'), + locale.translate('dialog.location.location_data'), style: TextStyle( fontWeight: FontWeight.bold, fontSize: 22.0, - color: Theme.of(context) - .extension()! - .primary, + color: Theme.of(context).extension()!.primary, ), ), ], ), Padding( - padding: const EdgeInsets.symmetric( - vertical: 24.0), + padding: const EdgeInsets.symmetric(vertical: 24.0), child: Icon( Icons.location_on, - color: Theme.of(context) - .extension()! - .primary, + color: Theme.of(context).extension()!.primary, size: 48, ), ), @@ -100,14 +92,11 @@ class LocationPermissionPage { ), child: TextButton( onPressed: () { - Permission.locationWhenInUse - .request() - .then((value) => context.pop(true)); + Permission.locationWhenInUse.request().then((value) => context.pop(true)); }, child: Text( locale.translate("dialog.location.continue"), - style: - const TextStyle(color: Color(0xffffffff), fontSize: 22), + style: const TextStyle(color: Color(0xffffffff), fontSize: 22), textAlign: TextAlign.center, ), ), diff --git a/lib/ui/widgets/location_usage_dialog.dart b/lib/ui/widgets/location_usage_dialog.dart index 33f5599a..85b3280e 100644 --- a/lib/ui/widgets/location_usage_dialog.dart +++ b/lib/ui/widgets/location_usage_dialog.dart @@ -15,8 +15,7 @@ class LocationUsageDialog { width: MediaQuery.of(context).size.width * 0.15, height: MediaQuery.of(context).size.height * 0.15, ), - Text(locale.translate("dialog.location.permission"), - style: fs20fw700), + Text(locale.translate("dialog.location.permission"), style: fs20fw700), ], ), contentPadding: const EdgeInsets.all(15), @@ -38,15 +37,11 @@ class LocationUsageDialog { actions: [ ElevatedButton( onPressed: () { - Permission.locationWhenInUse - .request() - .then((value) => context.pop(true)); + Permission.locationWhenInUse.request().then((value) => context.pop(true)); }, style: ButtonStyle( - backgroundColor: - WidgetStateProperty.all(Theme.of(context).primaryColor), - foregroundColor: WidgetStateProperty.all( - Theme.of(context).colorScheme.onPrimary), + backgroundColor: WidgetStateProperty.all(Theme.of(context).primaryColor), + foregroundColor: WidgetStateProperty.all(Theme.of(context).colorScheme.onPrimary), ), child: Text( locale.translate("dialog.location.continue"), diff --git a/lib/view_models/cards/activity_data_model.dart b/lib/view_models/cards/activity_data_model.dart index 4b7519b6..9bd47b4c 100644 --- a/lib/view_models/cards/activity_data_model.dart +++ b/lib/view_models/cards/activity_data_model.dart @@ -1,37 +1,30 @@ part of carp_study_app; class ActivityCardViewModel extends SerializableViewModel { - Measurement _lastActivity = - Measurement.fromData(Activity(type: ActivityType.STILL, confidence: 100)); + Measurement _lastActivity = Measurement.fromData(Activity(type: ActivityType.STILL, confidence: 100)); @override WeeklyActivities createModel() => WeeklyActivities(); Map> get activities => model.activities; - List activitiesByType(ActivityType type) => - model.activitiesByType(type); + List activitiesByType(ActivityType type) => model.activitiesByType(type); /// Stream of activity measurements. - Stream? get activityEvents => controller?.measurements - .where((measurement) => measurement.data is Activity); + Stream? get activityEvents => + controller?.measurements.where((measurement) => measurement.data is Activity); - final DateTime _startOfWeek = - DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)); - final DateTime _endOfWeek = DateTime.now() - .subtract(Duration(days: DateTime.now().weekday - 1)) - .add(Duration(days: 6)); + final DateTime _startOfWeek = DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)); + final DateTime _endOfWeek = + DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)).add(Duration(days: 6)); String get startOfWeek => DateFormat('dd').format(_startOfWeek); String get endOfWeek => DateFormat('dd').format(_endOfWeek); - String get currentMonth => - DateFormat('MMM').format(DateTime(_startOfWeek.year, _startOfWeek.month)); + String get currentMonth => DateFormat('MMM').format(DateTime(_startOfWeek.year, _startOfWeek.month)); - String get nextMonth => DateFormat('MMM') - .format(DateTime(_startOfWeek.year, _startOfWeek.month + 1, 1)); + String get nextMonth => DateFormat('MMM').format(DateTime(_startOfWeek.year, _startOfWeek.month + 1, 1)); - String get currentYear => - DateFormat('yyyy').format(DateTime(DateTime.now().year)); + String get currentYear => DateFormat('yyyy').format(DateTime(DateTime.now().year)); @override void init(SmartphoneDeploymentController ctrl) { @@ -41,14 +34,11 @@ class ActivityCardViewModel extends SerializableViewModel { activityEvents?.listen((measurement) { var lastActivity = _lastActivity; - if ((measurement.data as Activity).type != - (lastActivity.data as Activity).type) { + if ((measurement.data as Activity).type != (lastActivity.data as Activity).type) { // if we have a new type of activity // add the minutes to the last known activity type - DateTime start = - DateTime.fromMicrosecondsSinceEpoch(lastActivity.sensorStartTime); - DateTime end = - DateTime.fromMicrosecondsSinceEpoch(measurement.sensorStartTime); + DateTime start = DateTime.fromMicrosecondsSinceEpoch(lastActivity.sensorStartTime); + DateTime end = DateTime.fromMicrosecondsSinceEpoch(measurement.sensorStartTime); model.increaseActivityDuration( (lastActivity.data as Activity).type, start.weekday, @@ -73,10 +63,8 @@ class WeeklyActivities extends DataModel { Map> activities = {}; /// A list of activities of a specific [type]. - List activitiesByType(ActivityType type) => activities[type]! - .entries - .map((entry) => DailyActivity(entry.key, entry.value)) - .toList(); + List activitiesByType(ActivityType type) => + activities[type]!.entries.map((entry) => DailyActivity(entry.key, entry.value)).toList(); WeeklyActivities() { // initialize every week or if is the first time opening the app @@ -94,21 +82,19 @@ class WeeklyActivities extends DataModel { int weekday, int minutes, ) { - activities[activityType]![weekday] = - (activities[activityType]![weekday] ?? 0) + minutes; + activities[activityType]![weekday] = (activities[activityType]![weekday] ?? 0) + minutes; } @override - WeeklyActivities fromJson(Map json) => - _$WeeklyActivitiesFromJson(json); + WeeklyActivities fromJson(Map json) => _$WeeklyActivitiesFromJson(json); @override Map toJson() => _$WeeklyActivitiesToJson(this); @override String toString() { String str = ' TYPE\t| day | min.\n'; - activities.forEach((type, data) => data.forEach((day, minutes) => - str += '${type.toString().split(".").last}\t| $day | $minutes\n')); + activities.forEach((type, data) => + data.forEach((day, minutes) => str += '${type.toString().split(".").last}\t| $day | $minutes\n')); return str; } } diff --git a/lib/view_models/cards/heart_rate_data_model.dart b/lib/view_models/cards/heart_rate_data_model.dart index 75ef5be6..65c71ffe 100644 --- a/lib/view_models/cards/heart_rate_data_model.dart +++ b/lib/view_models/cards/heart_rate_data_model.dart @@ -11,8 +11,7 @@ class HeartRateCardViewModel extends SerializableViewModel { /// The current heart rate double? get currentHeartRate => model.currentHeartRate; - HeartRateMinMaxPrHour get dayMinMax => - HeartRateMinMaxPrHour(model.minHeartRate, model.maxHeartRate); + HeartRateMinMaxPrHour get dayMinMax => HeartRateMinMaxPrHour(model.minHeartRate, model.maxHeartRate); final StreamGroup _group = StreamGroup.broadcast(); @@ -21,9 +20,7 @@ class HeartRateCardViewModel extends SerializableViewModel { /// Stream of heart rate based on [PolarHR] measures. Stream? get polarHRStream => controller?.measurements .where((measurement) => measurement.data is PolarHR) - .map((measurement) => - (measurement.data as PolarHR).samples.firstOrNull?.hr.toDouble() ?? - 0); + .map((measurement) => (measurement.data as PolarHR).samples.firstOrNull?.hr.toDouble() ?? 0); /// Stream of heart rate based on [MovesenseHR] measures. Stream? get movesenseHRStream => controller?.measurements @@ -124,14 +121,12 @@ class HourlyHeartRate extends DataModel { @override String toString() { String str = 'time | heart rate\n'; - hourlyHeartRate - .forEach((time, heartRate) => str += '$time | $heartRate\n'); + hourlyHeartRate.forEach((time, heartRate) => str += '$time | $heartRate\n'); return str; } @override - HourlyHeartRate fromJson(Map json) => - _$HourlyHeartRateFromJson(json); + HourlyHeartRate fromJson(Map json) => _$HourlyHeartRateFromJson(json); @override Map toJson() => _$HourlyHeartRateToJson(this); } @@ -146,17 +141,13 @@ class HeartRateMinMaxPrHour { @override String toString() => {'min': min, 'max': max}.toString(); - factory HeartRateMinMaxPrHour.fromJson(Map json) => - _$HeartRateMinMaxPrHourFromJson(json); + factory HeartRateMinMaxPrHour.fromJson(Map json) => _$HeartRateMinMaxPrHourFromJson(json); Map toJson() => _$HeartRateMinMaxPrHourToJson(this); @override bool operator ==(Object other) => identical(this, other) || - other is HeartRateMinMaxPrHour && - runtimeType == other.runtimeType && - min == other.min && - max == other.max; + other is HeartRateMinMaxPrHour && runtimeType == other.runtimeType && min == other.min && max == other.max; @override int get hashCode => min.hashCode ^ max.hashCode; diff --git a/lib/view_models/cards/measurements_data_model.dart b/lib/view_models/cards/measurements_data_model.dart index 5b95c201..542b8286 100644 --- a/lib/view_models/cards/measurements_data_model.dart +++ b/lib/view_models/cards/measurements_data_model.dart @@ -7,12 +7,11 @@ class MeasurementsCardViewModel extends ViewModel { Stream? get measureEvents => controller?.measurements; /// Stream of more quiet [DataPoint] measures. - Stream? get quietMeasureEvents => controller?.measurements - .where((measurement) => measurement.dataType.name != 'sensor'); + Stream? get quietMeasureEvents => + controller?.measurements.where((measurement) => measurement.dataType.name != 'sensor'); /// The total sampling size - int get samplingSize => - controller?.samplingSize == null ? 0 : controller!.samplingSize; + int get samplingSize => controller?.samplingSize == null ? 0 : controller!.samplingSize; // samplingTable.values.fold(0, (prev, element) => prev + element); /// A table with sampling size of each measure type @@ -28,14 +27,12 @@ class MeasurementsCardViewModel extends ViewModel { /// The list of measures List get measures { // sort them first - var mapEntries = _samplingTable.entries.toList() - ..sort((b, a) => a.value.compareTo(b.value)); + var mapEntries = _samplingTable.entries.toList()..sort((b, a) => a.value.compareTo(b.value)); Map sortedTasksTable = {}..addEntries(mapEntries); // and map to the [TaskCount] model - List tasksList = sortedTasksTable.entries - .map((entry) => MeasureCount(entry.key, entry.value)) - .toList(); + List tasksList = + sortedTasksTable.entries.map((entry) => MeasureCount(entry.key, entry.value)).toList(); return tasksList; } diff --git a/lib/view_models/cards/mobility_data_model.dart b/lib/view_models/cards/mobility_data_model.dart index e53a15c4..03dcd0c7 100644 --- a/lib/view_models/cards/mobility_data_model.dart +++ b/lib/view_models/cards/mobility_data_model.dart @@ -7,27 +7,22 @@ class MobilityCardViewModel extends SerializableViewModel { Map get weekData => model.weekMobility; /// Stream of mobility [DataPoint] measures. - Stream? get mobilityEvents => controller?.measurements - .where((measurement) => measurement.data is Mobility); + Stream? get mobilityEvents => + controller?.measurements.where((measurement) => measurement.data is Mobility); - final DateTime _startOfWeek = - DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)); - final DateTime _endOfWeek = DateTime.now() - .subtract(Duration(days: DateTime.now().weekday - 1)) - .add(Duration(days: 6)); + final DateTime _startOfWeek = DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)); + final DateTime _endOfWeek = + DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)).add(Duration(days: 6)); String get startOfWeek => DateFormat('dd').format(_startOfWeek); String get endOfWeek => DateFormat('dd').format(_endOfWeek); - String get currentMonth => - DateFormat('MMM').format(DateTime(_startOfWeek.year, _startOfWeek.month)); + String get currentMonth => DateFormat('MMM').format(DateTime(_startOfWeek.year, _startOfWeek.month)); - String get nextMonth => DateFormat('MMM') - .format(DateTime(_startOfWeek.year, _startOfWeek.month + 1, 1)); + String get nextMonth => DateFormat('MMM').format(DateTime(_startOfWeek.year, _startOfWeek.month + 1, 1)); - String get currentYear => - DateFormat('yyyy').format(DateTime(DateTime.now().year)); + String get currentYear => DateFormat('yyyy').format(DateTime(DateTime.now().year)); MobilityCardViewModel(); @override @@ -64,18 +59,12 @@ class WeeklyMobility extends DataModel { void setMobilityFeatures(Mobility data) { DateTime day = data.date ?? DateTime.now(); - weekMobility[day.weekday] = DailyMobility( - day.weekday, - data.numberOfPlaces ?? 0, - data.homeStay != null && data.homeStay! > 0 - ? (100 * (data.homeStay!)).toInt() - : 0, - data.distanceTraveled ?? 0); + weekMobility[day.weekday] = DailyMobility(day.weekday, data.numberOfPlaces ?? 0, + data.homeStay != null && data.homeStay! > 0 ? (100 * (data.homeStay!)).toInt() : 0, data.distanceTraveled ?? 0); } @override - WeeklyMobility fromJson(Map json) => - _$WeeklyMobilityFromJson(json); + WeeklyMobility fromJson(Map json) => _$WeeklyMobilityFromJson(json); @override Map toJson() => _$WeeklyMobilityToJson(this); } @@ -90,6 +79,5 @@ class DailyMobility extends DailyMeasure { DailyMobility(super.weekday, this.places, this.homeStay, this.distance); Map toJson() => _$DailyMobilityToJson(this); - static DailyMobility fromJson(Map json) => - _$DailyMobilityFromJson(json); + static DailyMobility fromJson(Map json) => _$DailyMobilityFromJson(json); } diff --git a/lib/view_models/cards/steps_data_model.dart b/lib/view_models/cards/steps_data_model.dart index 02ecf2b4..da57763d 100644 --- a/lib/view_models/cards/steps_data_model.dart +++ b/lib/view_models/cards/steps_data_model.dart @@ -12,28 +12,23 @@ class StepsCardViewModel extends SerializableViewModel { /// The list of steps. List get steps => model.steps; - final DateTime _startOfWeek = - DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)); - final DateTime _endOfWeek = DateTime.now() - .subtract(Duration(days: DateTime.now().weekday - 1)) - .add(Duration(days: 6)); + final DateTime _startOfWeek = DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)); + final DateTime _endOfWeek = + DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)).add(Duration(days: 6)); String get startOfWeek => DateFormat('dd').format(_startOfWeek); String get endOfWeek => DateFormat('dd').format(_endOfWeek); - String get currentMonth => - DateFormat('MMM').format(DateTime(_startOfWeek.year, _startOfWeek.month)); + String get currentMonth => DateFormat('MMM').format(DateTime(_startOfWeek.year, _startOfWeek.month)); - String get nextMonth => DateFormat('MMM') - .format(DateTime(_startOfWeek.year, _startOfWeek.month + 1, 1)); + String get nextMonth => DateFormat('MMM').format(DateTime(_startOfWeek.year, _startOfWeek.month + 1, 1)); - String get currentYear => - DateFormat('yyyy').format(DateTime(DateTime.now().year)); + String get currentYear => DateFormat('yyyy').format(DateTime(DateTime.now().year)); /// Stream of pedometer (step) [DataPoint] measures. - Stream? get pedometerEvents => controller?.measurements - .where((dataPoint) => dataPoint.data is StepCount); + Stream? get pedometerEvents => + controller?.measurements.where((dataPoint) => dataPoint.data is StepCount); @override void init(SmartphoneDeploymentController ctrl) { @@ -43,8 +38,7 @@ class StepsCardViewModel extends SerializableViewModel { pedometerEvents?.listen((pedometerDataPoint) { StepCount? step = pedometerDataPoint.data as StepCount?; if (_lastStep != null) { - model.increaseStepCount( - DateTime.now().weekday, step!.steps - _lastStep!.steps); + model.increaseStepCount(DateTime.now().weekday, step!.steps - _lastStep!.steps); } _lastStep = step; @@ -71,12 +65,9 @@ class WeeklySteps extends DataModel { } /// The list of steps listed pr. weekday. - List get steps => weeklySteps.entries - .map((entry) => DailySteps(entry.key, entry.value)) - .toList(); + List get steps => weeklySteps.entries.map((entry) => DailySteps(entry.key, entry.value)).toList(); - void increaseStepCount(int weekday, int steps) => - weeklySteps[weekday] = (weeklySteps[weekday] ?? 0) + steps; + void increaseStepCount(int weekday, int steps) => weeklySteps[weekday] = (weeklySteps[weekday] ?? 0) + steps; @override String toString() { @@ -86,8 +77,7 @@ class WeeklySteps extends DataModel { } @override - WeeklySteps fromJson(Map json) => - _$WeeklyStepsFromJson(json); + WeeklySteps fromJson(Map json) => _$WeeklyStepsFromJson(json); @override Map toJson() => _$WeeklyStepsToJson(this); } diff --git a/lib/view_models/cards/study_progress_data_model.dart b/lib/view_models/cards/study_progress_data_model.dart index 215dbbdb..ee2fa8f9 100644 --- a/lib/view_models/cards/study_progress_data_model.dart +++ b/lib/view_models/cards/study_progress_data_model.dart @@ -20,9 +20,8 @@ class StudyProgressCardViewModel extends ViewModel { Map get progressTable => _progressTable; /// The list of measures - List get progress => _progressTable.entries - .map((entry) => StudyProgress(entry.key, entry.value)) - .toList(); + List get progress => + _progressTable.entries.map((entry) => StudyProgress(entry.key, entry.value)).toList(); StudyProgressCardViewModel() : super(); diff --git a/lib/view_models/cards/task_data_model.dart b/lib/view_models/cards/task_data_model.dart index 047ed85e..dcc0b374 100644 --- a/lib/view_models/cards/task_data_model.dart +++ b/lib/view_models/cards/task_data_model.dart @@ -19,8 +19,7 @@ class TaskCardViewModel extends ViewModel { AppTaskController() .userTaskQueue - .where( - (task) => task.state == UserTaskState.done && task.type == taskType) + .where((task) => task.state == UserTaskState.done && task.type == taskType) .forEach((task) { if (!tasksTable.containsKey(task.title)) tasksTable[task.title] = 0; tasksTable[task.title] = tasksTable[task.title]! + 1; @@ -31,21 +30,17 @@ class TaskCardViewModel extends ViewModel { /// The total number of tasks done of type [taskType]. int get tasksDone => AppTaskController() .userTaskQueue - .where( - (task) => task.state == UserTaskState.done && task.type == taskType) + .where((task) => task.state == UserTaskState.done && task.type == taskType) .length; /// The list of [TaskCount]s done. List get taskCount { // sort them first - var mapEntries = tasksTable.entries.toList() - ..sort((b, a) => a.value.compareTo(b.value)); + var mapEntries = tasksTable.entries.toList()..sort((b, a) => a.value.compareTo(b.value)); Map sortedTasksTable = {}..addEntries(mapEntries); // and map to the [TaskCount] model - List tasksList = sortedTasksTable.entries - .map((entry) => TaskCount(entry.key, entry.value)) - .toList(); + List tasksList = sortedTasksTable.entries.map((entry) => TaskCount(entry.key, entry.value)).toList(); return tasksList; } diff --git a/lib/view_models/data_visualization_page_model.dart b/lib/view_models/data_visualization_page_model.dart index 407a63bc..cfc1a9ff 100644 --- a/lib/view_models/data_visualization_page_model.dart +++ b/lib/view_models/data_visualization_page_model.dart @@ -3,21 +3,14 @@ part of carp_study_app; class DataVisualizationPageViewModel extends ViewModel { final ActivityCardViewModel _activityCardDataModel = ActivityCardViewModel(); final StepsCardViewModel _stepsCardDataModel = StepsCardViewModel(); - final MeasurementsCardViewModel _measuresCardDataModel = - MeasurementsCardViewModel(); + final MeasurementsCardViewModel _measuresCardDataModel = MeasurementsCardViewModel(); final MobilityCardViewModel _mobilityCardDataModel = MobilityCardViewModel(); - final TaskCardViewModel _surveysCardDataModel = - TaskCardViewModel(SurveyUserTask.SURVEY_TYPE); - final TaskCardViewModel _audioCardDataModel = - TaskCardViewModel(SurveyUserTask.AUDIO_TYPE); - final TaskCardViewModel _videoCardDataModel = - TaskCardViewModel(SurveyUserTask.VIDEO_TYPE); - final TaskCardViewModel _imageCardDataModel = - TaskCardViewModel(SurveyUserTask.IMAGE_TYPE); - final StudyProgressCardViewModel _studyProgressCardDataModel = - StudyProgressCardViewModel(); - final HeartRateCardViewModel _heartRateCardDataModel = - HeartRateCardViewModel(); + final TaskCardViewModel _surveysCardDataModel = TaskCardViewModel(SurveyUserTask.SURVEY_TYPE); + final TaskCardViewModel _audioCardDataModel = TaskCardViewModel(SurveyUserTask.AUDIO_TYPE); + final TaskCardViewModel _videoCardDataModel = TaskCardViewModel(SurveyUserTask.VIDEO_TYPE); + final TaskCardViewModel _imageCardDataModel = TaskCardViewModel(SurveyUserTask.IMAGE_TYPE); + final StudyProgressCardViewModel _studyProgressCardDataModel = StudyProgressCardViewModel(); + final HeartRateCardViewModel _heartRateCardDataModel = HeartRateCardViewModel(); ActivityCardViewModel get activityCardDataModel => _activityCardDataModel; StepsCardViewModel get stepsCardDataModel => _stepsCardDataModel; @@ -29,22 +22,17 @@ class DataVisualizationPageViewModel extends ViewModel { TaskCardViewModel get imageCardDataModel => _imageCardDataModel; HeartRateCardViewModel get heartRateCardDataModel => _heartRateCardDataModel; - StudyProgressCardViewModel get studyProgressCardDataModel => - _studyProgressCardDataModel; + StudyProgressCardViewModel get studyProgressCardDataModel => _studyProgressCardDataModel; /// A stream of [UserTask]s as they are generated. Stream get userTaskEvents => AppTaskController().userTaskEvents; /// The number of days the user has been part of this study. - int get daysInStudy => (bloc.studyStartTimestamp != null) - ? DateTime.now().difference(bloc.studyStartTimestamp!).inDays + 1 - : 0; + int get daysInStudy => + (bloc.studyStartTimestamp != null) ? DateTime.now().difference(bloc.studyStartTimestamp!).inDays + 1 : 0; /// The number of tasks completed so far. - int get taskCompleted => AppTaskController() - .userTaskQueue - .where((task) => task.state == UserTaskState.done) - .length; + int get taskCompleted => AppTaskController().userTaskQueue.where((task) => task.state == UserTaskState.done).length; DataVisualizationPageViewModel(); diff --git a/lib/view_models/device_view_models.dart b/lib/view_models/device_view_models.dart index 4ef202f0..03bbce31 100644 --- a/lib/view_models/device_view_models.dart +++ b/lib/view_models/device_view_models.dart @@ -18,8 +18,7 @@ class DeviceViewModel extends ViewModel { String? get type => deviceManager.type; /// A printer-friendly name for this [type] of device. - String get typeName => - _deviceTypeName[type!] ?? 'pages.devices.type.unknown.name'; + String get typeName => _deviceTypeName[type!] ?? 'pages.devices.type.unknown.name'; /// The status of this device. DeviceStatus get status => deviceManager.status; @@ -43,16 +42,14 @@ class DeviceViewModel extends ViewModel { } /// A printer-friendly description of this device. - String get description => - '${_deviceTypeDescription[type!]} - ${status.name}\n$batteryLevel% battery remaining.'; + String get description => '${_deviceTypeDescription[type!]} - ${status.name}\n$batteryLevel% battery remaining.'; /// The battery level of this device. /// /// Only relevant if this device is a [HardwareDeviceManager]. /// Returns null if not a hardware device. - int? get batteryLevel => (deviceManager is HardwareDeviceManager) - ? (deviceManager as HardwareDeviceManager).batteryLevel - : null; + int? get batteryLevel => + (deviceManager is HardwareDeviceManager) ? (deviceManager as HardwareDeviceManager).batteryLevel : null; /// The stream of battery level events. /// @@ -77,13 +74,11 @@ class DeviceViewModel extends ViewModel { /// Instructions to the user on how to connect to this type of device. String? get connectionInstructions => _deviceConnectionInstructions[type!]; - String? get connectionInstructionsImage => - _deviceConnectionInstructionsImage[type!]; + String? get connectionInstructionsImage => _deviceConnectionInstructionsImage[type!]; PolarDeviceType get polarDeviceType { if (deviceManager is PolarDeviceManager) { - return (deviceManager as PolarDeviceManager).configuration?.deviceType ?? - PolarDeviceType.UNKNOWN; + return (deviceManager as PolarDeviceManager).configuration?.deviceType ?? PolarDeviceType.UNKNOWN; } else { return PolarDeviceType.UNKNOWN; } @@ -91,10 +86,7 @@ class DeviceViewModel extends ViewModel { MovesenseDeviceType get movesenseDeviceType { if (deviceManager is MovesenseDeviceManager) { - return (deviceManager as MovesenseDeviceManager) - .configuration - ?.deviceType ?? - MovesenseDeviceType.UNKNOWN; + return (deviceManager as MovesenseDeviceManager).configuration?.deviceType ?? MovesenseDeviceType.UNKNOWN; } else { return MovesenseDeviceType.UNKNOWN; } @@ -103,18 +95,15 @@ class DeviceViewModel extends ViewModel { /// Display information about this phone. Map get phoneInfo => { 'name': '${DeviceInfo().deviceID}', - 'model': - '${DeviceInfo().deviceModel} (${DeviceInfo().deviceManufacturer?.toUpperCase()})', + 'model': '${DeviceInfo().deviceModel} (${DeviceInfo().deviceManufacturer?.toUpperCase()})', 'version': 'SDK ${DeviceInfo().sdk}', }; /// Map a selected device to the device in the protocol and connect to it. void connectToDevice(BluetoothDevice selectedDevice) { if (deviceManager is BTLEDeviceManager) { - (deviceManager as BTLEDeviceManager).btleAddress = - selectedDevice.remoteId.str; - (deviceManager as BTLEDeviceManager).btleName = - selectedDevice.platformName; + (deviceManager as BTLEDeviceManager).btleAddress = selectedDevice.remoteId.str; + (deviceManager as BTLEDeviceManager).btleName = selectedDevice.platformName; } Sensing().controller?.saveDeployment(); @@ -134,8 +123,7 @@ class DeviceViewModel extends ViewModel { Sensing().controller?.saveDeployment(); } catch (error) { - warning( - "$runtimeType - Error disconnecting to device '${deviceManager.id}' - $error."); + warning("$runtimeType - Error disconnecting to device '${deviceManager.id}' - $error."); } } } @@ -197,28 +185,22 @@ const Map _deviceTypeIcon = { const Map _deviceStatusIcon = { DeviceStatus.initialized: "pages.devices.status.action.connect", - DeviceStatus.connecting: Icon(Icons.bluetooth_searching_rounded, - color: CACHET.DARK_BLUE, size: 30), - DeviceStatus.connected: - Icon(Icons.bluetooth_rounded, color: CACHET.GREEN_1, size: 30), + DeviceStatus.connecting: Icon(Icons.bluetooth_searching_rounded, color: CACHET.DARK_BLUE, size: 30), + DeviceStatus.connected: Icon(Icons.bluetooth_rounded, color: CACHET.GREEN_1, size: 30), DeviceStatus.disconnected: "pages.devices.status.action.connect", DeviceStatus.paired: "pages.devices.status.action.connect", DeviceStatus.error: Icon(Icons.error_outline, color: CACHET.RED_1, size: 30), - DeviceStatus.unknown: - Icon(Icons.error_outline, color: CACHET.RED_1, size: 30), + DeviceStatus.unknown: Icon(Icons.error_outline, color: CACHET.RED_1, size: 30), }; const Map _serviceStatusIcon = { DeviceStatus.initialized: "pages.devices.status.action.connect", - DeviceStatus.connecting: - Icon(Icons.sensors_off_rounded, color: CACHET.GREEN_1, size: 30), - DeviceStatus.connected: - Icon(Icons.sensors_rounded, color: CACHET.GREEN_1, size: 30), + DeviceStatus.connecting: Icon(Icons.sensors_off_rounded, color: CACHET.GREEN_1, size: 30), + DeviceStatus.connected: Icon(Icons.sensors_rounded, color: CACHET.GREEN_1, size: 30), DeviceStatus.disconnected: "pages.devices.status.action.connect", DeviceStatus.paired: "pages.devices.status.action.connect", DeviceStatus.error: Icon(Icons.error_outline, color: CACHET.RED_1, size: 30), - DeviceStatus.unknown: - Icon(Icons.error_outline, color: CACHET.RED_1, size: 30), + DeviceStatus.unknown: Icon(Icons.error_outline, color: CACHET.RED_1, size: 30), }; const Map _deviceStatusText = { diff --git a/lib/view_models/invitations_view_model.dart b/lib/view_models/invitations_view_model.dart index f243ed4c..7fdc2325 100644 --- a/lib/view_models/invitations_view_model.dart +++ b/lib/view_models/invitations_view_model.dart @@ -1,10 +1,8 @@ part of carp_study_app; class InvitationsViewModel extends ViewModel { - List get invitations => - bloc.backend.invitations; + List get invitations => bloc.backend.invitations; ActiveParticipationInvitation getInvitation(String invitationId) => - invitations.firstWhere((invitation) => - invitation.participation.participantId == invitationId); + invitations.firstWhere((invitation) => invitation.participation.participantId == invitationId); } diff --git a/lib/view_models/participant_data_page_model.dart b/lib/view_models/participant_data_page_model.dart index d3d4aab1..b3a33c5b 100644 --- a/lib/view_models/participant_data_page_model.dart +++ b/lib/view_models/participant_data_page_model.dart @@ -1,8 +1,7 @@ part of carp_study_app; class ParticipantDataPageViewModel extends ViewModel { - Set get expectedData => - bloc.expectedParticipantData; + Set get expectedData => bloc.expectedParticipantData; late TextEditingController _address1Controller; late TextEditingController _address2Controller; diff --git a/lib/view_models/profile_page_model.dart b/lib/view_models/profile_page_model.dart index a78f5e6f..0229b7f4 100644 --- a/lib/view_models/profile_page_model.dart +++ b/lib/view_models/profile_page_model.dart @@ -10,19 +10,15 @@ class ProfilePageViewModel extends ViewModel { String get studyId => bloc.deployment?.studyId ?? ''; String get studyDeploymentId => bloc.deployment?.studyDeploymentId ?? ''; - String get studyDeploymentTitle => - bloc.deployment?.studyDescription?.title ?? ''; + String get studyDeploymentTitle => bloc.deployment?.studyDescription?.title ?? ''; String get participantId => bloc.deployment?.participantId ?? ''; String get participantRole => bloc.deployment?.participantRoleName ?? ''; String get deviceRole => bloc.deployment?.deviceRoleName ?? ''; - String get responsibleEmail => - bloc.deployment?.studyDescription?.responsible?.email ?? 'study@carp.dk'; + String get responsibleEmail => bloc.deployment?.studyDescription?.responsible?.email ?? 'study@carp.dk'; String get privacyPolicyUrl => - bloc.deployment?.studyDescription?.privacyPolicyUrl ?? - 'https://carp.dk/privacy-policy-app/'; - String get studyDescriptionUrl => - bloc.deployment?.studyDescription?.studyDescriptionUrl ?? ''; + bloc.deployment?.studyDescription?.privacyPolicyUrl ?? 'https://carp.dk/privacy-policy-app/'; + String get studyDescriptionUrl => bloc.deployment?.studyDescription?.studyDescriptionUrl ?? ''; String get deviceID => DeviceInfo().deviceID ?? ''; String get currentServer => bloc.backend.uri.toString(); diff --git a/lib/view_models/study_page_model.dart b/lib/view_models/study_page_model.dart index b77f3f45..9a19d47f 100644 --- a/lib/view_models/study_page_model.dart +++ b/lib/view_models/study_page_model.dart @@ -4,35 +4,28 @@ part of carp_study_app; /// news articles to be shown as part of the study. class StudyPageViewModel extends ViewModel { String get title => bloc.deployment?.studyDescription?.title ?? 'Unnamed'; - String get description => - bloc.deployment?.studyDescription?.description ?? ''; + String get description => bloc.deployment?.studyDescription?.description ?? ''; String get purpose => bloc.deployment?.studyDescription?.purpose ?? ''; Image get image => Image.asset('assets/images/exercise.png'); String? get userID => bloc.deployment?.participantId; String get studyDeploymentId => bloc.deployment?.studyDeploymentId ?? ''; - String get responsibleName => - bloc.deployment?.studyDescription?.responsible?.name ?? ''; - String get responsibleEmail => - bloc.deployment?.studyDescription?.responsible?.email ?? ''; - String get studyDescriptionUrl => - bloc.deployment?.studyDescription?.studyDescriptionUrl ?? ''; + String get responsibleName => bloc.deployment?.studyDescription?.responsible?.name ?? ''; + String get responsibleEmail => bloc.deployment?.studyDescription?.responsible?.email ?? ''; + String get studyDescriptionUrl => bloc.deployment?.studyDescription?.studyDescriptionUrl ?? ''; String get privacyPolicyUrl => - bloc.deployment?.studyDescription?.privacyPolicyUrl ?? - 'https://carp.dk/privacy-policy-app/'; + bloc.deployment?.studyDescription?.privacyPolicyUrl ?? 'https://carp.dk/privacy-policy-app/'; String get piTitle => bloc.deployment?.responsible?.title ?? ''; String get piName => bloc.deployment?.responsible?.name ?? ''; String get piAddress => bloc.deployment?.responsible?.address ?? ''; String get piEmail => bloc.deployment?.responsible?.email ?? ''; String get piAffiliation => - bloc.deployment?.responsible?.affiliation ?? - 'Department of Health Technology, Technical University of Denmark'; + bloc.deployment?.responsible?.affiliation ?? 'Department of Health Technology, Technical University of Denmark'; String get participantRole => bloc.deployment?.participantRoleName ?? ''; String get deviceRole => bloc.deployment?.deviceRoleName ?? ''; - Future get studyDeploymentStatus => - bloc.studyDeploymentStatus; + Future get studyDeploymentStatus => bloc.studyDeploymentStatus; /// The stream of messages (count) Stream get messageStream => bloc.messageStream; diff --git a/lib/view_models/tasklist_page_model.dart b/lib/view_models/tasklist_page_model.dart index c3afeced..338539c1 100644 --- a/lib/view_models/tasklist_page_model.dart +++ b/lib/view_models/tasklist_page_model.dart @@ -39,14 +39,9 @@ class TaskListPageViewModel extends ViewModel { /// [StudyDeploymentStatus]. /// Returns 0 if the study deployment status is not available. int get daysInStudy => (Sensing().studyDeploymentStatus != null) - ? DateTime.now() - .difference(Sensing().studyDeploymentStatus!.createdOn) - .inDays + ? DateTime.now().difference(Sensing().studyDeploymentStatus!.createdOn).inDays : 0; /// The number of tasks completed so far. - int get tasksCompleted => AppTaskController() - .userTaskQueue - .where((task) => task.state == UserTaskState.done) - .length; + int get tasksCompleted => AppTaskController().userTaskQueue.where((task) => task.state == UserTaskState.done).length; } diff --git a/lib/view_models/user_tasks.dart b/lib/view_models/user_tasks.dart index 2b66f65c..6ce14b68 100644 --- a/lib/view_models/user_tasks.dart +++ b/lib/view_models/user_tasks.dart @@ -36,9 +36,7 @@ class AudioUserTask extends UserTask { int ongoingRecordingDuration = 60; AudioUserTask(AppTaskExecutor executor) : super(executor) { - recordingDuration = (executor.task.minutesToComplete != null) - ? executor.task.minutesToComplete! * 60 - : 60; + recordingDuration = (executor.task.minutesToComplete != null) ? executor.task.minutesToComplete! * 60 : 60; } @override @@ -137,15 +135,11 @@ class VideoUserTask extends UserTask { // create the media measurement ... media = switch (_mediaType) { MediaType.image => ImageMedia( - filename: _file!.path, - startRecordingTime: _startRecordingTime!, - endRecordingTime: _endRecordingTime) + filename: _file!.path, startRecordingTime: _startRecordingTime!, endRecordingTime: _endRecordingTime) ..filename = _file!.path.split("/").last ..path = _file!.path, MediaType.video => VideoMedia( - filename: _file!.path, - startRecordingTime: _startRecordingTime!, - endRecordingTime: _endRecordingTime) + filename: _file!.path, startRecordingTime: _startRecordingTime!, endRecordingTime: _endRecordingTime) ..filename = _file!.path.split("/").last ..path = _file!.path, _ => null, diff --git a/lib/view_models/view_model.dart b/lib/view_models/view_model.dart index 9585bb84..d0b29f69 100644 --- a/lib/view_models/view_model.dart +++ b/lib/view_models/view_model.dart @@ -76,8 +76,7 @@ abstract class SerializableViewModel extends ViewModel { }); // save the data model on a regular basis. - _persistenceTimer = - Timer.periodic(const Duration(minutes: 3), (_) => save()); + _persistenceTimer = Timer.periodic(const Duration(minutes: 3), (_) => save()); /// Check if we are running in a test environment. /// If so, do not listen to app lifecycle events. @@ -171,9 +170,7 @@ class DailyMeasure { /// Get the localized name of the [weekday]. @override - String toString() => DateFormat('EEEE') - .format(DateTime(2021, 2, 7).add(Duration(days: weekday))) - .substring(0, 3); + String toString() => DateFormat('EEEE').format(DateTime(2021, 2, 7).add(Duration(days: weekday))).substring(0, 3); } /// A measure for a specific hour of the day. [hour] and [minute] is the time of the day in 24 hour format. @@ -190,33 +187,25 @@ class HourlyMeasure { /// The view model for the entire app. class CarpStudyAppViewModel extends ViewModel { - final DataVisualizationPageViewModel _dataVisualizationPageViewModel = - DataVisualizationPageViewModel(); + final DataVisualizationPageViewModel _dataVisualizationPageViewModel = DataVisualizationPageViewModel(); final StudyPageViewModel _studyPageViewModel = StudyPageViewModel(); final TaskListPageViewModel _taskListPageViewModel = TaskListPageViewModel(); final ProfilePageViewModel _profilePageViewModel = ProfilePageViewModel(); - final DeviceListPageViewModel _devicesPageViewModel = - DeviceListPageViewModel(); + final DeviceListPageViewModel _devicesPageViewModel = DeviceListPageViewModel(); final InvitationsViewModel _invitationsListViewModel = InvitationsViewModel(); - final InformedConsentViewModel _informedConsentViewModel = - InformedConsentViewModel(); - final ParticipantDataPageViewModel _participantDataPageViewModel = - ParticipantDataPageViewModel(); + final InformedConsentViewModel _informedConsentViewModel = InformedConsentViewModel(); + final ParticipantDataPageViewModel _participantDataPageViewModel = ParticipantDataPageViewModel(); CarpStudyAppViewModel() : super(); - DataVisualizationPageViewModel get dataVisualizationPageViewModel => - _dataVisualizationPageViewModel; + DataVisualizationPageViewModel get dataVisualizationPageViewModel => _dataVisualizationPageViewModel; StudyPageViewModel get studyPageViewModel => _studyPageViewModel; TaskListPageViewModel get taskListPageViewModel => _taskListPageViewModel; ProfilePageViewModel get profilePageViewModel => _profilePageViewModel; DeviceListPageViewModel get devicesPageViewModel => _devicesPageViewModel; - InvitationsViewModel get invitationsListViewModel => - _invitationsListViewModel; - InformedConsentViewModel get informedConsentViewModel => - _informedConsentViewModel; - ParticipantDataPageViewModel get participantDataPageViewModel => - _participantDataPageViewModel; + InvitationsViewModel get invitationsListViewModel => _invitationsListViewModel; + InformedConsentViewModel get informedConsentViewModel => _informedConsentViewModel; + ParticipantDataPageViewModel get participantDataPageViewModel => _participantDataPageViewModel; @override void init(SmartphoneDeploymentController ctrl) { diff --git a/test/cams_app_test.dart b/test/cams_app_test.dart index 120ac75a..aa89766e 100644 --- a/test/cams_app_test.dart +++ b/test/cams_app_test.dart @@ -42,11 +42,9 @@ void main() { group("Local Study Protocol Manager", () { // skipping this test since it is throwing strange "asUnmodifiableView" errors....? test('JSON File -> StudyProtocol', skip: true, () async { - final plainJson = - File('test/json/study_protocol.json').readAsStringSync(); + final plainJson = File('test/json/study_protocol.json').readAsStringSync(); - SmartphoneStudyProtocol.fromJson( - json.decode(plainJson) as Map); + SmartphoneStudyProtocol.fromJson(json.decode(plainJson) as Map); }); }); } diff --git a/test/heart_rate_data_model_test.dart b/test/heart_rate_data_model_test.dart index a723ca6f..a3df3ed2 100644 --- a/test/heart_rate_data_model_test.dart +++ b/test/heart_rate_data_model_test.dart @@ -25,18 +25,15 @@ void main() { }); group('init', () { group('should listen to heart rate events', () { - final mockSmartphoneDeploymentController = - MockSmartphoneDeploymentController(); + final mockSmartphoneDeploymentController = MockSmartphoneDeploymentController(); final mockPolarHRSample = MockPolarHRSample(); final mockPolarHRDatum = MockPolarHR(); final mockMeasurement = MockMeasurement(); final viewModel = HeartRateCardViewModel(); - final heartRateStreamController = - StreamController.broadcast(); + final heartRateStreamController = StreamController.broadcast(); setUp(() { - when(mockSmartphoneDeploymentController.measurements) - .thenAnswer((_) => heartRateStreamController.stream); + when(mockSmartphoneDeploymentController.measurements).thenAnswer((_) => heartRateStreamController.stream); viewModel.init(mockSmartphoneDeploymentController); }); @@ -55,10 +52,8 @@ void main() { await Future.delayed(const Duration(milliseconds: 100)); expect(viewModel.currentHeartRate, equals(80.0)); expect(viewModel.dayMinMax, equals(HeartRateMinMaxPrHour(80, 80))); - expect( - viewModel.hourlyHeartRate, - equals((HourlyHeartRate().addHeartRate(DateTime.now().hour, 80)) - .hourlyHeartRate)); + expect(viewModel.hourlyHeartRate, + equals((HourlyHeartRate().addHeartRate(DateTime.now().hour, 80)).hourlyHeartRate)); }); test('with multiple events', () async { // Add a heart rate data point to the stream @@ -80,9 +75,7 @@ void main() { expect(viewModel.dayMinMax, equals(HeartRateMinMaxPrHour(60, 90))); expect( viewModel.hourlyHeartRate, - equals((HourlyHeartRate() - .addHeartRate(DateTime.now().hour, 60) - .addHeartRate(DateTime.now().hour, 90)) + equals((HourlyHeartRate().addHeartRate(DateTime.now().hour, 60).addHeartRate(DateTime.now().hour, 90)) .hourlyHeartRate)); }); test('with events with data that is 0', () async { @@ -95,10 +88,8 @@ void main() { await Future.delayed(const Duration(milliseconds: 100)); expect(viewModel.currentHeartRate, equals(null)); - expect( - viewModel.dayMinMax, equals(HeartRateMinMaxPrHour(null, null))); - expect(viewModel.hourlyHeartRate, - equals((HourlyHeartRate()).hourlyHeartRate)); + expect(viewModel.dayMinMax, equals(HeartRateMinMaxPrHour(null, null))); + expect(viewModel.hourlyHeartRate, equals((HourlyHeartRate()).hourlyHeartRate)); // expect(viewModel.skinContact, equals(false)); }); test('with contactStatus being true', () async { @@ -129,8 +120,7 @@ void main() { hr.hourlyHeartRate[13] = HeartRateMinMaxPrHour(75, 85); hr.maxHeartRate = 85; hr.minHeartRate = 70; - hr.lastUpdated = - DateTime.now().subtract(const Duration(days: 1)); // yesterday + hr.lastUpdated = DateTime.now().subtract(const Duration(days: 1)); // yesterday // call resetDataAtMidnight hr.resetDataAtMidnight(); diff --git a/test/heart_rate_data_model_test.mocks.dart b/test/heart_rate_data_model_test.mocks.dart index 6d4076ff..41e4e452 100644 --- a/test/heart_rate_data_model_test.mocks.dart +++ b/test/heart_rate_data_model_test.mocks.dart @@ -28,8 +28,7 @@ import 'package:permission_handler/permission_handler.dart' as _i5; // ignore_for_file: camel_case_types // ignore_for_file: subtype_of_sealed_class -class _FakeDeviceController_0 extends _i1.SmartFake - implements _i2.DeviceController { +class _FakeDeviceController_0 extends _i1.SmartFake implements _i2.DeviceController { _FakeDeviceController_0( Object parent, Invocation parentInvocation, @@ -39,8 +38,7 @@ class _FakeDeviceController_0 extends _i1.SmartFake ); } -class _FakeSmartphoneDeploymentExecutor_1 extends _i1.SmartFake - implements _i2.SmartphoneDeploymentExecutor { +class _FakeSmartphoneDeploymentExecutor_1 extends _i1.SmartFake implements _i2.SmartphoneDeploymentExecutor { _FakeSmartphoneDeploymentExecutor_1( Object parent, Invocation parentInvocation, @@ -60,8 +58,7 @@ class _FakeData_2 extends _i1.SmartFake implements _i3.Data { ); } -class _FakeDeploymentService_3 extends _i1.SmartFake - implements _i3.DeploymentService { +class _FakeDeploymentService_3 extends _i1.SmartFake implements _i3.DeploymentService { _FakeDeploymentService_3( Object parent, Invocation parentInvocation, @@ -71,8 +68,7 @@ class _FakeDeploymentService_3 extends _i1.SmartFake ); } -class _FakeHeartRateMinMaxPrHour_4 extends _i1.SmartFake - implements _i4.HeartRateMinMaxPrHour { +class _FakeHeartRateMinMaxPrHour_4 extends _i1.SmartFake implements _i4.HeartRateMinMaxPrHour { _FakeHeartRateMinMaxPrHour_4( Object parent, Invocation parentInvocation, @@ -82,8 +78,7 @@ class _FakeHeartRateMinMaxPrHour_4 extends _i1.SmartFake ); } -class _FakeHourlyHeartRate_5 extends _i1.SmartFake - implements _i4.HourlyHeartRate { +class _FakeHourlyHeartRate_5 extends _i1.SmartFake implements _i4.HourlyHeartRate { _FakeHourlyHeartRate_5( Object parent, Invocation parentInvocation, @@ -126,8 +121,7 @@ class _FakeDataModel_8 extends _i1.SmartFake implements _i4.DataModel { /// A class which mocks [SmartphoneDeploymentController]. /// /// See the documentation for Mockito's code generation for more information. -class MockSmartphoneDeploymentController extends _i1.Mock - implements _i2.SmartphoneDeploymentController { +class MockSmartphoneDeploymentController extends _i1.Mock implements _i2.SmartphoneDeploymentController { @override _i2.DeviceController get deviceRegistry => (super.noSuchMethod( Invocation.getter(#deviceRegistry), @@ -142,8 +136,7 @@ class MockSmartphoneDeploymentController extends _i1.Mock ) as _i2.DeviceController); @override - Map<_i5.Permission, _i5.PermissionStatus> get permissions => - (super.noSuchMethod( + Map<_i5.Permission, _i5.PermissionStatus> get permissions => (super.noSuchMethod( Invocation.getter(#permissions), returnValue: <_i5.Permission, _i5.PermissionStatus>{}, returnValueForMissingStub: <_i5.Permission, _i5.PermissionStatus>{}, @@ -251,17 +244,14 @@ class MockSmartphoneDeploymentController extends _i1.Mock ) as bool); @override - List<_i3.DeviceConfiguration<_i3.DeviceRegistration>> - get remainingDevicesToRegister => (super.noSuchMethod( - Invocation.getter(#remainingDevicesToRegister), - returnValue: <_i3.DeviceConfiguration<_i3.DeviceRegistration>>[], - returnValueForMissingStub: <_i3 - .DeviceConfiguration<_i3.DeviceRegistration>>[], - ) as List<_i3.DeviceConfiguration<_i3.DeviceRegistration>>); + List<_i3.DeviceConfiguration<_i3.DeviceRegistration>> get remainingDevicesToRegister => (super.noSuchMethod( + Invocation.getter(#remainingDevicesToRegister), + returnValue: <_i3.DeviceConfiguration<_i3.DeviceRegistration>>[], + returnValueForMissingStub: <_i3.DeviceConfiguration<_i3.DeviceRegistration>>[], + ) as List<_i3.DeviceConfiguration<_i3.DeviceRegistration>>); @override - set deployment(_i3.PrimaryDeviceDeployment? _deployment) => - super.noSuchMethod( + set deployment(_i3.PrimaryDeviceDeployment? _deployment) => super.noSuchMethod( Invocation.setter( #deployment, _deployment, @@ -270,8 +260,7 @@ class MockSmartphoneDeploymentController extends _i1.Mock ); @override - set deviceRegistry(_i3.DeviceDataCollectorFactory? _deviceRegistry) => - super.noSuchMethod( + set deviceRegistry(_i3.DeviceDataCollectorFactory? _deviceRegistry) => super.noSuchMethod( Invocation.setter( #deviceRegistry, _deviceRegistry, @@ -280,8 +269,7 @@ class MockSmartphoneDeploymentController extends _i1.Mock ); @override - set deploymentService(_i3.DeploymentService? _deploymentService) => - super.noSuchMethod( + set deploymentService(_i3.DeploymentService? _deploymentService) => super.noSuchMethod( Invocation.setter( #deploymentService, _deploymentService, @@ -290,8 +278,7 @@ class MockSmartphoneDeploymentController extends _i1.Mock ); @override - set deploymentStatus(_i3.StudyDeploymentStatus? _deploymentStatus) => - super.noSuchMethod( + set deploymentStatus(_i3.StudyDeploymentStatus? _deploymentStatus) => super.noSuchMethod( Invocation.setter( #deploymentStatus, _deploymentStatus, @@ -309,8 +296,7 @@ class MockSmartphoneDeploymentController extends _i1.Mock ); @override - _i7.Stream<_i3.Measurement> measurementsByType(String? type) => - (super.noSuchMethod( + _i7.Stream<_i3.Measurement> measurementsByType(String? type) => (super.noSuchMethod( Invocation.method( #measurementsByType, [type], @@ -357,9 +343,7 @@ class MockSmartphoneDeploymentController extends _i1.Mock ); @override - void initializeDevice( - _i3.DeviceConfiguration<_i3.DeviceRegistration>? configuration) => - super.noSuchMethod( + void initializeDevice(_i3.DeviceConfiguration<_i3.DeviceRegistration>? configuration) => super.noSuchMethod( Invocation.method( #initializeDevice, [configuration], @@ -387,17 +371,14 @@ class MockSmartphoneDeploymentController extends _i1.Mock ) as _i7.Future); @override - _i7.Future<_i3.StudyStatus> tryDeployment({bool? useCached = true}) => - (super.noSuchMethod( + _i7.Future<_i3.StudyStatus> tryDeployment({bool? useCached = true}) => (super.noSuchMethod( Invocation.method( #tryDeployment, [], {#useCached: useCached}, ), - returnValue: _i7.Future<_i3.StudyStatus>.value( - _i3.StudyStatus.DeploymentNotStarted), - returnValueForMissingStub: _i7.Future<_i3.StudyStatus>.value( - _i3.StudyStatus.DeploymentNotStarted), + returnValue: _i7.Future<_i3.StudyStatus>.value(_i3.StudyStatus.DeploymentNotStarted), + returnValueForMissingStub: _i7.Future<_i3.StudyStatus>.value(_i3.StudyStatus.DeploymentNotStarted), ) as _i7.Future<_i3.StudyStatus>); @override @@ -487,20 +468,17 @@ class MockSmartphoneDeploymentController extends _i1.Mock ) as _i7.Future); @override - _i7.Future<_i3.StudyDeploymentStatus?> getStudyDeploymentStatus() => - (super.noSuchMethod( + _i7.Future<_i3.StudyDeploymentStatus?> getStudyDeploymentStatus() => (super.noSuchMethod( Invocation.method( #getStudyDeploymentStatus, [], ), returnValue: _i7.Future<_i3.StudyDeploymentStatus?>.value(), - returnValueForMissingStub: - _i7.Future<_i3.StudyDeploymentStatus?>.value(), + returnValueForMissingStub: _i7.Future<_i3.StudyDeploymentStatus?>.value(), ) as _i7.Future<_i3.StudyDeploymentStatus?>); @override - _i7.Future tryRegisterConnectedDevice( - _i3.DeviceConfiguration<_i3.DeviceRegistration>? device) => + _i7.Future tryRegisterConnectedDevice(_i3.DeviceConfiguration<_i3.DeviceRegistration>? device) => (super.noSuchMethod( Invocation.method( #tryRegisterConnectedDevice, @@ -511,8 +489,7 @@ class MockSmartphoneDeploymentController extends _i1.Mock ) as _i7.Future); @override - _i7.Future tryRegisterRemainingDevicesToRegister() => - (super.noSuchMethod( + _i7.Future tryRegisterRemainingDevicesToRegister() => (super.noSuchMethod( Invocation.method( #tryRegisterRemainingDevicesToRegister, [], @@ -525,11 +502,9 @@ class MockSmartphoneDeploymentController extends _i1.Mock /// A class which mocks [HeartRateCardViewModel]. /// /// See the documentation for Mockito's code generation for more information. -class MockHeartRateCardViewModel extends _i1.Mock - implements _i4.HeartRateCardViewModel { +class MockHeartRateCardViewModel extends _i1.Mock implements _i4.HeartRateCardViewModel { @override - Map get hourlyHeartRate => - (super.noSuchMethod( + Map get hourlyHeartRate => (super.noSuchMethod( Invocation.getter(#hourlyHeartRate), returnValue: {}, returnValueForMissingStub: {}, @@ -568,8 +543,7 @@ class MockHeartRateCardViewModel extends _i1.Mock this, Invocation.getter(#filename), )), - returnValueForMissingStub: - _i7.Future.value(_i6.dummyValue( + returnValueForMissingStub: _i7.Future.value(_i6.dummyValue( this, Invocation.getter(#filename), )), @@ -694,8 +668,7 @@ class MockHeartRateCardViewModel extends _i1.Mock /// See the documentation for Mockito's code generation for more information. class MockHourlyHeartRate extends _i1.Mock implements _i4.HourlyHeartRate { @override - Map get hourlyHeartRate => - (super.noSuchMethod( + Map get hourlyHeartRate => (super.noSuchMethod( Invocation.getter(#hourlyHeartRate), returnValue: {}, returnValueForMissingStub: {}, @@ -715,8 +688,7 @@ class MockHourlyHeartRate extends _i1.Mock implements _i4.HourlyHeartRate { ) as DateTime); @override - set hourlyHeartRate(Map? _hourlyHeartRate) => - super.noSuchMethod( + set hourlyHeartRate(Map? _hourlyHeartRate) => super.noSuchMethod( Invocation.setter( #hourlyHeartRate, _hourlyHeartRate, @@ -818,8 +790,7 @@ class MockHourlyHeartRate extends _i1.Mock implements _i4.HourlyHeartRate { ) as _i4.HourlyHeartRate); @override - _i4.HourlyHeartRate fromJson(Map? json) => - (super.noSuchMethod( + _i4.HourlyHeartRate fromJson(Map? json) => (super.noSuchMethod( Invocation.method( #fromJson, [json],