From 4093b53be44e85d885e7e5d81b00e88cc27cf91a Mon Sep 17 00:00:00 2001 From: Naveen Renati Date: Mon, 25 Nov 2024 15:46:23 +0530 Subject: [PATCH 01/16] nearby share init --- .../project_beneficiaries_downsync.dart | 10 +- .../lib/pages/home.dart | 27 +- .../lib/pages/near_by_share_list.dart | 409 ++++++++++++++++++ .../beneficiary/beneficaries_report.dart | 13 + .../lib/widgets/sidebar/side_bar.dart | 18 +- .../pubspec.lock | 19 +- .../pubspec.yaml | 5 + packages/closed_household/pubspec.lock | 62 ++- packages/complaints/example/pubspec.lock | 13 +- packages/complaints/pubspec.lock | 71 ++- packages/referral_reconciliation/pubspec.lock | 69 ++- packages/registration_delivery/pubspec.lock | 69 ++- packages/survey_form/pubspec.lock | 62 ++- 13 files changed, 787 insertions(+), 60 deletions(-) create mode 100644 apps/health_campaign_field_worker_app/lib/pages/near_by_share_list.dart diff --git a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart index a443250b12..51c567e07f 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart @@ -30,16 +30,16 @@ class BeneficiaryDownSyncBloc final NetworkManager networkManager; final BandwidthCheckRepository bandwidthCheckRepository; final LocalRepository - householdLocalRepository; + householdLocalRepository; final LocalRepository - householdMemberLocalRepository; + householdMemberLocalRepository; final LocalRepository - projectBeneficiaryLocalRepository; + projectBeneficiaryLocalRepository; final LocalRepository taskLocalRepository; final LocalRepository - sideEffectLocalRepository; + sideEffectLocalRepository; final LocalRepository - referralLocalRepository; + referralLocalRepository; BeneficiaryDownSyncBloc({ required this.individualLocalRepository, required this.downSyncRemoteRepository, diff --git a/apps/health_campaign_field_worker_app/lib/pages/home.dart b/apps/health_campaign_field_worker_app/lib/pages/home.dart index 51477d1041..473996f7bc 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/home.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/home.dart @@ -2,11 +2,10 @@ import 'dart:async'; import 'package:attendance_management/attendance_management.dart'; import 'package:attendance_management/router/attendance_router.gm.dart'; -import 'package:survey_form/survey_form.dart'; -import 'package:complaints/complaints.dart'; -import 'package:complaints/router/complaints_router.gm.dart'; import 'package:closed_household/closed_household.dart'; import 'package:closed_household/router/closed_household_router.gm.dart'; +import 'package:complaints/complaints.dart'; +import 'package:complaints/router/complaints_router.gm.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:digit_components/digit_components.dart'; import 'package:digit_components/widgets/atoms/digit_toaster.dart'; @@ -31,6 +30,7 @@ import 'package:referral_reconciliation/router/referral_reconciliation_router.gm import 'package:registration_delivery/registration_delivery.dart'; import 'package:registration_delivery/router/registration_delivery_router.gm.dart'; import 'package:survey_form/router/survey_form_router.gm.dart'; +import 'package:survey_form/survey_form.dart'; import '../blocs/app_initialization/app_initialization.dart'; import '../blocs/auth/auth.dart'; @@ -511,7 +511,8 @@ class _HomePageState extends LocalizedState { homeShowcaseData.warehouseManagerManageStock.showcaseKey, i18.home.stockReconciliationLabel: homeShowcaseData.wareHouseManagerStockReconciliation.showcaseKey, - i18.home.mySurveyForm: homeShowcaseData.supervisorMySurveyForm.showcaseKey, + i18.home.mySurveyForm: + homeShowcaseData.supervisorMySurveyForm.showcaseKey, i18.home.fileComplaint: homeShowcaseData.distributorFileComplaint.showcaseKey, i18.home.syncDataLabel: homeShowcaseData.distributorSyncData.showcaseKey, @@ -725,14 +726,18 @@ void setPackagesSingleton(BuildContext context) { loggedInIndividualId: context.loggedInIndividualId ?? '', loggedInUserUuid: context.loggedInUserUuid, appVersion: Constants().version, - isHealthFacilityWorker: context.loggedInUserRoles.where((role) => role.code == RolesType.healthFacilityWorker.toValue()).toList().isNotEmpty, + isHealthFacilityWorker: context.loggedInUserRoles + .where((role) => + role.code == RolesType.healthFacilityWorker.toValue()) + .toList() + .isNotEmpty, roles: context.read().state.maybeMap( - orElse: () => const Offstage(), - authenticated: (res) { - return res.userModel.roles - .map((e) => e.code.snakeCase.toUpperCase()) - .toList(); - }), + orElse: () => const Offstage(), + authenticated: (res) { + return res.userModel.roles + .map((e) => e.code.snakeCase.toUpperCase()) + .toList(); + }), ); ReferralReconSingleton().setInitialData( diff --git a/apps/health_campaign_field_worker_app/lib/pages/near_by_share_list.dart b/apps/health_campaign_field_worker_app/lib/pages/near_by_share_list.dart new file mode 100644 index 0000000000..49e109a478 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/near_by_share_list.dart @@ -0,0 +1,409 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; +import 'package:registration_delivery/models/entities/household.dart'; + +import '../utils/extensions/extensions.dart'; + +enum DeviceType { receiver, sender } + +class DevicesListScreen extends StatefulWidget { + const DevicesListScreen({super.key, required this.deviceType}); + + final DeviceType deviceType; + + @override + _DevicesListScreenState createState() => _DevicesListScreenState(); +} + +class _DevicesListScreenState extends State + with TickerProviderStateMixin { + List devices = []; + List connectedDevices = []; + late NearbyService nearbyService; + late StreamSubscription subscription; + late StreamSubscription receivedDataSubscription; + late AnimationController _controller; + late AnimationController _radarController; + + late Animation _colorAnimation1; + late Animation _colorAnimation2; + + bool isInit = false; + double rippleRadius = 0; + + @override + void initState() { + super.initState(); + createAnimation(); + init(); + } + + @override + void dispose() { + subscription.cancel(); + receivedDataSubscription.cancel(); + nearbyService.stopBrowsingForPeers(); + nearbyService.stopAdvertisingPeer(); + _controller.dispose(); + _radarController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: DigitTheme.instance.colors.regalBlue, + body: Column( + children: [ + Text( + widget.deviceType.name, + style: TextStyle( + color: Colors.white, + fontSize: 20, + ), + ), + Expanded( + child: Center( + child: Stack( + alignment: Alignment.center, + children: [ + // Radar Circles + ...List.generate(4, (index) { + return Container( + width: 200.0 + (index * 50), + height: 200.0 + (index * 50), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white.withOpacity(0.3), + ), + ), + ); + }), + // Radar Sweep + AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return Transform.rotate( + angle: _controller.value * 2 * pi, + child: Container( + width: 400, + height: 400, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: SweepGradient( + colors: [ + Colors.white.withOpacity(0.3), + Colors.transparent, + ], + stops: [0.7, 1.0], + ), + ), + ), + ); + }, + ), + ..._generateRandomDevicePositions(devices, 400, 200), + ], + ), + ), + ), + ], + ), + ); + } + + List _generateRandomDevicePositions( + List devices, + double size, + double + rippleRadius // Pass rippleRadius here to position devices inside it + ) { + final random = Random(); + return widget.deviceType == DeviceType.receiver + ? connectedDevices.asMap().entries.map((entry) { + // Ensure that the device is placed within the ripple's growing radius + final angle = random.nextDouble() * 2 * pi; // Random angle + final radius = random.nextDouble() * + rippleRadius; // Ensure radius is within ripple radius + final x = radius * cos(angle); + final y = radius * sin(angle); + + return Positioned( + left: size / 2 + + x - + 40, // Adjust icon position (centered around the circle) + top: size / 2 + y - 40, + child: _buildDeviceWidget(entry.value), + ); + }).toList() + : devices.asMap().entries.map((entry) { + // Ensure that the device is placed within the ripple's growing radius + final angle = random.nextDouble() * 2 * pi; // Random angle + final radius = random.nextDouble() * + rippleRadius; // Ensure radius is within ripple radius + final x = radius * cos(angle); + final y = radius * sin(angle); + + return Positioned( + left: size / 2 + + x - + 40, // Adjust icon position (centered around the circle) + top: size / 2 + y - 40, + child: _buildDeviceWidget(entry.value), + ); + }).toList(); + } + + // Build each device widget with icon and name + Widget _buildDeviceWidget(Device device) { + return GestureDetector( + onTap: () { + _onButtonClicked(device); + }, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Material( + elevation: 5, + borderRadius: BorderRadius.circular(20), + child: Icon( + Icons.phone_android, + size: 50, // Adjust size of the device icon + color: DigitTheme.instance.colors.amber, + ), + ), + const SizedBox( + height: kPadding, + ), + Text( + device.deviceName, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, color: DigitTheme.instance.colors.amber), + ), + ], + ), + ); + } + + String getStateName(SessionState state) { + switch (state) { + case SessionState.notConnected: + return "disconnected"; + case SessionState.connecting: + return "waiting"; + default: + return "connected"; + } + } + + String getButtonStateName(SessionState state) { + switch (state) { + case SessionState.notConnected: + case SessionState.connecting: + return "Connect"; + default: + return "Disconnect"; + } + } + + Color getStateColor(SessionState state) { + switch (state) { + case SessionState.notConnected: + return Colors.black; + case SessionState.connecting: + return Colors.grey; + default: + return Colors.green; + } + } + + Color getButtonColor(SessionState state) { + switch (state) { + case SessionState.notConnected: + case SessionState.connecting: + return Colors.green; + default: + return Colors.red; + } + } + + int getItemCount() { + if (widget.deviceType == DeviceType.receiver) { + return connectedDevices.length; + } else { + return devices.length; + } + } + + _onButtonClicked(Device device) { + switch (device.state) { + case SessionState.notConnected: + nearbyService.invitePeer( + deviceID: device.deviceId, + deviceName: device.deviceName, + ); + break; + case SessionState.connected: + nearbyService.disconnectPeer(deviceID: device.deviceId); + break; + case SessionState.connecting: + break; + } + } + + void init() async { + nearbyService = NearbyService(); + String devInfo = ''; + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + devInfo = androidInfo.model; + } + if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + devInfo = iosInfo.localizedModel; + } + await nearbyService.init( + serviceType: 'mpconn', + deviceName: devInfo, + strategy: Strategy.P2P_CLUSTER, + callback: (isRunning) async { + if (isRunning) { + if (widget.deviceType == DeviceType.sender) { + await nearbyService.stopBrowsingForPeers(); + await Future.delayed(const Duration(microseconds: 200)); + await nearbyService.startBrowsingForPeers(); + } else { + await nearbyService.stopAdvertisingPeer(); + await nearbyService.stopBrowsingForPeers(); + await Future.delayed(const Duration(microseconds: 200)); + await nearbyService.startAdvertisingPeer(); + await nearbyService.startBrowsingForPeers(); + } + } + }); + subscription = + nearbyService.stateChangedSubscription(callback: (devicesList) { + for (var element in devicesList) { + print( + "deviceId: ${element.deviceId} | deviceName: ${element.deviceName} | state: ${element.state}"); + + // Handle Android-specific browsing + if (Platform.isAndroid) { + if (element.state == SessionState.connected) { + print('connection successful'); + showModalBottomSheet( + context: context, + elevation: 5, + builder: (context) => Column( + children: [ + Text( + "Connected to ${element.deviceName}...", + style: Theme.of(context).textTheme.displayMedium, + ), + ], + )); + // nearbyService.stopBrowsingForPeers(); + } else if (element.state == SessionState.notConnected) { + nearbyService.startBrowsingForPeers(); + } + } + } + + setState(() { + // Deduplicate the devices list + final uniqueDevices = {}; // Use a map for deduplication + for (var device in devicesList) { + uniqueDevices[device.deviceId] = + device; // Replace entries with the same deviceId + } + + // Update the devices list and connected devices + devices + ..clear() + ..addAll(uniqueDevices.values); // Add only unique devices + + connectedDevices + ..clear() + ..addAll(devices.where((d) => d.state == SessionState.connected)); + }); + }); + + receivedDataSubscription = + nearbyService.dataReceivedSubscription(callback: (data) { + try { + // Extract the raw JSON string + var receivedData = data["message"]; + print('Decoded data: $receivedData'); + + // Step 1: Decode the outer JSON string (array) + Map outerArray = jsonDecode(receivedData); + print('data ${outerArray["model"][0]}'); + + HouseholdModel model = + HouseholdModelMapper.fromJson(outerArray["model"][0]); + print('model $model'); + // saveDataInDb(model); + // // Step 3: Use the parsed data + // if (models.isNotEmpty) { + // saveDataInDb(models.first); + // } + } catch (e) { + debugPrint('Error parsing data: $e'); + } + + // showToast(jsonEncode(data["message"]), + // context: context, + // axis: Axis.horizontal, + // alignment: Alignment.center, + // position: StyledToastPosition.bottom); + }); + } + + void fetchDbRecords(Device device) async { + var records = await context + .repository() + .search(HouseholdSearchModel()); + + // Convert the list of models to JSON + var serializedData = records.map((model) => model).toList(); + + nearbyService.sendMessage( + device.deviceId, jsonEncode({'model': serializedData})); + } + + void saveDataInDb(HouseholdModel model) async { + var projectBeneficiaryModel = await context + .repository() + .create(model); + } + + void createAnimation() { + _controller = + AnimationController(vsync: this, duration: const Duration(seconds: 10)) + ..repeat(); + _radarController = AnimationController( + duration: const Duration(seconds: 10), + vsync: this, + )..repeat(reverse: false); + + _colorAnimation1 = ColorTween( + begin: const Color.fromRGBO(255, 255, 255, 1.0), + end: const Color.fromRGBO(234, 138, 59, 1), + ).animate(_controller); + + _colorAnimation2 = ColorTween( + begin: const Color.fromRGBO(234, 138, 59, 1), + end: const Color.fromRGBO(234, 138, 59, 1), + ).animate(_controller); + } +} diff --git a/apps/health_campaign_field_worker_app/lib/pages/reports/beneficiary/beneficaries_report.dart b/apps/health_campaign_field_worker_app/lib/pages/reports/beneficiary/beneficaries_report.dart index 4ea93bd81c..36b2691c54 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/reports/beneficiary/beneficaries_report.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/reports/beneficiary/beneficaries_report.dart @@ -18,6 +18,7 @@ import '../../../utils/utils.dart'; import '../../../widgets/header/back_navigation_help_header.dart'; import '../../../widgets/localized.dart'; import '../../../widgets/no_result_card/no_result_card.dart'; +import '../../near_by_share_list.dart'; @RoutePage() class BeneficiariesReportPage extends LocalizedStatefulWidget { @@ -416,6 +417,18 @@ class BeneficiariesReportState extends LocalizedState { ), ), ), + SizedBox( + height: kPadding, + ), + ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => const DevicesListScreen( + deviceType: DeviceType.sender))); + }, + child: Text('Data Transfer')), downSyncList.isEmpty ? NoResultCard( align: Alignment.center, diff --git a/apps/health_campaign_field_worker_app/lib/widgets/sidebar/side_bar.dart b/apps/health_campaign_field_worker_app/lib/widgets/sidebar/side_bar.dart index 07530a05dc..6fcca2c23c 100644 --- a/apps/health_campaign_field_worker_app/lib/widgets/sidebar/side_bar.dart +++ b/apps/health_campaign_field_worker_app/lib/widgets/sidebar/side_bar.dart @@ -12,6 +12,7 @@ import '../../blocs/auth/auth.dart'; import '../../blocs/localization/localization.dart'; import '../../models/data_model.dart'; import '../../models/entities/roles_type.dart'; +import '../../pages/near_by_share_list.dart'; import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../utils/utils.dart'; @@ -110,9 +111,7 @@ class SideBar extends StatelessWidget { i18.common.coreCommonlanguage, ), icon: Icons.language, - onPressed: () { - - }, + onPressed: () {}, content: Offstage( offstage: languages == null, child: BlocBuilder( @@ -230,6 +229,19 @@ class SideBar extends StatelessWidget { context.router.push(const BeneficiariesReportRoute()); }, ), + DigitIconTile( + title: AppLocalizations.of(context).translate( + 'RECEIVE_DATA', + ), + icon: Icons.emergency_share, + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => const DevicesListScreen( + deviceType: DeviceType.receiver))); + }, + ), DigitIconTile( title: AppLocalizations.of(context) .translate(i18.common.coreCommonLogout), diff --git a/apps/health_campaign_field_worker_app/pubspec.lock b/apps/health_campaign_field_worker_app/pubspec.lock index d096797b29..9ec8aea929 100644 --- a/apps/health_campaign_field_worker_app/pubspec.lock +++ b/apps/health_campaign_field_worker_app/pubspec.lock @@ -342,7 +342,7 @@ packages: path: "../../packages/closed_household" relative: true source: path - version: "1.0.1+1" + version: "1.0.2-dev.1" code_builder: dependency: transitive description: @@ -943,6 +943,15 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_nearby_connections: + dependency: "direct dev" + description: + path: "." + ref: master + resolved-ref: "9ead63aa7e01f7603a453368de1ee2b4dc009ed6" + url: "https://github.com/champeauxr/flutter_nearby_connections" + source: git + version: "1.1.2" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -1936,6 +1945,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + simple_ripple_animation: + dependency: "direct dev" + description: + name: simple_ripple_animation + sha256: "09a80a6d352ce12d33c2ca43423bf5b544179cc5bc78bf3ff73bd5c08ea378bd" + url: "https://pub.dev" + source: hosted + version: "0.1.0" sky_engine: dependency: transitive description: flutter diff --git a/apps/health_campaign_field_worker_app/pubspec.yaml b/apps/health_campaign_field_worker_app/pubspec.yaml index c5c9d53809..a1b18bb398 100644 --- a/apps/health_campaign_field_worker_app/pubspec.yaml +++ b/apps/health_campaign_field_worker_app/pubspec.yaml @@ -101,6 +101,11 @@ dev_dependencies: isar_generator: ^3.0.5 flutter_launcher_icons: ^0.13.1 hrk_flutter_test_batteries: ^0.8.0 + flutter_nearby_connections: + git: + url: https://github.com/champeauxr/flutter_nearby_connections + ref: master + simple_ripple_animation: ^0.1.0 dependency_overrides: intl: ^0.18.0 diff --git a/packages/closed_household/pubspec.lock b/packages/closed_household/pubspec.lock index 76890865c8..d58e8b6794 100644 --- a/packages/closed_household/pubspec.lock +++ b/packages/closed_household/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "61.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + url: "https://pub.dev" + source: hosted + version: "1.3.25" analyzer: dependency: transitive description: @@ -413,11 +421,17 @@ packages: digit_data_model: dependency: "direct main" description: - name: digit_data_model - sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" - url: "https://pub.dev" - source: hosted + path: "../digit_data_model" + relative: true + source: path version: "1.0.5-dev.1" + digit_firebase_services: + dependency: "direct overridden" + description: + path: "../digit_firebase_services" + relative: true + source: path + version: "0.0.1" digit_scanner: dependency: "direct main" description: @@ -562,6 +576,46 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + url: "https://pub.dev" + source: hosted + version: "2.27.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 + url: "https://pub.dev" + source: hosted + version: "5.3.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + url: "https://pub.dev" + source: hosted + version: "2.11.5" + firebase_crashlytics: + dependency: transitive + description: + name: firebase_crashlytics + sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 + url: "https://pub.dev" + source: hosted + version: "3.4.18" + firebase_crashlytics_platform_interface: + dependency: transitive + description: + name: firebase_crashlytics_platform_interface + sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 + url: "https://pub.dev" + source: hosted + version: "3.6.25" fixnum: dependency: transitive description: diff --git a/packages/complaints/example/pubspec.lock b/packages/complaints/example/pubspec.lock index e78473cf30..22d3a4b45f 100644 --- a/packages/complaints/example/pubspec.lock +++ b/packages/complaints/example/pubspec.lock @@ -175,7 +175,7 @@ packages: path: ".." relative: true source: path - version: "0.0.1-dev.1" + version: "0.0.1-dev.2" convert: dependency: transitive description: @@ -227,11 +227,10 @@ packages: digit_components: dependency: "direct main" description: - name: digit_components - sha256: "01320d4c72829045e789d1a56e23ff2bd85dad6a1831d27bd507a1acaceae17e" - url: "https://pub.dev" - source: hosted - version: "1.0.1" + path: "../../digit_components" + relative: true + source: path + version: "1.0.2+1" digit_data_model: dependency: transitive description: @@ -1069,5 +1068,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <3.9.0" + dart: ">=3.2.0 <4.0.0" flutter: ">=3.16.0" diff --git a/packages/complaints/pubspec.lock b/packages/complaints/pubspec.lock index e451fcd62b..7fdffffec4 100644 --- a/packages/complaints/pubspec.lock +++ b/packages/complaints/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "64.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + url: "https://pub.dev" + source: hosted + version: "1.3.25" analyzer: dependency: transitive description: @@ -269,19 +277,24 @@ packages: digit_components: dependency: "direct main" description: - name: digit_components - sha256: "07b585e5d8010639366da72a4a8b215ce9b8790c75b2162b66af3cea57ca35d9" - url: "https://pub.dev" - source: hosted + path: "../digit_components" + relative: true + source: path version: "1.0.2+1" digit_data_model: dependency: "direct main" description: - name: digit_data_model - sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" - url: "https://pub.dev" - source: hosted + path: "../digit_data_model" + relative: true + source: path version: "1.0.5-dev.1" + digit_firebase_services: + dependency: "direct overridden" + description: + path: "../digit_firebase_services" + relative: true + source: path + version: "0.0.1" dio: dependency: "direct main" description: @@ -346,6 +359,46 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + url: "https://pub.dev" + source: hosted + version: "2.27.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 + url: "https://pub.dev" + source: hosted + version: "5.3.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + url: "https://pub.dev" + source: hosted + version: "2.11.5" + firebase_crashlytics: + dependency: transitive + description: + name: firebase_crashlytics + sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 + url: "https://pub.dev" + source: hosted + version: "3.4.18" + firebase_crashlytics_platform_interface: + dependency: transitive + description: + name: firebase_crashlytics_platform_interface + sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 + url: "https://pub.dev" + source: hosted + version: "3.6.25" fixnum: dependency: transitive description: @@ -1215,5 +1268,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <3.9.0" + dart: ">=3.2.0 <4.0.0" flutter: ">=3.16.0" diff --git a/packages/referral_reconciliation/pubspec.lock b/packages/referral_reconciliation/pubspec.lock index 61b85de941..cbee32ec63 100644 --- a/packages/referral_reconciliation/pubspec.lock +++ b/packages/referral_reconciliation/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "61.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + url: "https://pub.dev" + source: hosted + version: "1.3.25" analyzer: dependency: transitive description: @@ -413,11 +421,17 @@ packages: digit_data_model: dependency: "direct main" description: - name: digit_data_model - sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" - url: "https://pub.dev" - source: hosted + path: "../digit_data_model" + relative: true + source: path version: "1.0.5-dev.1" + digit_firebase_services: + dependency: "direct overridden" + description: + path: "../digit_firebase_services" + relative: true + source: path + version: "0.0.1" digit_scanner: dependency: "direct main" description: @@ -546,6 +560,46 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + url: "https://pub.dev" + source: hosted + version: "2.27.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 + url: "https://pub.dev" + source: hosted + version: "5.3.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + url: "https://pub.dev" + source: hosted + version: "2.11.5" + firebase_crashlytics: + dependency: transitive + description: + name: firebase_crashlytics + sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 + url: "https://pub.dev" + source: hosted + version: "3.4.18" + firebase_crashlytics_platform_interface: + dependency: transitive + description: + name: firebase_crashlytics_platform_interface + sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 + url: "https://pub.dev" + source: hosted + version: "3.6.25" fixnum: dependency: transitive description: @@ -1462,10 +1516,9 @@ packages: survey_form: dependency: "direct main" description: - name: survey_form - sha256: "52532fb3fae06883828d22f870045587bf7122f67cb4de236c82ad4d6de1d7d7" - url: "https://pub.dev" - source: hosted + path: "../survey_form" + relative: true + source: path version: "0.0.1-dev.2" synchronized: dependency: transitive diff --git a/packages/registration_delivery/pubspec.lock b/packages/registration_delivery/pubspec.lock index f43c0acdf2..f8308b0134 100644 --- a/packages/registration_delivery/pubspec.lock +++ b/packages/registration_delivery/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "61.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + url: "https://pub.dev" + source: hosted + version: "1.3.25" analyzer: dependency: transitive description: @@ -413,11 +421,17 @@ packages: digit_data_model: dependency: "direct main" description: - name: digit_data_model - sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" - url: "https://pub.dev" - source: hosted + path: "../digit_data_model" + relative: true + source: path version: "1.0.5-dev.1" + digit_firebase_services: + dependency: "direct overridden" + description: + path: "../digit_firebase_services" + relative: true + source: path + version: "0.0.1" digit_scanner: dependency: "direct main" description: @@ -562,6 +576,46 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + url: "https://pub.dev" + source: hosted + version: "2.27.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 + url: "https://pub.dev" + source: hosted + version: "5.3.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + url: "https://pub.dev" + source: hosted + version: "2.11.5" + firebase_crashlytics: + dependency: transitive + description: + name: firebase_crashlytics + sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 + url: "https://pub.dev" + source: hosted + version: "3.4.18" + firebase_crashlytics_platform_interface: + dependency: transitive + description: + name: firebase_crashlytics_platform_interface + sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 + url: "https://pub.dev" + source: hosted + version: "3.6.25" fixnum: dependency: transitive description: @@ -1486,10 +1540,9 @@ packages: survey_form: dependency: "direct main" description: - name: survey_form - sha256: "52532fb3fae06883828d22f870045587bf7122f67cb4de236c82ad4d6de1d7d7" - url: "https://pub.dev" - source: hosted + path: "../survey_form" + relative: true + source: path version: "0.0.1-dev.2" synchronized: dependency: transitive diff --git a/packages/survey_form/pubspec.lock b/packages/survey_form/pubspec.lock index ca017de05e..2d068be649 100644 --- a/packages/survey_form/pubspec.lock +++ b/packages/survey_form/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "64.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + url: "https://pub.dev" + source: hosted + version: "1.3.25" analyzer: dependency: transitive description: @@ -341,11 +349,17 @@ packages: digit_data_model: dependency: "direct main" description: - name: digit_data_model - sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" - url: "https://pub.dev" - source: hosted + path: "../digit_data_model" + relative: true + source: path version: "1.0.5-dev.1" + digit_firebase_services: + dependency: "direct overridden" + description: + path: "../digit_firebase_services" + relative: true + source: path + version: "0.0.1" digit_ui_components: dependency: "direct main" description: @@ -466,6 +480,46 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + url: "https://pub.dev" + source: hosted + version: "2.27.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 + url: "https://pub.dev" + source: hosted + version: "5.3.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + url: "https://pub.dev" + source: hosted + version: "2.11.5" + firebase_crashlytics: + dependency: transitive + description: + name: firebase_crashlytics + sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 + url: "https://pub.dev" + source: hosted + version: "3.4.18" + firebase_crashlytics_platform_interface: + dependency: transitive + description: + name: firebase_crashlytics_platform_interface + sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 + url: "https://pub.dev" + source: hosted + version: "3.6.25" fixnum: dependency: transitive description: From 315439fc929a3adf10a806a18825f1a554336784 Mon Sep 17 00:00:00 2001 From: Naveen Renati Date: Thu, 28 Nov 2024 18:36:06 +0530 Subject: [PATCH 02/16] updated ui and transferring down sync data --- .../lib/blocs/peer_to_peer/send_data.dart | 90 ++ .../blocs/peer_to_peer/send_data.freezed.dart | 994 ++++++++++++++++++ .../lib/blocs/project/project.dart | 3 +- .../project_beneficiaries_downsync.dart | 66 +- ...roject_beneficiaries_downsync.freezed.dart | 224 +++- .../lib/data/network_manager.dart | 55 +- .../lib/pages/home.dart | 13 + .../lib/pages/login.dart | 4 +- .../lib/pages/near_by_share_list.dart | 409 ------- .../lib/pages/peer_to_peer/data_receiver.dart | 160 +++ .../pages/peer_to_peer/data_share_home.dart | 60 ++ .../lib/pages/peer_to_peer/data_transfer.dart | 188 ++++ .../lib/pages/peer_to_peer/devices_list.dart | 371 +++++++ .../beneficiary/beneficaries_report.dart | 10 - .../lib/router/app_router.gr.dart | 122 +++ .../lib/utils/i18_key_constants.dart | 12 +- .../lib/utils/utils.dart | 56 +- .../showcase/config/home_showcase.dart | 4 + .../lib/widgets/sidebar/side_bar.dart | 14 - .../pubspec.lock | 10 +- .../pubspec.yaml | 9 +- 21 files changed, 2334 insertions(+), 540 deletions(-) create mode 100644 apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.dart create mode 100644 apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.freezed.dart delete mode 100644 apps/health_campaign_field_worker_app/lib/pages/near_by_share_list.dart create mode 100644 apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart create mode 100644 apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart create mode 100644 apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart create mode 100644 apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.dart new file mode 100644 index 0000000000..1b886ef94e --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.dart @@ -0,0 +1,90 @@ +// GENERATED using mason_cli +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'send_data.freezed.dart'; + +typedef DeviceConnectionEmitter = Emitter; + +class DeviceConnectionBloc + extends Bloc { + final NearbyService nearbyService; + final Device connectedDevice; + + DeviceConnectionBloc({ + required this.nearbyService, + required this.connectedDevice, + }) : super(const DeviceConnectionInitial()) { + on(_handleSendEntities); + } + + FutureOr _handleSendEntities( + SendEntitiesEvent event, + DeviceConnectionEmitter emit, + ) async { + try { + emit(const DeviceConnectionState.sending(progress: 0)); + + for (var entityName in event.entities.keys) { + List entityData = event.entities[entityName]!; + int totalSize = entityData.length; + int offset = 0; + + while (offset < totalSize) { + // Calculate the chunk + const int chunkSize = 100; + int end = + (offset + chunkSize < totalSize) ? offset + chunkSize : totalSize; + List chunk = entityData.sublist(offset, end); + + // Send the chunk + await nearbyService.sendMessage( + connectedDevice.deviceId, + jsonEncode({ + "entityType": entityName, + "message": chunk, + "offset": offset + chunk.length, + "totalData": totalSize, + }), + ); + + // Update progress + final progress = (offset + chunk.length) / totalSize; + emit(DeviceConnectionState.sending(progress: progress)); + offset = end; + } + } + + // Notify completion + emit(const DeviceConnectionState.completed()); + } catch (e) { + emit(DeviceConnectionState.failed(error: e.toString())); + } + } +} + +@freezed +class DeviceConnectionEvent with _$DeviceConnectionEvent { + const factory DeviceConnectionEvent.sendEntities( + Map entities, + ) = SendEntitiesEvent; +} + +@freezed +class DeviceConnectionState with _$DeviceConnectionState { + const factory DeviceConnectionState.initial() = DeviceConnectionInitial; + + const factory DeviceConnectionState.loading() = DeviceConnectionLoading; + + const factory DeviceConnectionState.sending({required double progress}) = + DeviceConnectionSending; + + const factory DeviceConnectionState.completed() = DeviceConnectionCompleted; + + const factory DeviceConnectionState.failed({required String error}) = + DeviceConnectionFailed; +} diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.freezed.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.freezed.dart new file mode 100644 index 0000000000..93ba4284f0 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.freezed.dart @@ -0,0 +1,994 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'send_data.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +/// @nodoc +mixin _$DeviceConnectionEvent { + Map get entities => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult when({ + required TResult Function(Map entities) sendEntities, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(Map entities)? sendEntities, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(Map entities)? sendEntities, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(SendEntitiesEvent value) sendEntities, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(SendEntitiesEvent value)? sendEntities, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(SendEntitiesEvent value)? sendEntities, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $DeviceConnectionEventCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DeviceConnectionEventCopyWith<$Res> { + factory $DeviceConnectionEventCopyWith(DeviceConnectionEvent value, + $Res Function(DeviceConnectionEvent) then) = + _$DeviceConnectionEventCopyWithImpl<$Res, DeviceConnectionEvent>; + @useResult + $Res call({Map entities}); +} + +/// @nodoc +class _$DeviceConnectionEventCopyWithImpl<$Res, + $Val extends DeviceConnectionEvent> + implements $DeviceConnectionEventCopyWith<$Res> { + _$DeviceConnectionEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? entities = null, + }) { + return _then(_value.copyWith( + entities: null == entities + ? _value.entities + : entities // ignore: cast_nullable_to_non_nullable + as Map, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$SendEntitiesEventImplCopyWith<$Res> + implements $DeviceConnectionEventCopyWith<$Res> { + factory _$$SendEntitiesEventImplCopyWith(_$SendEntitiesEventImpl value, + $Res Function(_$SendEntitiesEventImpl) then) = + __$$SendEntitiesEventImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({Map entities}); +} + +/// @nodoc +class __$$SendEntitiesEventImplCopyWithImpl<$Res> + extends _$DeviceConnectionEventCopyWithImpl<$Res, _$SendEntitiesEventImpl> + implements _$$SendEntitiesEventImplCopyWith<$Res> { + __$$SendEntitiesEventImplCopyWithImpl(_$SendEntitiesEventImpl _value, + $Res Function(_$SendEntitiesEventImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? entities = null, + }) { + return _then(_$SendEntitiesEventImpl( + null == entities + ? _value._entities + : entities // ignore: cast_nullable_to_non_nullable + as Map, + )); + } +} + +/// @nodoc + +class _$SendEntitiesEventImpl implements SendEntitiesEvent { + const _$SendEntitiesEventImpl(final Map entities) + : _entities = entities; + + final Map _entities; + @override + Map get entities { + if (_entities is EqualUnmodifiableMapView) return _entities; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_entities); + } + + @override + String toString() { + return 'DeviceConnectionEvent.sendEntities(entities: $entities)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SendEntitiesEventImpl && + const DeepCollectionEquality().equals(other._entities, _entities)); + } + + @override + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(_entities)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$SendEntitiesEventImplCopyWith<_$SendEntitiesEventImpl> get copyWith => + __$$SendEntitiesEventImplCopyWithImpl<_$SendEntitiesEventImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(Map entities) sendEntities, + }) { + return sendEntities(entities); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(Map entities)? sendEntities, + }) { + return sendEntities?.call(entities); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(Map entities)? sendEntities, + required TResult orElse(), + }) { + if (sendEntities != null) { + return sendEntities(entities); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(SendEntitiesEvent value) sendEntities, + }) { + return sendEntities(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(SendEntitiesEvent value)? sendEntities, + }) { + return sendEntities?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(SendEntitiesEvent value)? sendEntities, + required TResult orElse(), + }) { + if (sendEntities != null) { + return sendEntities(this); + } + return orElse(); + } +} + +abstract class SendEntitiesEvent implements DeviceConnectionEvent { + const factory SendEntitiesEvent(final Map entities) = + _$SendEntitiesEventImpl; + + @override + Map get entities; + @override + @JsonKey(ignore: true) + _$$SendEntitiesEventImplCopyWith<_$SendEntitiesEventImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DeviceConnectionState { + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) sending, + required TResult Function() completed, + required TResult Function(String error) failed, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? sending, + TResult? Function()? completed, + TResult? Function(String error)? failed, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? sending, + TResult Function()? completed, + TResult Function(String error)? failed, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(DeviceConnectionInitial value) initial, + required TResult Function(DeviceConnectionLoading value) loading, + required TResult Function(DeviceConnectionSending value) sending, + required TResult Function(DeviceConnectionCompleted value) completed, + required TResult Function(DeviceConnectionFailed value) failed, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(DeviceConnectionInitial value)? initial, + TResult? Function(DeviceConnectionLoading value)? loading, + TResult? Function(DeviceConnectionSending value)? sending, + TResult? Function(DeviceConnectionCompleted value)? completed, + TResult? Function(DeviceConnectionFailed value)? failed, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(DeviceConnectionInitial value)? initial, + TResult Function(DeviceConnectionLoading value)? loading, + TResult Function(DeviceConnectionSending value)? sending, + TResult Function(DeviceConnectionCompleted value)? completed, + TResult Function(DeviceConnectionFailed value)? failed, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DeviceConnectionStateCopyWith<$Res> { + factory $DeviceConnectionStateCopyWith(DeviceConnectionState value, + $Res Function(DeviceConnectionState) then) = + _$DeviceConnectionStateCopyWithImpl<$Res, DeviceConnectionState>; +} + +/// @nodoc +class _$DeviceConnectionStateCopyWithImpl<$Res, + $Val extends DeviceConnectionState> + implements $DeviceConnectionStateCopyWith<$Res> { + _$DeviceConnectionStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; +} + +/// @nodoc +abstract class _$$DeviceConnectionInitialImplCopyWith<$Res> { + factory _$$DeviceConnectionInitialImplCopyWith( + _$DeviceConnectionInitialImpl value, + $Res Function(_$DeviceConnectionInitialImpl) then) = + __$$DeviceConnectionInitialImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$DeviceConnectionInitialImplCopyWithImpl<$Res> + extends _$DeviceConnectionStateCopyWithImpl<$Res, + _$DeviceConnectionInitialImpl> + implements _$$DeviceConnectionInitialImplCopyWith<$Res> { + __$$DeviceConnectionInitialImplCopyWithImpl( + _$DeviceConnectionInitialImpl _value, + $Res Function(_$DeviceConnectionInitialImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$DeviceConnectionInitialImpl implements DeviceConnectionInitial { + const _$DeviceConnectionInitialImpl(); + + @override + String toString() { + return 'DeviceConnectionState.initial()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DeviceConnectionInitialImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) sending, + required TResult Function() completed, + required TResult Function(String error) failed, + }) { + return initial(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? sending, + TResult? Function()? completed, + TResult? Function(String error)? failed, + }) { + return initial?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? sending, + TResult Function()? completed, + TResult Function(String error)? failed, + required TResult orElse(), + }) { + if (initial != null) { + return initial(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(DeviceConnectionInitial value) initial, + required TResult Function(DeviceConnectionLoading value) loading, + required TResult Function(DeviceConnectionSending value) sending, + required TResult Function(DeviceConnectionCompleted value) completed, + required TResult Function(DeviceConnectionFailed value) failed, + }) { + return initial(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(DeviceConnectionInitial value)? initial, + TResult? Function(DeviceConnectionLoading value)? loading, + TResult? Function(DeviceConnectionSending value)? sending, + TResult? Function(DeviceConnectionCompleted value)? completed, + TResult? Function(DeviceConnectionFailed value)? failed, + }) { + return initial?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(DeviceConnectionInitial value)? initial, + TResult Function(DeviceConnectionLoading value)? loading, + TResult Function(DeviceConnectionSending value)? sending, + TResult Function(DeviceConnectionCompleted value)? completed, + TResult Function(DeviceConnectionFailed value)? failed, + required TResult orElse(), + }) { + if (initial != null) { + return initial(this); + } + return orElse(); + } +} + +abstract class DeviceConnectionInitial implements DeviceConnectionState { + const factory DeviceConnectionInitial() = _$DeviceConnectionInitialImpl; +} + +/// @nodoc +abstract class _$$DeviceConnectionLoadingImplCopyWith<$Res> { + factory _$$DeviceConnectionLoadingImplCopyWith( + _$DeviceConnectionLoadingImpl value, + $Res Function(_$DeviceConnectionLoadingImpl) then) = + __$$DeviceConnectionLoadingImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$DeviceConnectionLoadingImplCopyWithImpl<$Res> + extends _$DeviceConnectionStateCopyWithImpl<$Res, + _$DeviceConnectionLoadingImpl> + implements _$$DeviceConnectionLoadingImplCopyWith<$Res> { + __$$DeviceConnectionLoadingImplCopyWithImpl( + _$DeviceConnectionLoadingImpl _value, + $Res Function(_$DeviceConnectionLoadingImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$DeviceConnectionLoadingImpl implements DeviceConnectionLoading { + const _$DeviceConnectionLoadingImpl(); + + @override + String toString() { + return 'DeviceConnectionState.loading()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DeviceConnectionLoadingImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) sending, + required TResult Function() completed, + required TResult Function(String error) failed, + }) { + return loading(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? sending, + TResult? Function()? completed, + TResult? Function(String error)? failed, + }) { + return loading?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? sending, + TResult Function()? completed, + TResult Function(String error)? failed, + required TResult orElse(), + }) { + if (loading != null) { + return loading(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(DeviceConnectionInitial value) initial, + required TResult Function(DeviceConnectionLoading value) loading, + required TResult Function(DeviceConnectionSending value) sending, + required TResult Function(DeviceConnectionCompleted value) completed, + required TResult Function(DeviceConnectionFailed value) failed, + }) { + return loading(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(DeviceConnectionInitial value)? initial, + TResult? Function(DeviceConnectionLoading value)? loading, + TResult? Function(DeviceConnectionSending value)? sending, + TResult? Function(DeviceConnectionCompleted value)? completed, + TResult? Function(DeviceConnectionFailed value)? failed, + }) { + return loading?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(DeviceConnectionInitial value)? initial, + TResult Function(DeviceConnectionLoading value)? loading, + TResult Function(DeviceConnectionSending value)? sending, + TResult Function(DeviceConnectionCompleted value)? completed, + TResult Function(DeviceConnectionFailed value)? failed, + required TResult orElse(), + }) { + if (loading != null) { + return loading(this); + } + return orElse(); + } +} + +abstract class DeviceConnectionLoading implements DeviceConnectionState { + const factory DeviceConnectionLoading() = _$DeviceConnectionLoadingImpl; +} + +/// @nodoc +abstract class _$$DeviceConnectionSendingImplCopyWith<$Res> { + factory _$$DeviceConnectionSendingImplCopyWith( + _$DeviceConnectionSendingImpl value, + $Res Function(_$DeviceConnectionSendingImpl) then) = + __$$DeviceConnectionSendingImplCopyWithImpl<$Res>; + @useResult + $Res call({double progress}); +} + +/// @nodoc +class __$$DeviceConnectionSendingImplCopyWithImpl<$Res> + extends _$DeviceConnectionStateCopyWithImpl<$Res, + _$DeviceConnectionSendingImpl> + implements _$$DeviceConnectionSendingImplCopyWith<$Res> { + __$$DeviceConnectionSendingImplCopyWithImpl( + _$DeviceConnectionSendingImpl _value, + $Res Function(_$DeviceConnectionSendingImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? progress = null, + }) { + return _then(_$DeviceConnectionSendingImpl( + progress: null == progress + ? _value.progress + : progress // ignore: cast_nullable_to_non_nullable + as double, + )); + } +} + +/// @nodoc + +class _$DeviceConnectionSendingImpl implements DeviceConnectionSending { + const _$DeviceConnectionSendingImpl({required this.progress}); + + @override + final double progress; + + @override + String toString() { + return 'DeviceConnectionState.sending(progress: $progress)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DeviceConnectionSendingImpl && + (identical(other.progress, progress) || + other.progress == progress)); + } + + @override + int get hashCode => Object.hash(runtimeType, progress); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$DeviceConnectionSendingImplCopyWith<_$DeviceConnectionSendingImpl> + get copyWith => __$$DeviceConnectionSendingImplCopyWithImpl< + _$DeviceConnectionSendingImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) sending, + required TResult Function() completed, + required TResult Function(String error) failed, + }) { + return sending(progress); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? sending, + TResult? Function()? completed, + TResult? Function(String error)? failed, + }) { + return sending?.call(progress); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? sending, + TResult Function()? completed, + TResult Function(String error)? failed, + required TResult orElse(), + }) { + if (sending != null) { + return sending(progress); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(DeviceConnectionInitial value) initial, + required TResult Function(DeviceConnectionLoading value) loading, + required TResult Function(DeviceConnectionSending value) sending, + required TResult Function(DeviceConnectionCompleted value) completed, + required TResult Function(DeviceConnectionFailed value) failed, + }) { + return sending(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(DeviceConnectionInitial value)? initial, + TResult? Function(DeviceConnectionLoading value)? loading, + TResult? Function(DeviceConnectionSending value)? sending, + TResult? Function(DeviceConnectionCompleted value)? completed, + TResult? Function(DeviceConnectionFailed value)? failed, + }) { + return sending?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(DeviceConnectionInitial value)? initial, + TResult Function(DeviceConnectionLoading value)? loading, + TResult Function(DeviceConnectionSending value)? sending, + TResult Function(DeviceConnectionCompleted value)? completed, + TResult Function(DeviceConnectionFailed value)? failed, + required TResult orElse(), + }) { + if (sending != null) { + return sending(this); + } + return orElse(); + } +} + +abstract class DeviceConnectionSending implements DeviceConnectionState { + const factory DeviceConnectionSending({required final double progress}) = + _$DeviceConnectionSendingImpl; + + double get progress; + @JsonKey(ignore: true) + _$$DeviceConnectionSendingImplCopyWith<_$DeviceConnectionSendingImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$DeviceConnectionCompletedImplCopyWith<$Res> { + factory _$$DeviceConnectionCompletedImplCopyWith( + _$DeviceConnectionCompletedImpl value, + $Res Function(_$DeviceConnectionCompletedImpl) then) = + __$$DeviceConnectionCompletedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$DeviceConnectionCompletedImplCopyWithImpl<$Res> + extends _$DeviceConnectionStateCopyWithImpl<$Res, + _$DeviceConnectionCompletedImpl> + implements _$$DeviceConnectionCompletedImplCopyWith<$Res> { + __$$DeviceConnectionCompletedImplCopyWithImpl( + _$DeviceConnectionCompletedImpl _value, + $Res Function(_$DeviceConnectionCompletedImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$DeviceConnectionCompletedImpl implements DeviceConnectionCompleted { + const _$DeviceConnectionCompletedImpl(); + + @override + String toString() { + return 'DeviceConnectionState.completed()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DeviceConnectionCompletedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) sending, + required TResult Function() completed, + required TResult Function(String error) failed, + }) { + return completed(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? sending, + TResult? Function()? completed, + TResult? Function(String error)? failed, + }) { + return completed?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? sending, + TResult Function()? completed, + TResult Function(String error)? failed, + required TResult orElse(), + }) { + if (completed != null) { + return completed(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(DeviceConnectionInitial value) initial, + required TResult Function(DeviceConnectionLoading value) loading, + required TResult Function(DeviceConnectionSending value) sending, + required TResult Function(DeviceConnectionCompleted value) completed, + required TResult Function(DeviceConnectionFailed value) failed, + }) { + return completed(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(DeviceConnectionInitial value)? initial, + TResult? Function(DeviceConnectionLoading value)? loading, + TResult? Function(DeviceConnectionSending value)? sending, + TResult? Function(DeviceConnectionCompleted value)? completed, + TResult? Function(DeviceConnectionFailed value)? failed, + }) { + return completed?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(DeviceConnectionInitial value)? initial, + TResult Function(DeviceConnectionLoading value)? loading, + TResult Function(DeviceConnectionSending value)? sending, + TResult Function(DeviceConnectionCompleted value)? completed, + TResult Function(DeviceConnectionFailed value)? failed, + required TResult orElse(), + }) { + if (completed != null) { + return completed(this); + } + return orElse(); + } +} + +abstract class DeviceConnectionCompleted implements DeviceConnectionState { + const factory DeviceConnectionCompleted() = _$DeviceConnectionCompletedImpl; +} + +/// @nodoc +abstract class _$$DeviceConnectionFailedImplCopyWith<$Res> { + factory _$$DeviceConnectionFailedImplCopyWith( + _$DeviceConnectionFailedImpl value, + $Res Function(_$DeviceConnectionFailedImpl) then) = + __$$DeviceConnectionFailedImplCopyWithImpl<$Res>; + @useResult + $Res call({String error}); +} + +/// @nodoc +class __$$DeviceConnectionFailedImplCopyWithImpl<$Res> + extends _$DeviceConnectionStateCopyWithImpl<$Res, + _$DeviceConnectionFailedImpl> + implements _$$DeviceConnectionFailedImplCopyWith<$Res> { + __$$DeviceConnectionFailedImplCopyWithImpl( + _$DeviceConnectionFailedImpl _value, + $Res Function(_$DeviceConnectionFailedImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? error = null, + }) { + return _then(_$DeviceConnectionFailedImpl( + error: null == error + ? _value.error + : error // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$DeviceConnectionFailedImpl implements DeviceConnectionFailed { + const _$DeviceConnectionFailedImpl({required this.error}); + + @override + final String error; + + @override + String toString() { + return 'DeviceConnectionState.failed(error: $error)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DeviceConnectionFailedImpl && + (identical(other.error, error) || other.error == error)); + } + + @override + int get hashCode => Object.hash(runtimeType, error); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$DeviceConnectionFailedImplCopyWith<_$DeviceConnectionFailedImpl> + get copyWith => __$$DeviceConnectionFailedImplCopyWithImpl< + _$DeviceConnectionFailedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) sending, + required TResult Function() completed, + required TResult Function(String error) failed, + }) { + return failed(error); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? sending, + TResult? Function()? completed, + TResult? Function(String error)? failed, + }) { + return failed?.call(error); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? sending, + TResult Function()? completed, + TResult Function(String error)? failed, + required TResult orElse(), + }) { + if (failed != null) { + return failed(error); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(DeviceConnectionInitial value) initial, + required TResult Function(DeviceConnectionLoading value) loading, + required TResult Function(DeviceConnectionSending value) sending, + required TResult Function(DeviceConnectionCompleted value) completed, + required TResult Function(DeviceConnectionFailed value) failed, + }) { + return failed(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(DeviceConnectionInitial value)? initial, + TResult? Function(DeviceConnectionLoading value)? loading, + TResult? Function(DeviceConnectionSending value)? sending, + TResult? Function(DeviceConnectionCompleted value)? completed, + TResult? Function(DeviceConnectionFailed value)? failed, + }) { + return failed?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(DeviceConnectionInitial value)? initial, + TResult Function(DeviceConnectionLoading value)? loading, + TResult Function(DeviceConnectionSending value)? sending, + TResult Function(DeviceConnectionCompleted value)? completed, + TResult Function(DeviceConnectionFailed value)? failed, + required TResult orElse(), + }) { + if (failed != null) { + return failed(this); + } + return orElse(); + } +} + +abstract class DeviceConnectionFailed implements DeviceConnectionState { + const factory DeviceConnectionFailed({required final String error}) = + _$DeviceConnectionFailedImpl; + + String get error; + @JsonKey(ignore: true) + _$$DeviceConnectionFailedImplCopyWith<_$DeviceConnectionFailedImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/apps/health_campaign_field_worker_app/lib/blocs/project/project.dart b/apps/health_campaign_field_worker_app/lib/blocs/project/project.dart index 3be8eec58f..8308cb9d69 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/project/project.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/project/project.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'dart:core'; import 'package:attendance_management/attendance_management.dart'; -import 'package:survey_form/survey_form.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:digit_components/digit_components.dart'; import 'package:digit_data_model/data_model.dart'; @@ -14,6 +13,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:inventory_management/inventory_management.dart'; import 'package:isar/isar.dart'; import 'package:recase/recase.dart'; +import 'package:survey_form/survey_form.dart'; import '../../../models/app_config/app_config_model.dart' as app_configuration; import '../../data/local_store/no_sql/schema/app_configuration.dart'; @@ -296,7 +296,6 @@ class ProjectBloc extends Bloc { } if (projects.isNotEmpty) { - // INFO : Need to add project load functions try { diff --git a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart index 51c567e07f..ee4787e15e 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart @@ -1,10 +1,14 @@ // GENERATED using mason_cli import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; import 'package:digit_data_model/data_model.dart'; import 'package:disk_space/disk_space.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:registration_delivery/registration_delivery.dart'; import '../../data/local_store/no_sql/schema/app_configuration.dart'; @@ -203,7 +207,9 @@ class BeneficiaryDownSyncBloc ); // check if the API response is there or it failed if (downSyncResults.isNotEmpty) { - await networkManager.writeToEntityDB(downSyncResults, [ + writeToFile(event.boundaryCode, downSyncResults); + await networkManager + .writeToEntityDB(event.boundaryCode, downSyncResults, [ individualLocalRepository, householdLocalRepository, householdMemberLocalRepository, @@ -260,6 +266,64 @@ class BeneficiaryDownSyncBloc } } + void writeToFile( + String selectedBoundaryCode, + Map response, + ) async { + Map storedData = {}; + + // Get the Downloads directory + final downloadsDirectory = await getDownloadsDirectory(); + if (downloadsDirectory == null) { + if (kDebugMode) { + print("Downloads directory is not available."); + } + return; + } + + // Define the file path + final file = File('${downloadsDirectory.path}/down_sync_data.json'); + + // Read existing file content if available + if (file.existsSync()) { + final content = await file.readAsString(); + if (content.isNotEmpty) { + storedData = jsonDecode(content); + } + } else { + // Create the file if it doesn't exist + await file.create(recursive: true); + await file.writeAsString( + jsonEncode({})); // Initialize with an empty JSON object + } + + // Merge new response with stored data + response.forEach((key, value) { + if (key != "DownsyncCriteria") { + if (storedData.containsKey(key)) { + final existingList = storedData[key] as List? ?? []; + final newList = value as List? ?? []; + + final mergedList = [ + ...existingList, + ...newList.where((newItem) => existingList + .every((existingItem) => existingItem['id'] != newItem['id'])) + ]; + storedData[key] = mergedList; + } else { + storedData[key] = value; + } + } + }); + + // Write the merged data back to the file + await file.writeAsString(jsonEncode(storedData)); + + if (kDebugMode) { + print("Data successfully written to ${file.path}"); + } + } + FutureOr _handleDownSyncReport( DownSyncReportEvent event, BeneficiaryDownSyncEmitter emit, diff --git a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.freezed.dart b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.freezed.dart index 092150d1b5..9f91e55c5a 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.freezed.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.freezed.dart @@ -176,7 +176,9 @@ class __$$DownSyncBeneficiaryEventImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncBeneficiaryEventImpl implements DownSyncBeneficiaryEvent { +class _$DownSyncBeneficiaryEventImpl + with DiagnosticableTreeMixin + implements DownSyncBeneficiaryEvent { const _$DownSyncBeneficiaryEventImpl( {required this.projectId, required this.boundaryCode, @@ -196,10 +198,22 @@ class _$DownSyncBeneficiaryEventImpl implements DownSyncBeneficiaryEvent { final String boundaryName; @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncEvent.downSync(projectId: $projectId, boundaryCode: $boundaryCode, batchSize: $batchSize, initialServerCount: $initialServerCount, boundaryName: $boundaryName)'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'BeneficiaryDownSyncEvent.downSync')) + ..add(DiagnosticsProperty('projectId', projectId)) + ..add(DiagnosticsProperty('boundaryCode', boundaryCode)) + ..add(DiagnosticsProperty('batchSize', batchSize)) + ..add(DiagnosticsProperty('initialServerCount', initialServerCount)) + ..add(DiagnosticsProperty('boundaryName', boundaryName)); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -414,6 +428,7 @@ class __$$DownSyncCheckTotalCountEventImplCopyWithImpl<$Res> /// @nodoc class _$DownSyncCheckTotalCountEventImpl + with DiagnosticableTreeMixin implements DownSyncCheckTotalCountEvent { const _$DownSyncCheckTotalCountEventImpl( {required this.projectId, @@ -434,10 +449,23 @@ class _$DownSyncCheckTotalCountEventImpl final String boundaryName; @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncEvent.checkForData(projectId: $projectId, boundaryCode: $boundaryCode, pendingSyncCount: $pendingSyncCount, batchSize: $batchSize, boundaryName: $boundaryName)'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add( + DiagnosticsProperty('type', 'BeneficiaryDownSyncEvent.checkForData')) + ..add(DiagnosticsProperty('projectId', projectId)) + ..add(DiagnosticsProperty('boundaryCode', boundaryCode)) + ..add(DiagnosticsProperty('pendingSyncCount', pendingSyncCount)) + ..add(DiagnosticsProperty('batchSize', batchSize)) + ..add(DiagnosticsProperty('boundaryName', boundaryName)); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -654,7 +682,9 @@ class __$$DownSyncGetBatchSizeEventImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncGetBatchSizeEventImpl implements DownSyncGetBatchSizeEvent { +class _$DownSyncGetBatchSizeEventImpl + with DiagnosticableTreeMixin + implements DownSyncGetBatchSizeEvent { const _$DownSyncGetBatchSizeEventImpl( {required final List appConfiguration, required this.projectId, @@ -682,10 +712,23 @@ class _$DownSyncGetBatchSizeEventImpl implements DownSyncGetBatchSizeEvent { final String boundaryName; @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncEvent.getBatchSize(appConfiguration: $appConfiguration, projectId: $projectId, boundaryCode: $boundaryCode, pendingSyncCount: $pendingSyncCount, boundaryName: $boundaryName)'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add( + DiagnosticsProperty('type', 'BeneficiaryDownSyncEvent.getBatchSize')) + ..add(DiagnosticsProperty('appConfiguration', appConfiguration)) + ..add(DiagnosticsProperty('projectId', projectId)) + ..add(DiagnosticsProperty('boundaryCode', boundaryCode)) + ..add(DiagnosticsProperty('pendingSyncCount', pendingSyncCount)) + ..add(DiagnosticsProperty('boundaryName', boundaryName)); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -862,14 +905,23 @@ class __$$DownSyncReportEventImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncReportEventImpl implements DownSyncReportEvent { +class _$DownSyncReportEventImpl + with DiagnosticableTreeMixin + implements DownSyncReportEvent { const _$DownSyncReportEventImpl(); @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncEvent.downSyncReport()'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add( + DiagnosticsProperty('type', 'BeneficiaryDownSyncEvent.downSyncReport')); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -1008,14 +1060,23 @@ class __$$DownSyncResetStateEventImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncResetStateEventImpl implements DownSyncResetStateEvent { +class _$DownSyncResetStateEventImpl + with DiagnosticableTreeMixin + implements DownSyncResetStateEvent { const _$DownSyncResetStateEventImpl(); @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncEvent.resetState()'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add( + DiagnosticsProperty('type', 'BeneficiaryDownSyncEvent.resetState')); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -1301,7 +1362,8 @@ class __$$DownSyncInProgressStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncInProgressStateImpl extends _DownSyncInProgressState { +class _$DownSyncInProgressStateImpl extends _DownSyncInProgressState + with DiagnosticableTreeMixin { const _$DownSyncInProgressStateImpl(this.syncedCount, this.totalCount) : super._(); @@ -1311,10 +1373,19 @@ class _$DownSyncInProgressStateImpl extends _DownSyncInProgressState { final int totalCount; @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.inProgress(syncedCount: $syncedCount, totalCount: $totalCount)'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'BeneficiaryDownSyncState.inProgress')) + ..add(DiagnosticsProperty('syncedCount', syncedCount)) + ..add(DiagnosticsProperty('totalCount', totalCount)); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -1512,17 +1583,26 @@ class __$$DownSyncSuccessStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncSuccessStateImpl extends _DownSyncSuccessState { +class _$DownSyncSuccessStateImpl extends _DownSyncSuccessState + with DiagnosticableTreeMixin { const _$DownSyncSuccessStateImpl(this.downSyncResult) : super._(); @override final DownsyncModel downSyncResult; @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.success(downSyncResult: $downSyncResult)'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'BeneficiaryDownSyncState.success')) + ..add(DiagnosticsProperty('downSyncResult', downSyncResult)); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -1744,7 +1824,8 @@ class __$$DownSyncGetBatchSizeStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncGetBatchSizeStateImpl extends _DownSyncGetBatchSizeState { +class _$DownSyncGetBatchSizeStateImpl extends _DownSyncGetBatchSizeState + with DiagnosticableTreeMixin { const _$DownSyncGetBatchSizeStateImpl(this.batchSize, this.projectId, this.boundaryCode, this.pendingSyncCount, this.boundaryName) : super._(); @@ -1761,10 +1842,23 @@ class _$DownSyncGetBatchSizeStateImpl extends _DownSyncGetBatchSizeState { final String boundaryName; @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.getBatchSize(batchSize: $batchSize, projectId: $projectId, boundaryCode: $boundaryCode, pendingSyncCount: $pendingSyncCount, boundaryName: $boundaryName)'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add( + DiagnosticsProperty('type', 'BeneficiaryDownSyncState.getBatchSize')) + ..add(DiagnosticsProperty('batchSize', batchSize)) + ..add(DiagnosticsProperty('projectId', projectId)) + ..add(DiagnosticsProperty('boundaryCode', boundaryCode)) + ..add(DiagnosticsProperty('pendingSyncCount', pendingSyncCount)) + ..add(DiagnosticsProperty('boundaryName', boundaryName)); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -1978,17 +2072,26 @@ class __$$DownSyncLoadingStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncLoadingStateImpl extends _DownSyncLoadingState { +class _$DownSyncLoadingStateImpl extends _DownSyncLoadingState + with DiagnosticableTreeMixin { const _$DownSyncLoadingStateImpl(this.isPop) : super._(); @override final bool isPop; @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.loading(isPop: $isPop)'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'BeneficiaryDownSyncState.loading')) + ..add(DiagnosticsProperty('isPop', isPop)); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -2170,14 +2273,21 @@ class __$$DownSyncInsufficientStorageStateImplCopyWithImpl<$Res> /// @nodoc class _$DownSyncInsufficientStorageStateImpl - extends _DownSyncInsufficientStorageState { + extends _DownSyncInsufficientStorageState with DiagnosticableTreeMixin { const _$DownSyncInsufficientStorageStateImpl() : super._(); @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.insufficientStorage()'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty( + 'type', 'BeneficiaryDownSyncState.insufficientStorage')); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -2365,7 +2475,8 @@ class __$$DownSyncDataFoundStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncDataFoundStateImpl extends _DownSyncDataFoundState { +class _$DownSyncDataFoundStateImpl extends _DownSyncDataFoundState + with DiagnosticableTreeMixin { const _$DownSyncDataFoundStateImpl(this.initialServerCount, this.batchSize) : super._(); @@ -2375,10 +2486,19 @@ class _$DownSyncDataFoundStateImpl extends _DownSyncDataFoundState { final int batchSize; @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.dataFound(initialServerCount: $initialServerCount, batchSize: $batchSize)'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'BeneficiaryDownSyncState.dataFound')) + ..add(DiagnosticsProperty('initialServerCount', initialServerCount)) + ..add(DiagnosticsProperty('batchSize', batchSize)); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -2561,14 +2681,22 @@ class __$$DownSyncResetStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncResetStateImpl extends _DownSyncResetState { +class _$DownSyncResetStateImpl extends _DownSyncResetState + with DiagnosticableTreeMixin { const _$DownSyncResetStateImpl() : super._(); @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.resetState()'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add( + DiagnosticsProperty('type', 'BeneficiaryDownSyncState.resetState')); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -2733,15 +2861,22 @@ class __$$DownSynnCountCheckFailedStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSynnCountCheckFailedStateImpl - extends _DownSynnCountCheckFailedState { +class _$DownSynnCountCheckFailedStateImpl extends _DownSynnCountCheckFailedState + with DiagnosticableTreeMixin { const _$DownSynnCountCheckFailedStateImpl() : super._(); @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.totalCountCheckFailed()'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty( + 'type', 'BeneficiaryDownSyncState.totalCountCheckFailed')); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -2906,14 +3041,22 @@ class __$$DownSyncFailureStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncFailureStateImpl extends _DownSyncFailureState { +class _$DownSyncFailureStateImpl extends _DownSyncFailureState + with DiagnosticableTreeMixin { const _$DownSyncFailureStateImpl() : super._(); @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.failed()'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + .add(DiagnosticsProperty('type', 'BeneficiaryDownSyncState.failed')); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -3092,7 +3235,8 @@ class __$$DownSyncReportStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncReportStateImpl extends _DownSyncReportState { +class _$DownSyncReportStateImpl extends _DownSyncReportState + with DiagnosticableTreeMixin { const _$DownSyncReportStateImpl( final List downsyncCriteriaList) : _downsyncCriteriaList = downsyncCriteriaList, @@ -3108,10 +3252,18 @@ class _$DownSyncReportStateImpl extends _DownSyncReportState { } @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.report(downsyncCriteriaList: $downsyncCriteriaList)'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'BeneficiaryDownSyncState.report')) + ..add(DiagnosticsProperty('downsyncCriteriaList', downsyncCriteriaList)); + } + @override bool operator ==(Object other) { return identical(this, other) || @@ -3294,14 +3446,22 @@ class __$$DownSyncPendingSyncStateImplCopyWithImpl<$Res> /// @nodoc -class _$DownSyncPendingSyncStateImpl extends _DownSyncPendingSyncState { +class _$DownSyncPendingSyncStateImpl extends _DownSyncPendingSyncState + with DiagnosticableTreeMixin { const _$DownSyncPendingSyncStateImpl() : super._(); @override - String toString() { + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return 'BeneficiaryDownSyncState.pendingSync()'; } + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add( + DiagnosticsProperty('type', 'BeneficiaryDownSyncState.pendingSync')); + } + @override bool operator ==(Object other) { return identical(this, other) || diff --git a/apps/health_campaign_field_worker_app/lib/data/network_manager.dart b/apps/health_campaign_field_worker_app/lib/data/network_manager.dart index 7445775304..a2aa4f348f 100644 --- a/apps/health_campaign_field_worker_app/lib/data/network_manager.dart +++ b/apps/health_campaign_field_worker_app/lib/data/network_manager.dart @@ -1,14 +1,13 @@ import 'dart:async'; -import 'dart:convert'; import 'package:digit_data_model/data_model.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_background_service/flutter_background_service.dart'; import 'package:provider/provider.dart'; -import 'package:registration_delivery/registration_delivery.dart'; import '../models/bandwidth/bandwidth_model.dart'; +import '../utils/utils.dart'; import 'local_store/secure_store/secure_store.dart'; import 'repositories/sync/remote_type.dart'; import 'repositories/sync/sync_down.dart'; @@ -109,8 +108,8 @@ class NetworkManager { return isSyncCompleted; } - FutureOr writeToEntityDB( + String selectedBoundaryCode, Map response, List localRepositories, ) async { @@ -126,54 +125,8 @@ class NetworkManager { final entityList = entityResponse.whereType>().toList(); - - switch (response.keys.elementAt(i)) { - case "Individuals": - final entity = entityList - .map((e) => IndividualModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "Households": - final entity = entityList - .map((e) => HouseholdModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "HouseholdMembers": - final entity = entityList - .map( - (e) => HouseholdMemberModelMapper.fromJson( - jsonEncode(e), - ), - ) - .toList(); - await local.bulkCreate(entity); - case "ProjectBeneficiaries": - final entity = entityList - .map((e) => - ProjectBeneficiaryModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "Tasks": - final entity = entityList - .map((e) => TaskModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "SideEffects": - final entity = entityList - .map((e) => SideEffectModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "Referrals": - final entity = entityList - .map((e) => ReferralModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - default: - final entity = entityList - .map((e) => EntityModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - } + var key = response.keys.elementAt(i); + createDbRecords(local, entityList, key); // write to local database } } } catch (e) { diff --git a/apps/health_campaign_field_worker_app/lib/pages/home.dart b/apps/health_campaign_field_worker_app/lib/pages/home.dart index 473996f7bc..33a0ad6830 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/home.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/home.dart @@ -51,6 +51,7 @@ import '../widgets/home/home_item_card.dart'; import '../widgets/localized.dart'; import '../widgets/showcase/config/showcase_constants.dart'; import '../widgets/showcase/showcase_button.dart'; +import 'peer_to_peer/data_share_home.dart'; @RoutePage() class HomePage extends LocalizedStatefulWidget { @@ -492,6 +493,16 @@ class _HomePageState extends LocalizedState { }, ), ), + i18.home.dataShare: homeShowcaseData.dataShare.buildWith( + child: HomeItemCard( + icon: Icons.send, + label: i18.home.dataShare, + onPressed: () async { + Navigator.push(context, + MaterialPageRoute(builder: (_) => const DataShareHomePage())); + }, + ), + ), i18.home.dashboard: homeShowcaseData.dashBoard.buildWith( child: HomeItemCard( icon: Icons.bar_chart_sharp, @@ -557,6 +568,8 @@ class _HomePageState extends LocalizedState { .map((label) => homeItemsShowcaseMap[label]!) .toList(); + filteredLabels.add(i18.home.dataShare); // TODO: Role action mapping + final List widgetList = filteredLabels.map((label) => homeItemsMap[label]!).toList(); diff --git a/apps/health_campaign_field_worker_app/lib/pages/login.dart b/apps/health_campaign_field_worker_app/lib/pages/login.dart index cb1277d204..d96adb190f 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/login.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/login.dart @@ -229,12 +229,12 @@ class _LoginPageState extends LocalizedState { FormGroup buildForm() => fb.group({ _userId: FormControl( - value: '', + value: 'QADistributor', validators: [Validators.required], ), _password: FormControl( validators: [Validators.required], - value: '', + value: 'eGov@1234', ), _privacyCheck: FormControl( value: false, diff --git a/apps/health_campaign_field_worker_app/lib/pages/near_by_share_list.dart b/apps/health_campaign_field_worker_app/lib/pages/near_by_share_list.dart deleted file mode 100644 index 49e109a478..0000000000 --- a/apps/health_campaign_field_worker_app/lib/pages/near_by_share_list.dart +++ /dev/null @@ -1,409 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; -import 'dart:math'; - -import 'package:device_info_plus/device_info_plus.dart'; -import 'package:digit_components/digit_components.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; -import 'package:registration_delivery/models/entities/household.dart'; - -import '../utils/extensions/extensions.dart'; - -enum DeviceType { receiver, sender } - -class DevicesListScreen extends StatefulWidget { - const DevicesListScreen({super.key, required this.deviceType}); - - final DeviceType deviceType; - - @override - _DevicesListScreenState createState() => _DevicesListScreenState(); -} - -class _DevicesListScreenState extends State - with TickerProviderStateMixin { - List devices = []; - List connectedDevices = []; - late NearbyService nearbyService; - late StreamSubscription subscription; - late StreamSubscription receivedDataSubscription; - late AnimationController _controller; - late AnimationController _radarController; - - late Animation _colorAnimation1; - late Animation _colorAnimation2; - - bool isInit = false; - double rippleRadius = 0; - - @override - void initState() { - super.initState(); - createAnimation(); - init(); - } - - @override - void dispose() { - subscription.cancel(); - receivedDataSubscription.cancel(); - nearbyService.stopBrowsingForPeers(); - nearbyService.stopAdvertisingPeer(); - _controller.dispose(); - _radarController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: DigitTheme.instance.colors.regalBlue, - body: Column( - children: [ - Text( - widget.deviceType.name, - style: TextStyle( - color: Colors.white, - fontSize: 20, - ), - ), - Expanded( - child: Center( - child: Stack( - alignment: Alignment.center, - children: [ - // Radar Circles - ...List.generate(4, (index) { - return Container( - width: 200.0 + (index * 50), - height: 200.0 + (index * 50), - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: Colors.white.withOpacity(0.3), - ), - ), - ); - }), - // Radar Sweep - AnimatedBuilder( - animation: _controller, - builder: (context, child) { - return Transform.rotate( - angle: _controller.value * 2 * pi, - child: Container( - width: 400, - height: 400, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: SweepGradient( - colors: [ - Colors.white.withOpacity(0.3), - Colors.transparent, - ], - stops: [0.7, 1.0], - ), - ), - ), - ); - }, - ), - ..._generateRandomDevicePositions(devices, 400, 200), - ], - ), - ), - ), - ], - ), - ); - } - - List _generateRandomDevicePositions( - List devices, - double size, - double - rippleRadius // Pass rippleRadius here to position devices inside it - ) { - final random = Random(); - return widget.deviceType == DeviceType.receiver - ? connectedDevices.asMap().entries.map((entry) { - // Ensure that the device is placed within the ripple's growing radius - final angle = random.nextDouble() * 2 * pi; // Random angle - final radius = random.nextDouble() * - rippleRadius; // Ensure radius is within ripple radius - final x = radius * cos(angle); - final y = radius * sin(angle); - - return Positioned( - left: size / 2 + - x - - 40, // Adjust icon position (centered around the circle) - top: size / 2 + y - 40, - child: _buildDeviceWidget(entry.value), - ); - }).toList() - : devices.asMap().entries.map((entry) { - // Ensure that the device is placed within the ripple's growing radius - final angle = random.nextDouble() * 2 * pi; // Random angle - final radius = random.nextDouble() * - rippleRadius; // Ensure radius is within ripple radius - final x = radius * cos(angle); - final y = radius * sin(angle); - - return Positioned( - left: size / 2 + - x - - 40, // Adjust icon position (centered around the circle) - top: size / 2 + y - 40, - child: _buildDeviceWidget(entry.value), - ); - }).toList(); - } - - // Build each device widget with icon and name - Widget _buildDeviceWidget(Device device) { - return GestureDetector( - onTap: () { - _onButtonClicked(device); - }, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Material( - elevation: 5, - borderRadius: BorderRadius.circular(20), - child: Icon( - Icons.phone_android, - size: 50, // Adjust size of the device icon - color: DigitTheme.instance.colors.amber, - ), - ), - const SizedBox( - height: kPadding, - ), - Text( - device.deviceName, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, color: DigitTheme.instance.colors.amber), - ), - ], - ), - ); - } - - String getStateName(SessionState state) { - switch (state) { - case SessionState.notConnected: - return "disconnected"; - case SessionState.connecting: - return "waiting"; - default: - return "connected"; - } - } - - String getButtonStateName(SessionState state) { - switch (state) { - case SessionState.notConnected: - case SessionState.connecting: - return "Connect"; - default: - return "Disconnect"; - } - } - - Color getStateColor(SessionState state) { - switch (state) { - case SessionState.notConnected: - return Colors.black; - case SessionState.connecting: - return Colors.grey; - default: - return Colors.green; - } - } - - Color getButtonColor(SessionState state) { - switch (state) { - case SessionState.notConnected: - case SessionState.connecting: - return Colors.green; - default: - return Colors.red; - } - } - - int getItemCount() { - if (widget.deviceType == DeviceType.receiver) { - return connectedDevices.length; - } else { - return devices.length; - } - } - - _onButtonClicked(Device device) { - switch (device.state) { - case SessionState.notConnected: - nearbyService.invitePeer( - deviceID: device.deviceId, - deviceName: device.deviceName, - ); - break; - case SessionState.connected: - nearbyService.disconnectPeer(deviceID: device.deviceId); - break; - case SessionState.connecting: - break; - } - } - - void init() async { - nearbyService = NearbyService(); - String devInfo = ''; - DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - if (Platform.isAndroid) { - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - devInfo = androidInfo.model; - } - if (Platform.isIOS) { - IosDeviceInfo iosInfo = await deviceInfo.iosInfo; - devInfo = iosInfo.localizedModel; - } - await nearbyService.init( - serviceType: 'mpconn', - deviceName: devInfo, - strategy: Strategy.P2P_CLUSTER, - callback: (isRunning) async { - if (isRunning) { - if (widget.deviceType == DeviceType.sender) { - await nearbyService.stopBrowsingForPeers(); - await Future.delayed(const Duration(microseconds: 200)); - await nearbyService.startBrowsingForPeers(); - } else { - await nearbyService.stopAdvertisingPeer(); - await nearbyService.stopBrowsingForPeers(); - await Future.delayed(const Duration(microseconds: 200)); - await nearbyService.startAdvertisingPeer(); - await nearbyService.startBrowsingForPeers(); - } - } - }); - subscription = - nearbyService.stateChangedSubscription(callback: (devicesList) { - for (var element in devicesList) { - print( - "deviceId: ${element.deviceId} | deviceName: ${element.deviceName} | state: ${element.state}"); - - // Handle Android-specific browsing - if (Platform.isAndroid) { - if (element.state == SessionState.connected) { - print('connection successful'); - showModalBottomSheet( - context: context, - elevation: 5, - builder: (context) => Column( - children: [ - Text( - "Connected to ${element.deviceName}...", - style: Theme.of(context).textTheme.displayMedium, - ), - ], - )); - // nearbyService.stopBrowsingForPeers(); - } else if (element.state == SessionState.notConnected) { - nearbyService.startBrowsingForPeers(); - } - } - } - - setState(() { - // Deduplicate the devices list - final uniqueDevices = {}; // Use a map for deduplication - for (var device in devicesList) { - uniqueDevices[device.deviceId] = - device; // Replace entries with the same deviceId - } - - // Update the devices list and connected devices - devices - ..clear() - ..addAll(uniqueDevices.values); // Add only unique devices - - connectedDevices - ..clear() - ..addAll(devices.where((d) => d.state == SessionState.connected)); - }); - }); - - receivedDataSubscription = - nearbyService.dataReceivedSubscription(callback: (data) { - try { - // Extract the raw JSON string - var receivedData = data["message"]; - print('Decoded data: $receivedData'); - - // Step 1: Decode the outer JSON string (array) - Map outerArray = jsonDecode(receivedData); - print('data ${outerArray["model"][0]}'); - - HouseholdModel model = - HouseholdModelMapper.fromJson(outerArray["model"][0]); - print('model $model'); - // saveDataInDb(model); - // // Step 3: Use the parsed data - // if (models.isNotEmpty) { - // saveDataInDb(models.first); - // } - } catch (e) { - debugPrint('Error parsing data: $e'); - } - - // showToast(jsonEncode(data["message"]), - // context: context, - // axis: Axis.horizontal, - // alignment: Alignment.center, - // position: StyledToastPosition.bottom); - }); - } - - void fetchDbRecords(Device device) async { - var records = await context - .repository() - .search(HouseholdSearchModel()); - - // Convert the list of models to JSON - var serializedData = records.map((model) => model).toList(); - - nearbyService.sendMessage( - device.deviceId, jsonEncode({'model': serializedData})); - } - - void saveDataInDb(HouseholdModel model) async { - var projectBeneficiaryModel = await context - .repository() - .create(model); - } - - void createAnimation() { - _controller = - AnimationController(vsync: this, duration: const Duration(seconds: 10)) - ..repeat(); - _radarController = AnimationController( - duration: const Duration(seconds: 10), - vsync: this, - )..repeat(reverse: false); - - _colorAnimation1 = ColorTween( - begin: const Color.fromRGBO(255, 255, 255, 1.0), - end: const Color.fromRGBO(234, 138, 59, 1), - ).animate(_controller); - - _colorAnimation2 = ColorTween( - begin: const Color.fromRGBO(234, 138, 59, 1), - end: const Color.fromRGBO(234, 138, 59, 1), - ).animate(_controller); - } -} diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart new file mode 100644 index 0000000000..1eb86e78f8 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -0,0 +1,160 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:digit_data_model/data_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; +import 'package:registration_delivery/registration_delivery.dart'; + +import '../../utils/i18_key_constants.dart' as i18; +import '../../utils/utils.dart'; +import '../../widgets/localized.dart'; + +class DataReceiverPage extends LocalizedStatefulWidget { + final Device connectedDevice; + final NearbyService nearbyService; + const DataReceiverPage( + {super.key, required this.connectedDevice, required this.nearbyService}); + + @override + State createState() => _DataReceiverPageState(); +} + +class _DataReceiverPageState extends LocalizedState { + late NearbyService nearbyService; + List receivedData = []; + double progress = 0.0; + int receivedBytes = 0; + int totalBytes = 0; + late StreamSubscription receivedDataSubscription; + + @override + void initState() { + super.initState(); + nearbyService = widget.nearbyService; + initReceiver(); + } + + @override + void dispose() { + nearbyService.stopAdvertisingPeer(); + nearbyService.stopBrowsingForPeers(); + receivedDataSubscription.cancel(); + super.dispose(); + } + + Future initReceiver() async { + nearbyService.stateChangedSubscription(callback: (state) { + debugPrint("Nearby state changed: $state"); + }); + + receivedDataSubscription = + nearbyService.dataReceivedSubscription(callback: (data) { + try { + var receivedJson = jsonDecode(data["message"]); + String entityType = receivedJson["entityType"]; + int offset = receivedJson["offset"]; + int totalData = receivedJson["totalData"]; + List receivedChunk = receivedJson["message"]; + + // Update progress + setState(() { + receivedBytes = offset; + progress = receivedBytes / totalData; + receivedData.addAll(receivedChunk); + }); + + // When data for this entity is fully received + if (receivedBytes >= totalData) { + // Save the received entity data + LocalRepository repository = _getRepositoryForEntity(entityType); + final entityList = + receivedData.whereType>().toList(); + createDbRecords(repository, entityList, entityType); + + debugPrint("$entityType data saved successfully."); + + // Clear the received data buffer for the next entity + receivedData.clear(); + + // Send confirmation back to the sender + nearbyService.sendMessage( + data["senderDeviceId"], + jsonEncode({ + "type": "confirmation", + "entityType": entityType, + "status": "success", + "message": "$entityType saved successfully." + }), + ); + } + } catch (e) { + debugPrint("Error processing received data: $e"); + } + }); + } + + LocalRepository _getRepositoryForEntity(String entityType) { + switch (entityType) { + case 'Individuals': + return context + .read>(); + case 'Households': + return context + .read>(); + case 'HouseholdMembers': + return context.read< + LocalRepository>(); + case 'ProjectBeneficiaries': + return context.read< + LocalRepository>(); + case 'SideEffects': + return context + .read>(); + case 'Tasks': + return context.read>(); + case 'Referrals': + return context + .read>(); + default: + throw Exception("Unknown entity type: $entityType"); + } + } + + @override + Widget build(BuildContext context) { + return PopScope( + onPopInvoked: (pop) { + if (pop) { + widget.nearbyService + .disconnectPeer(deviceID: widget.connectedDevice.deviceId); + } + }, + child: Scaffold( + appBar: AppBar( + title: Text( + "${localizations.translate(i18.dataShare.connectedTo)} ${widget.connectedDevice.deviceName}"), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + "Receiving data from the connected device...", + style: TextStyle(fontSize: 18), + ), + LinearProgressIndicator(value: progress), + const SizedBox(height: 10), + Text("${(progress * 100).toStringAsFixed(1)}%"), + const SizedBox(height: 30), + ], + ), + ), + ), + ); + } +} diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart new file mode 100644 index 0000000000..98e82f4fce --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart @@ -0,0 +1,60 @@ +import 'package:attendance_management/widgets/localized.dart'; +import 'package:auto_route/annotations.dart'; +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +import '../../utils/i18_key_constants.dart' as i18; +import 'devices_list.dart'; + +@RoutePage() +class DataShareHomePage extends LocalizedStatefulWidget { + const DataShareHomePage({super.key}); + + @override + State createState() => _DataShareHomeState(); +} + +class _DataShareHomeState extends LocalizedState { + @override + Widget build(BuildContext context) { + return ScrollableContent( + children: [ + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.3, + child: DigitCard( + child: Center( + child: DigitElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => const DevicesListPage( + deviceType: DeviceType.sender))); + }, + child: Text( + localizations.translate(i18.dataShare.sendAction)))), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.3, + child: DigitCard( + margin: const EdgeInsets.all(kPadding), + child: Center( + child: DigitElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => const DevicesListPage( + deviceType: DeviceType.receiver))); + }, + child: Text( + localizations.translate(i18.dataShare.receiveAction)))), + ), + ) + ], + ); + } +} diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart new file mode 100644 index 0000000000..2ef2322e67 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -0,0 +1,188 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:auto_route/annotations.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; +import 'package:path_provider/path_provider.dart'; + +import '../../utils/i18_key_constants.dart' as i18; +import '../../widgets/localized.dart'; + +@RoutePage() +class DataTransferPage extends LocalizedStatefulWidget { + final Device connectedDevice; + final NearbyService nearbyService; + + const DataTransferPage( + {super.key, required this.nearbyService, required this.connectedDevice}); + + @override + State createState() => _DataTransferScreenState(); +} + +class _DataTransferScreenState extends LocalizedState { + late NearbyService nearbyService; + double progress = 0.0; // To track progress + + @override + void initState() { + super.initState(); + nearbyService = widget.nearbyService; + } + + @override + void dispose() { + super.dispose(); + } + + void sendEntities(Map entities) async { + for (var entityName in entities.keys) { + List entityData = entities[entityName]!; + int totalSize = entityData.length; + int offset = 0; + + try { + while (offset < totalSize) { + const int chunkSize = 100; + int end = + (offset + chunkSize < totalSize) ? offset + chunkSize : totalSize; + List chunk = entityData.sublist(offset, end); + + // Send the chunk + widget.nearbyService.sendMessage( + widget.connectedDevice.deviceId, + jsonEncode({ + "entityType": entityName, + "message": chunk, + "offset": offset + chunk.length, + "totalData": totalSize, + }), + ); + + // Update progress for the entity + setState(() { + progress = (offset + chunk.length) / totalSize; + }); + + // Simulate delay for smoother UX + await Future.delayed(const Duration(milliseconds: 200)); + offset = end; + } + + // Wait for receiver's confirmation for the current entity + await waitForConfirmation(entityName); + } catch (e) { + debugPrint('Error sending $entityName: $e'); + } + } + + // Notify completion + if (mounted) { + setState(() { + progress = 1.0; + }); + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text("Transfer Complete"), + content: const Text("All entities have been sent successfully."), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text("OK"), + ), + ], + ), + ); + } + } + + Future waitForConfirmation(String entityName) async { + final completer = Completer(); + + final subscription = + nearbyService.dataReceivedSubscription(callback: (data) { + try { + var receivedJson = jsonDecode(data["message"]); + if (receivedJson["type"] == "confirmation" && + receivedJson["entityType"] == entityName && + receivedJson["status"] == "success") { + debugPrint("Confirmation received for $entityName"); + completer.complete(); + } + } catch (e) { + debugPrint("Error processing confirmation: $e"); + } + }); + + Future.delayed(const Duration(seconds: 10), () { + if (!completer.isCompleted) { + completer + .completeError("Timeout waiting for confirmation for $entityName"); + } + }); + + await completer.future; + subscription.cancel(); + } + + @override + Widget build(BuildContext context) { + return PopScope( + onPopInvoked: (pop) { + if (pop) { + widget.nearbyService + .disconnectPeer(deviceID: widget.connectedDevice.deviceId); + } + }, + child: Scaffold( + appBar: AppBar( + title: Text( + "${localizations.translate(i18.dataShare.connectedTo)} ${widget.connectedDevice.deviceName}"), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + const Text( + "Transferring data to the connected device...", + style: TextStyle(fontSize: 18), + ), + const SizedBox(height: 20), + LinearProgressIndicator(value: progress), + const SizedBox(height: 10), + Text("${(progress * 100).toStringAsFixed(1)}%"), + const SizedBox(height: 30), + ElevatedButton( + onPressed: () async { + // Example data to transfer + readDownSyncData(); + }, + child: const Text("Start Transfer"), + ), + ], + ), + ), + ), + ); + } + + void readDownSyncData() async { + final downloadsDirectory = await getDownloadsDirectory(); + + final file = File('${downloadsDirectory!.path}/down_sync_data.json'); + + final content = await file.readAsString(); + if (content.isNotEmpty) { + try { + sendEntities(jsonDecode(content)); + // nearbyService.sendMessage(widget.connectedDevice.deviceId, content); + } catch (e) { + debugPrint('Error parsing data: $e'); + } + } + } +} diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart new file mode 100644 index 0000000000..9523888d71 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -0,0 +1,371 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:math'; + +import 'package:attendance_management/widgets/back_navigation_help_header.dart'; +import 'package:auto_route/annotations.dart'; +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:digit_components/digit_components.dart'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; + +import '../../utils/i18_key_constants.dart' as i18; +import '../../widgets/localized.dart'; +import 'data_receiver.dart'; +import 'data_transfer.dart'; + +enum DeviceType { receiver, sender } + +@RoutePage() +class DevicesListPage extends LocalizedStatefulWidget { + const DevicesListPage({super.key, required this.deviceType}); + + final DeviceType deviceType; + + @override + DevicesListPageState createState() => DevicesListPageState(); +} + +class DevicesListPageState extends LocalizedState + with TickerProviderStateMixin { + List devices = []; + List connectedDevices = []; + late NearbyService nearbyService; + late StreamSubscription subscription; + late AnimationController _controller; + late AnimationController _radarController; + + bool isInit = false; + double rippleRadius = 0; + + @override + void initState() { + super.initState(); + createAnimation(); + init(); + } + + @override + void dispose() { + subscription.cancel(); + nearbyService.stopBrowsingForPeers(); + nearbyService.stopAdvertisingPeer(); + _controller.dispose(); + _radarController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return Scaffold( + body: ScrollableContent( + backgroundColor: DigitTheme.instance.colors.white, + footer: widget.deviceType == DeviceType.sender + ? DigitElevatedButton( + onPressed: connectedDevices.isNotEmpty + ? () { + Navigator.push(context, + MaterialPageRoute(builder: (context) { + return DataTransferPage( + connectedDevice: connectedDevices.first, + nearbyService: nearbyService, + ); + })); + } + : null, + child: Text(localizations.translate(i18.dataShare.sendAction)), + ) + : const Spacer(), + children: [ + const BackNavigationHelpHeaderWidget(), + Text( + widget.deviceType.name.toUpperCase(), + style: textTheme.headingM, + ), + Container( + height: MediaQuery.of(context).size.height * 0.6, + color: DigitTheme.instance.colors.regalBlue, + child: Stack( + alignment: Alignment.center, + children: [ + // Radar Circles + ...List.generate(4, (index) { + return Container( + width: 200.0 + (index * 50), + height: 200.0 + (index * 50), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white.withOpacity(0.3), + ), + ), + ); + }), + // Radar Sweep + AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return Transform.rotate( + angle: _controller.value * 2 * pi, + child: Container( + width: 400, + height: 400, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: SweepGradient( + colors: [ + Colors.white.withOpacity(0.3), + Colors.transparent, + ], + stops: const [0.7, 1.0], + ), + ), + ), + ); + }, + ), + ..._generateRandomDevicePositions(devices, 400, 200), + ], + ), + ) + ], + ), + ); + } + + List _generateRandomDevicePositions( + List devices, + double size, + double + rippleRadius // Pass rippleRadius here to position devices inside it + ) { + final random = Random(); + return widget.deviceType == DeviceType.receiver + ? connectedDevices.asMap().entries.map((entry) { + // Ensure that the device is placed within the ripple's growing radius + final angle = random.nextDouble() * 2 * pi; // Random angle + final radius = random.nextDouble() * + rippleRadius; // Ensure radius is within ripple radius + final x = radius * cos(angle); + final y = radius * sin(angle); + + return Positioned( + left: size / 2 + + x - + 40, // Adjust icon position (centered around the circle) + top: size / 2 + y - 40, + child: _buildDeviceWidget(entry.value), + ); + }).toList() + : devices.asMap().entries.map((entry) { + // Ensure that the device is placed within the ripple's growing radius + final angle = random.nextDouble() * 2 * pi; // Random angle + final radius = random.nextDouble() * + rippleRadius; // Ensure radius is within ripple radius + final x = radius * cos(angle); + final y = radius * sin(angle); + + return Positioned( + left: size / 2 + + x - + 40, // Adjust icon position (centered around the circle) + top: size / 2 + y - 40, + child: _buildDeviceWidget(entry.value), + ); + }).toList(); + } + + // Build each device widget with icon and name + Widget _buildDeviceWidget(Device device) { + return GestureDetector( + onTap: () { + _onButtonClicked(device); + }, + child: Material( + elevation: 5, + borderRadius: BorderRadius.circular(kPadding), + child: Padding( + padding: const EdgeInsets.all(kPadding), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.phone_android, + size: 50, // Adjust size of the device icon + color: DigitTheme.instance.colors.amber, + ), + const SizedBox( + height: kPadding, + ), + Text( + device.deviceName, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, color: DigitTheme.instance.colors.amber), + ), + Text( + getStateName(device.state), + textAlign: TextAlign.center, + style: + TextStyle(fontSize: 8, color: getStateColor(device.state)), + ), + ], + ), + ), + ), + ); + } + + String getStateName(SessionState state) { + switch (state) { + case SessionState.notConnected: + return SessionState.notConnected.name.toUpperCase(); + case SessionState.connecting: + return SessionState.connecting.name.toUpperCase(); + case SessionState.connected: + return SessionState.connected.name.toUpperCase(); + default: + return "UNKNOWN"; + } + } + + Color getStateColor(SessionState state) { + switch (state) { + case SessionState.notConnected: + return DigitTheme.instance.colors.amber; + case SessionState.connecting: + return DigitTheme.instance.colors.white; + default: + return DigitTheme.instance.colors.darkSpringGreen; + } + } + + int getItemCount() { + if (widget.deviceType == DeviceType.receiver) { + return connectedDevices.length; + } else { + return devices.length; + } + } + + _onButtonClicked(Device device) { + switch (device.state) { + case SessionState.notConnected: + nearbyService.invitePeer( + deviceID: device.deviceId, + deviceName: device.deviceName, + ); + break; + case SessionState.connected: + nearbyService.disconnectPeer(deviceID: device.deviceId); + break; + case SessionState.connecting: + break; + } + } + + void init() async { + nearbyService = NearbyService(); + String deviceId = ''; + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + final Set navigatedDevices = {}; + + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + deviceId = androidInfo.model; + } + if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + deviceId = iosInfo.localizedModel; + } + await nearbyService.init( + serviceType: 'mpconn', + deviceName: deviceId, + strategy: Strategy.Wi_Fi_P2P, + callback: (isRunning) async { + if (isRunning) { + if (widget.deviceType == DeviceType.sender) { + await nearbyService.stopBrowsingForPeers(); + await Future.delayed(const Duration(microseconds: 200)); + await nearbyService.startBrowsingForPeers(); + } else { + await nearbyService.stopAdvertisingPeer(); + await nearbyService.stopBrowsingForPeers(); + await Future.delayed(const Duration(microseconds: 200)); + await nearbyService.startAdvertisingPeer(); + await nearbyService.startBrowsingForPeers(); + } + } + }); + subscription = + nearbyService.stateChangedSubscription(callback: (devicesList) { + if (devicesList.isNotEmpty) { + var element = devicesList.first; + if (kDebugMode) { + print( + "deviceId: ${element.deviceId} | deviceName: ${element.deviceName} | state: ${element.state}"); + } + + // Handle Android-specific browsing + if (Platform.isAndroid) { + if (element.state == SessionState.connected) { + if (!navigatedDevices.contains(element.deviceId)) { + if (kDebugMode) { + print('connection successful'); + } + navigatedDevices.add(element.deviceId); + if (widget.deviceType == DeviceType.receiver) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DataReceiverPage( + connectedDevice: element, + nearbyService: nearbyService, + ))); + } + nearbyService.stopBrowsingForPeers(); + } + } else if (element.state == SessionState.notConnected) { + nearbyService.startBrowsingForPeers(); + navigatedDevices.remove( + element.deviceId); // Allow re-navigation if disconnected + } + } + + setState(() { + // Deduplicate the devices list + final uniqueDevices = + {}; // Use a map for deduplication + for (var device in devicesList) { + uniqueDevices[device.deviceId] = + device; // Replace entries with the same deviceId + } + + // Update the devices list and connected devices + devices + ..clear() + ..addAll(uniqueDevices.values); // Add only unique devices + + connectedDevices + ..clear() + ..addAll(devices.where((d) => d.state == SessionState.connected)); + }); + } + }); + } + + void createAnimation() { + _controller = + AnimationController(vsync: this, duration: const Duration(seconds: 10)) + ..repeat(); + _radarController = AnimationController( + duration: const Duration(seconds: 10), + vsync: this, + )..repeat(reverse: false); + } +} diff --git a/apps/health_campaign_field_worker_app/lib/pages/reports/beneficiary/beneficaries_report.dart b/apps/health_campaign_field_worker_app/lib/pages/reports/beneficiary/beneficaries_report.dart index 36b2691c54..b7d063fb0b 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/reports/beneficiary/beneficaries_report.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/reports/beneficiary/beneficaries_report.dart @@ -18,7 +18,6 @@ import '../../../utils/utils.dart'; import '../../../widgets/header/back_navigation_help_header.dart'; import '../../../widgets/localized.dart'; import '../../../widgets/no_result_card/no_result_card.dart'; -import '../../near_by_share_list.dart'; @RoutePage() class BeneficiariesReportPage extends LocalizedStatefulWidget { @@ -420,15 +419,6 @@ class BeneficiariesReportState extends LocalizedState { SizedBox( height: kPadding, ), - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => const DevicesListScreen( - deviceType: DeviceType.sender))); - }, - child: Text('Data Transfer')), downSyncList.isEmpty ? NoResultCard( align: Alignment.center, diff --git a/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart b/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart index 2fcad75eef..3a768e7a17 100644 --- a/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart +++ b/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart @@ -55,6 +55,33 @@ abstract class _$AppRouter extends RootStackRouter { ), ); }, + DataShareHomeRoute.name: (routeData) { + return AutoRoutePage( + routeData: routeData, + child: const DataShareHomePage(), + ); + }, + DataTransferRoute.name: (routeData) { + final args = routeData.argsAs(); + return AutoRoutePage( + routeData: routeData, + child: DataTransferPage( + key: args.key, + nearbyService: args.nearbyService, + connectedDevice: args.connectedDevice, + ), + ); + }, + DevicesListRoute.name: (routeData) { + final args = routeData.argsAs(); + return AutoRoutePage( + routeData: routeData, + child: DevicesListPage( + key: args.key, + deviceType: args.deviceType, + ), + ); + }, HomeRoute.name: (routeData) { final args = routeData.argsAs(orElse: () => const HomeRouteArgs()); @@ -284,6 +311,101 @@ class BoundarySelectionRouteArgs { } } +/// generated route for +/// [DataShareHomePage] +class DataShareHomeRoute extends PageRouteInfo { + const DataShareHomeRoute({List? children}) + : super( + DataShareHomeRoute.name, + initialChildren: children, + ); + + static const String name = 'DataShareHomeRoute'; + + static const PageInfo page = PageInfo(name); +} + +/// generated route for +/// [DataTransferPage] +class DataTransferRoute extends PageRouteInfo { + DataTransferRoute({ + Key? key, + required NearbyService nearbyService, + required Device connectedDevice, + List? children, + }) : super( + DataTransferRoute.name, + args: DataTransferRouteArgs( + key: key, + nearbyService: nearbyService, + connectedDevice: connectedDevice, + ), + initialChildren: children, + ); + + static const String name = 'DataTransferRoute'; + + static const PageInfo page = + PageInfo(name); +} + +class DataTransferRouteArgs { + const DataTransferRouteArgs({ + this.key, + required this.nearbyService, + required this.connectedDevice, + }); + + final Key? key; + + final NearbyService nearbyService; + + final Device connectedDevice; + + @override + String toString() { + return 'DataTransferRouteArgs{key: $key, nearbyService: $nearbyService, connectedDevice: $connectedDevice}'; + } +} + +/// generated route for +/// [DevicesListPage] +class DevicesListRoute extends PageRouteInfo { + DevicesListRoute({ + Key? key, + required DeviceType deviceType, + List? children, + }) : super( + DevicesListRoute.name, + args: DevicesListRouteArgs( + key: key, + deviceType: deviceType, + ), + initialChildren: children, + ); + + static const String name = 'DevicesListRoute'; + + static const PageInfo page = + PageInfo(name); +} + +class DevicesListRouteArgs { + const DevicesListRouteArgs({ + this.key, + required this.deviceType, + }); + + final Key? key; + + final DeviceType deviceType; + + @override + String toString() { + return 'DevicesListRouteArgs{key: $key, deviceType: $deviceType}'; + } +} + /// generated route for /// [HomePage] class HomeRoute extends PageRouteInfo { diff --git a/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart b/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart index 6e09406123..5662be3abe 100644 --- a/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart +++ b/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart @@ -4,6 +4,7 @@ const common = Common(); const login = Login(); const forgotPassword = ForgotPassword(); const home = Home(); +const dataShare = DataShare(); const acknowledgementSuccess = AcknowledgementSuccess(); const adverseEvents = AdverseEvents(); const projectSelection = ProjectSelection(); @@ -510,7 +511,6 @@ class ComplaintsInboxShowcase { } } - class ForgotPassword { const ForgotPassword(); @@ -556,6 +556,7 @@ class Home { String get deleteAllLabel => 'HOME_DELETE_ALL_LABEL'; String get db => 'HOME_DB_LABEL'; + String get dataShare => 'HOME_DATA_SHARE_LABEL'; String get dashboard => 'HOME_DASHBOARD_LABEL'; String get beneficiaryReferralLabel => 'HOME_BENEFICIARY_REFERRAL_LABEL'; String get manageAttendanceLabel => 'HOME_MANAGE_ATTENDANCE_LABEL'; @@ -563,6 +564,14 @@ class Home { String get closedHouseHoldLabel => 'HOME_CLOSE_HOUSEHOLD_LABEL'; } +class DataShare { + const DataShare(); + + String get sendAction => 'SEND_ACTION'; + String get receiveAction => 'RECEIVE_ACTION'; + String get connectedTo => 'CONNECTED_TO'; +} + class AcknowledgementSuccess { const AcknowledgementSuccess(); @@ -1014,7 +1023,6 @@ class PrivacyPolicy { String get privacyNoticeText => 'PRIVACY_POLICY_TEXT'; String get privacyPolicyLinkText => 'PRIVACY_POLICY_LINK_TEXT'; String get privacyPolicyValidationText => 'PRIVACY_POLICY_VALIDATION_TEXT'; - } class Dashboard { diff --git a/apps/health_campaign_field_worker_app/lib/utils/utils.dart b/apps/health_campaign_field_worker_app/lib/utils/utils.dart index 6b5d19fc32..0f84ac6488 100644 --- a/apps/health_campaign_field_worker_app/lib/utils/utils.dart +++ b/apps/health_campaign_field_worker_app/lib/utils/utils.dart @@ -1,11 +1,11 @@ library app_utils; import 'dart:async'; +import 'dart:convert'; import 'dart:io'; import 'package:attendance_management/attendance_management.dart' as attendance_mappers; - import 'package:complaints/complaints.init.dart' as complaints_mappers; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:digit_components/theme/digit_theme.dart'; @@ -25,10 +25,10 @@ import 'package:isar/isar.dart'; import 'package:reactive_forms/reactive_forms.dart'; import 'package:referral_reconciliation/referral_reconciliation.dart' as referral_reconciliation_mappers; +import 'package:registration_delivery/registration_delivery.dart'; import 'package:registration_delivery/registration_delivery.init.dart' as registration_delivery_mappers; -import 'package:survey_form/survey_form.init.dart' - as survey_form_mappers; +import 'package:survey_form/survey_form.init.dart' as survey_form_mappers; import '../blocs/app_initialization/app_initialization.dart'; import '../blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart'; @@ -456,6 +456,56 @@ int getSyncCount(List oplogs) { return count; } +void createDbRecords(LocalRepository local, + List> entityList, String key) async { + switch (key) { + case "Individuals": + final entity = entityList + .map((e) => IndividualModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "Households": + final entity = entityList + .map((e) => HouseholdModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "HouseholdMembers": + final entity = entityList + .map( + (e) => HouseholdMemberModelMapper.fromJson( + jsonEncode(e), + ), + ) + .toList(); + await local.bulkCreate(entity); + case "ProjectBeneficiaries": + final entity = entityList + .map((e) => ProjectBeneficiaryModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "Tasks": + final entity = entityList + .map((e) => TaskModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "SideEffects": + final entity = entityList + .map((e) => SideEffectModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "Referrals": + final entity = entityList + .map((e) => ReferralModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + default: + final entity = entityList + .map((e) => EntityModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + } +} + class LocalizationParams { static final LocalizationParams _singleton = LocalizationParams._internal(); diff --git a/apps/health_campaign_field_worker_app/lib/widgets/showcase/config/home_showcase.dart b/apps/health_campaign_field_worker_app/lib/widgets/showcase/config/home_showcase.dart index c5bc7380e9..9421455b8e 100644 --- a/apps/health_campaign_field_worker_app/lib/widgets/showcase/config/home_showcase.dart +++ b/apps/health_campaign_field_worker_app/lib/widgets/showcase/config/home_showcase.dart @@ -99,6 +99,10 @@ class _HomePageShowcaseData { messageLocalizationKey: i18.home.db, ); + final dataShare = ShowcaseItemBuilder( + messageLocalizationKey: i18.home.dataShare, + ); + final dashBoard = ShowcaseItemBuilder( messageLocalizationKey: i18.home.dashboard, ); diff --git a/apps/health_campaign_field_worker_app/lib/widgets/sidebar/side_bar.dart b/apps/health_campaign_field_worker_app/lib/widgets/sidebar/side_bar.dart index 6fcca2c23c..a2b0cae5c2 100644 --- a/apps/health_campaign_field_worker_app/lib/widgets/sidebar/side_bar.dart +++ b/apps/health_campaign_field_worker_app/lib/widgets/sidebar/side_bar.dart @@ -12,7 +12,6 @@ import '../../blocs/auth/auth.dart'; import '../../blocs/localization/localization.dart'; import '../../models/data_model.dart'; import '../../models/entities/roles_type.dart'; -import '../../pages/near_by_share_list.dart'; import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../utils/utils.dart'; @@ -229,19 +228,6 @@ class SideBar extends StatelessWidget { context.router.push(const BeneficiariesReportRoute()); }, ), - DigitIconTile( - title: AppLocalizations.of(context).translate( - 'RECEIVE_DATA', - ), - icon: Icons.emergency_share, - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => const DevicesListScreen( - deviceType: DeviceType.receiver))); - }, - ), DigitIconTile( title: AppLocalizations.of(context) .translate(i18.common.coreCommonLogout), diff --git a/apps/health_campaign_field_worker_app/pubspec.lock b/apps/health_campaign_field_worker_app/pubspec.lock index 9ec8aea929..2ca6d4e118 100644 --- a/apps/health_campaign_field_worker_app/pubspec.lock +++ b/apps/health_campaign_field_worker_app/pubspec.lock @@ -944,7 +944,7 @@ packages: source: sdk version: "0.0.0" flutter_nearby_connections: - dependency: "direct dev" + dependency: "direct main" description: path: "." ref: master @@ -1945,14 +1945,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" - simple_ripple_animation: - dependency: "direct dev" - description: - name: simple_ripple_animation - sha256: "09a80a6d352ce12d33c2ca43423bf5b544179cc5bc78bf3ff73bd5c08ea378bd" - url: "https://pub.dev" - source: hosted - version: "0.1.0" sky_engine: dependency: transitive description: flutter diff --git a/apps/health_campaign_field_worker_app/pubspec.yaml b/apps/health_campaign_field_worker_app/pubspec.yaml index a1b18bb398..32b5401fef 100644 --- a/apps/health_campaign_field_worker_app/pubspec.yaml +++ b/apps/health_campaign_field_worker_app/pubspec.yaml @@ -79,6 +79,10 @@ dependencies: permission_handler: ^11.3.1 survey_form: ^0.0.1-dev.2 complaints: ^0.0.1-dev.2 + flutter_nearby_connections: + git: + url: https://github.com/champeauxr/flutter_nearby_connections + ref: master dev_dependencies: flutter_test: @@ -101,11 +105,6 @@ dev_dependencies: isar_generator: ^3.0.5 flutter_launcher_icons: ^0.13.1 hrk_flutter_test_batteries: ^0.8.0 - flutter_nearby_connections: - git: - url: https://github.com/champeauxr/flutter_nearby_connections - ref: master - simple_ripple_animation: ^0.1.0 dependency_overrides: intl: ^0.18.0 From 10987aea30265d212cd98bfe2f79a218659a4217 Mon Sep 17 00:00:00 2001 From: Naveen Renati Date: Tue, 3 Dec 2024 15:57:25 +0530 Subject: [PATCH 03/16] moved logic to bloc --- .../lib/blocs/peer_to_peer/peer_to_peer.dart | 255 +++ .../peer_to_peer/peer_to_peer.freezed.dart | 1863 +++++++++++++++++ .../lib/blocs/peer_to_peer/send_data.dart | 90 - .../blocs/peer_to_peer/send_data.freezed.dart | 994 --------- .../lib/pages/home.dart | 4 +- .../lib/pages/peer_to_peer/data_receiver.dart | 146 +- .../pages/peer_to_peer/data_share_home.dart | 91 +- .../lib/pages/peer_to_peer/data_transfer.dart | 285 ++- .../lib/pages/peer_to_peer/devices_list.dart | 301 +-- .../peer_to_peer/peer_to_peer_wrapper.dart | 41 + .../lib/router/app_router.dart | 39 +- .../lib/router/app_router.gr.dart | 78 +- .../lib/utils/i18_key_constants.dart | 1 + 13 files changed, 2679 insertions(+), 1509 deletions(-) create mode 100644 apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart create mode 100644 apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart delete mode 100644 apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.dart delete mode 100644 apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.freezed.dart create mode 100644 apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/peer_to_peer_wrapper.dart diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart new file mode 100644 index 0000000000..bdae150049 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -0,0 +1,255 @@ +// GENERATED using mason_cli +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:digit_data_model/data_model.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:registration_delivery/registration_delivery.dart'; + +import '../../data/repositories/sync/remote_type.dart'; +import '../../utils/utils.dart'; + +part 'peer_to_peer.freezed.dart'; + +typedef PeerToPeerEmitter = Emitter; + +class PeerToPeerBloc extends Bloc { + final LocalRepository + individualLocalRepository; + final LocalRepository + householdLocalRepository; + final LocalRepository + householdMemberLocalRepository; + final LocalRepository + projectBeneficiaryLocalRepository; + final LocalRepository taskLocalRepository; + final LocalRepository + sideEffectLocalRepository; + final LocalRepository + referralLocalRepository; + + List receivedData = []; + int receivedBytes = 0; + int totalData = 0; + String entityType = ''; + late Device connectedDevice; + PeerToPeerBloc({ + required this.individualLocalRepository, + required this.householdLocalRepository, + required this.householdMemberLocalRepository, + required this.projectBeneficiaryLocalRepository, + required this.taskLocalRepository, + required this.sideEffectLocalRepository, + required this.referralLocalRepository, + }) : super(const PeerToPeerInitial()) { + on(_handleSendEntities); + on(_handleReceiveEntities); + } + + FutureOr _handleSendEntities( + DataTransferEvent event, + PeerToPeerEmitter emit, + ) async { + try { + emit(const PeerToPeerState.transferInProgress(progress: 0)); + + final downloadsDirectory = await getDownloadsDirectory(); + final file = File('${downloadsDirectory!.path}/down_sync_data.json'); + final content = await file.readAsString(); + + if (content.isNotEmpty) { + final entities = jsonDecode(content); + + try { + for (var entityName in entities.keys) { + List entityData = entities[entityName]!; + int totalSize = entityData.length; + int offset = 0; + + while (offset < totalSize) { + // Calculate the chunk + const int chunkSize = 500; + int end = (offset + chunkSize < totalSize) + ? offset + chunkSize + : totalSize; + List chunk = entityData.sublist(offset, end); + + // Send the chunk + for (var element in event.connectedDevice) { + await event.nearbyService.sendMessage( + element.deviceId, + jsonEncode({ + "entityType": entityName, + "message": chunk, + "offset": offset + chunk.length, + "totalData": totalSize, + }), + ); + } + + final progress = (offset + chunk.length) / totalSize; + emit(PeerToPeerState.transferInProgress(progress: progress)); + + // Wait for confirmation from the receiver before sending the next chunk + bool confirmed = await _waitForConfirmation(entityName, + event.nearbyService, event.connectedDevice.first.deviceId); + + if (confirmed) { + offset = end; // Move to the next chunk + } else { + emit(PeerToPeerState.failedToTransfer( + error: "Confirmation failed for chunk")); + return; + } + } + + // Notify completion + emit(const PeerToPeerState.completedDataTransfer()); + } + } catch (e) { + emit(PeerToPeerState.failedToTransfer(error: e.toString())); + } + } + } catch (e) { + emit(PeerToPeerState.failedToTransfer(error: e.toString())); + } + } + + Future _waitForConfirmation( + String entityName, NearbyService nearbyService, String deviceId) async { + final completer = Completer(); + + // Listen for the confirmation message + final subscription = + nearbyService.dataReceivedSubscription(callback: (data) { + try { + var receivedJson = jsonDecode(data["message"]); + if (receivedJson["type"] == "confirmation" && + receivedJson["entityType"] == entityName && + receivedJson["status"] == "success" && + receivedJson["deviceId"] == deviceId) { + debugPrint("Confirmation received for $entityName"); + completer.complete(true); + } + } catch (e) { + debugPrint("Error processing confirmation: $e"); + completer.complete(false); + } + }); + + // Timeout after a certain period + Future.delayed(const Duration(seconds: 10), () { + if (!completer.isCompleted) { + completer.complete(false); + } + }); + + bool confirmed = await completer.future; + subscription.cancel(); + return confirmed; + } + + Future _handleReceiveEntities( + DataReceiverEvent event, + Emitter emit, + ) async { + try { + var receivedJson = jsonDecode(event.data["message"]); + entityType = receivedJson["entityType"]; + int offset = receivedJson["offset"]; + totalData = receivedJson["totalData"]; + List receivedChunk = receivedJson["message"]; + + // Update received bytes and data + receivedBytes = offset; + double progress = receivedBytes / totalData; + receivedData.addAll(receivedChunk); + + // Calculate and emit progress + emit(PeerToPeerState.receivingInProgress(progress: progress)); + + // When all data is received + if (receivedBytes >= totalData) { + // Save the received entity data to the local database + final local = RepositoryType.getLocalForType( + DataModels.getDataModelForEntityName(entityType), + [ + individualLocalRepository, + householdLocalRepository, + householdMemberLocalRepository, + projectBeneficiaryLocalRepository, + taskLocalRepository, + sideEffectLocalRepository, + referralLocalRepository, + ], + ); + + final entityList = + receivedData.whereType>().toList(); + createDbRecords(local, entityList, entityType); + + debugPrint("$entityType data saved successfully."); + + // Clear the received data buffer for the next entity + receivedData.clear(); + receivedBytes = 0; + + // Send confirmation back to the sender + event.nearbyService.sendMessage( + event.data["deviceId"], + jsonEncode({ + "type": "confirmation", + "entityType": entityType, + "status": "success", + "deviceId": event.data["deviceId"], + "message": "$entityType saved successfully." + }), + ); + + // Emit final state + emit(const PeerToPeerState.dataReceived()); + } + } catch (e) { + debugPrint("Error processing received data: $e"); + emit(PeerToPeerState.failedToReceive(error: e.toString())); + } + } +} + +@freezed +class PeerToPeerEvent with _$PeerToPeerEvent { + const factory PeerToPeerEvent.dataTransfer( + {required NearbyService nearbyService, + required List connectedDevice}) = DataTransferEvent; + const factory PeerToPeerEvent.dataReceiver( + {required NearbyService nearbyService, + required dynamic data}) = DataReceiverEvent; +} + +@freezed +class PeerToPeerState with _$PeerToPeerState { + const factory PeerToPeerState.initial() = PeerToPeerInitial; + + const factory PeerToPeerState.loading() = PeerToPeerLoading; + + const factory PeerToPeerState.transferInProgress({required double progress}) = + TransferInProgress; + + const factory PeerToPeerState.completedDataTransfer() = CompletedDataTransfer; + + const factory PeerToPeerState.failedToTransfer({required String error}) = + FailedToTransfer; + + const factory PeerToPeerState.receivingInProgress( + {required double progress}) = ReceivingInProgress; + + const factory PeerToPeerState.dataReceived() = DataReceived; + + const factory PeerToPeerState.failedToReceive({required String error}) = + FailedDataTransfer; +} diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart new file mode 100644 index 0000000000..6fc9be260e --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart @@ -0,0 +1,1863 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'peer_to_peer.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +/// @nodoc +mixin _$PeerToPeerEvent { + NearbyService get nearbyService => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult when({ + required TResult Function( + NearbyService nearbyService, List connectedDevice) + dataTransfer, + required TResult Function(NearbyService nearbyService, dynamic data) + dataReceiver, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function( + NearbyService nearbyService, List connectedDevice)? + dataTransfer, + TResult? Function(NearbyService nearbyService, dynamic data)? dataReceiver, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(NearbyService nearbyService, List connectedDevice)? + dataTransfer, + TResult Function(NearbyService nearbyService, dynamic data)? dataReceiver, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(DataTransferEvent value) dataTransfer, + required TResult Function(DataReceiverEvent value) dataReceiver, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(DataTransferEvent value)? dataTransfer, + TResult? Function(DataReceiverEvent value)? dataReceiver, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(DataTransferEvent value)? dataTransfer, + TResult Function(DataReceiverEvent value)? dataReceiver, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $PeerToPeerEventCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PeerToPeerEventCopyWith<$Res> { + factory $PeerToPeerEventCopyWith( + PeerToPeerEvent value, $Res Function(PeerToPeerEvent) then) = + _$PeerToPeerEventCopyWithImpl<$Res, PeerToPeerEvent>; + @useResult + $Res call({NearbyService nearbyService}); +} + +/// @nodoc +class _$PeerToPeerEventCopyWithImpl<$Res, $Val extends PeerToPeerEvent> + implements $PeerToPeerEventCopyWith<$Res> { + _$PeerToPeerEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? nearbyService = null, + }) { + return _then(_value.copyWith( + nearbyService: null == nearbyService + ? _value.nearbyService + : nearbyService // ignore: cast_nullable_to_non_nullable + as NearbyService, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$DataTransferEventImplCopyWith<$Res> + implements $PeerToPeerEventCopyWith<$Res> { + factory _$$DataTransferEventImplCopyWith(_$DataTransferEventImpl value, + $Res Function(_$DataTransferEventImpl) then) = + __$$DataTransferEventImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({NearbyService nearbyService, List connectedDevice}); +} + +/// @nodoc +class __$$DataTransferEventImplCopyWithImpl<$Res> + extends _$PeerToPeerEventCopyWithImpl<$Res, _$DataTransferEventImpl> + implements _$$DataTransferEventImplCopyWith<$Res> { + __$$DataTransferEventImplCopyWithImpl(_$DataTransferEventImpl _value, + $Res Function(_$DataTransferEventImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? nearbyService = null, + Object? connectedDevice = null, + }) { + return _then(_$DataTransferEventImpl( + nearbyService: null == nearbyService + ? _value.nearbyService + : nearbyService // ignore: cast_nullable_to_non_nullable + as NearbyService, + connectedDevice: null == connectedDevice + ? _value._connectedDevice + : connectedDevice // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc + +class _$DataTransferEventImpl + with DiagnosticableTreeMixin + implements DataTransferEvent { + const _$DataTransferEventImpl( + {required this.nearbyService, + required final List connectedDevice}) + : _connectedDevice = connectedDevice; + + @override + final NearbyService nearbyService; + final List _connectedDevice; + @override + List get connectedDevice { + if (_connectedDevice is EqualUnmodifiableListView) return _connectedDevice; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_connectedDevice); + } + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerEvent.dataTransfer(nearbyService: $nearbyService, connectedDevice: $connectedDevice)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PeerToPeerEvent.dataTransfer')) + ..add(DiagnosticsProperty('nearbyService', nearbyService)) + ..add(DiagnosticsProperty('connectedDevice', connectedDevice)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DataTransferEventImpl && + (identical(other.nearbyService, nearbyService) || + other.nearbyService == nearbyService) && + const DeepCollectionEquality() + .equals(other._connectedDevice, _connectedDevice)); + } + + @override + int get hashCode => Object.hash(runtimeType, nearbyService, + const DeepCollectionEquality().hash(_connectedDevice)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$DataTransferEventImplCopyWith<_$DataTransferEventImpl> get copyWith => + __$$DataTransferEventImplCopyWithImpl<_$DataTransferEventImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function( + NearbyService nearbyService, List connectedDevice) + dataTransfer, + required TResult Function(NearbyService nearbyService, dynamic data) + dataReceiver, + }) { + return dataTransfer(nearbyService, connectedDevice); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function( + NearbyService nearbyService, List connectedDevice)? + dataTransfer, + TResult? Function(NearbyService nearbyService, dynamic data)? dataReceiver, + }) { + return dataTransfer?.call(nearbyService, connectedDevice); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(NearbyService nearbyService, List connectedDevice)? + dataTransfer, + TResult Function(NearbyService nearbyService, dynamic data)? dataReceiver, + required TResult orElse(), + }) { + if (dataTransfer != null) { + return dataTransfer(nearbyService, connectedDevice); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(DataTransferEvent value) dataTransfer, + required TResult Function(DataReceiverEvent value) dataReceiver, + }) { + return dataTransfer(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(DataTransferEvent value)? dataTransfer, + TResult? Function(DataReceiverEvent value)? dataReceiver, + }) { + return dataTransfer?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(DataTransferEvent value)? dataTransfer, + TResult Function(DataReceiverEvent value)? dataReceiver, + required TResult orElse(), + }) { + if (dataTransfer != null) { + return dataTransfer(this); + } + return orElse(); + } +} + +abstract class DataTransferEvent implements PeerToPeerEvent { + const factory DataTransferEvent( + {required final NearbyService nearbyService, + required final List connectedDevice}) = _$DataTransferEventImpl; + + @override + NearbyService get nearbyService; + List get connectedDevice; + @override + @JsonKey(ignore: true) + _$$DataTransferEventImplCopyWith<_$DataTransferEventImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$DataReceiverEventImplCopyWith<$Res> + implements $PeerToPeerEventCopyWith<$Res> { + factory _$$DataReceiverEventImplCopyWith(_$DataReceiverEventImpl value, + $Res Function(_$DataReceiverEventImpl) then) = + __$$DataReceiverEventImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({NearbyService nearbyService, dynamic data}); +} + +/// @nodoc +class __$$DataReceiverEventImplCopyWithImpl<$Res> + extends _$PeerToPeerEventCopyWithImpl<$Res, _$DataReceiverEventImpl> + implements _$$DataReceiverEventImplCopyWith<$Res> { + __$$DataReceiverEventImplCopyWithImpl(_$DataReceiverEventImpl _value, + $Res Function(_$DataReceiverEventImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? nearbyService = null, + Object? data = freezed, + }) { + return _then(_$DataReceiverEventImpl( + nearbyService: null == nearbyService + ? _value.nearbyService + : nearbyService // ignore: cast_nullable_to_non_nullable + as NearbyService, + data: freezed == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as dynamic, + )); + } +} + +/// @nodoc + +class _$DataReceiverEventImpl + with DiagnosticableTreeMixin + implements DataReceiverEvent { + const _$DataReceiverEventImpl( + {required this.nearbyService, required this.data}); + + @override + final NearbyService nearbyService; + @override + final dynamic data; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerEvent.dataReceiver(nearbyService: $nearbyService, data: $data)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PeerToPeerEvent.dataReceiver')) + ..add(DiagnosticsProperty('nearbyService', nearbyService)) + ..add(DiagnosticsProperty('data', data)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DataReceiverEventImpl && + (identical(other.nearbyService, nearbyService) || + other.nearbyService == nearbyService) && + const DeepCollectionEquality().equals(other.data, data)); + } + + @override + int get hashCode => Object.hash( + runtimeType, nearbyService, const DeepCollectionEquality().hash(data)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$DataReceiverEventImplCopyWith<_$DataReceiverEventImpl> get copyWith => + __$$DataReceiverEventImplCopyWithImpl<_$DataReceiverEventImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function( + NearbyService nearbyService, List connectedDevice) + dataTransfer, + required TResult Function(NearbyService nearbyService, dynamic data) + dataReceiver, + }) { + return dataReceiver(nearbyService, data); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function( + NearbyService nearbyService, List connectedDevice)? + dataTransfer, + TResult? Function(NearbyService nearbyService, dynamic data)? dataReceiver, + }) { + return dataReceiver?.call(nearbyService, data); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(NearbyService nearbyService, List connectedDevice)? + dataTransfer, + TResult Function(NearbyService nearbyService, dynamic data)? dataReceiver, + required TResult orElse(), + }) { + if (dataReceiver != null) { + return dataReceiver(nearbyService, data); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(DataTransferEvent value) dataTransfer, + required TResult Function(DataReceiverEvent value) dataReceiver, + }) { + return dataReceiver(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(DataTransferEvent value)? dataTransfer, + TResult? Function(DataReceiverEvent value)? dataReceiver, + }) { + return dataReceiver?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(DataTransferEvent value)? dataTransfer, + TResult Function(DataReceiverEvent value)? dataReceiver, + required TResult orElse(), + }) { + if (dataReceiver != null) { + return dataReceiver(this); + } + return orElse(); + } +} + +abstract class DataReceiverEvent implements PeerToPeerEvent { + const factory DataReceiverEvent( + {required final NearbyService nearbyService, + required final dynamic data}) = _$DataReceiverEventImpl; + + @override + NearbyService get nearbyService; + dynamic get data; + @override + @JsonKey(ignore: true) + _$$DataReceiverEventImplCopyWith<_$DataReceiverEventImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$PeerToPeerState { + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress) receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress)? receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress)? receivingInProgress, + TResult Function()? dataReceived, + TResult Function(String error)? failedToReceive, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(PeerToPeerInitial value) initial, + required TResult Function(PeerToPeerLoading value) loading, + required TResult Function(TransferInProgress value) transferInProgress, + required TResult Function(CompletedDataTransfer value) + completedDataTransfer, + required TResult Function(FailedToTransfer value) failedToTransfer, + required TResult Function(ReceivingInProgress value) receivingInProgress, + required TResult Function(DataReceived value) dataReceived, + required TResult Function(FailedDataTransfer value) failedToReceive, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(PeerToPeerInitial value)? initial, + TResult? Function(PeerToPeerLoading value)? loading, + TResult? Function(TransferInProgress value)? transferInProgress, + TResult? Function(CompletedDataTransfer value)? completedDataTransfer, + TResult? Function(FailedToTransfer value)? failedToTransfer, + TResult? Function(ReceivingInProgress value)? receivingInProgress, + TResult? Function(DataReceived value)? dataReceived, + TResult? Function(FailedDataTransfer value)? failedToReceive, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(PeerToPeerInitial value)? initial, + TResult Function(PeerToPeerLoading value)? loading, + TResult Function(TransferInProgress value)? transferInProgress, + TResult Function(CompletedDataTransfer value)? completedDataTransfer, + TResult Function(FailedToTransfer value)? failedToTransfer, + TResult Function(ReceivingInProgress value)? receivingInProgress, + TResult Function(DataReceived value)? dataReceived, + TResult Function(FailedDataTransfer value)? failedToReceive, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PeerToPeerStateCopyWith<$Res> { + factory $PeerToPeerStateCopyWith( + PeerToPeerState value, $Res Function(PeerToPeerState) then) = + _$PeerToPeerStateCopyWithImpl<$Res, PeerToPeerState>; +} + +/// @nodoc +class _$PeerToPeerStateCopyWithImpl<$Res, $Val extends PeerToPeerState> + implements $PeerToPeerStateCopyWith<$Res> { + _$PeerToPeerStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; +} + +/// @nodoc +abstract class _$$PeerToPeerInitialImplCopyWith<$Res> { + factory _$$PeerToPeerInitialImplCopyWith(_$PeerToPeerInitialImpl value, + $Res Function(_$PeerToPeerInitialImpl) then) = + __$$PeerToPeerInitialImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$PeerToPeerInitialImplCopyWithImpl<$Res> + extends _$PeerToPeerStateCopyWithImpl<$Res, _$PeerToPeerInitialImpl> + implements _$$PeerToPeerInitialImplCopyWith<$Res> { + __$$PeerToPeerInitialImplCopyWithImpl(_$PeerToPeerInitialImpl _value, + $Res Function(_$PeerToPeerInitialImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$PeerToPeerInitialImpl + with DiagnosticableTreeMixin + implements PeerToPeerInitial { + const _$PeerToPeerInitialImpl(); + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.initial()'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('type', 'PeerToPeerState.initial')); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$PeerToPeerInitialImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress) receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return initial(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress)? receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return initial?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress)? receivingInProgress, + TResult Function()? dataReceived, + TResult Function(String error)? failedToReceive, + required TResult orElse(), + }) { + if (initial != null) { + return initial(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(PeerToPeerInitial value) initial, + required TResult Function(PeerToPeerLoading value) loading, + required TResult Function(TransferInProgress value) transferInProgress, + required TResult Function(CompletedDataTransfer value) + completedDataTransfer, + required TResult Function(FailedToTransfer value) failedToTransfer, + required TResult Function(ReceivingInProgress value) receivingInProgress, + required TResult Function(DataReceived value) dataReceived, + required TResult Function(FailedDataTransfer value) failedToReceive, + }) { + return initial(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(PeerToPeerInitial value)? initial, + TResult? Function(PeerToPeerLoading value)? loading, + TResult? Function(TransferInProgress value)? transferInProgress, + TResult? Function(CompletedDataTransfer value)? completedDataTransfer, + TResult? Function(FailedToTransfer value)? failedToTransfer, + TResult? Function(ReceivingInProgress value)? receivingInProgress, + TResult? Function(DataReceived value)? dataReceived, + TResult? Function(FailedDataTransfer value)? failedToReceive, + }) { + return initial?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(PeerToPeerInitial value)? initial, + TResult Function(PeerToPeerLoading value)? loading, + TResult Function(TransferInProgress value)? transferInProgress, + TResult Function(CompletedDataTransfer value)? completedDataTransfer, + TResult Function(FailedToTransfer value)? failedToTransfer, + TResult Function(ReceivingInProgress value)? receivingInProgress, + TResult Function(DataReceived value)? dataReceived, + TResult Function(FailedDataTransfer value)? failedToReceive, + required TResult orElse(), + }) { + if (initial != null) { + return initial(this); + } + return orElse(); + } +} + +abstract class PeerToPeerInitial implements PeerToPeerState { + const factory PeerToPeerInitial() = _$PeerToPeerInitialImpl; +} + +/// @nodoc +abstract class _$$PeerToPeerLoadingImplCopyWith<$Res> { + factory _$$PeerToPeerLoadingImplCopyWith(_$PeerToPeerLoadingImpl value, + $Res Function(_$PeerToPeerLoadingImpl) then) = + __$$PeerToPeerLoadingImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$PeerToPeerLoadingImplCopyWithImpl<$Res> + extends _$PeerToPeerStateCopyWithImpl<$Res, _$PeerToPeerLoadingImpl> + implements _$$PeerToPeerLoadingImplCopyWith<$Res> { + __$$PeerToPeerLoadingImplCopyWithImpl(_$PeerToPeerLoadingImpl _value, + $Res Function(_$PeerToPeerLoadingImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$PeerToPeerLoadingImpl + with DiagnosticableTreeMixin + implements PeerToPeerLoading { + const _$PeerToPeerLoadingImpl(); + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.loading()'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('type', 'PeerToPeerState.loading')); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$PeerToPeerLoadingImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress) receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return loading(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress)? receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return loading?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress)? receivingInProgress, + TResult Function()? dataReceived, + TResult Function(String error)? failedToReceive, + required TResult orElse(), + }) { + if (loading != null) { + return loading(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(PeerToPeerInitial value) initial, + required TResult Function(PeerToPeerLoading value) loading, + required TResult Function(TransferInProgress value) transferInProgress, + required TResult Function(CompletedDataTransfer value) + completedDataTransfer, + required TResult Function(FailedToTransfer value) failedToTransfer, + required TResult Function(ReceivingInProgress value) receivingInProgress, + required TResult Function(DataReceived value) dataReceived, + required TResult Function(FailedDataTransfer value) failedToReceive, + }) { + return loading(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(PeerToPeerInitial value)? initial, + TResult? Function(PeerToPeerLoading value)? loading, + TResult? Function(TransferInProgress value)? transferInProgress, + TResult? Function(CompletedDataTransfer value)? completedDataTransfer, + TResult? Function(FailedToTransfer value)? failedToTransfer, + TResult? Function(ReceivingInProgress value)? receivingInProgress, + TResult? Function(DataReceived value)? dataReceived, + TResult? Function(FailedDataTransfer value)? failedToReceive, + }) { + return loading?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(PeerToPeerInitial value)? initial, + TResult Function(PeerToPeerLoading value)? loading, + TResult Function(TransferInProgress value)? transferInProgress, + TResult Function(CompletedDataTransfer value)? completedDataTransfer, + TResult Function(FailedToTransfer value)? failedToTransfer, + TResult Function(ReceivingInProgress value)? receivingInProgress, + TResult Function(DataReceived value)? dataReceived, + TResult Function(FailedDataTransfer value)? failedToReceive, + required TResult orElse(), + }) { + if (loading != null) { + return loading(this); + } + return orElse(); + } +} + +abstract class PeerToPeerLoading implements PeerToPeerState { + const factory PeerToPeerLoading() = _$PeerToPeerLoadingImpl; +} + +/// @nodoc +abstract class _$$TransferInProgressImplCopyWith<$Res> { + factory _$$TransferInProgressImplCopyWith(_$TransferInProgressImpl value, + $Res Function(_$TransferInProgressImpl) then) = + __$$TransferInProgressImplCopyWithImpl<$Res>; + @useResult + $Res call({double progress}); +} + +/// @nodoc +class __$$TransferInProgressImplCopyWithImpl<$Res> + extends _$PeerToPeerStateCopyWithImpl<$Res, _$TransferInProgressImpl> + implements _$$TransferInProgressImplCopyWith<$Res> { + __$$TransferInProgressImplCopyWithImpl(_$TransferInProgressImpl _value, + $Res Function(_$TransferInProgressImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? progress = null, + }) { + return _then(_$TransferInProgressImpl( + progress: null == progress + ? _value.progress + : progress // ignore: cast_nullable_to_non_nullable + as double, + )); + } +} + +/// @nodoc + +class _$TransferInProgressImpl + with DiagnosticableTreeMixin + implements TransferInProgress { + const _$TransferInProgressImpl({required this.progress}); + + @override + final double progress; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.transferInProgress(progress: $progress)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PeerToPeerState.transferInProgress')) + ..add(DiagnosticsProperty('progress', progress)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$TransferInProgressImpl && + (identical(other.progress, progress) || + other.progress == progress)); + } + + @override + int get hashCode => Object.hash(runtimeType, progress); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$TransferInProgressImplCopyWith<_$TransferInProgressImpl> get copyWith => + __$$TransferInProgressImplCopyWithImpl<_$TransferInProgressImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress) receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return transferInProgress(progress); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress)? receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return transferInProgress?.call(progress); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress)? receivingInProgress, + TResult Function()? dataReceived, + TResult Function(String error)? failedToReceive, + required TResult orElse(), + }) { + if (transferInProgress != null) { + return transferInProgress(progress); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(PeerToPeerInitial value) initial, + required TResult Function(PeerToPeerLoading value) loading, + required TResult Function(TransferInProgress value) transferInProgress, + required TResult Function(CompletedDataTransfer value) + completedDataTransfer, + required TResult Function(FailedToTransfer value) failedToTransfer, + required TResult Function(ReceivingInProgress value) receivingInProgress, + required TResult Function(DataReceived value) dataReceived, + required TResult Function(FailedDataTransfer value) failedToReceive, + }) { + return transferInProgress(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(PeerToPeerInitial value)? initial, + TResult? Function(PeerToPeerLoading value)? loading, + TResult? Function(TransferInProgress value)? transferInProgress, + TResult? Function(CompletedDataTransfer value)? completedDataTransfer, + TResult? Function(FailedToTransfer value)? failedToTransfer, + TResult? Function(ReceivingInProgress value)? receivingInProgress, + TResult? Function(DataReceived value)? dataReceived, + TResult? Function(FailedDataTransfer value)? failedToReceive, + }) { + return transferInProgress?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(PeerToPeerInitial value)? initial, + TResult Function(PeerToPeerLoading value)? loading, + TResult Function(TransferInProgress value)? transferInProgress, + TResult Function(CompletedDataTransfer value)? completedDataTransfer, + TResult Function(FailedToTransfer value)? failedToTransfer, + TResult Function(ReceivingInProgress value)? receivingInProgress, + TResult Function(DataReceived value)? dataReceived, + TResult Function(FailedDataTransfer value)? failedToReceive, + required TResult orElse(), + }) { + if (transferInProgress != null) { + return transferInProgress(this); + } + return orElse(); + } +} + +abstract class TransferInProgress implements PeerToPeerState { + const factory TransferInProgress({required final double progress}) = + _$TransferInProgressImpl; + + double get progress; + @JsonKey(ignore: true) + _$$TransferInProgressImplCopyWith<_$TransferInProgressImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$CompletedDataTransferImplCopyWith<$Res> { + factory _$$CompletedDataTransferImplCopyWith( + _$CompletedDataTransferImpl value, + $Res Function(_$CompletedDataTransferImpl) then) = + __$$CompletedDataTransferImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$CompletedDataTransferImplCopyWithImpl<$Res> + extends _$PeerToPeerStateCopyWithImpl<$Res, _$CompletedDataTransferImpl> + implements _$$CompletedDataTransferImplCopyWith<$Res> { + __$$CompletedDataTransferImplCopyWithImpl(_$CompletedDataTransferImpl _value, + $Res Function(_$CompletedDataTransferImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$CompletedDataTransferImpl + with DiagnosticableTreeMixin + implements CompletedDataTransfer { + const _$CompletedDataTransferImpl(); + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.completedDataTransfer()'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add( + DiagnosticsProperty('type', 'PeerToPeerState.completedDataTransfer')); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CompletedDataTransferImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress) receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return completedDataTransfer(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress)? receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return completedDataTransfer?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress)? receivingInProgress, + TResult Function()? dataReceived, + TResult Function(String error)? failedToReceive, + required TResult orElse(), + }) { + if (completedDataTransfer != null) { + return completedDataTransfer(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(PeerToPeerInitial value) initial, + required TResult Function(PeerToPeerLoading value) loading, + required TResult Function(TransferInProgress value) transferInProgress, + required TResult Function(CompletedDataTransfer value) + completedDataTransfer, + required TResult Function(FailedToTransfer value) failedToTransfer, + required TResult Function(ReceivingInProgress value) receivingInProgress, + required TResult Function(DataReceived value) dataReceived, + required TResult Function(FailedDataTransfer value) failedToReceive, + }) { + return completedDataTransfer(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(PeerToPeerInitial value)? initial, + TResult? Function(PeerToPeerLoading value)? loading, + TResult? Function(TransferInProgress value)? transferInProgress, + TResult? Function(CompletedDataTransfer value)? completedDataTransfer, + TResult? Function(FailedToTransfer value)? failedToTransfer, + TResult? Function(ReceivingInProgress value)? receivingInProgress, + TResult? Function(DataReceived value)? dataReceived, + TResult? Function(FailedDataTransfer value)? failedToReceive, + }) { + return completedDataTransfer?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(PeerToPeerInitial value)? initial, + TResult Function(PeerToPeerLoading value)? loading, + TResult Function(TransferInProgress value)? transferInProgress, + TResult Function(CompletedDataTransfer value)? completedDataTransfer, + TResult Function(FailedToTransfer value)? failedToTransfer, + TResult Function(ReceivingInProgress value)? receivingInProgress, + TResult Function(DataReceived value)? dataReceived, + TResult Function(FailedDataTransfer value)? failedToReceive, + required TResult orElse(), + }) { + if (completedDataTransfer != null) { + return completedDataTransfer(this); + } + return orElse(); + } +} + +abstract class CompletedDataTransfer implements PeerToPeerState { + const factory CompletedDataTransfer() = _$CompletedDataTransferImpl; +} + +/// @nodoc +abstract class _$$FailedToTransferImplCopyWith<$Res> { + factory _$$FailedToTransferImplCopyWith(_$FailedToTransferImpl value, + $Res Function(_$FailedToTransferImpl) then) = + __$$FailedToTransferImplCopyWithImpl<$Res>; + @useResult + $Res call({String error}); +} + +/// @nodoc +class __$$FailedToTransferImplCopyWithImpl<$Res> + extends _$PeerToPeerStateCopyWithImpl<$Res, _$FailedToTransferImpl> + implements _$$FailedToTransferImplCopyWith<$Res> { + __$$FailedToTransferImplCopyWithImpl(_$FailedToTransferImpl _value, + $Res Function(_$FailedToTransferImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? error = null, + }) { + return _then(_$FailedToTransferImpl( + error: null == error + ? _value.error + : error // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$FailedToTransferImpl + with DiagnosticableTreeMixin + implements FailedToTransfer { + const _$FailedToTransferImpl({required this.error}); + + @override + final String error; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.failedToTransfer(error: $error)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PeerToPeerState.failedToTransfer')) + ..add(DiagnosticsProperty('error', error)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FailedToTransferImpl && + (identical(other.error, error) || other.error == error)); + } + + @override + int get hashCode => Object.hash(runtimeType, error); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$FailedToTransferImplCopyWith<_$FailedToTransferImpl> get copyWith => + __$$FailedToTransferImplCopyWithImpl<_$FailedToTransferImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress) receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return failedToTransfer(error); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress)? receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return failedToTransfer?.call(error); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress)? receivingInProgress, + TResult Function()? dataReceived, + TResult Function(String error)? failedToReceive, + required TResult orElse(), + }) { + if (failedToTransfer != null) { + return failedToTransfer(error); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(PeerToPeerInitial value) initial, + required TResult Function(PeerToPeerLoading value) loading, + required TResult Function(TransferInProgress value) transferInProgress, + required TResult Function(CompletedDataTransfer value) + completedDataTransfer, + required TResult Function(FailedToTransfer value) failedToTransfer, + required TResult Function(ReceivingInProgress value) receivingInProgress, + required TResult Function(DataReceived value) dataReceived, + required TResult Function(FailedDataTransfer value) failedToReceive, + }) { + return failedToTransfer(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(PeerToPeerInitial value)? initial, + TResult? Function(PeerToPeerLoading value)? loading, + TResult? Function(TransferInProgress value)? transferInProgress, + TResult? Function(CompletedDataTransfer value)? completedDataTransfer, + TResult? Function(FailedToTransfer value)? failedToTransfer, + TResult? Function(ReceivingInProgress value)? receivingInProgress, + TResult? Function(DataReceived value)? dataReceived, + TResult? Function(FailedDataTransfer value)? failedToReceive, + }) { + return failedToTransfer?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(PeerToPeerInitial value)? initial, + TResult Function(PeerToPeerLoading value)? loading, + TResult Function(TransferInProgress value)? transferInProgress, + TResult Function(CompletedDataTransfer value)? completedDataTransfer, + TResult Function(FailedToTransfer value)? failedToTransfer, + TResult Function(ReceivingInProgress value)? receivingInProgress, + TResult Function(DataReceived value)? dataReceived, + TResult Function(FailedDataTransfer value)? failedToReceive, + required TResult orElse(), + }) { + if (failedToTransfer != null) { + return failedToTransfer(this); + } + return orElse(); + } +} + +abstract class FailedToTransfer implements PeerToPeerState { + const factory FailedToTransfer({required final String error}) = + _$FailedToTransferImpl; + + String get error; + @JsonKey(ignore: true) + _$$FailedToTransferImplCopyWith<_$FailedToTransferImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ReceivingInProgressImplCopyWith<$Res> { + factory _$$ReceivingInProgressImplCopyWith(_$ReceivingInProgressImpl value, + $Res Function(_$ReceivingInProgressImpl) then) = + __$$ReceivingInProgressImplCopyWithImpl<$Res>; + @useResult + $Res call({double progress}); +} + +/// @nodoc +class __$$ReceivingInProgressImplCopyWithImpl<$Res> + extends _$PeerToPeerStateCopyWithImpl<$Res, _$ReceivingInProgressImpl> + implements _$$ReceivingInProgressImplCopyWith<$Res> { + __$$ReceivingInProgressImplCopyWithImpl(_$ReceivingInProgressImpl _value, + $Res Function(_$ReceivingInProgressImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? progress = null, + }) { + return _then(_$ReceivingInProgressImpl( + progress: null == progress + ? _value.progress + : progress // ignore: cast_nullable_to_non_nullable + as double, + )); + } +} + +/// @nodoc + +class _$ReceivingInProgressImpl + with DiagnosticableTreeMixin + implements ReceivingInProgress { + const _$ReceivingInProgressImpl({required this.progress}); + + @override + final double progress; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.receivingInProgress(progress: $progress)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PeerToPeerState.receivingInProgress')) + ..add(DiagnosticsProperty('progress', progress)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ReceivingInProgressImpl && + (identical(other.progress, progress) || + other.progress == progress)); + } + + @override + int get hashCode => Object.hash(runtimeType, progress); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ReceivingInProgressImplCopyWith<_$ReceivingInProgressImpl> get copyWith => + __$$ReceivingInProgressImplCopyWithImpl<_$ReceivingInProgressImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress) receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return receivingInProgress(progress); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress)? receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return receivingInProgress?.call(progress); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress)? receivingInProgress, + TResult Function()? dataReceived, + TResult Function(String error)? failedToReceive, + required TResult orElse(), + }) { + if (receivingInProgress != null) { + return receivingInProgress(progress); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(PeerToPeerInitial value) initial, + required TResult Function(PeerToPeerLoading value) loading, + required TResult Function(TransferInProgress value) transferInProgress, + required TResult Function(CompletedDataTransfer value) + completedDataTransfer, + required TResult Function(FailedToTransfer value) failedToTransfer, + required TResult Function(ReceivingInProgress value) receivingInProgress, + required TResult Function(DataReceived value) dataReceived, + required TResult Function(FailedDataTransfer value) failedToReceive, + }) { + return receivingInProgress(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(PeerToPeerInitial value)? initial, + TResult? Function(PeerToPeerLoading value)? loading, + TResult? Function(TransferInProgress value)? transferInProgress, + TResult? Function(CompletedDataTransfer value)? completedDataTransfer, + TResult? Function(FailedToTransfer value)? failedToTransfer, + TResult? Function(ReceivingInProgress value)? receivingInProgress, + TResult? Function(DataReceived value)? dataReceived, + TResult? Function(FailedDataTransfer value)? failedToReceive, + }) { + return receivingInProgress?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(PeerToPeerInitial value)? initial, + TResult Function(PeerToPeerLoading value)? loading, + TResult Function(TransferInProgress value)? transferInProgress, + TResult Function(CompletedDataTransfer value)? completedDataTransfer, + TResult Function(FailedToTransfer value)? failedToTransfer, + TResult Function(ReceivingInProgress value)? receivingInProgress, + TResult Function(DataReceived value)? dataReceived, + TResult Function(FailedDataTransfer value)? failedToReceive, + required TResult orElse(), + }) { + if (receivingInProgress != null) { + return receivingInProgress(this); + } + return orElse(); + } +} + +abstract class ReceivingInProgress implements PeerToPeerState { + const factory ReceivingInProgress({required final double progress}) = + _$ReceivingInProgressImpl; + + double get progress; + @JsonKey(ignore: true) + _$$ReceivingInProgressImplCopyWith<_$ReceivingInProgressImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$DataReceivedImplCopyWith<$Res> { + factory _$$DataReceivedImplCopyWith( + _$DataReceivedImpl value, $Res Function(_$DataReceivedImpl) then) = + __$$DataReceivedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$DataReceivedImplCopyWithImpl<$Res> + extends _$PeerToPeerStateCopyWithImpl<$Res, _$DataReceivedImpl> + implements _$$DataReceivedImplCopyWith<$Res> { + __$$DataReceivedImplCopyWithImpl( + _$DataReceivedImpl _value, $Res Function(_$DataReceivedImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$DataReceivedImpl with DiagnosticableTreeMixin implements DataReceived { + const _$DataReceivedImpl(); + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.dataReceived()'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('type', 'PeerToPeerState.dataReceived')); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$DataReceivedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress) receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return dataReceived(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress)? receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return dataReceived?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress)? receivingInProgress, + TResult Function()? dataReceived, + TResult Function(String error)? failedToReceive, + required TResult orElse(), + }) { + if (dataReceived != null) { + return dataReceived(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(PeerToPeerInitial value) initial, + required TResult Function(PeerToPeerLoading value) loading, + required TResult Function(TransferInProgress value) transferInProgress, + required TResult Function(CompletedDataTransfer value) + completedDataTransfer, + required TResult Function(FailedToTransfer value) failedToTransfer, + required TResult Function(ReceivingInProgress value) receivingInProgress, + required TResult Function(DataReceived value) dataReceived, + required TResult Function(FailedDataTransfer value) failedToReceive, + }) { + return dataReceived(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(PeerToPeerInitial value)? initial, + TResult? Function(PeerToPeerLoading value)? loading, + TResult? Function(TransferInProgress value)? transferInProgress, + TResult? Function(CompletedDataTransfer value)? completedDataTransfer, + TResult? Function(FailedToTransfer value)? failedToTransfer, + TResult? Function(ReceivingInProgress value)? receivingInProgress, + TResult? Function(DataReceived value)? dataReceived, + TResult? Function(FailedDataTransfer value)? failedToReceive, + }) { + return dataReceived?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(PeerToPeerInitial value)? initial, + TResult Function(PeerToPeerLoading value)? loading, + TResult Function(TransferInProgress value)? transferInProgress, + TResult Function(CompletedDataTransfer value)? completedDataTransfer, + TResult Function(FailedToTransfer value)? failedToTransfer, + TResult Function(ReceivingInProgress value)? receivingInProgress, + TResult Function(DataReceived value)? dataReceived, + TResult Function(FailedDataTransfer value)? failedToReceive, + required TResult orElse(), + }) { + if (dataReceived != null) { + return dataReceived(this); + } + return orElse(); + } +} + +abstract class DataReceived implements PeerToPeerState { + const factory DataReceived() = _$DataReceivedImpl; +} + +/// @nodoc +abstract class _$$FailedDataTransferImplCopyWith<$Res> { + factory _$$FailedDataTransferImplCopyWith(_$FailedDataTransferImpl value, + $Res Function(_$FailedDataTransferImpl) then) = + __$$FailedDataTransferImplCopyWithImpl<$Res>; + @useResult + $Res call({String error}); +} + +/// @nodoc +class __$$FailedDataTransferImplCopyWithImpl<$Res> + extends _$PeerToPeerStateCopyWithImpl<$Res, _$FailedDataTransferImpl> + implements _$$FailedDataTransferImplCopyWith<$Res> { + __$$FailedDataTransferImplCopyWithImpl(_$FailedDataTransferImpl _value, + $Res Function(_$FailedDataTransferImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? error = null, + }) { + return _then(_$FailedDataTransferImpl( + error: null == error + ? _value.error + : error // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$FailedDataTransferImpl + with DiagnosticableTreeMixin + implements FailedDataTransfer { + const _$FailedDataTransferImpl({required this.error}); + + @override + final String error; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.failedToReceive(error: $error)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PeerToPeerState.failedToReceive')) + ..add(DiagnosticsProperty('error', error)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FailedDataTransferImpl && + (identical(other.error, error) || other.error == error)); + } + + @override + int get hashCode => Object.hash(runtimeType, error); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$FailedDataTransferImplCopyWith<_$FailedDataTransferImpl> get copyWith => + __$$FailedDataTransferImplCopyWithImpl<_$FailedDataTransferImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(double progress) transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress) receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return failedToReceive(error); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress)? transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress)? receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return failedToReceive?.call(error); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress)? transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress)? receivingInProgress, + TResult Function()? dataReceived, + TResult Function(String error)? failedToReceive, + required TResult orElse(), + }) { + if (failedToReceive != null) { + return failedToReceive(error); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(PeerToPeerInitial value) initial, + required TResult Function(PeerToPeerLoading value) loading, + required TResult Function(TransferInProgress value) transferInProgress, + required TResult Function(CompletedDataTransfer value) + completedDataTransfer, + required TResult Function(FailedToTransfer value) failedToTransfer, + required TResult Function(ReceivingInProgress value) receivingInProgress, + required TResult Function(DataReceived value) dataReceived, + required TResult Function(FailedDataTransfer value) failedToReceive, + }) { + return failedToReceive(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(PeerToPeerInitial value)? initial, + TResult? Function(PeerToPeerLoading value)? loading, + TResult? Function(TransferInProgress value)? transferInProgress, + TResult? Function(CompletedDataTransfer value)? completedDataTransfer, + TResult? Function(FailedToTransfer value)? failedToTransfer, + TResult? Function(ReceivingInProgress value)? receivingInProgress, + TResult? Function(DataReceived value)? dataReceived, + TResult? Function(FailedDataTransfer value)? failedToReceive, + }) { + return failedToReceive?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(PeerToPeerInitial value)? initial, + TResult Function(PeerToPeerLoading value)? loading, + TResult Function(TransferInProgress value)? transferInProgress, + TResult Function(CompletedDataTransfer value)? completedDataTransfer, + TResult Function(FailedToTransfer value)? failedToTransfer, + TResult Function(ReceivingInProgress value)? receivingInProgress, + TResult Function(DataReceived value)? dataReceived, + TResult Function(FailedDataTransfer value)? failedToReceive, + required TResult orElse(), + }) { + if (failedToReceive != null) { + return failedToReceive(this); + } + return orElse(); + } +} + +abstract class FailedDataTransfer implements PeerToPeerState { + const factory FailedDataTransfer({required final String error}) = + _$FailedDataTransferImpl; + + String get error; + @JsonKey(ignore: true) + _$$FailedDataTransferImplCopyWith<_$FailedDataTransferImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.dart deleted file mode 100644 index 1b886ef94e..0000000000 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.dart +++ /dev/null @@ -1,90 +0,0 @@ -// GENERATED using mason_cli -import 'dart:async'; -import 'dart:convert'; - -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; - -part 'send_data.freezed.dart'; - -typedef DeviceConnectionEmitter = Emitter; - -class DeviceConnectionBloc - extends Bloc { - final NearbyService nearbyService; - final Device connectedDevice; - - DeviceConnectionBloc({ - required this.nearbyService, - required this.connectedDevice, - }) : super(const DeviceConnectionInitial()) { - on(_handleSendEntities); - } - - FutureOr _handleSendEntities( - SendEntitiesEvent event, - DeviceConnectionEmitter emit, - ) async { - try { - emit(const DeviceConnectionState.sending(progress: 0)); - - for (var entityName in event.entities.keys) { - List entityData = event.entities[entityName]!; - int totalSize = entityData.length; - int offset = 0; - - while (offset < totalSize) { - // Calculate the chunk - const int chunkSize = 100; - int end = - (offset + chunkSize < totalSize) ? offset + chunkSize : totalSize; - List chunk = entityData.sublist(offset, end); - - // Send the chunk - await nearbyService.sendMessage( - connectedDevice.deviceId, - jsonEncode({ - "entityType": entityName, - "message": chunk, - "offset": offset + chunk.length, - "totalData": totalSize, - }), - ); - - // Update progress - final progress = (offset + chunk.length) / totalSize; - emit(DeviceConnectionState.sending(progress: progress)); - offset = end; - } - } - - // Notify completion - emit(const DeviceConnectionState.completed()); - } catch (e) { - emit(DeviceConnectionState.failed(error: e.toString())); - } - } -} - -@freezed -class DeviceConnectionEvent with _$DeviceConnectionEvent { - const factory DeviceConnectionEvent.sendEntities( - Map entities, - ) = SendEntitiesEvent; -} - -@freezed -class DeviceConnectionState with _$DeviceConnectionState { - const factory DeviceConnectionState.initial() = DeviceConnectionInitial; - - const factory DeviceConnectionState.loading() = DeviceConnectionLoading; - - const factory DeviceConnectionState.sending({required double progress}) = - DeviceConnectionSending; - - const factory DeviceConnectionState.completed() = DeviceConnectionCompleted; - - const factory DeviceConnectionState.failed({required String error}) = - DeviceConnectionFailed; -} diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.freezed.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.freezed.dart deleted file mode 100644 index 93ba4284f0..0000000000 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/send_data.freezed.dart +++ /dev/null @@ -1,994 +0,0 @@ -// coverage:ignore-file -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'send_data.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -T _$identity(T value) => value; - -final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); - -/// @nodoc -mixin _$DeviceConnectionEvent { - Map get entities => throw _privateConstructorUsedError; - @optionalTypeArgs - TResult when({ - required TResult Function(Map entities) sendEntities, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult? whenOrNull({ - TResult? Function(Map entities)? sendEntities, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult maybeWhen({ - TResult Function(Map entities)? sendEntities, - required TResult orElse(), - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult map({ - required TResult Function(SendEntitiesEvent value) sendEntities, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult? mapOrNull({ - TResult? Function(SendEntitiesEvent value)? sendEntities, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult maybeMap({ - TResult Function(SendEntitiesEvent value)? sendEntities, - required TResult orElse(), - }) => - throw _privateConstructorUsedError; - - @JsonKey(ignore: true) - $DeviceConnectionEventCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $DeviceConnectionEventCopyWith<$Res> { - factory $DeviceConnectionEventCopyWith(DeviceConnectionEvent value, - $Res Function(DeviceConnectionEvent) then) = - _$DeviceConnectionEventCopyWithImpl<$Res, DeviceConnectionEvent>; - @useResult - $Res call({Map entities}); -} - -/// @nodoc -class _$DeviceConnectionEventCopyWithImpl<$Res, - $Val extends DeviceConnectionEvent> - implements $DeviceConnectionEventCopyWith<$Res> { - _$DeviceConnectionEventCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? entities = null, - }) { - return _then(_value.copyWith( - entities: null == entities - ? _value.entities - : entities // ignore: cast_nullable_to_non_nullable - as Map, - ) as $Val); - } -} - -/// @nodoc -abstract class _$$SendEntitiesEventImplCopyWith<$Res> - implements $DeviceConnectionEventCopyWith<$Res> { - factory _$$SendEntitiesEventImplCopyWith(_$SendEntitiesEventImpl value, - $Res Function(_$SendEntitiesEventImpl) then) = - __$$SendEntitiesEventImplCopyWithImpl<$Res>; - @override - @useResult - $Res call({Map entities}); -} - -/// @nodoc -class __$$SendEntitiesEventImplCopyWithImpl<$Res> - extends _$DeviceConnectionEventCopyWithImpl<$Res, _$SendEntitiesEventImpl> - implements _$$SendEntitiesEventImplCopyWith<$Res> { - __$$SendEntitiesEventImplCopyWithImpl(_$SendEntitiesEventImpl _value, - $Res Function(_$SendEntitiesEventImpl) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? entities = null, - }) { - return _then(_$SendEntitiesEventImpl( - null == entities - ? _value._entities - : entities // ignore: cast_nullable_to_non_nullable - as Map, - )); - } -} - -/// @nodoc - -class _$SendEntitiesEventImpl implements SendEntitiesEvent { - const _$SendEntitiesEventImpl(final Map entities) - : _entities = entities; - - final Map _entities; - @override - Map get entities { - if (_entities is EqualUnmodifiableMapView) return _entities; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_entities); - } - - @override - String toString() { - return 'DeviceConnectionEvent.sendEntities(entities: $entities)'; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$SendEntitiesEventImpl && - const DeepCollectionEquality().equals(other._entities, _entities)); - } - - @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(_entities)); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$SendEntitiesEventImplCopyWith<_$SendEntitiesEventImpl> get copyWith => - __$$SendEntitiesEventImplCopyWithImpl<_$SendEntitiesEventImpl>( - this, _$identity); - - @override - @optionalTypeArgs - TResult when({ - required TResult Function(Map entities) sendEntities, - }) { - return sendEntities(entities); - } - - @override - @optionalTypeArgs - TResult? whenOrNull({ - TResult? Function(Map entities)? sendEntities, - }) { - return sendEntities?.call(entities); - } - - @override - @optionalTypeArgs - TResult maybeWhen({ - TResult Function(Map entities)? sendEntities, - required TResult orElse(), - }) { - if (sendEntities != null) { - return sendEntities(entities); - } - return orElse(); - } - - @override - @optionalTypeArgs - TResult map({ - required TResult Function(SendEntitiesEvent value) sendEntities, - }) { - return sendEntities(this); - } - - @override - @optionalTypeArgs - TResult? mapOrNull({ - TResult? Function(SendEntitiesEvent value)? sendEntities, - }) { - return sendEntities?.call(this); - } - - @override - @optionalTypeArgs - TResult maybeMap({ - TResult Function(SendEntitiesEvent value)? sendEntities, - required TResult orElse(), - }) { - if (sendEntities != null) { - return sendEntities(this); - } - return orElse(); - } -} - -abstract class SendEntitiesEvent implements DeviceConnectionEvent { - const factory SendEntitiesEvent(final Map entities) = - _$SendEntitiesEventImpl; - - @override - Map get entities; - @override - @JsonKey(ignore: true) - _$$SendEntitiesEventImplCopyWith<_$SendEntitiesEventImpl> get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -mixin _$DeviceConnectionState { - @optionalTypeArgs - TResult when({ - required TResult Function() initial, - required TResult Function() loading, - required TResult Function(double progress) sending, - required TResult Function() completed, - required TResult Function(String error) failed, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult? whenOrNull({ - TResult? Function()? initial, - TResult? Function()? loading, - TResult? Function(double progress)? sending, - TResult? Function()? completed, - TResult? Function(String error)? failed, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult maybeWhen({ - TResult Function()? initial, - TResult Function()? loading, - TResult Function(double progress)? sending, - TResult Function()? completed, - TResult Function(String error)? failed, - required TResult orElse(), - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult map({ - required TResult Function(DeviceConnectionInitial value) initial, - required TResult Function(DeviceConnectionLoading value) loading, - required TResult Function(DeviceConnectionSending value) sending, - required TResult Function(DeviceConnectionCompleted value) completed, - required TResult Function(DeviceConnectionFailed value) failed, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult? mapOrNull({ - TResult? Function(DeviceConnectionInitial value)? initial, - TResult? Function(DeviceConnectionLoading value)? loading, - TResult? Function(DeviceConnectionSending value)? sending, - TResult? Function(DeviceConnectionCompleted value)? completed, - TResult? Function(DeviceConnectionFailed value)? failed, - }) => - throw _privateConstructorUsedError; - @optionalTypeArgs - TResult maybeMap({ - TResult Function(DeviceConnectionInitial value)? initial, - TResult Function(DeviceConnectionLoading value)? loading, - TResult Function(DeviceConnectionSending value)? sending, - TResult Function(DeviceConnectionCompleted value)? completed, - TResult Function(DeviceConnectionFailed value)? failed, - required TResult orElse(), - }) => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $DeviceConnectionStateCopyWith<$Res> { - factory $DeviceConnectionStateCopyWith(DeviceConnectionState value, - $Res Function(DeviceConnectionState) then) = - _$DeviceConnectionStateCopyWithImpl<$Res, DeviceConnectionState>; -} - -/// @nodoc -class _$DeviceConnectionStateCopyWithImpl<$Res, - $Val extends DeviceConnectionState> - implements $DeviceConnectionStateCopyWith<$Res> { - _$DeviceConnectionStateCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; -} - -/// @nodoc -abstract class _$$DeviceConnectionInitialImplCopyWith<$Res> { - factory _$$DeviceConnectionInitialImplCopyWith( - _$DeviceConnectionInitialImpl value, - $Res Function(_$DeviceConnectionInitialImpl) then) = - __$$DeviceConnectionInitialImplCopyWithImpl<$Res>; -} - -/// @nodoc -class __$$DeviceConnectionInitialImplCopyWithImpl<$Res> - extends _$DeviceConnectionStateCopyWithImpl<$Res, - _$DeviceConnectionInitialImpl> - implements _$$DeviceConnectionInitialImplCopyWith<$Res> { - __$$DeviceConnectionInitialImplCopyWithImpl( - _$DeviceConnectionInitialImpl _value, - $Res Function(_$DeviceConnectionInitialImpl) _then) - : super(_value, _then); -} - -/// @nodoc - -class _$DeviceConnectionInitialImpl implements DeviceConnectionInitial { - const _$DeviceConnectionInitialImpl(); - - @override - String toString() { - return 'DeviceConnectionState.initial()'; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$DeviceConnectionInitialImpl); - } - - @override - int get hashCode => runtimeType.hashCode; - - @override - @optionalTypeArgs - TResult when({ - required TResult Function() initial, - required TResult Function() loading, - required TResult Function(double progress) sending, - required TResult Function() completed, - required TResult Function(String error) failed, - }) { - return initial(); - } - - @override - @optionalTypeArgs - TResult? whenOrNull({ - TResult? Function()? initial, - TResult? Function()? loading, - TResult? Function(double progress)? sending, - TResult? Function()? completed, - TResult? Function(String error)? failed, - }) { - return initial?.call(); - } - - @override - @optionalTypeArgs - TResult maybeWhen({ - TResult Function()? initial, - TResult Function()? loading, - TResult Function(double progress)? sending, - TResult Function()? completed, - TResult Function(String error)? failed, - required TResult orElse(), - }) { - if (initial != null) { - return initial(); - } - return orElse(); - } - - @override - @optionalTypeArgs - TResult map({ - required TResult Function(DeviceConnectionInitial value) initial, - required TResult Function(DeviceConnectionLoading value) loading, - required TResult Function(DeviceConnectionSending value) sending, - required TResult Function(DeviceConnectionCompleted value) completed, - required TResult Function(DeviceConnectionFailed value) failed, - }) { - return initial(this); - } - - @override - @optionalTypeArgs - TResult? mapOrNull({ - TResult? Function(DeviceConnectionInitial value)? initial, - TResult? Function(DeviceConnectionLoading value)? loading, - TResult? Function(DeviceConnectionSending value)? sending, - TResult? Function(DeviceConnectionCompleted value)? completed, - TResult? Function(DeviceConnectionFailed value)? failed, - }) { - return initial?.call(this); - } - - @override - @optionalTypeArgs - TResult maybeMap({ - TResult Function(DeviceConnectionInitial value)? initial, - TResult Function(DeviceConnectionLoading value)? loading, - TResult Function(DeviceConnectionSending value)? sending, - TResult Function(DeviceConnectionCompleted value)? completed, - TResult Function(DeviceConnectionFailed value)? failed, - required TResult orElse(), - }) { - if (initial != null) { - return initial(this); - } - return orElse(); - } -} - -abstract class DeviceConnectionInitial implements DeviceConnectionState { - const factory DeviceConnectionInitial() = _$DeviceConnectionInitialImpl; -} - -/// @nodoc -abstract class _$$DeviceConnectionLoadingImplCopyWith<$Res> { - factory _$$DeviceConnectionLoadingImplCopyWith( - _$DeviceConnectionLoadingImpl value, - $Res Function(_$DeviceConnectionLoadingImpl) then) = - __$$DeviceConnectionLoadingImplCopyWithImpl<$Res>; -} - -/// @nodoc -class __$$DeviceConnectionLoadingImplCopyWithImpl<$Res> - extends _$DeviceConnectionStateCopyWithImpl<$Res, - _$DeviceConnectionLoadingImpl> - implements _$$DeviceConnectionLoadingImplCopyWith<$Res> { - __$$DeviceConnectionLoadingImplCopyWithImpl( - _$DeviceConnectionLoadingImpl _value, - $Res Function(_$DeviceConnectionLoadingImpl) _then) - : super(_value, _then); -} - -/// @nodoc - -class _$DeviceConnectionLoadingImpl implements DeviceConnectionLoading { - const _$DeviceConnectionLoadingImpl(); - - @override - String toString() { - return 'DeviceConnectionState.loading()'; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$DeviceConnectionLoadingImpl); - } - - @override - int get hashCode => runtimeType.hashCode; - - @override - @optionalTypeArgs - TResult when({ - required TResult Function() initial, - required TResult Function() loading, - required TResult Function(double progress) sending, - required TResult Function() completed, - required TResult Function(String error) failed, - }) { - return loading(); - } - - @override - @optionalTypeArgs - TResult? whenOrNull({ - TResult? Function()? initial, - TResult? Function()? loading, - TResult? Function(double progress)? sending, - TResult? Function()? completed, - TResult? Function(String error)? failed, - }) { - return loading?.call(); - } - - @override - @optionalTypeArgs - TResult maybeWhen({ - TResult Function()? initial, - TResult Function()? loading, - TResult Function(double progress)? sending, - TResult Function()? completed, - TResult Function(String error)? failed, - required TResult orElse(), - }) { - if (loading != null) { - return loading(); - } - return orElse(); - } - - @override - @optionalTypeArgs - TResult map({ - required TResult Function(DeviceConnectionInitial value) initial, - required TResult Function(DeviceConnectionLoading value) loading, - required TResult Function(DeviceConnectionSending value) sending, - required TResult Function(DeviceConnectionCompleted value) completed, - required TResult Function(DeviceConnectionFailed value) failed, - }) { - return loading(this); - } - - @override - @optionalTypeArgs - TResult? mapOrNull({ - TResult? Function(DeviceConnectionInitial value)? initial, - TResult? Function(DeviceConnectionLoading value)? loading, - TResult? Function(DeviceConnectionSending value)? sending, - TResult? Function(DeviceConnectionCompleted value)? completed, - TResult? Function(DeviceConnectionFailed value)? failed, - }) { - return loading?.call(this); - } - - @override - @optionalTypeArgs - TResult maybeMap({ - TResult Function(DeviceConnectionInitial value)? initial, - TResult Function(DeviceConnectionLoading value)? loading, - TResult Function(DeviceConnectionSending value)? sending, - TResult Function(DeviceConnectionCompleted value)? completed, - TResult Function(DeviceConnectionFailed value)? failed, - required TResult orElse(), - }) { - if (loading != null) { - return loading(this); - } - return orElse(); - } -} - -abstract class DeviceConnectionLoading implements DeviceConnectionState { - const factory DeviceConnectionLoading() = _$DeviceConnectionLoadingImpl; -} - -/// @nodoc -abstract class _$$DeviceConnectionSendingImplCopyWith<$Res> { - factory _$$DeviceConnectionSendingImplCopyWith( - _$DeviceConnectionSendingImpl value, - $Res Function(_$DeviceConnectionSendingImpl) then) = - __$$DeviceConnectionSendingImplCopyWithImpl<$Res>; - @useResult - $Res call({double progress}); -} - -/// @nodoc -class __$$DeviceConnectionSendingImplCopyWithImpl<$Res> - extends _$DeviceConnectionStateCopyWithImpl<$Res, - _$DeviceConnectionSendingImpl> - implements _$$DeviceConnectionSendingImplCopyWith<$Res> { - __$$DeviceConnectionSendingImplCopyWithImpl( - _$DeviceConnectionSendingImpl _value, - $Res Function(_$DeviceConnectionSendingImpl) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? progress = null, - }) { - return _then(_$DeviceConnectionSendingImpl( - progress: null == progress - ? _value.progress - : progress // ignore: cast_nullable_to_non_nullable - as double, - )); - } -} - -/// @nodoc - -class _$DeviceConnectionSendingImpl implements DeviceConnectionSending { - const _$DeviceConnectionSendingImpl({required this.progress}); - - @override - final double progress; - - @override - String toString() { - return 'DeviceConnectionState.sending(progress: $progress)'; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$DeviceConnectionSendingImpl && - (identical(other.progress, progress) || - other.progress == progress)); - } - - @override - int get hashCode => Object.hash(runtimeType, progress); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$DeviceConnectionSendingImplCopyWith<_$DeviceConnectionSendingImpl> - get copyWith => __$$DeviceConnectionSendingImplCopyWithImpl< - _$DeviceConnectionSendingImpl>(this, _$identity); - - @override - @optionalTypeArgs - TResult when({ - required TResult Function() initial, - required TResult Function() loading, - required TResult Function(double progress) sending, - required TResult Function() completed, - required TResult Function(String error) failed, - }) { - return sending(progress); - } - - @override - @optionalTypeArgs - TResult? whenOrNull({ - TResult? Function()? initial, - TResult? Function()? loading, - TResult? Function(double progress)? sending, - TResult? Function()? completed, - TResult? Function(String error)? failed, - }) { - return sending?.call(progress); - } - - @override - @optionalTypeArgs - TResult maybeWhen({ - TResult Function()? initial, - TResult Function()? loading, - TResult Function(double progress)? sending, - TResult Function()? completed, - TResult Function(String error)? failed, - required TResult orElse(), - }) { - if (sending != null) { - return sending(progress); - } - return orElse(); - } - - @override - @optionalTypeArgs - TResult map({ - required TResult Function(DeviceConnectionInitial value) initial, - required TResult Function(DeviceConnectionLoading value) loading, - required TResult Function(DeviceConnectionSending value) sending, - required TResult Function(DeviceConnectionCompleted value) completed, - required TResult Function(DeviceConnectionFailed value) failed, - }) { - return sending(this); - } - - @override - @optionalTypeArgs - TResult? mapOrNull({ - TResult? Function(DeviceConnectionInitial value)? initial, - TResult? Function(DeviceConnectionLoading value)? loading, - TResult? Function(DeviceConnectionSending value)? sending, - TResult? Function(DeviceConnectionCompleted value)? completed, - TResult? Function(DeviceConnectionFailed value)? failed, - }) { - return sending?.call(this); - } - - @override - @optionalTypeArgs - TResult maybeMap({ - TResult Function(DeviceConnectionInitial value)? initial, - TResult Function(DeviceConnectionLoading value)? loading, - TResult Function(DeviceConnectionSending value)? sending, - TResult Function(DeviceConnectionCompleted value)? completed, - TResult Function(DeviceConnectionFailed value)? failed, - required TResult orElse(), - }) { - if (sending != null) { - return sending(this); - } - return orElse(); - } -} - -abstract class DeviceConnectionSending implements DeviceConnectionState { - const factory DeviceConnectionSending({required final double progress}) = - _$DeviceConnectionSendingImpl; - - double get progress; - @JsonKey(ignore: true) - _$$DeviceConnectionSendingImplCopyWith<_$DeviceConnectionSendingImpl> - get copyWith => throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class _$$DeviceConnectionCompletedImplCopyWith<$Res> { - factory _$$DeviceConnectionCompletedImplCopyWith( - _$DeviceConnectionCompletedImpl value, - $Res Function(_$DeviceConnectionCompletedImpl) then) = - __$$DeviceConnectionCompletedImplCopyWithImpl<$Res>; -} - -/// @nodoc -class __$$DeviceConnectionCompletedImplCopyWithImpl<$Res> - extends _$DeviceConnectionStateCopyWithImpl<$Res, - _$DeviceConnectionCompletedImpl> - implements _$$DeviceConnectionCompletedImplCopyWith<$Res> { - __$$DeviceConnectionCompletedImplCopyWithImpl( - _$DeviceConnectionCompletedImpl _value, - $Res Function(_$DeviceConnectionCompletedImpl) _then) - : super(_value, _then); -} - -/// @nodoc - -class _$DeviceConnectionCompletedImpl implements DeviceConnectionCompleted { - const _$DeviceConnectionCompletedImpl(); - - @override - String toString() { - return 'DeviceConnectionState.completed()'; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$DeviceConnectionCompletedImpl); - } - - @override - int get hashCode => runtimeType.hashCode; - - @override - @optionalTypeArgs - TResult when({ - required TResult Function() initial, - required TResult Function() loading, - required TResult Function(double progress) sending, - required TResult Function() completed, - required TResult Function(String error) failed, - }) { - return completed(); - } - - @override - @optionalTypeArgs - TResult? whenOrNull({ - TResult? Function()? initial, - TResult? Function()? loading, - TResult? Function(double progress)? sending, - TResult? Function()? completed, - TResult? Function(String error)? failed, - }) { - return completed?.call(); - } - - @override - @optionalTypeArgs - TResult maybeWhen({ - TResult Function()? initial, - TResult Function()? loading, - TResult Function(double progress)? sending, - TResult Function()? completed, - TResult Function(String error)? failed, - required TResult orElse(), - }) { - if (completed != null) { - return completed(); - } - return orElse(); - } - - @override - @optionalTypeArgs - TResult map({ - required TResult Function(DeviceConnectionInitial value) initial, - required TResult Function(DeviceConnectionLoading value) loading, - required TResult Function(DeviceConnectionSending value) sending, - required TResult Function(DeviceConnectionCompleted value) completed, - required TResult Function(DeviceConnectionFailed value) failed, - }) { - return completed(this); - } - - @override - @optionalTypeArgs - TResult? mapOrNull({ - TResult? Function(DeviceConnectionInitial value)? initial, - TResult? Function(DeviceConnectionLoading value)? loading, - TResult? Function(DeviceConnectionSending value)? sending, - TResult? Function(DeviceConnectionCompleted value)? completed, - TResult? Function(DeviceConnectionFailed value)? failed, - }) { - return completed?.call(this); - } - - @override - @optionalTypeArgs - TResult maybeMap({ - TResult Function(DeviceConnectionInitial value)? initial, - TResult Function(DeviceConnectionLoading value)? loading, - TResult Function(DeviceConnectionSending value)? sending, - TResult Function(DeviceConnectionCompleted value)? completed, - TResult Function(DeviceConnectionFailed value)? failed, - required TResult orElse(), - }) { - if (completed != null) { - return completed(this); - } - return orElse(); - } -} - -abstract class DeviceConnectionCompleted implements DeviceConnectionState { - const factory DeviceConnectionCompleted() = _$DeviceConnectionCompletedImpl; -} - -/// @nodoc -abstract class _$$DeviceConnectionFailedImplCopyWith<$Res> { - factory _$$DeviceConnectionFailedImplCopyWith( - _$DeviceConnectionFailedImpl value, - $Res Function(_$DeviceConnectionFailedImpl) then) = - __$$DeviceConnectionFailedImplCopyWithImpl<$Res>; - @useResult - $Res call({String error}); -} - -/// @nodoc -class __$$DeviceConnectionFailedImplCopyWithImpl<$Res> - extends _$DeviceConnectionStateCopyWithImpl<$Res, - _$DeviceConnectionFailedImpl> - implements _$$DeviceConnectionFailedImplCopyWith<$Res> { - __$$DeviceConnectionFailedImplCopyWithImpl( - _$DeviceConnectionFailedImpl _value, - $Res Function(_$DeviceConnectionFailedImpl) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? error = null, - }) { - return _then(_$DeviceConnectionFailedImpl( - error: null == error - ? _value.error - : error // ignore: cast_nullable_to_non_nullable - as String, - )); - } -} - -/// @nodoc - -class _$DeviceConnectionFailedImpl implements DeviceConnectionFailed { - const _$DeviceConnectionFailedImpl({required this.error}); - - @override - final String error; - - @override - String toString() { - return 'DeviceConnectionState.failed(error: $error)'; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$DeviceConnectionFailedImpl && - (identical(other.error, error) || other.error == error)); - } - - @override - int get hashCode => Object.hash(runtimeType, error); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$DeviceConnectionFailedImplCopyWith<_$DeviceConnectionFailedImpl> - get copyWith => __$$DeviceConnectionFailedImplCopyWithImpl< - _$DeviceConnectionFailedImpl>(this, _$identity); - - @override - @optionalTypeArgs - TResult when({ - required TResult Function() initial, - required TResult Function() loading, - required TResult Function(double progress) sending, - required TResult Function() completed, - required TResult Function(String error) failed, - }) { - return failed(error); - } - - @override - @optionalTypeArgs - TResult? whenOrNull({ - TResult? Function()? initial, - TResult? Function()? loading, - TResult? Function(double progress)? sending, - TResult? Function()? completed, - TResult? Function(String error)? failed, - }) { - return failed?.call(error); - } - - @override - @optionalTypeArgs - TResult maybeWhen({ - TResult Function()? initial, - TResult Function()? loading, - TResult Function(double progress)? sending, - TResult Function()? completed, - TResult Function(String error)? failed, - required TResult orElse(), - }) { - if (failed != null) { - return failed(error); - } - return orElse(); - } - - @override - @optionalTypeArgs - TResult map({ - required TResult Function(DeviceConnectionInitial value) initial, - required TResult Function(DeviceConnectionLoading value) loading, - required TResult Function(DeviceConnectionSending value) sending, - required TResult Function(DeviceConnectionCompleted value) completed, - required TResult Function(DeviceConnectionFailed value) failed, - }) { - return failed(this); - } - - @override - @optionalTypeArgs - TResult? mapOrNull({ - TResult? Function(DeviceConnectionInitial value)? initial, - TResult? Function(DeviceConnectionLoading value)? loading, - TResult? Function(DeviceConnectionSending value)? sending, - TResult? Function(DeviceConnectionCompleted value)? completed, - TResult? Function(DeviceConnectionFailed value)? failed, - }) { - return failed?.call(this); - } - - @override - @optionalTypeArgs - TResult maybeMap({ - TResult Function(DeviceConnectionInitial value)? initial, - TResult Function(DeviceConnectionLoading value)? loading, - TResult Function(DeviceConnectionSending value)? sending, - TResult Function(DeviceConnectionCompleted value)? completed, - TResult Function(DeviceConnectionFailed value)? failed, - required TResult orElse(), - }) { - if (failed != null) { - return failed(this); - } - return orElse(); - } -} - -abstract class DeviceConnectionFailed implements DeviceConnectionState { - const factory DeviceConnectionFailed({required final String error}) = - _$DeviceConnectionFailedImpl; - - String get error; - @JsonKey(ignore: true) - _$$DeviceConnectionFailedImplCopyWith<_$DeviceConnectionFailedImpl> - get copyWith => throw _privateConstructorUsedError; -} diff --git a/apps/health_campaign_field_worker_app/lib/pages/home.dart b/apps/health_campaign_field_worker_app/lib/pages/home.dart index 33a0ad6830..0241e114e7 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/home.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/home.dart @@ -51,7 +51,6 @@ import '../widgets/home/home_item_card.dart'; import '../widgets/localized.dart'; import '../widgets/showcase/config/showcase_constants.dart'; import '../widgets/showcase/showcase_button.dart'; -import 'peer_to_peer/data_share_home.dart'; @RoutePage() class HomePage extends LocalizedStatefulWidget { @@ -498,8 +497,7 @@ class _HomePageState extends LocalizedState { icon: Icons.send, label: i18.home.dataShare, onPressed: () async { - Navigator.push(context, - MaterialPageRoute(builder: (_) => const DataShareHomePage())); + context.router.push(const DataShareHomeRoute()); }, ), ), diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart index 1eb86e78f8..4339cb5c35 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -1,16 +1,14 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:digit_data_model/data_model.dart'; +import 'package:auto_route/annotations.dart'; +import 'package:digit_ui_components/digit_components.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; -import 'package:registration_delivery/registration_delivery.dart'; +import '../../blocs/peer_to_peer/peer_to_peer.dart'; import '../../utils/i18_key_constants.dart' as i18; -import '../../utils/utils.dart'; import '../../widgets/localized.dart'; +@RoutePage() class DataReceiverPage extends LocalizedStatefulWidget { final Device connectedDevice; final NearbyService nearbyService; @@ -23,107 +21,26 @@ class DataReceiverPage extends LocalizedStatefulWidget { class _DataReceiverPageState extends LocalizedState { late NearbyService nearbyService; - List receivedData = []; - double progress = 0.0; - int receivedBytes = 0; - int totalBytes = 0; - late StreamSubscription receivedDataSubscription; + late PeerToPeerBloc peerToPeerBloc; @override void initState() { super.initState(); nearbyService = widget.nearbyService; - initReceiver(); + peerToPeerBloc = context.read(); + nearbyService.dataReceivedSubscription(callback: (data) { + peerToPeerBloc.add( + DataReceiverEvent(nearbyService: widget.nearbyService, data: data)); + }); } @override void dispose() { nearbyService.stopAdvertisingPeer(); nearbyService.stopBrowsingForPeers(); - receivedDataSubscription.cancel(); super.dispose(); } - Future initReceiver() async { - nearbyService.stateChangedSubscription(callback: (state) { - debugPrint("Nearby state changed: $state"); - }); - - receivedDataSubscription = - nearbyService.dataReceivedSubscription(callback: (data) { - try { - var receivedJson = jsonDecode(data["message"]); - String entityType = receivedJson["entityType"]; - int offset = receivedJson["offset"]; - int totalData = receivedJson["totalData"]; - List receivedChunk = receivedJson["message"]; - - // Update progress - setState(() { - receivedBytes = offset; - progress = receivedBytes / totalData; - receivedData.addAll(receivedChunk); - }); - - // When data for this entity is fully received - if (receivedBytes >= totalData) { - // Save the received entity data - LocalRepository repository = _getRepositoryForEntity(entityType); - final entityList = - receivedData.whereType>().toList(); - createDbRecords(repository, entityList, entityType); - - debugPrint("$entityType data saved successfully."); - - // Clear the received data buffer for the next entity - receivedData.clear(); - - // Send confirmation back to the sender - nearbyService.sendMessage( - data["senderDeviceId"], - jsonEncode({ - "type": "confirmation", - "entityType": entityType, - "status": "success", - "message": "$entityType saved successfully." - }), - ); - } - } catch (e) { - debugPrint("Error processing received data: $e"); - } - }); - } - - LocalRepository _getRepositoryForEntity(String entityType) { - switch (entityType) { - case 'Individuals': - return context - .read>(); - case 'Households': - return context - .read>(); - case 'HouseholdMembers': - return context.read< - LocalRepository>(); - case 'ProjectBeneficiaries': - return context.read< - LocalRepository>(); - case 'SideEffects': - return context - .read>(); - case 'Tasks': - return context.read>(); - case 'Referrals': - return context - .read>(); - default: - throw Exception("Unknown entity type: $entityType"); - } - } - @override Widget build(BuildContext context) { return PopScope( @@ -138,21 +55,34 @@ class _DataReceiverPageState extends LocalizedState { title: Text( "${localizations.translate(i18.dataShare.connectedTo)} ${widget.connectedDevice.deviceName}"), ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Text( - "Receiving data from the connected device...", - style: TextStyle(fontSize: 18), - ), - LinearProgressIndicator(value: progress), - const SizedBox(height: 10), - Text("${(progress * 100).toStringAsFixed(1)}%"), - const SizedBox(height: 30), - ], - ), + body: BlocBuilder( + builder: (context, state) { + return state.maybeWhen( + orElse: () => const Center(child: CircularProgressIndicator()), + receivingInProgress: (progress) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * 0.2, + width: MediaQuery.of(context).size.height * 0.2, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + DigitTheme + .instance.colors.light.alertSuccess), + backgroundColor: + DigitTheme.instance.colors.light.textDisabled, + value: progress), + ), + const SizedBox(height: 16), + Text('${(progress * 100).toInt()} / 100') + ], + ), + ); + }); + }, ), ), ); diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart index 98e82f4fce..753e07ed06 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart @@ -1,9 +1,13 @@ +import 'package:attendance_management/widgets/back_navigation_help_header.dart'; import 'package:attendance_management/widgets/localized.dart'; -import 'package:auto_route/annotations.dart'; -import 'package:digit_components/digit_components.dart'; +import 'package:digit_ui_components/digit_components.dart'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; import 'package:flutter/material.dart'; +import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; +import '../../widgets/showcase/showcase_wrappers.dart'; import 'devices_list.dart'; @RoutePage() @@ -17,42 +21,71 @@ class DataShareHomePage extends LocalizedStatefulWidget { class _DataShareHomeState extends LocalizedState { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + return ScrollableContent( + header: const BackNavigationHelpHeaderWidget( + showHelp: true, + ), children: [ + Padding( + padding: const EdgeInsets.all(kPadding), + child: Align( + alignment: Alignment.topLeft, + child: Text( + localizations.translate(i18.dataShare.sendAction), + style: textTheme.headingM, + ), + ), + ), SizedBox( width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height * 0.3, + height: MediaQuery.of(context).size.height * 0.2, child: DigitCard( - child: Center( - child: DigitElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => const DevicesListPage( - deviceType: DeviceType.sender))); - }, - child: Text( - localizations.translate(i18.dataShare.sendAction)))), - ), + margin: const EdgeInsets.all(kPadding * 2), + onPressed: () { + context.router + .push(DevicesListRoute(deviceType: DeviceType.sender)); + }, + children: [ + Center( + child: Icon(Icons.upload, + size: 20, + color: DigitTheme.instance.colors.light.primary1), + ), + Center( + child: Text( + localizations.translate(i18.dataShare.sendAction), + style: TextStyle( + color: DigitTheme.instance.colors.light.primary1), + ), + ) + ]), ), SizedBox( width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height * 0.3, + height: MediaQuery.of(context).size.height * 0.2, child: DigitCard( - margin: const EdgeInsets.all(kPadding), - child: Center( - child: DigitElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => const DevicesListPage( - deviceType: DeviceType.receiver))); - }, - child: Text( - localizations.translate(i18.dataShare.receiveAction)))), - ), + margin: const EdgeInsets.all(kPadding * 2), + onPressed: () { + context.router + .push(DevicesListRoute(deviceType: DeviceType.receiver)); + }, + children: [ + Center( + child: Icon(Icons.download, + size: 20, + color: DigitTheme.instance.colors.light.primary1), + ), + Center( + child: Text( + localizations.translate(i18.dataShare.receiveAction), + style: TextStyle( + color: DigitTheme.instance.colors.light.primary1), + ), + ) + ]), ) ], ); diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart index 2ef2322e67..28501da5dc 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -1,18 +1,20 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - +import 'package:attendance_management/widgets/back_navigation_help_header.dart'; import 'package:auto_route/annotations.dart'; +import 'package:digit_ui_components/digit_components.dart'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; -import 'package:path_provider/path_provider.dart'; +import '../../blocs/peer_to_peer/peer_to_peer.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../widgets/localized.dart'; +import '../../widgets/showcase/showcase_wrappers.dart'; @RoutePage() class DataTransferPage extends LocalizedStatefulWidget { - final Device connectedDevice; + final List connectedDevice; final NearbyService nearbyService; const DataTransferPage( @@ -24,12 +26,14 @@ class DataTransferPage extends LocalizedStatefulWidget { class _DataTransferScreenState extends LocalizedState { late NearbyService nearbyService; - double progress = 0.0; // To track progress - + late PeerToPeerBloc peerToPeerBloc; @override void initState() { super.initState(); nearbyService = widget.nearbyService; + peerToPeerBloc = context.read(); + peerToPeerBloc.add(DataTransferEvent( + connectedDevice: widget.connectedDevice, nearbyService: nearbyService)); } @override @@ -37,152 +41,133 @@ class _DataTransferScreenState extends LocalizedState { super.dispose(); } - void sendEntities(Map entities) async { - for (var entityName in entities.keys) { - List entityData = entities[entityName]!; - int totalSize = entityData.length; - int offset = 0; - - try { - while (offset < totalSize) { - const int chunkSize = 100; - int end = - (offset + chunkSize < totalSize) ? offset + chunkSize : totalSize; - List chunk = entityData.sublist(offset, end); - - // Send the chunk - widget.nearbyService.sendMessage( - widget.connectedDevice.deviceId, - jsonEncode({ - "entityType": entityName, - "message": chunk, - "offset": offset + chunk.length, - "totalData": totalSize, - }), - ); - - // Update progress for the entity - setState(() { - progress = (offset + chunk.length) / totalSize; - }); - - // Simulate delay for smoother UX - await Future.delayed(const Duration(milliseconds: 200)); - offset = end; - } - - // Wait for receiver's confirmation for the current entity - await waitForConfirmation(entityName); - } catch (e) { - debugPrint('Error sending $entityName: $e'); - } - } - - // Notify completion - if (mounted) { - setState(() { - progress = 1.0; - }); - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text("Transfer Complete"), - content: const Text("All entities have been sent successfully."), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: const Text("OK"), - ), - ], - ), - ); - } - } - - Future waitForConfirmation(String entityName) async { - final completer = Completer(); - - final subscription = - nearbyService.dataReceivedSubscription(callback: (data) { - try { - var receivedJson = jsonDecode(data["message"]); - if (receivedJson["type"] == "confirmation" && - receivedJson["entityType"] == entityName && - receivedJson["status"] == "success") { - debugPrint("Confirmation received for $entityName"); - completer.complete(); - } - } catch (e) { - debugPrint("Error processing confirmation: $e"); - } - }); - - Future.delayed(const Duration(seconds: 10), () { - if (!completer.isCompleted) { - completer - .completeError("Timeout waiting for confirmation for $entityName"); - } - }); - - await completer.future; - subscription.cancel(); - } - @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + return PopScope( - onPopInvoked: (pop) { - if (pop) { - widget.nearbyService - .disconnectPeer(deviceID: widget.connectedDevice.deviceId); - } - }, - child: Scaffold( - appBar: AppBar( - title: Text( - "${localizations.translate(i18.dataShare.connectedTo)} ${widget.connectedDevice.deviceName}"), - ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - const Text( - "Transferring data to the connected device...", - style: TextStyle(fontSize: 18), - ), - const SizedBox(height: 20), - LinearProgressIndicator(value: progress), - const SizedBox(height: 10), - Text("${(progress * 100).toStringAsFixed(1)}%"), - const SizedBox(height: 30), - ElevatedButton( - onPressed: () async { - // Example data to transfer - readDownSyncData(); - }, - child: const Text("Start Transfer"), - ), - ], + onPopInvoked: (pop) {}, + child: BlocBuilder( + builder: (context, state) { + return ScrollableContent( + header: const BackNavigationHelpHeaderWidget( + showHelp: true, ), - ), - ), + footer: DigitCard( + margin: const EdgeInsets.only(top: spacer2), + padding: const EdgeInsets.all(spacer2), + children: [ + Button( + type: ButtonType.secondary, + mainAxisSize: MainAxisSize.max, + onPressed: () {}, + label: localizations.translate(i18.common.coreCommonCancel), + size: ButtonSize.large, + ), + ]), + slivers: [ + SliverToBoxAdapter( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(kPadding), + child: Align( + alignment: Alignment.topLeft, + child: Text( + localizations.translate(i18.dataShare.sendAction), + style: textTheme.headingM, + ), + ), + ), + Material( + child: Column( + children: [ + state.maybeWhen( + orElse: () => Center( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 16), + SizedBox( + height: + MediaQuery.of(context).size.height * + 0.2, + width: + MediaQuery.of(context).size.height * + 0.2, + child: CircularProgressIndicator( + valueColor: + AlwaysStoppedAnimation( + DigitTheme.instance.colors + .light.alertSuccess), + backgroundColor: DigitTheme.instance + .colors.light.textDisabled, + value: 0), + ), + ], + ), + ), + transferInProgress: (progress) => Column( + children: [ + SizedBox( + height: + MediaQuery.of(context).size.height * + 0.2, + width: + MediaQuery.of(context).size.height * + 0.2, + child: CircularProgressIndicator( + valueColor: + AlwaysStoppedAnimation( + DigitTheme.instance.colors + .light.alertSuccess), + backgroundColor: DigitTheme.instance + .colors.light.textDisabled, + value: progress), + ), + const SizedBox(height: 16), + Button( + onPressed: () { + context.read().add( + DataTransferEvent( + nearbyService: nearbyService, + connectedDevice: + widget.connectedDevice)); + }, + size: ButtonSize.large, + label: localizations.translate( + i18.common.coreCommonRetry), + type: ButtonType.primary, + ), + ], + ), + failedToTransfer: (error) => Center( + child: Button( + onPressed: () { + context.read().add( + DataTransferEvent( + nearbyService: nearbyService, + connectedDevice: + widget.connectedDevice)); + }, + size: ButtonSize.large, + label: localizations + .translate(i18.common.coreCommonRetry), + type: ButtonType.primary, + ), + )) + ], + ), + ), + ], + ), + ) + ], + ); + }), ); } - - void readDownSyncData() async { - final downloadsDirectory = await getDownloadsDirectory(); - - final file = File('${downloadsDirectory!.path}/down_sync_data.json'); - - final content = await file.readAsString(); - if (content.isNotEmpty) { - try { - sendEntities(jsonDecode(content)); - // nearbyService.sendMessage(widget.connectedDevice.deviceId, content); - } catch (e) { - debugPrint('Error parsing data: $e'); - } - } - } } diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart index 9523888d71..f296f6a0a7 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -3,18 +3,20 @@ import 'dart:io'; import 'dart:math'; import 'package:attendance_management/widgets/back_navigation_help_header.dart'; -import 'package:auto_route/annotations.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:digit_components/digit_components.dart'; +import 'package:digit_components/widgets/atoms/digit_toaster.dart'; +import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; +import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../widgets/localized.dart'; +import '../../widgets/showcase/showcase_wrappers.dart'; import 'data_receiver.dart'; -import 'data_transfer.dart'; enum DeviceType { receiver, sender } @@ -57,79 +59,116 @@ class DevicesListPageState extends LocalizedState super.dispose(); } + @override @override Widget build(BuildContext context) { final theme = Theme.of(context); final textTheme = theme.digitTextTheme(context); + final screenWidth = MediaQuery.of(context).size.width; + final screenHeight = MediaQuery.of(context).size.height; return Scaffold( body: ScrollableContent( - backgroundColor: DigitTheme.instance.colors.white, - footer: widget.deviceType == DeviceType.sender - ? DigitElevatedButton( - onPressed: connectedDevices.isNotEmpty - ? () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return DataTransferPage( - connectedDevice: connectedDevices.first, - nearbyService: nearbyService, - ); - })); - } - : null, - child: Text(localizations.translate(i18.dataShare.sendAction)), - ) - : const Spacer(), - children: [ - const BackNavigationHelpHeaderWidget(), - Text( - widget.deviceType.name.toUpperCase(), - style: textTheme.headingM, - ), - Container( - height: MediaQuery.of(context).size.height * 0.6, - color: DigitTheme.instance.colors.regalBlue, - child: Stack( - alignment: Alignment.center, + backgroundColor: DigitTheme.instance.colors.light.primary1Bg, + enableFixedButton: true, + footer: DigitCard( + margin: const EdgeInsets.only(top: spacer2), + padding: const EdgeInsets.all(spacer2), + children: [ + if (widget.deviceType == DeviceType.sender) + Button( + onPressed: () { + if (connectedDevices.isNotEmpty) { + context.router.push(DataTransferRoute( + connectedDevice: connectedDevices, + nearbyService: nearbyService, + )); + } else { + DigitToast.show(context, + options: DigitToastOptions( + localizations + .translate(i18.dataShare.noDevicesConnected), + true, + theme)); + } + }, + type: ButtonType.primary, + label: localizations.translate(i18.dataShare.sendAction), + size: ButtonSize.large, + mainAxisSize: MainAxisSize.max, + ), + ], + ), + slivers: [ + SliverToBoxAdapter( + child: Column( children: [ - // Radar Circles - ...List.generate(4, (index) { - return Container( - width: 200.0 + (index * 50), - height: 200.0 + (index * 50), - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: Colors.white.withOpacity(0.3), - ), + const BackNavigationHelpHeaderWidget( + showHelp: true, + ), + Padding( + padding: const EdgeInsets.all(kPadding), + child: Align( + alignment: Alignment.topLeft, + child: Text( + widget.deviceType.name.toUpperCase(), + style: textTheme.headingM, ), - ); - }), - // Radar Sweep - AnimatedBuilder( - animation: _controller, - builder: (context, child) { - return Transform.rotate( - angle: _controller.value * 2 * pi, - child: Container( - width: 400, - height: 400, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: SweepGradient( - colors: [ - Colors.white.withOpacity(0.3), - Colors.transparent, - ], - stops: const [0.7, 1.0], + ), + ), + Container( + height: screenHeight * 0.6, + width: screenWidth * 0.9, + margin: const EdgeInsets.all(kPadding), + decoration: BoxDecoration( + color: DigitTheme.instance.colors.light.primary2, + borderRadius: BorderRadius.circular(kPadding), + ), + child: Stack( + alignment: Alignment.center, + children: [ + // Radar Circles + ...List.generate(3, (index) { + return Container( + width: screenWidth * 0.5 + (index * 50), + height: screenHeight * 0.3 + (index * 50), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: DigitTheme.instance.colors.light.primary1Bg + .withOpacity(0.3), + ), ), - ), + ); + }), + // Radar Sweep + AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return Transform.rotate( + angle: _controller.value * 2 * pi, + child: Container( + width: screenWidth * 0.9, + height: screenHeight * 0.6, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: SweepGradient( + colors: [ + Colors.white.withOpacity(0.3), + Colors.transparent, + ], + stops: const [0.7, 1.0], + ), + ), + ), + ); + }, ), - ); - }, - ), - ..._generateRandomDevicePositions(devices, 400, 200), + ..._generateRandomDevicePositions( + devices, screenWidth * 0.9, screenHeight * 0.6), + ], + ), + ) ], ), ) @@ -139,42 +178,34 @@ class DevicesListPageState extends LocalizedState } List _generateRandomDevicePositions( - List devices, - double size, - double - rippleRadius // Pass rippleRadius here to position devices inside it - ) { + List devices, double width, double height) { final random = Random(); return widget.deviceType == DeviceType.receiver ? connectedDevices.asMap().entries.map((entry) { - // Ensure that the device is placed within the ripple's growing radius - final angle = random.nextDouble() * 2 * pi; // Random angle - final radius = random.nextDouble() * - rippleRadius; // Ensure radius is within ripple radius + // Use the device index to offset the randomization for uniqueness + final angle = random.nextDouble() * 2 * pi + + entry.key * 0.1; // slight offset for uniqueness + final radius = random.nextDouble() * rippleRadius; final x = radius * cos(angle); final y = radius * sin(angle); return Positioned( - left: size / 2 + - x - - 40, // Adjust icon position (centered around the circle) - top: size / 2 + y - 40, + left: width / 2 + x - 20, // Adjust based on the container size + top: height / 2 + y - 20, child: _buildDeviceWidget(entry.value), ); }).toList() : devices.asMap().entries.map((entry) { - // Ensure that the device is placed within the ripple's growing radius - final angle = random.nextDouble() * 2 * pi; // Random angle - final radius = random.nextDouble() * - rippleRadius; // Ensure radius is within ripple radius + final angle = random.nextDouble() * 2 * pi + + entry.key * 0.1; // slight offset for uniqueness + final radius = (random.nextDouble() * rippleRadius) + + 20; // Ensure enough space between devices final x = radius * cos(angle); final y = radius * sin(angle); return Positioned( - left: size / 2 + - x - - 40, // Adjust icon position (centered around the circle) - top: size / 2 + y - 40, + left: width / 2 + x - 20, + top: height / 2 + y - 20, child: _buildDeviceWidget(entry.value), ); }).toList(); @@ -182,43 +213,61 @@ class DevicesListPageState extends LocalizedState // Build each device widget with icon and name Widget _buildDeviceWidget(Device device) { - return GestureDetector( - onTap: () { - _onButtonClicked(device); - }, - child: Material( - elevation: 5, - borderRadius: BorderRadius.circular(kPadding), - child: Padding( - padding: const EdgeInsets.all(kPadding), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.phone_android, - size: 50, // Adjust size of the device icon - color: DigitTheme.instance.colors.amber, - ), - const SizedBox( - height: kPadding, - ), - Text( - device.deviceName, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, color: DigitTheme.instance.colors.amber), - ), - Text( - getStateName(device.state), - textAlign: TextAlign.center, - style: - TextStyle(fontSize: 8, color: getStateColor(device.state)), - ), - ], - ), - ), - ), - ); + return device.state == SessionState.connecting + ? const CircularProgressIndicator() + : GestureDetector( + onTap: () { + _onButtonClicked(device); + }, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + decoration: BoxDecoration( + color: DigitTheme.instance.colors.light.primary1Bg + .withOpacity(0.5), + borderRadius: BorderRadius.circular(kPadding), + border: Border.all( + color: DigitTheme.instance.colors.light.primary1Bg + .withOpacity(0.2), + width: 1.5)), + child: Padding( + padding: const EdgeInsets.all(kPadding), + child: Column( + children: [ + Icon( + Icons.account_circle, + size: 24, // Adjust size of the device icon + color: DigitTheme.instance.colors.light.primary1Bg, + ), + Text( + device.deviceName, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 8, + color: DigitTheme.instance.colors.light.primary1Bg, + ), + ) + ], + ), + ), + ), + Material( + borderRadius: BorderRadius.circular(kPadding), + color: DigitTheme.instance.colors.light.primary1Bg, + child: Padding( + padding: const EdgeInsets.all(kPadding / 2), + child: Text( + getStateName(device.state), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 8, color: getStateColor(device.state)), + ), + ), + ), + ], + ), + ); } String getStateName(SessionState state) { @@ -237,11 +286,11 @@ class DevicesListPageState extends LocalizedState Color getStateColor(SessionState state) { switch (state) { case SessionState.notConnected: - return DigitTheme.instance.colors.amber; + return DigitTheme.instance.colors.light.alertWarning; case SessionState.connecting: - return DigitTheme.instance.colors.white; + return DigitTheme.instance.colors.light.alertWarning; default: - return DigitTheme.instance.colors.darkSpringGreen; + return DigitTheme.instance.colors.light.alertSuccess; } } diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/peer_to_peer_wrapper.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/peer_to_peer_wrapper.dart new file mode 100644 index 0000000000..bb8f63a637 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/peer_to_peer_wrapper.dart @@ -0,0 +1,41 @@ +import 'package:digit_data_model/data_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:registration_delivery/registration_delivery.dart'; + +import '../../blocs/peer_to_peer/peer_to_peer.dart'; +import '../../router/app_router.dart'; + +@RoutePage() +class PeerToPeerWrapperPage extends StatelessWidget + implements AutoRouteWrapper { + const PeerToPeerWrapperPage({super.key}); + + @override + Widget build(BuildContext context) { + return const AutoRouter(); + } + + @override + Widget wrappedRoute(BuildContext context) { + return BlocProvider( + child: this, + create: (_) => PeerToPeerBloc( + individualLocalRepository: context.read< + LocalRepository>(), + householdLocalRepository: context + .read>(), + householdMemberLocalRepository: context.read< + LocalRepository>(), + projectBeneficiaryLocalRepository: context.read< + LocalRepository>(), + taskLocalRepository: + context.read>(), + sideEffectLocalRepository: context.read< + LocalRepository>(), + referralLocalRepository: context + .read>())); + } +} diff --git a/apps/health_campaign_field_worker_app/lib/router/app_router.dart b/apps/health_campaign_field_worker_app/lib/router/app_router.dart index 09b634f348..7144af8f8c 100644 --- a/apps/health_campaign_field_worker_app/lib/router/app_router.dart +++ b/apps/health_campaign_field_worker_app/lib/router/app_router.dart @@ -5,20 +5,21 @@ import 'package:closed_household/router/closed_household_router.dart'; import 'package:closed_household/router/closed_household_router.gm.dart'; import 'package:complaints/router/complaints_router.dart'; import 'package:complaints/router/complaints_router.gm.dart'; +import 'package:digit_data_model/data_model.dart'; import 'package:digit_dss/router/dashboard_router.dart'; import 'package:digit_dss/router/dashboard_router.gm.dart'; import 'package:digit_scanner/router/digit_scanner_router.dart'; import 'package:digit_scanner/router/digit_scanner_router.gm.dart'; -import 'package:digit_data_model/data_model.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; import 'package:inventory_management/router/inventory_router.dart'; import 'package:inventory_management/router/inventory_router.gm.dart'; -import 'package:survey_form/router/survey_form_router.dart'; -import 'package:survey_form/router/survey_form_router.gm.dart'; import 'package:referral_reconciliation/router/referral_reconciliation_router.dart'; import 'package:referral_reconciliation/router/referral_reconciliation_router.gm.dart'; import 'package:registration_delivery/router/registration_delivery_router.dart'; import 'package:registration_delivery/router/registration_delivery_router.gm.dart'; +import 'package:survey_form/router/survey_form_router.dart'; +import 'package:survey_form/router/survey_form_router.gm.dart'; import '../blocs/localization/app_localization.dart'; import '../pages/acknowledgement.dart'; @@ -27,6 +28,11 @@ import '../pages/boundary_selection.dart'; import '../pages/home.dart'; import '../pages/language_selection.dart'; import '../pages/login.dart'; +import '../pages/peer_to_peer/data_receiver.dart'; +import '../pages/peer_to_peer/data_share_home.dart'; +import '../pages/peer_to_peer/data_transfer.dart'; +import '../pages/peer_to_peer/devices_list.dart'; +import '../pages/peer_to_peer/peer_to_peer_wrapper.dart'; import '../pages/profile.dart'; import '../pages/project_facility_selection.dart'; import '../pages/project_selection.dart'; @@ -229,10 +235,13 @@ class AppRouter extends _$AppRouter { path: '', ), AutoRoute( - page: SurveyFormBoundaryViewRoute.page, path: 'view-boundary'), + page: SurveyFormBoundaryViewRoute.page, + path: 'view-boundary'), AutoRoute(page: SurveyFormViewRoute.page, path: 'view'), AutoRoute(page: SurveyFormPreviewRoute.page, path: 'preview'), - AutoRoute(page: SurveyFormAcknowledgementRoute.page, path: 'surveyForm-acknowledgement'), + AutoRoute( + page: SurveyFormAcknowledgementRoute.page, + path: 'surveyForm-acknowledgement'), ]), AutoRoute( page: BeneficiaryAcknowledgementRoute.page, @@ -320,8 +329,8 @@ class AppRouter extends _$AppRouter { // Attendance Route AutoRoute( - page: MarkAttendanceRoute.page, - path: 'mark-attendance', + page: MarkAttendanceRoute.page, + path: 'mark-attendance', ), AutoRoute( page: ManageAttendanceRoute.page, @@ -399,6 +408,22 @@ class AppRouter extends _$AppRouter { page: SearchReferralReconciliationsRoute.page, path: 'search-referrals', ), + + AutoRoute( + page: DataShareHomeRoute.page, + path: 'data-share-home', + ), + AutoRoute( + page: PeerToPeerWrapperRoute.page, + path: 'peer-to-peer-wrapper', + children: [ + AutoRoute( + page: DevicesListRoute.page, + path: 'devices-list', + initial: true), + AutoRoute(page: DataTransferRoute.page, path: 'data-transfer'), + AutoRoute(page: DataReceiverRoute.page, path: 'data-receiver'), + ]), ], ) ]; diff --git a/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart b/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart index 3a768e7a17..af264f2cdf 100644 --- a/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart +++ b/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart @@ -55,6 +55,17 @@ abstract class _$AppRouter extends RootStackRouter { ), ); }, + DataReceiverRoute.name: (routeData) { + final args = routeData.argsAs(); + return AutoRoutePage( + routeData: routeData, + child: DataReceiverPage( + key: args.key, + connectedDevice: args.connectedDevice, + nearbyService: args.nearbyService, + ), + ); + }, DataShareHomeRoute.name: (routeData) { return AutoRoutePage( routeData: routeData, @@ -110,6 +121,12 @@ abstract class _$AppRouter extends RootStackRouter { ), ); }, + PeerToPeerWrapperRoute.name: (routeData) { + return AutoRoutePage( + routeData: routeData, + child: WrappedRoute(child: const PeerToPeerWrapperPage()), + ); + }, ProfileRoute.name: (routeData) { final args = routeData.argsAs( orElse: () => const ProfileRouteArgs()); @@ -311,6 +328,49 @@ class BoundarySelectionRouteArgs { } } +/// generated route for +/// [DataReceiverPage] +class DataReceiverRoute extends PageRouteInfo { + DataReceiverRoute({ + Key? key, + required Device connectedDevice, + required NearbyService nearbyService, + List? children, + }) : super( + DataReceiverRoute.name, + args: DataReceiverRouteArgs( + key: key, + connectedDevice: connectedDevice, + nearbyService: nearbyService, + ), + initialChildren: children, + ); + + static const String name = 'DataReceiverRoute'; + + static const PageInfo page = + PageInfo(name); +} + +class DataReceiverRouteArgs { + const DataReceiverRouteArgs({ + this.key, + required this.connectedDevice, + required this.nearbyService, + }); + + final Key? key; + + final Device connectedDevice; + + final NearbyService nearbyService; + + @override + String toString() { + return 'DataReceiverRouteArgs{key: $key, connectedDevice: $connectedDevice, nearbyService: $nearbyService}'; + } +} + /// generated route for /// [DataShareHomePage] class DataShareHomeRoute extends PageRouteInfo { @@ -331,7 +391,7 @@ class DataTransferRoute extends PageRouteInfo { DataTransferRoute({ Key? key, required NearbyService nearbyService, - required Device connectedDevice, + required List connectedDevice, List? children, }) : super( DataTransferRoute.name, @@ -360,7 +420,7 @@ class DataTransferRouteArgs { final NearbyService nearbyService; - final Device connectedDevice; + final List connectedDevice; @override String toString() { @@ -494,6 +554,20 @@ class LoginRouteArgs { } } +/// generated route for +/// [PeerToPeerWrapperPage] +class PeerToPeerWrapperRoute extends PageRouteInfo { + const PeerToPeerWrapperRoute({List? children}) + : super( + PeerToPeerWrapperRoute.name, + initialChildren: children, + ); + + static const String name = 'PeerToPeerWrapperRoute'; + + static const PageInfo page = PageInfo(name); +} + /// generated route for /// [ProfilePage] class ProfileRoute extends PageRouteInfo { diff --git a/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart b/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart index 5662be3abe..36336a4b2f 100644 --- a/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart +++ b/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart @@ -570,6 +570,7 @@ class DataShare { String get sendAction => 'SEND_ACTION'; String get receiveAction => 'RECEIVE_ACTION'; String get connectedTo => 'CONNECTED_TO'; + String get noDevicesConnected => 'NO_DEVICES_CONNECTED'; } class AcknowledgementSuccess { From dddbda4cfc0c00a1aec8e2cdb3c408488fe996ba Mon Sep 17 00:00:00 2001 From: Naveen Renati Date: Wed, 4 Dec 2024 19:24:34 +0530 Subject: [PATCH 04/16] ui changes individual_global_search.dart total members in household in individual type fix --- .../lib/blocs/peer_to_peer/peer_to_peer.dart | 175 +++++---- .../peer_to_peer/peer_to_peer.freezed.dart | 196 ++++++---- .../lib/blocs/project/project.dart | 2 +- .../lib/pages/peer_to_peer/data_receiver.dart | 331 +++++++++++++++-- .../lib/pages/peer_to_peer/data_transfer.dart | 346 ++++++++++++------ .../lib/pages/peer_to_peer/devices_list.dart | 108 +++--- .../lib/router/app_router.gr.dart | 12 +- .../pubspec.lock | 8 + .../pubspec.yaml | 1 + .../individual_global_search.dart | 44 ++- .../local/individual_global_search.dart | 7 +- 11 files changed, 861 insertions(+), 369 deletions(-) diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart index bdae150049..35c3a42dd1 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -56,102 +56,107 @@ class PeerToPeerBloc extends Bloc { PeerToPeerEmitter emit, ) async { try { - emit(const PeerToPeerState.transferInProgress(progress: 0)); + emit(const PeerToPeerState.transferInProgress( + progress: 0, entityName: '')); final downloadsDirectory = await getDownloadsDirectory(); + final file = File('${downloadsDirectory!.path}/down_sync_data.json'); + final content = await file.readAsString(); if (content.isNotEmpty) { final entities = jsonDecode(content); - try { - for (var entityName in entities.keys) { - List entityData = entities[entityName]!; - int totalSize = entityData.length; - int offset = 0; - - while (offset < totalSize) { - // Calculate the chunk - const int chunkSize = 500; - int end = (offset + chunkSize < totalSize) - ? offset + chunkSize - : totalSize; - List chunk = entityData.sublist(offset, end); - - // Send the chunk - for (var element in event.connectedDevice) { - await event.nearbyService.sendMessage( - element.deviceId, - jsonEncode({ - "entityType": entityName, - "message": chunk, - "offset": offset + chunk.length, - "totalData": totalSize, - }), - ); - } - - final progress = (offset + chunk.length) / totalSize; - emit(PeerToPeerState.transferInProgress(progress: progress)); - - // Wait for confirmation from the receiver before sending the next chunk - bool confirmed = await _waitForConfirmation(entityName, - event.nearbyService, event.connectedDevice.first.deviceId); - - if (confirmed) { - offset = end; // Move to the next chunk - } else { - emit(PeerToPeerState.failedToTransfer( - error: "Confirmation failed for chunk")); - return; - } + for (var entityName in entities.keys) { + List entityData = entities[entityName]!; + int totalSize = entityData.length; + int offset = 0; + + while (offset < totalSize) { + // Calculate the chunk + const int chunkSize = 1000; + int end = (offset + chunkSize < totalSize) + ? offset + chunkSize + : totalSize; + List chunk = entityData.sublist(offset, end); + + // Send the chunk + for (var device in event.connectedDevice) { + await event.nearbyService.sendMessage( + device.deviceId, + jsonEncode({ + "entityType": entityName, + "message": chunk, + "offset": offset + chunk.length, + "totalData": totalSize, + }), + ); } - // Notify completion - emit(const PeerToPeerState.completedDataTransfer()); + // Wait for chunk confirmation + await waitForConfirmation( + entityName, + event.nearbyService, + confirmationType: "chunk", + offset: offset + chunk.length, + ); + + // Update progress + final progress = (offset + chunk.length) / totalSize; + emit(PeerToPeerState.transferInProgress( + progress: progress, entityName: entityName)); + offset = end; } - } catch (e) { - emit(PeerToPeerState.failedToTransfer(error: e.toString())); + + // Wait for final confirmation + await waitForConfirmation( + entityName, + event.nearbyService, + confirmationType: "final", + ); } + + emit(const PeerToPeerState.completedDataTransfer()); } } catch (e) { emit(PeerToPeerState.failedToTransfer(error: e.toString())); } } - Future _waitForConfirmation( - String entityName, NearbyService nearbyService, String deviceId) async { - final completer = Completer(); + Future waitForConfirmation( + String entityName, + NearbyService nearbyService, { + required String confirmationType, + int? offset, + }) async { + final completer = Completer(); - // Listen for the confirmation message final subscription = nearbyService.dataReceivedSubscription(callback: (data) { try { var receivedJson = jsonDecode(data["message"]); if (receivedJson["type"] == "confirmation" && receivedJson["entityType"] == entityName && - receivedJson["status"] == "success" && - receivedJson["deviceId"] == deviceId) { - debugPrint("Confirmation received for $entityName"); - completer.complete(true); + receivedJson["confirmationType"] == confirmationType) { + if (confirmationType == "chunk" && + receivedJson["offset"] != null && + receivedJson["offset"] == offset) { + debugPrint("Chunk confirmation received for $entityName"); + completer.complete(); + } else if (confirmationType == "final") { + debugPrint("Final confirmation received for $entityName"); + completer.complete(); + } } } catch (e) { debugPrint("Error processing confirmation: $e"); - completer.complete(false); } }); - // Timeout after a certain period - Future.delayed(const Duration(seconds: 10), () { - if (!completer.isCompleted) { - completer.complete(false); - } - }); - - bool confirmed = await completer.future; + // Add timeout logic if required + await completer.future; subscription.cancel(); - return confirmed; } Future _handleReceiveEntities( @@ -159,6 +164,7 @@ class PeerToPeerBloc extends Bloc { Emitter emit, ) async { try { + // Decode the received data var receivedJson = jsonDecode(event.data["message"]); entityType = receivedJson["entityType"]; int offset = receivedJson["offset"]; @@ -170,12 +176,27 @@ class PeerToPeerBloc extends Bloc { double progress = receivedBytes / totalData; receivedData.addAll(receivedChunk); - // Calculate and emit progress - emit(PeerToPeerState.receivingInProgress(progress: progress)); - - // When all data is received + // Emit progress for UI/State tracking + emit(PeerToPeerState.receivingInProgress( + progress: progress, entityName: entityType)); + + // Send a chunk-level confirmation + event.nearbyService.sendMessage( + event.data["deviceId"], + jsonEncode({ + "type": "confirmation", + "confirmationType": "chunk", + "entityType": entityType, + "status": "received", + "offset": offset, + "progress": progress, + "message": "Chunk received successfully.", + }), + ); + + // Check if all data is received if (receivedBytes >= totalData) { - // Save the received entity data to the local database + // Save the received entity data final local = RepositoryType.getLocalForType( DataModels.getDataModelForEntityName(entityType), [ @@ -195,19 +216,19 @@ class PeerToPeerBloc extends Bloc { debugPrint("$entityType data saved successfully."); - // Clear the received data buffer for the next entity + // Clear buffer for the next entity receivedData.clear(); receivedBytes = 0; - // Send confirmation back to the sender + // Send a final confirmation event.nearbyService.sendMessage( event.data["deviceId"], jsonEncode({ "type": "confirmation", + "confirmationType": "final", "entityType": entityType, "status": "success", - "deviceId": event.data["deviceId"], - "message": "$entityType saved successfully." + "message": "$entityType saved successfully.", }), ); @@ -237,8 +258,9 @@ class PeerToPeerState with _$PeerToPeerState { const factory PeerToPeerState.loading() = PeerToPeerLoading; - const factory PeerToPeerState.transferInProgress({required double progress}) = - TransferInProgress; + const factory PeerToPeerState.transferInProgress( + {required double progress, + required String entityName}) = TransferInProgress; const factory PeerToPeerState.completedDataTransfer() = CompletedDataTransfer; @@ -246,7 +268,8 @@ class PeerToPeerState with _$PeerToPeerState { FailedToTransfer; const factory PeerToPeerState.receivingInProgress( - {required double progress}) = ReceivingInProgress; + {required double progress, + required String entityName}) = ReceivingInProgress; const factory PeerToPeerState.dataReceived() = DataReceived; diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart index 6fc9be260e..7ea34437fc 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart @@ -452,10 +452,12 @@ mixin _$PeerToPeerState { TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress) transferInProgress, + required TResult Function(double progress, String entityName) + transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress) receivingInProgress, + required TResult Function(double progress, String entityName) + receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) => @@ -464,10 +466,10 @@ mixin _$PeerToPeerState { TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress)? transferInProgress, + TResult? Function(double progress, String entityName)? transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress)? receivingInProgress, + TResult? Function(double progress, String entityName)? receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) => @@ -476,10 +478,10 @@ mixin _$PeerToPeerState { TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress)? transferInProgress, + TResult Function(double progress, String entityName)? transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress)? receivingInProgress, + TResult Function(double progress, String entityName)? receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -591,10 +593,12 @@ class _$PeerToPeerInitialImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress) transferInProgress, + required TResult Function(double progress, String entityName) + transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress) receivingInProgress, + required TResult Function(double progress, String entityName) + receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { @@ -606,10 +610,10 @@ class _$PeerToPeerInitialImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress)? transferInProgress, + TResult? Function(double progress, String entityName)? transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress)? receivingInProgress, + TResult? Function(double progress, String entityName)? receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -621,10 +625,10 @@ class _$PeerToPeerInitialImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress)? transferInProgress, + TResult Function(double progress, String entityName)? transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress)? receivingInProgress, + TResult Function(double progress, String entityName)? receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -738,10 +742,12 @@ class _$PeerToPeerLoadingImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress) transferInProgress, + required TResult Function(double progress, String entityName) + transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress) receivingInProgress, + required TResult Function(double progress, String entityName) + receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { @@ -753,10 +759,10 @@ class _$PeerToPeerLoadingImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress)? transferInProgress, + TResult? Function(double progress, String entityName)? transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress)? receivingInProgress, + TResult? Function(double progress, String entityName)? receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -768,10 +774,10 @@ class _$PeerToPeerLoadingImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress)? transferInProgress, + TResult Function(double progress, String entityName)? transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress)? receivingInProgress, + TResult Function(double progress, String entityName)? receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -843,7 +849,7 @@ abstract class _$$TransferInProgressImplCopyWith<$Res> { $Res Function(_$TransferInProgressImpl) then) = __$$TransferInProgressImplCopyWithImpl<$Res>; @useResult - $Res call({double progress}); + $Res call({double progress, String entityName}); } /// @nodoc @@ -858,12 +864,17 @@ class __$$TransferInProgressImplCopyWithImpl<$Res> @override $Res call({ Object? progress = null, + Object? entityName = null, }) { return _then(_$TransferInProgressImpl( progress: null == progress ? _value.progress : progress // ignore: cast_nullable_to_non_nullable as double, + entityName: null == entityName + ? _value.entityName + : entityName // ignore: cast_nullable_to_non_nullable + as String, )); } } @@ -873,14 +884,17 @@ class __$$TransferInProgressImplCopyWithImpl<$Res> class _$TransferInProgressImpl with DiagnosticableTreeMixin implements TransferInProgress { - const _$TransferInProgressImpl({required this.progress}); + const _$TransferInProgressImpl( + {required this.progress, required this.entityName}); @override final double progress; + @override + final String entityName; @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'PeerToPeerState.transferInProgress(progress: $progress)'; + return 'PeerToPeerState.transferInProgress(progress: $progress, entityName: $entityName)'; } @override @@ -888,7 +902,8 @@ class _$TransferInProgressImpl super.debugFillProperties(properties); properties ..add(DiagnosticsProperty('type', 'PeerToPeerState.transferInProgress')) - ..add(DiagnosticsProperty('progress', progress)); + ..add(DiagnosticsProperty('progress', progress)) + ..add(DiagnosticsProperty('entityName', entityName)); } @override @@ -897,11 +912,13 @@ class _$TransferInProgressImpl (other.runtimeType == runtimeType && other is _$TransferInProgressImpl && (identical(other.progress, progress) || - other.progress == progress)); + other.progress == progress) && + (identical(other.entityName, entityName) || + other.entityName == entityName)); } @override - int get hashCode => Object.hash(runtimeType, progress); + int get hashCode => Object.hash(runtimeType, progress, entityName); @JsonKey(ignore: true) @override @@ -915,14 +932,16 @@ class _$TransferInProgressImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress) transferInProgress, + required TResult Function(double progress, String entityName) + transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress) receivingInProgress, + required TResult Function(double progress, String entityName) + receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { - return transferInProgress(progress); + return transferInProgress(progress, entityName); } @override @@ -930,14 +949,14 @@ class _$TransferInProgressImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress)? transferInProgress, + TResult? Function(double progress, String entityName)? transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress)? receivingInProgress, + TResult? Function(double progress, String entityName)? receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { - return transferInProgress?.call(progress); + return transferInProgress?.call(progress, entityName); } @override @@ -945,16 +964,16 @@ class _$TransferInProgressImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress)? transferInProgress, + TResult Function(double progress, String entityName)? transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress)? receivingInProgress, + TResult Function(double progress, String entityName)? receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), }) { if (transferInProgress != null) { - return transferInProgress(progress); + return transferInProgress(progress, entityName); } return orElse(); } @@ -1011,10 +1030,12 @@ class _$TransferInProgressImpl } abstract class TransferInProgress implements PeerToPeerState { - const factory TransferInProgress({required final double progress}) = - _$TransferInProgressImpl; + const factory TransferInProgress( + {required final double progress, + required final String entityName}) = _$TransferInProgressImpl; double get progress; + String get entityName; @JsonKey(ignore: true) _$$TransferInProgressImplCopyWith<_$TransferInProgressImpl> get copyWith => throw _privateConstructorUsedError; @@ -1071,10 +1092,12 @@ class _$CompletedDataTransferImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress) transferInProgress, + required TResult Function(double progress, String entityName) + transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress) receivingInProgress, + required TResult Function(double progress, String entityName) + receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { @@ -1086,10 +1109,10 @@ class _$CompletedDataTransferImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress)? transferInProgress, + TResult? Function(double progress, String entityName)? transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress)? receivingInProgress, + TResult? Function(double progress, String entityName)? receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -1101,10 +1124,10 @@ class _$CompletedDataTransferImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress)? transferInProgress, + TResult Function(double progress, String entityName)? transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress)? receivingInProgress, + TResult Function(double progress, String entityName)? receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -1247,10 +1270,12 @@ class _$FailedToTransferImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress) transferInProgress, + required TResult Function(double progress, String entityName) + transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress) receivingInProgress, + required TResult Function(double progress, String entityName) + receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { @@ -1262,10 +1287,10 @@ class _$FailedToTransferImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress)? transferInProgress, + TResult? Function(double progress, String entityName)? transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress)? receivingInProgress, + TResult? Function(double progress, String entityName)? receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -1277,10 +1302,10 @@ class _$FailedToTransferImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress)? transferInProgress, + TResult Function(double progress, String entityName)? transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress)? receivingInProgress, + TResult Function(double progress, String entityName)? receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -1358,7 +1383,7 @@ abstract class _$$ReceivingInProgressImplCopyWith<$Res> { $Res Function(_$ReceivingInProgressImpl) then) = __$$ReceivingInProgressImplCopyWithImpl<$Res>; @useResult - $Res call({double progress}); + $Res call({double progress, String entityName}); } /// @nodoc @@ -1373,12 +1398,17 @@ class __$$ReceivingInProgressImplCopyWithImpl<$Res> @override $Res call({ Object? progress = null, + Object? entityName = null, }) { return _then(_$ReceivingInProgressImpl( progress: null == progress ? _value.progress : progress // ignore: cast_nullable_to_non_nullable as double, + entityName: null == entityName + ? _value.entityName + : entityName // ignore: cast_nullable_to_non_nullable + as String, )); } } @@ -1388,14 +1418,17 @@ class __$$ReceivingInProgressImplCopyWithImpl<$Res> class _$ReceivingInProgressImpl with DiagnosticableTreeMixin implements ReceivingInProgress { - const _$ReceivingInProgressImpl({required this.progress}); + const _$ReceivingInProgressImpl( + {required this.progress, required this.entityName}); @override final double progress; + @override + final String entityName; @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'PeerToPeerState.receivingInProgress(progress: $progress)'; + return 'PeerToPeerState.receivingInProgress(progress: $progress, entityName: $entityName)'; } @override @@ -1403,7 +1436,8 @@ class _$ReceivingInProgressImpl super.debugFillProperties(properties); properties ..add(DiagnosticsProperty('type', 'PeerToPeerState.receivingInProgress')) - ..add(DiagnosticsProperty('progress', progress)); + ..add(DiagnosticsProperty('progress', progress)) + ..add(DiagnosticsProperty('entityName', entityName)); } @override @@ -1412,11 +1446,13 @@ class _$ReceivingInProgressImpl (other.runtimeType == runtimeType && other is _$ReceivingInProgressImpl && (identical(other.progress, progress) || - other.progress == progress)); + other.progress == progress) && + (identical(other.entityName, entityName) || + other.entityName == entityName)); } @override - int get hashCode => Object.hash(runtimeType, progress); + int get hashCode => Object.hash(runtimeType, progress, entityName); @JsonKey(ignore: true) @override @@ -1430,14 +1466,16 @@ class _$ReceivingInProgressImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress) transferInProgress, + required TResult Function(double progress, String entityName) + transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress) receivingInProgress, + required TResult Function(double progress, String entityName) + receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { - return receivingInProgress(progress); + return receivingInProgress(progress, entityName); } @override @@ -1445,14 +1483,14 @@ class _$ReceivingInProgressImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress)? transferInProgress, + TResult? Function(double progress, String entityName)? transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress)? receivingInProgress, + TResult? Function(double progress, String entityName)? receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { - return receivingInProgress?.call(progress); + return receivingInProgress?.call(progress, entityName); } @override @@ -1460,16 +1498,16 @@ class _$ReceivingInProgressImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress)? transferInProgress, + TResult Function(double progress, String entityName)? transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress)? receivingInProgress, + TResult Function(double progress, String entityName)? receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), }) { if (receivingInProgress != null) { - return receivingInProgress(progress); + return receivingInProgress(progress, entityName); } return orElse(); } @@ -1526,10 +1564,12 @@ class _$ReceivingInProgressImpl } abstract class ReceivingInProgress implements PeerToPeerState { - const factory ReceivingInProgress({required final double progress}) = - _$ReceivingInProgressImpl; + const factory ReceivingInProgress( + {required final double progress, + required final String entityName}) = _$ReceivingInProgressImpl; double get progress; + String get entityName; @JsonKey(ignore: true) _$$ReceivingInProgressImplCopyWith<_$ReceivingInProgressImpl> get copyWith => throw _privateConstructorUsedError; @@ -1581,10 +1621,12 @@ class _$DataReceivedImpl with DiagnosticableTreeMixin implements DataReceived { TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress) transferInProgress, + required TResult Function(double progress, String entityName) + transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress) receivingInProgress, + required TResult Function(double progress, String entityName) + receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { @@ -1596,10 +1638,10 @@ class _$DataReceivedImpl with DiagnosticableTreeMixin implements DataReceived { TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress)? transferInProgress, + TResult? Function(double progress, String entityName)? transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress)? receivingInProgress, + TResult? Function(double progress, String entityName)? receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -1611,10 +1653,10 @@ class _$DataReceivedImpl with DiagnosticableTreeMixin implements DataReceived { TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress)? transferInProgress, + TResult Function(double progress, String entityName)? transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress)? receivingInProgress, + TResult Function(double progress, String entityName)? receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -1757,10 +1799,12 @@ class _$FailedDataTransferImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress) transferInProgress, + required TResult Function(double progress, String entityName) + transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress) receivingInProgress, + required TResult Function(double progress, String entityName) + receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { @@ -1772,10 +1816,10 @@ class _$FailedDataTransferImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress)? transferInProgress, + TResult? Function(double progress, String entityName)? transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress)? receivingInProgress, + TResult? Function(double progress, String entityName)? receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -1787,10 +1831,10 @@ class _$FailedDataTransferImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress)? transferInProgress, + TResult Function(double progress, String entityName)? transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress)? receivingInProgress, + TResult Function(double progress, String entityName)? receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), diff --git a/apps/health_campaign_field_worker_app/lib/blocs/project/project.dart b/apps/health_campaign_field_worker_app/lib/blocs/project/project.dart index 8308cb9d69..29d4086bce 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/project/project.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/project/project.dart @@ -568,7 +568,7 @@ class ProjectBloc extends Bloc { rowVersionList.add(rowVersion); } isar.writeTxnSync(() { - isar.rowVersionLists.clear(); + isar.rowVersionLists.clearSync(); isar.rowVersionLists.putAllSync(rowVersionList); }); diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart index 4339cb5c35..6938526845 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -1,12 +1,21 @@ -import 'package:auto_route/annotations.dart'; +import 'dart:io'; + +import 'package:attendance_management/widgets/back_navigation_help_header.dart'; +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:digit_components/widgets/atoms/digit_toaster.dart'; import 'package:digit_ui_components/digit_components.dart'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; +import 'package:percent_indicator/percent_indicator.dart'; import '../../blocs/peer_to_peer/peer_to_peer.dart'; +import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../widgets/localized.dart'; +import '../../widgets/showcase/showcase_wrappers.dart'; @RoutePage() class DataReceiverPage extends LocalizedStatefulWidget { @@ -22,6 +31,7 @@ class DataReceiverPage extends LocalizedStatefulWidget { class _DataReceiverPageState extends LocalizedState { late NearbyService nearbyService; late PeerToPeerBloc peerToPeerBloc; + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); @override void initState() { @@ -32,6 +42,19 @@ class _DataReceiverPageState extends LocalizedState { peerToPeerBloc.add( DataReceiverEvent(nearbyService: widget.nearbyService, data: data)); }); + nearbyService.stateChangedSubscription(callback: (devices) { + for (var device in devices) { + if (device.state == SessionState.notConnected) { + context.router.maybePop(); + DigitToast.show(context, + options: DigitToastOptions( + localizations.translate( + '${device.deviceName} ${SessionState.notConnected.name}'), + true, + Theme.of(context))); + } + } + }); } @override @@ -43,48 +66,276 @@ class _DataReceiverPageState extends LocalizedState { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + return PopScope( - onPopInvoked: (pop) { - if (pop) { - widget.nearbyService - .disconnectPeer(deviceID: widget.connectedDevice.deviceId); - } - }, - child: Scaffold( - appBar: AppBar( - title: Text( - "${localizations.translate(i18.dataShare.connectedTo)} ${widget.connectedDevice.deviceName}"), - ), - body: BlocBuilder( - builder: (context, state) { - return state.maybeWhen( - orElse: () => const Center(child: CircularProgressIndicator()), - receivingInProgress: (progress) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + onPopInvoked: (pop) {}, + child: BlocListener( + listener: (context, state) { + if (state is DataReceived) { + context.router.push(AcknowledgementRoute()); + } + }, + child: BlocBuilder( + builder: (context, state) { + return ScrollableContent( + header: const BackNavigationHelpHeaderWidget( + showHelp: true, + ), + footer: DigitCard( + margin: const EdgeInsets.only(top: spacer2), + padding: const EdgeInsets.all(spacer2), children: [ - SizedBox( - height: MediaQuery.of(context).size.height * 0.2, - width: MediaQuery.of(context).size.height * 0.2, - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - DigitTheme - .instance.colors.light.alertSuccess), - backgroundColor: - DigitTheme.instance.colors.light.textDisabled, - value: progress), + Button( + type: ButtonType.secondary, + mainAxisSize: MainAxisSize.max, + onPressed: () {}, + label: localizations + .translate(i18.common.coreCommonCancel), + size: ButtonSize.large, ), - const SizedBox(height: 16), - Text('${(progress * 100).toInt()} / 100') - ], - ), - ); - }); - }, - ), - ), + ]), + slivers: [ + SliverToBoxAdapter( + child: Column(children: [ + Padding( + padding: const EdgeInsets.all(kPadding), + child: Align( + alignment: Alignment.topLeft, + child: Text( + localizations + .translate(i18.dataShare.receiveAction), + style: textTheme.headingM, + ), + ), + ), + Container( + height: MediaQuery.of(context).size.height * 0.6, + color: DigitTheme.instance.colors.light.paperPrimary, + margin: const EdgeInsets.all(kPadding), + child: state.maybeWhen( + orElse: () => Center( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + const SizedBox(height: 16), + CircularPercentIndicator( + radius: MediaQuery.of(context) + .size + .height * + 0.15, + lineWidth: kPadding * 1.5, + animation: false, + percent: + 0, // Update this dynamically for progress + center: const Text( + '0 %', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), + ), + + progressBorderColor: DigitTheme + .instance.colors.light.primary1Bg, + progressColor: DigitTheme.instance + .colors.light.alertSuccess, + backgroundColor: DigitTheme + .instance.colors.light.primary1Bg, + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon(Icons.smartphone, + size: 40, + color: DigitTheme.instance + .colors.light.primary2), + const SizedBox(width: 8), + const Text( + 'Receiving from', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500), + ), + const SizedBox(width: 8), + Icon(Icons.smartphone, + size: 40, + color: DigitTheme.instance + .colors.light.primary2), + ], + ), + Wrap( + spacing: 8.0, + runSpacing: 4.0, + children: [ + buildDeviceChip(), + Container( + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme + .instance + .colors + .light + .primary1Bg, + ), + borderRadius: + BorderRadius.circular( + kPadding), + ), + child: Text( + widget.connectedDevice + .deviceName, + style: TextStyle( + color: DigitTheme.instance + .colors.light.primary2, + ), + ), + ), + ]), + ], + ), + ), + receivingInProgress: (progress, receivingEntity) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Text('Receiving $receivingEntity'), + const SizedBox(height: 16), + CircularPercentIndicator( + radius: + MediaQuery.of(context).size.height * + 0.15, + lineWidth: kPadding * 1.5, + animation: false, + percent: + progress, // Update this dynamically for progress + center: Text( + '${(progress * 100).toStringAsFixed(1)} %', + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), + ), + + progressBorderColor: DigitTheme + .instance.colors.light.primary1Bg, + progressColor: DigitTheme + .instance.colors.light.alertSuccess, + backgroundColor: DigitTheme + .instance.colors.light.primary1Bg, + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon(Icons.smartphone, + size: 40, + color: DigitTheme.instance.colors + .light.primary2), + const SizedBox(width: 8), + const Text( + 'Receiving from', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500), + ), + const SizedBox(width: 8), + Icon(Icons.smartphone, + size: 40, + color: DigitTheme.instance.colors + .light.primary2), + ], + ), + Wrap( + spacing: 8.0, + runSpacing: 4.0, + children: [ + buildDeviceChip(), + Container( + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme.instance + .colors.light.primary1Bg, + ), + borderRadius: + BorderRadius.circular( + kPadding), + ), + child: Text( + widget + .connectedDevice.deviceName, + style: TextStyle( + color: DigitTheme.instance + .colors.light.primary2, + ), + ), + ), + ]), + ], + ), + ); + })), + ])) + ]); + }, + ), + )); + } + + Future getCurrentDeviceName() async { + var deviceId = ''; + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + deviceId = androidInfo.model; + } + if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + deviceId = iosInfo.localizedModel; + } + return deviceId; + } + + Widget buildDeviceChip() { + return FutureBuilder( + future: getCurrentDeviceName(), // Call your async method here + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + // Show a loading indicator while the future is being resolved + return const CircularProgressIndicator(); + } else if (snapshot.hasError) { + // Handle error case + return Chip( + label: Text(localizations.translate(i18.common.coreCommonNA)), + backgroundColor: DigitTheme.instance.colors.light.primary1Bg, + ); + } else if (snapshot.hasData) { + // Display the device name when available + return Container( + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme.instance.colors.light.primary1Bg, + ), + borderRadius: BorderRadius.circular(kPadding), + ), + child: Text( + snapshot.data!, + style: TextStyle( + color: DigitTheme.instance.colors.light.primary2, + ), + ), + ); + } else { + return const SizedBox.shrink(); // Handle unexpected case + } + }, ); } } diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart index 28501da5dc..5d0a0edda2 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -1,24 +1,29 @@ +import 'dart:io'; + import 'package:attendance_management/widgets/back_navigation_help_header.dart'; -import 'package:auto_route/annotations.dart'; +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:digit_components/widgets/atoms/digit_toaster.dart'; import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/digit_extended_theme.dart'; import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; +import 'package:percent_indicator/percent_indicator.dart'; import '../../blocs/peer_to_peer/peer_to_peer.dart'; +import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../widgets/localized.dart'; import '../../widgets/showcase/showcase_wrappers.dart'; @RoutePage() class DataTransferPage extends LocalizedStatefulWidget { - final List connectedDevice; + final List connectedDevices; final NearbyService nearbyService; const DataTransferPage( - {super.key, required this.nearbyService, required this.connectedDevice}); + {super.key, required this.nearbyService, required this.connectedDevices}); @override State createState() => _DataTransferScreenState(); @@ -27,13 +32,29 @@ class DataTransferPage extends LocalizedStatefulWidget { class _DataTransferScreenState extends LocalizedState { late NearbyService nearbyService; late PeerToPeerBloc peerToPeerBloc; + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + @override void initState() { super.initState(); nearbyService = widget.nearbyService; peerToPeerBloc = context.read(); peerToPeerBloc.add(DataTransferEvent( - connectedDevice: widget.connectedDevice, nearbyService: nearbyService)); + connectedDevice: widget.connectedDevices, + nearbyService: nearbyService)); + nearbyService.stateChangedSubscription(callback: (devices) { + for (var device in devices) { + if (device.state == SessionState.notConnected) { + context.router.maybePop(); + DigitToast.show(context, + options: DigitToastOptions( + localizations.translate( + '${device.deviceName} ${SessionState.notConnected.name}'), + true, + Theme.of(context))); + } + } + }); } @override @@ -48,126 +69,221 @@ class _DataTransferScreenState extends LocalizedState { return PopScope( onPopInvoked: (pop) {}, - child: BlocBuilder( - builder: (context, state) { - return ScrollableContent( - header: const BackNavigationHelpHeaderWidget( - showHelp: true, - ), - footer: DigitCard( - margin: const EdgeInsets.only(top: spacer2), - padding: const EdgeInsets.all(spacer2), - children: [ - Button( - type: ButtonType.secondary, - mainAxisSize: MainAxisSize.max, - onPressed: () {}, - label: localizations.translate(i18.common.coreCommonCancel), - size: ButtonSize.large, - ), - ]), - slivers: [ - SliverToBoxAdapter( - child: Column( + child: BlocListener( + listener: (context, state) { + if (state is CompletedDataTransfer) { + context.router.push(AcknowledgementRoute()); + } + }, + child: BlocBuilder( + builder: (context, state) { + return ScrollableContent( + header: const BackNavigationHelpHeaderWidget( + showHelp: true, + ), + footer: DigitCard( + margin: const EdgeInsets.only(top: spacer2), + padding: const EdgeInsets.all(spacer2), children: [ - Padding( - padding: const EdgeInsets.all(kPadding), - child: Align( - alignment: Alignment.topLeft, - child: Text( - localizations.translate(i18.dataShare.sendAction), - style: textTheme.headingM, + Button( + type: ButtonType.secondary, + mainAxisSize: MainAxisSize.max, + onPressed: () {}, + label: localizations.translate(i18.common.coreCommonCancel), + size: ButtonSize.large, + ), + ]), + slivers: [ + SliverToBoxAdapter( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(kPadding), + child: Align( + alignment: Alignment.topLeft, + child: Text( + localizations.translate(i18.dataShare.sendAction), + style: textTheme.headingM, + ), ), ), - ), - Material( - child: Column( - children: [ - state.maybeWhen( - orElse: () => Center( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox(height: 16), - SizedBox( - height: - MediaQuery.of(context).size.height * - 0.2, - width: - MediaQuery.of(context).size.height * - 0.2, - child: CircularProgressIndicator( - valueColor: - AlwaysStoppedAnimation( - DigitTheme.instance.colors - .light.alertSuccess), - backgroundColor: DigitTheme.instance - .colors.light.textDisabled, - value: 0), - ), - ], + Container( + height: MediaQuery.of(context).size.height * 0.6, + color: DigitTheme.instance.colors.light.paperPrimary, + margin: const EdgeInsets.all(kPadding), + child: state.maybeWhen( + orElse: () => Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 16), + CircularPercentIndicator( + radius: + MediaQuery.of(context).size.height * 0.15, + lineWidth: kPadding * 1.5, + animation: false, + percent: + 0, // Update this dynamically for progress + center: const Text( + '0 %', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), ), + progressBorderColor: DigitTheme + .instance.colors.light.primary1Bg, + progressColor: DigitTheme + .instance.colors.light.alertSuccess, + backgroundColor: DigitTheme + .instance.colors.light.primary1Bg, ), - transferInProgress: (progress) => Column( - children: [ - SizedBox( - height: - MediaQuery.of(context).size.height * - 0.2, - width: - MediaQuery.of(context).size.height * - 0.2, - child: CircularProgressIndicator( - valueColor: - AlwaysStoppedAnimation( - DigitTheme.instance.colors - .light.alertSuccess), - backgroundColor: DigitTheme.instance - .colors.light.textDisabled, - value: progress), + ], + ), + ), + transferInProgress: (progress, sendingEntity) => + Column( + mainAxisSize: MainAxisSize.max, + children: [ + const SizedBox(height: 16), + Text('Transferring $sendingEntity'), + const SizedBox(height: 16), + CircularPercentIndicator( + radius: + MediaQuery.of(context).size.height * 0.15, + lineWidth: kPadding * 1.5, + animation: false, + percent: + progress, // Update this dynamically for progress + center: Text( + '${(progress * 100).toStringAsFixed(1)} %', + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), + ), + progressBorderColor: + DigitTheme.instance.colors.light.primary1Bg, + progressColor: DigitTheme + .instance.colors.light.alertSuccess, + backgroundColor: + DigitTheme.instance.colors.light.primary1Bg, + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.smartphone, + size: 40, + color: DigitTheme + .instance.colors.light.primary2), + const SizedBox(width: 8), + const Text( + 'Transferring to', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500), + ), + const SizedBox(width: 8), + Icon(Icons.smartphone, + size: 40, + color: DigitTheme + .instance.colors.light.primary2), + ], + ), + Wrap(spacing: 8.0, runSpacing: 4.0, children: [ + buildDeviceChip(), + Container( + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme + .instance.colors.light.primary1Bg, ), - const SizedBox(height: 16), - Button( - onPressed: () { - context.read().add( - DataTransferEvent( - nearbyService: nearbyService, - connectedDevice: - widget.connectedDevice)); - }, - size: ButtonSize.large, - label: localizations.translate( - i18.common.coreCommonRetry), - type: ButtonType.primary, + borderRadius: + BorderRadius.circular(kPadding), + ), + child: Text( + widget.connectedDevices.first.deviceName, + style: TextStyle( + color: DigitTheme + .instance.colors.light.primary2, ), - ], - ), - failedToTransfer: (error) => Center( - child: Button( - onPressed: () { - context.read().add( - DataTransferEvent( - nearbyService: nearbyService, - connectedDevice: - widget.connectedDevice)); - }, - size: ButtonSize.large, - label: localizations - .translate(i18.common.coreCommonRetry), - type: ButtonType.primary, ), - )) - ], - ), - ), - ], + ), + ]), + ], + ), + failedToTransfer: (error) => Center( + child: Button( + onPressed: () { + context.read().add( + DataTransferEvent( + nearbyService: nearbyService, + connectedDevice: + widget.connectedDevices)); + }, + size: ButtonSize.large, + label: localizations + .translate(i18.common.coreCommonRetry), + type: ButtonType.primary, + ), + ), + )), + ], + ), + ) + ], + ); + }), + ), + ); + } + + Future getCurrentDeviceName() async { + var deviceId = ''; + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + deviceId = androidInfo.model; + } + if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + deviceId = iosInfo.localizedModel; + } + return deviceId; + } + + Widget buildDeviceChip() { + return FutureBuilder( + future: getCurrentDeviceName(), // Call your async method here + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + // Show a loading indicator while the future is being resolved + return const CircularProgressIndicator(); + } else if (snapshot.hasError) { + // Handle error case + return Chip( + label: Text(localizations.translate(i18.common.coreCommonNA)), + backgroundColor: DigitTheme.instance.colors.light.primary1Bg, + ); + } else if (snapshot.hasData) { + // Display the device name when available + return Container( + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme.instance.colors.light.primary1Bg, + ), + borderRadius: BorderRadius.circular(kPadding), + ), + child: Text( + snapshot.data!, + style: TextStyle( + color: DigitTheme.instance.colors.light.primary2, ), - ) - ], - ); - }), + ), + ); + } else { + return const SizedBox.shrink(); // Handle unexpected case + } + }, ); } } diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart index f296f6a0a7..7d753d2ea5 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -16,7 +16,6 @@ import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../widgets/localized.dart'; import '../../widgets/showcase/showcase_wrappers.dart'; -import 'data_receiver.dart'; enum DeviceType { receiver, sender } @@ -80,7 +79,7 @@ class DevicesListPageState extends LocalizedState onPressed: () { if (connectedDevices.isNotEmpty) { context.router.push(DataTransferRoute( - connectedDevice: connectedDevices, + connectedDevices: connectedDevices, nearbyService: nearbyService, )); } else { @@ -97,6 +96,28 @@ class DevicesListPageState extends LocalizedState size: ButtonSize.large, mainAxisSize: MainAxisSize.max, ), + if (widget.deviceType == DeviceType.receiver) + Button( + onPressed: () { + if (connectedDevices.isNotEmpty) { + context.router.push(DataReceiverRoute( + connectedDevice: connectedDevices.first, + nearbyService: nearbyService, + )); + } else { + DigitToast.show(context, + options: DigitToastOptions( + localizations + .translate(i18.dataShare.noDevicesConnected), + true, + theme)); + } + }, + type: ButtonType.primary, + label: localizations.translate(i18.dataShare.receiveAction), + size: ButtonSize.large, + mainAxisSize: MainAxisSize.max, + ), ], ), slivers: [ @@ -333,7 +354,7 @@ class DevicesListPageState extends LocalizedState deviceId = iosInfo.localizedModel; } await nearbyService.init( - serviceType: 'mpconn', + serviceType: 'mpconn', // TODO: Replace with Digit service type deviceName: deviceId, strategy: Strategy.Wi_Fi_P2P, callback: (isRunning) async { @@ -354,56 +375,49 @@ class DevicesListPageState extends LocalizedState subscription = nearbyService.stateChangedSubscription(callback: (devicesList) { if (devicesList.isNotEmpty) { - var element = devicesList.first; - if (kDebugMode) { - print( - "deviceId: ${element.deviceId} | deviceName: ${element.deviceName} | state: ${element.state}"); - } + for (var device in devicesList) { + var element = device; - // Handle Android-specific browsing - if (Platform.isAndroid) { - if (element.state == SessionState.connected) { - if (!navigatedDevices.contains(element.deviceId)) { - if (kDebugMode) { - print('connection successful'); - } - navigatedDevices.add(element.deviceId); - if (widget.deviceType == DeviceType.receiver) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => DataReceiverPage( - connectedDevice: element, - nearbyService: nearbyService, - ))); - } - nearbyService.stopBrowsingForPeers(); - } - } else if (element.state == SessionState.notConnected) { - nearbyService.startBrowsingForPeers(); - navigatedDevices.remove( - element.deviceId); // Allow re-navigation if disconnected + if (kDebugMode) { + print( + "deviceId: ${element.deviceId} | deviceName: ${element.deviceName} | state: ${element.state}"); } - } - setState(() { - // Deduplicate the devices list - final uniqueDevices = - {}; // Use a map for deduplication - for (var device in devicesList) { - uniqueDevices[device.deviceId] = - device; // Replace entries with the same deviceId + // Handle Android-specific browsing + if (Platform.isAndroid) { + if (element.state == SessionState.connected) { + DigitToast.show(context, + options: DigitToastOptions( + localizations + .translate('${element.deviceName} is connected'), + false, + Theme.of(context))); + } else if (element.state == SessionState.notConnected) { + nearbyService.startBrowsingForPeers(); + navigatedDevices.remove( + element.deviceId); // Allow re-navigation if disconnected + } } - // Update the devices list and connected devices - devices - ..clear() - ..addAll(uniqueDevices.values); // Add only unique devices + setState(() { + // Deduplicate the devices list + final uniqueDevices = + {}; // Use a map for deduplication + for (var device in devicesList) { + uniqueDevices[device.deviceId] = + device; // Replace entries with the same deviceId + } + + // Update the devices list and connected devices + devices + ..clear() + ..addAll(uniqueDevices.values); // Add only unique devices - connectedDevices - ..clear() - ..addAll(devices.where((d) => d.state == SessionState.connected)); - }); + connectedDevices + ..clear() + ..addAll(devices.where((d) => d.state == SessionState.connected)); + }); + } } }); } diff --git a/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart b/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart index af264f2cdf..0f2c91492a 100644 --- a/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart +++ b/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart @@ -79,7 +79,7 @@ abstract class _$AppRouter extends RootStackRouter { child: DataTransferPage( key: args.key, nearbyService: args.nearbyService, - connectedDevice: args.connectedDevice, + connectedDevices: args.connectedDevices, ), ); }, @@ -391,14 +391,14 @@ class DataTransferRoute extends PageRouteInfo { DataTransferRoute({ Key? key, required NearbyService nearbyService, - required List connectedDevice, + required List connectedDevices, List? children, }) : super( DataTransferRoute.name, args: DataTransferRouteArgs( key: key, nearbyService: nearbyService, - connectedDevice: connectedDevice, + connectedDevices: connectedDevices, ), initialChildren: children, ); @@ -413,18 +413,18 @@ class DataTransferRouteArgs { const DataTransferRouteArgs({ this.key, required this.nearbyService, - required this.connectedDevice, + required this.connectedDevices, }); final Key? key; final NearbyService nearbyService; - final List connectedDevice; + final List connectedDevices; @override String toString() { - return 'DataTransferRouteArgs{key: $key, nearbyService: $nearbyService, connectedDevice: $connectedDevice}'; + return 'DataTransferRouteArgs{key: $key, nearbyService: $nearbyService, connectedDevices: $connectedDevices}'; } } diff --git a/apps/health_campaign_field_worker_app/pubspec.lock b/apps/health_campaign_field_worker_app/pubspec.lock index 2ca6d4e118..a215a1a0ee 100644 --- a/apps/health_campaign_field_worker_app/pubspec.lock +++ b/apps/health_campaign_field_worker_app/pubspec.lock @@ -1651,6 +1651,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.11.1" + percent_indicator: + dependency: "direct main" + description: + name: percent_indicator + sha256: "0d77d5c6fa9b7f60202cedf748b568ba9ba38d3f30405d6ceae4da76f5185462" + url: "https://pub.dev" + source: hosted + version: "4.2.4" permission_handler: dependency: "direct main" description: diff --git a/apps/health_campaign_field_worker_app/pubspec.yaml b/apps/health_campaign_field_worker_app/pubspec.yaml index 32b5401fef..104b072673 100644 --- a/apps/health_campaign_field_worker_app/pubspec.yaml +++ b/apps/health_campaign_field_worker_app/pubspec.yaml @@ -83,6 +83,7 @@ dependencies: git: url: https://github.com/champeauxr/flutter_nearby_connections ref: master + percent_indicator: ^4.2.4 dev_dependencies: flutter_test: diff --git a/packages/registration_delivery/lib/blocs/search_households/individual_global_search.dart b/packages/registration_delivery/lib/blocs/search_households/individual_global_search.dart index 696df872ef..93b4436c76 100644 --- a/packages/registration_delivery/lib/blocs/search_households/individual_global_search.dart +++ b/packages/registration_delivery/lib/blocs/search_households/individual_global_search.dart @@ -94,6 +94,20 @@ class IndividualGlobalSearchBloc extends SearchHouseholdsBloc { ), ); + var finalHouseholdMembersList = await fetchHouseholdMembersBulk( + null, householdList.map((e) => e.clientReferenceId).toList()); + + individualsList = await individual.search(IndividualSearchModel( + clientReferenceId: finalHouseholdMembersList + .map((e) => e.individualClientReferenceId!) + .toList())); + + projectBeneficiariesList = await projectBeneficiary.search( + ProjectBeneficiarySearchModel( + projectId: [RegistrationDeliverySingleton().projectId.toString()], + beneficiaryClientReferenceId: + individualsList.map((e) => e.clientReferenceId).toList())); + projectBeneficiariesList = await projectBeneficiary.search( ProjectBeneficiarySearchModel( projectId: [RegistrationDeliverySingleton().projectId.toString()], @@ -108,7 +122,7 @@ class IndividualGlobalSearchBloc extends SearchHouseholdsBloc { referralsList = tasksRelated[2]; await _processHouseholdEntries( - householdMembers, + finalHouseholdMembersList, householdList, individualsList, projectBeneficiariesList, @@ -159,6 +173,20 @@ class IndividualGlobalSearchBloc extends SearchHouseholdsBloc { clientReferenceId: houseHoldClientReferenceIds, )); + var finalHouseholdMembersList = await fetchHouseholdMembersBulk( + null, householdList.map((e) => e.clientReferenceId).toList()); + + individualsList = await individual.search(IndividualSearchModel( + clientReferenceId: finalHouseholdMembersList + .map((e) => e.individualClientReferenceId!) + .toList())); + + projectBeneficiariesList = await projectBeneficiary.search( + ProjectBeneficiarySearchModel( + projectId: [RegistrationDeliverySingleton().projectId.toString()], + beneficiaryClientReferenceId: + individualsList.map((e) => e.clientReferenceId).toList())); + finalResults.forEach((element) { taskList.add(element); }); @@ -172,7 +200,7 @@ class IndividualGlobalSearchBloc extends SearchHouseholdsBloc { // Process household entries and add to containers await _processHouseholdEntries( - householdMembersList, + finalHouseholdMembersList, householdList, individualsList, projectBeneficiariesList, @@ -205,11 +233,19 @@ class IndividualGlobalSearchBloc extends SearchHouseholdsBloc { .toList(), )); + var finalHouseholdMembersList = await fetchHouseholdMembersBulk( + null, householdList.map((e) => e.clientReferenceId).toList()); + + individualsList = await individual.search(IndividualSearchModel( + clientReferenceId: finalHouseholdMembersList + .map((e) => e.individualClientReferenceId!) + .toList())); + projectBeneficiariesList = await projectBeneficiary.search( ProjectBeneficiarySearchModel( projectId: [RegistrationDeliverySingleton().projectId.toString()], beneficiaryClientReferenceId: - individualClientReferenceIds.map((e) => e).toList())); + individualsList.map((e) => e.clientReferenceId).toList())); List tasksRelated = await _processTasksAndRelatedData( projectBeneficiariesList, taskList, sideEffectsList, referralsList); @@ -219,7 +255,7 @@ class IndividualGlobalSearchBloc extends SearchHouseholdsBloc { referralsList = tasksRelated[2]; await _processHouseholdEntries( - householdMembers, + finalHouseholdMembersList, householdList, individualsList, projectBeneficiariesList, diff --git a/packages/registration_delivery/lib/data/repositories/local/individual_global_search.dart b/packages/registration_delivery/lib/data/repositories/local/individual_global_search.dart index abd395fef5..220a5fdd34 100644 --- a/packages/registration_delivery/lib/data/repositories/local/individual_global_search.dart +++ b/packages/registration_delivery/lib/data/repositories/local/individual_global_search.dart @@ -230,8 +230,7 @@ class IndividualGlobalSearchRepository extends LocalRepository { sql.householdMember, sql.householdMember.individualClientReferenceId .equalsExp(sql.individual.clientReferenceId)) - ]) - ..where(sql.householdMember.isHeadOfHousehold.equals(true)); + ]); selectQuery.join([ leftOuterJoin( sql.household, @@ -333,8 +332,8 @@ class IndividualGlobalSearchRepository extends LocalRepository { .equalsExp(sql.task.projectBeneficiaryClientReferenceId)), leftOuterJoin( sql.individual, - sql.individual.clientReferenceId - .equalsExp(sql.projectBeneficiary.beneficiaryClientReferenceId)), + sql.individual.clientReferenceId.equalsExp( + sql.projectBeneficiary.beneficiaryClientReferenceId)), ]) ..where(sql.task.status.equals( statusMap[applyFilter]!.toValue(), From 22d534cee2bb88ba082fd71e5633c7a465ea7508 Mon Sep 17 00:00:00 2001 From: Naveen Renati Date: Thu, 5 Dec 2024 12:57:35 +0530 Subject: [PATCH 05/16] updated hardcoded sync count, retry count and error api path --- .../digit_data_model/lib/data/data_repository.dart | 2 +- .../lib/data/repositories/oplog/oplog.dart | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/digit_data_model/lib/data/data_repository.dart b/packages/digit_data_model/lib/data/data_repository.dart index 6561840fde..869831b1f3 100644 --- a/packages/digit_data_model/lib/data/data_repository.dart +++ b/packages/digit_data_model/lib/data/data_repository.dart @@ -297,7 +297,7 @@ abstract class RemoteRepository { .syncedDownEqualTo(false) .nonRecoverableErrorEqualTo(false) .syncDownRetryCountGreaterThan( - 5 - 1, + DigitDataModelSingleton().syncDownRetryCount - 1, ) .createdByEqualTo(createdBy) .findAllSync(); @@ -112,7 +112,8 @@ abstract class OpLogManager { var oplogs = isar.opLogs .filter() .syncedUpEqualTo(true) - .syncDownRetryCountLessThan(5) + .syncDownRetryCountLessThan( + DigitDataModelSingleton().syncDownRetryCount) .syncedDownEqualTo(false) .entityTypeEqualTo(type) .findAllSync(); @@ -299,7 +300,8 @@ abstract class OpLogManager { OpLogEntry updatedEntry = entry.copyWith( syncDownRetryCount: syncDownRetryCount + 1, ); - if (updatedEntry.syncDownRetryCount >= 5) { + if (updatedEntry.syncDownRetryCount >= + DigitDataModelSingleton().syncDownRetryCount) { markAsNonRecoverable = true; updatedEntry = updatedEntry.copyWith(nonRecoverableError: true); } @@ -315,7 +317,8 @@ abstract class OpLogManager { await Future.delayed(const Duration(seconds: 1)); } else { await Future.delayed(Duration( - seconds: 5 * oplogs.first.syncDownRetryCount, + seconds: DigitDataModelSingleton().retryTimeInterval * + oplogs.first.syncDownRetryCount, )); } From d0a360a661af94583151d84f085ebe0ba90d62c4 Mon Sep 17 00:00:00 2001 From: Naveen Renati Date: Thu, 5 Dec 2024 14:57:43 +0530 Subject: [PATCH 06/16] Published digit_data_model version update --- .../health_campaign_field_worker_app/pubspec.lock | 15 ++++++++------- .../health_campaign_field_worker_app/pubspec.yaml | 2 +- packages/attendance_management/pubspec.lock | 4 ++-- packages/digit_data_model/CHANGELOG.md | 5 +++++ packages/digit_data_model/pubspec.yaml | 2 +- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/apps/health_campaign_field_worker_app/pubspec.lock b/apps/health_campaign_field_worker_app/pubspec.lock index c47910a9c9..20561c7a76 100644 --- a/apps/health_campaign_field_worker_app/pubspec.lock +++ b/apps/health_campaign_field_worker_app/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: "direct main" description: name: attendance_management - sha256: f1b4373e8d0d9f8227ede0d25d4141f0d16d18ac2525c0347b844098cdab080f + sha256: "8a09814ca11cca736d771be70fb6174303ea0cb3525aa72e7239cbc14b915303" url: "https://pub.dev" source: hosted - version: "1.0.2+1" + version: "1.0.2+4" audioplayers: dependency: "direct main" description: @@ -502,10 +502,10 @@ packages: dependency: "direct main" description: name: digit_data_model - sha256: "0e5a1f8c5f0548e573af9c0279942f2dbc332042865614e0b89fe5952002ef1f" + sha256: "08f5273e691cc16e0f89aefac97887abb63739b7db3a00165c1be269aacedffd" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.4+1" digit_dss: dependency: "direct main" description: @@ -517,9 +517,10 @@ packages: digit_firebase_services: dependency: "direct main" description: - path: "../../packages/digit_firebase_services" - relative: true - source: path + name: digit_firebase_services + sha256: ce76521d797e123b6fc95c9dfad7d4a918a93b97f57aecd0e1d517b46190909d + url: "https://pub.dev" + source: hosted version: "0.0.1" digit_location_tracker: dependency: "direct main" diff --git a/apps/health_campaign_field_worker_app/pubspec.yaml b/apps/health_campaign_field_worker_app/pubspec.yaml index 06d188a413..28a15c64d4 100644 --- a/apps/health_campaign_field_worker_app/pubspec.yaml +++ b/apps/health_campaign_field_worker_app/pubspec.yaml @@ -69,7 +69,7 @@ dependencies: digit_scanner: ^1.0.3+1 inventory_management: ^1.0.3+4 referral_reconciliation: ^1.0.2+2 - digit_data_model: ^1.0.4 + digit_data_model: ^1.0.4+1 registration_delivery: ^1.0.3+2 disable_battery_optimization: ^1.1.1 digit_dss: ^1.0.1 diff --git a/packages/attendance_management/pubspec.lock b/packages/attendance_management/pubspec.lock index 92c10cb88b..065d428475 100644 --- a/packages/attendance_management/pubspec.lock +++ b/packages/attendance_management/pubspec.lock @@ -326,10 +326,10 @@ packages: dependency: "direct main" description: name: digit_data_model - sha256: "0b81e96636496b56b4f9c5d918690a17d8985d6b131e0ab54968eb5471ee4f54" + sha256: "0e5a1f8c5f0548e573af9c0279942f2dbc332042865614e0b89fe5952002ef1f" url: "https://pub.dev" source: hosted - version: "1.0.3+1" + version: "1.0.4" dio: dependency: "direct main" description: diff --git a/packages/digit_data_model/CHANGELOG.md b/packages/digit_data_model/CHANGELOG.md index a297e79303..f433699dd2 100644 --- a/packages/digit_data_model/CHANGELOG.md +++ b/packages/digit_data_model/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.4+1 + +* Bug Fix: + * Updated syncRetryCount,syncRetryInterval and errorPath to dynamic + ## 1.0.4 * Added user_action entity for digit_location_tracker package diff --git a/packages/digit_data_model/pubspec.yaml b/packages/digit_data_model/pubspec.yaml index fd69a0da9d..5785218848 100644 --- a/packages/digit_data_model/pubspec.yaml +++ b/packages/digit_data_model/pubspec.yaml @@ -1,6 +1,6 @@ name: digit_data_model description: The digit_data_model package is a data modeling library. It defines various classes, enums, and functions. -version: 1.0.4 +version: 1.0.4+1 homepage: https://github.com/egovernments/health-campaign-field-worker-app/tree/master/packages/digit_data_model repository: https://github.com/egovernments/health-campaign-field-worker-app From 2260a0dc111051e5905058d8b10fce09d4fa8929 Mon Sep 17 00:00:00 2001 From: Naveen Renati Date: Fri, 6 Dec 2024 16:08:42 +0530 Subject: [PATCH 07/16] modified file structure of downsync data with batch wise added animation for file transfer and ui updates updated sender receiver logic to compress and decompress the data --- .../lib/blocs/peer_to_peer/peer_to_peer.dart | 345 ++++++++------ .../peer_to_peer/peer_to_peer.freezed.dart | 238 ++++++---- .../project_beneficiaries_downsync.dart | 40 +- .../lib/pages/peer_to_peer/data_receiver.dart | 70 ++- .../pages/peer_to_peer/data_share_home.dart | 2 + .../lib/pages/peer_to_peer/data_transfer.dart | 52 +-- .../lib/pages/peer_to_peer/devices_list.dart | 439 ++++++++---------- .../peer_to_peer/file_transfer_animation.dart | 76 +++ packages/attendance_management/pubspec.lock | 67 ++- 9 files changed, 738 insertions(+), 591 deletions(-) create mode 100644 apps/health_campaign_field_worker_app/lib/widgets/peer_to_peer/file_transfer_animation.dart diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart index 35c3a42dd1..c178b94cfe 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -35,7 +35,7 @@ class PeerToPeerBloc extends Bloc { List receivedData = []; int receivedBytes = 0; - int totalData = 0; + int totalCount = 0; String entityType = ''; late Device connectedDevice; PeerToPeerBloc({ @@ -57,189 +57,252 @@ class PeerToPeerBloc extends Bloc { ) async { try { emit(const PeerToPeerState.transferInProgress( - progress: 0, entityName: '')); + progress: 0, offset: 0, totalCount: 0)); final downloadsDirectory = await getDownloadsDirectory(); - final file = File('${downloadsDirectory!.path}/down_sync_data.json'); - final content = await file.readAsString(); - - if (content.isNotEmpty) { - final entities = jsonDecode(content); - - for (var entityName in entities.keys) { - List entityData = entities[entityName]!; - int totalSize = entityData.length; - int offset = 0; - - while (offset < totalSize) { - // Calculate the chunk - const int chunkSize = 1000; - int end = (offset + chunkSize < totalSize) - ? offset + chunkSize - : totalSize; - List chunk = entityData.sublist(offset, end); - - // Send the chunk - for (var device in event.connectedDevice) { - await event.nearbyService.sendMessage( - device.deviceId, - jsonEncode({ - "entityType": entityName, - "message": chunk, - "offset": offset + chunk.length, - "totalData": totalSize, - }), + if (await file.exists()) { + final fileStream = file.openRead(); + final jsonStream = + fileStream.transform(utf8.decoder).transform(json.decoder); + + await for (final offsets in jsonStream) { + // Ensure that 'entities' is a Map + if (offsets is! Map) { + emit(PeerToPeerState.failedToTransfer( + error: + 'Expected a Map, but got ${offsets.runtimeType}')); + return; + } + + final castedOffsets = offsets; + + for (var offset in castedOffsets.entries) { + int offsetValue = int.parse(offset.key); + Map offsetData = offset.value; + + var entityData = offsetData.keys + .where((element) => element == 'response') + .map((e) => offsetData[e]) + .toList(); + + totalCount = offsetData.keys + .where((element) => element == 'totalCount') + .map((e) => offsetData[e]) + .toList() + .first; + + for (var entity in entityData) { + Map entityResponse = entity; + + for (var device in event.connectedDevice) { + await event.nearbyService.sendMessage( + device.deviceId, + jsonEncode({ + "type": "chunk", + "message": compressJson(entityResponse), + "offset": offsetValue, + "totalData": totalCount, + }), + ); + } + + // Wait for confirmation before proceeding + await waitForConfirmation( + event.nearbyService, + confirmationType: "chunk", + offset: offsetValue, ); + + emit(PeerToPeerState.transferInProgress( + progress: offsetValue / totalCount, + offset: offsetValue, + totalCount: totalCount)); } + } - // Wait for chunk confirmation - await waitForConfirmation( - entityName, - event.nearbyService, - confirmationType: "chunk", - offset: offset + chunk.length, - ); + // Wait for final confirmation for the entity + await waitForConfirmation( + event.nearbyService, + confirmationType: "final", + ); - // Update progress - final progress = (offset + chunk.length) / totalSize; - emit(PeerToPeerState.transferInProgress( - progress: progress, entityName: entityName)); - offset = end; + // Send final acknowledgment to all devices + for (var device in event.connectedDevice) { + await event.nearbyService.sendMessage( + device.deviceId, + jsonEncode({ + "type": "confirmation", + "confirmationType": "finalTransfer", + "status": "completed", + "message": "All entities have been sent successfully.", + }), + ); } - // Wait for final confirmation + // Wait for receiver's overall acknowledgment await waitForConfirmation( - entityName, event.nearbyService, - confirmationType: "final", + confirmationType: "finalAcknowledgment", ); - } - emit(const PeerToPeerState.completedDataTransfer()); + emit(const PeerToPeerState.completedDataTransfer()); + } } } catch (e) { emit(PeerToPeerState.failedToTransfer(error: e.toString())); } } - Future waitForConfirmation( - String entityName, - NearbyService nearbyService, { - required String confirmationType, - int? offset, - }) async { - final completer = Completer(); + String compressJson(Map jsonData) { + // Convert JSON data to string + final jsonString = jsonEncode(jsonData); - final subscription = - nearbyService.dataReceivedSubscription(callback: (data) { - try { - var receivedJson = jsonDecode(data["message"]); - if (receivedJson["type"] == "confirmation" && - receivedJson["entityType"] == entityName && - receivedJson["confirmationType"] == confirmationType) { - if (confirmationType == "chunk" && - receivedJson["offset"] != null && - receivedJson["offset"] == offset) { - debugPrint("Chunk confirmation received for $entityName"); - completer.complete(); - } else if (confirmationType == "final") { - debugPrint("Final confirmation received for $entityName"); - completer.complete(); - } - } - } catch (e) { - debugPrint("Error processing confirmation: $e"); - } - }); + // Compress using zlib + final compressedData = zlib.encode(utf8.encode(jsonString)); - // Add timeout logic if required - await completer.future; - subscription.cancel(); + // Encode to Base64 to ensure JSON-compatible transmission + return base64.encode(compressedData); + } + + // Function to decompress JSON data + Map decompressJson(String base64Data) { + // Decode Base64 to binary data + final compressedData = base64.decode(base64Data); + + // Decompress using zlib + final decompressedString = utf8.decode(zlib.decode(compressedData)); + + // Convert back to JSON + return jsonDecode(decompressedString); } Future _handleReceiveEntities( DataReceiverEvent event, - Emitter emit, + PeerToPeerEmitter emit, ) async { try { - // Decode the received data var receivedJson = jsonDecode(event.data["message"]); - entityType = receivedJson["entityType"]; - int offset = receivedJson["offset"]; - totalData = receivedJson["totalData"]; - List receivedChunk = receivedJson["message"]; - - // Update received bytes and data - receivedBytes = offset; - double progress = receivedBytes / totalData; - receivedData.addAll(receivedChunk); - - // Emit progress for UI/State tracking - emit(PeerToPeerState.receivingInProgress( - progress: progress, entityName: entityType)); - - // Send a chunk-level confirmation - event.nearbyService.sendMessage( - event.data["deviceId"], - jsonEncode({ - "type": "confirmation", - "confirmationType": "chunk", - "entityType": entityType, - "status": "received", - "offset": offset, - "progress": progress, - "message": "Chunk received successfully.", - }), - ); + var messageType = receivedJson["type"]; + + if (messageType == "chunk") { + // Process chunk + int offset = receivedJson["offset"]; + int totalCount = receivedJson["totalData"]; + final compressedMessage = receivedJson["message"]; + final entityList = decompressJson(compressedMessage).entries; + + for (var entity in entityList) { + entityType = entity.key; + final List entityResponse = entity.value ?? []; + final entityList = + entityResponse.whereType>().toList(); + // Save chunk to database immediately + final local = RepositoryType.getLocalForType( + DataModels.getDataModelForEntityName(entityType), + [ + individualLocalRepository, + householdLocalRepository, + householdMemberLocalRepository, + projectBeneficiaryLocalRepository, + taskLocalRepository, + sideEffectLocalRepository, + referralLocalRepository, + ], + ); - // Check if all data is received - if (receivedBytes >= totalData) { - // Save the received entity data - final local = RepositoryType.getLocalForType( - DataModels.getDataModelForEntityName(entityType), - [ - individualLocalRepository, - householdLocalRepository, - householdMemberLocalRepository, - projectBeneficiaryLocalRepository, - taskLocalRepository, - sideEffectLocalRepository, - referralLocalRepository, - ], - ); + // Convert chunk to entity list and save it + createDbRecords(local, entityList, entityType); + } - final entityList = - receivedData.whereType>().toList(); - createDbRecords(local, entityList, entityType); + // Update progress and clear processed data + receivedBytes = offset; + double progress = receivedBytes / totalCount; - debugPrint("$entityType data saved successfully."); + // Emit progress + emit(PeerToPeerState.receivingInProgress( + progress: progress, + offset: offset, + totalCount: totalCount, + )); - // Clear buffer for the next entity - receivedData.clear(); - receivedBytes = 0; + // Send chunk acknowledgment + await event.nearbyService.sendMessage( + event.data["deviceId"], + jsonEncode({ + "type": "confirmation", + "confirmationType": "chunk", + "status": "received", + "offset": offset, + "progress": progress, + "message": "Chunk received and saved successfully.", + }), + ); + } else if (messageType == "confirmation" && + receivedJson["confirmationType"] == "allEntitiesTransferComplete") { + // Handle overall transfer final acknowledgment + emit(const PeerToPeerState.dataReceived()); - // Send a final confirmation - event.nearbyService.sendMessage( + // Send overall transfer acknowledgment + await event.nearbyService.sendMessage( event.data["deviceId"], jsonEncode({ "type": "confirmation", - "confirmationType": "final", - "entityType": entityType, + "confirmationType": "finalAcknowledgment", + "level": "overall", // Differentiator "status": "success", - "message": "$entityType saved successfully.", + "message": "All entities received and processed successfully.", }), ); - - // Emit final state - emit(const PeerToPeerState.dataReceived()); } } catch (e) { debugPrint("Error processing received data: $e"); emit(PeerToPeerState.failedToReceive(error: e.toString())); + await event.nearbyService.sendMessage( + event.data["deviceId"], + jsonEncode({ + "type": "confirmation", + "confirmationType": "failed", + "status": "fail", + "message": "$e", + }), + ); } } + + Future waitForConfirmation( + NearbyService nearbyService, { + required String confirmationType, + int? offset, + }) async { + final completer = Completer(); + + final subscription = nearbyService.dataReceivedSubscription( + callback: (data) { + try { + var receivedJson = jsonDecode(data["message"]); + if (receivedJson["type"] == "confirmation" && + receivedJson["confirmationType"] == confirmationType) { + if (confirmationType == "chunk" && + receivedJson["offset"] == offset) { + completer.complete(); + } else if (confirmationType == "final") { + completer.complete(); + } else if (confirmationType == "failed") { + completer.complete(); + throw "Failed to transfer ${receivedJson['message']}"; + } + } + } catch (e) { + debugPrint("Error processing confirmation: $e"); + } + }, + ); + + await completer.future; + subscription.cancel(); + } } @freezed @@ -260,7 +323,8 @@ class PeerToPeerState with _$PeerToPeerState { const factory PeerToPeerState.transferInProgress( {required double progress, - required String entityName}) = TransferInProgress; + required int offset, + required int totalCount}) = TransferInProgress; const factory PeerToPeerState.completedDataTransfer() = CompletedDataTransfer; @@ -269,7 +333,8 @@ class PeerToPeerState with _$PeerToPeerState { const factory PeerToPeerState.receivingInProgress( {required double progress, - required String entityName}) = ReceivingInProgress; + required int offset, + required int totalCount}) = ReceivingInProgress; const factory PeerToPeerState.dataReceived() = DataReceived; diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart index 7ea34437fc..715ea21f68 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart @@ -452,11 +452,11 @@ mixin _$PeerToPeerState { TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, @@ -466,10 +466,12 @@ mixin _$PeerToPeerState { TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress, String entityName)? transferInProgress, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress, String entityName)? receivingInProgress, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) => @@ -478,10 +480,12 @@ mixin _$PeerToPeerState { TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress, String entityName)? transferInProgress, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress, String entityName)? receivingInProgress, + TResult Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -593,11 +597,11 @@ class _$PeerToPeerInitialImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, @@ -610,10 +614,12 @@ class _$PeerToPeerInitialImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress, String entityName)? transferInProgress, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress, String entityName)? receivingInProgress, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -625,10 +631,12 @@ class _$PeerToPeerInitialImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress, String entityName)? transferInProgress, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress, String entityName)? receivingInProgress, + TResult Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -742,11 +750,11 @@ class _$PeerToPeerLoadingImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, @@ -759,10 +767,12 @@ class _$PeerToPeerLoadingImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress, String entityName)? transferInProgress, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress, String entityName)? receivingInProgress, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -774,10 +784,12 @@ class _$PeerToPeerLoadingImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress, String entityName)? transferInProgress, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress, String entityName)? receivingInProgress, + TResult Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -849,7 +861,7 @@ abstract class _$$TransferInProgressImplCopyWith<$Res> { $Res Function(_$TransferInProgressImpl) then) = __$$TransferInProgressImplCopyWithImpl<$Res>; @useResult - $Res call({double progress, String entityName}); + $Res call({double progress, int offset, int totalCount}); } /// @nodoc @@ -864,17 +876,22 @@ class __$$TransferInProgressImplCopyWithImpl<$Res> @override $Res call({ Object? progress = null, - Object? entityName = null, + Object? offset = null, + Object? totalCount = null, }) { return _then(_$TransferInProgressImpl( progress: null == progress ? _value.progress : progress // ignore: cast_nullable_to_non_nullable as double, - entityName: null == entityName - ? _value.entityName - : entityName // ignore: cast_nullable_to_non_nullable - as String, + offset: null == offset + ? _value.offset + : offset // ignore: cast_nullable_to_non_nullable + as int, + totalCount: null == totalCount + ? _value.totalCount + : totalCount // ignore: cast_nullable_to_non_nullable + as int, )); } } @@ -885,16 +902,18 @@ class _$TransferInProgressImpl with DiagnosticableTreeMixin implements TransferInProgress { const _$TransferInProgressImpl( - {required this.progress, required this.entityName}); + {required this.progress, required this.offset, required this.totalCount}); @override final double progress; @override - final String entityName; + final int offset; + @override + final int totalCount; @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'PeerToPeerState.transferInProgress(progress: $progress, entityName: $entityName)'; + return 'PeerToPeerState.transferInProgress(progress: $progress, offset: $offset, totalCount: $totalCount)'; } @override @@ -903,7 +922,8 @@ class _$TransferInProgressImpl properties ..add(DiagnosticsProperty('type', 'PeerToPeerState.transferInProgress')) ..add(DiagnosticsProperty('progress', progress)) - ..add(DiagnosticsProperty('entityName', entityName)); + ..add(DiagnosticsProperty('offset', offset)) + ..add(DiagnosticsProperty('totalCount', totalCount)); } @override @@ -913,12 +933,13 @@ class _$TransferInProgressImpl other is _$TransferInProgressImpl && (identical(other.progress, progress) || other.progress == progress) && - (identical(other.entityName, entityName) || - other.entityName == entityName)); + (identical(other.offset, offset) || other.offset == offset) && + (identical(other.totalCount, totalCount) || + other.totalCount == totalCount)); } @override - int get hashCode => Object.hash(runtimeType, progress, entityName); + int get hashCode => Object.hash(runtimeType, progress, offset, totalCount); @JsonKey(ignore: true) @override @@ -932,16 +953,16 @@ class _$TransferInProgressImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { - return transferInProgress(progress, entityName); + return transferInProgress(progress, offset, totalCount); } @override @@ -949,14 +970,16 @@ class _$TransferInProgressImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress, String entityName)? transferInProgress, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress, String entityName)? receivingInProgress, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { - return transferInProgress?.call(progress, entityName); + return transferInProgress?.call(progress, offset, totalCount); } @override @@ -964,16 +987,18 @@ class _$TransferInProgressImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress, String entityName)? transferInProgress, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress, String entityName)? receivingInProgress, + TResult Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), }) { if (transferInProgress != null) { - return transferInProgress(progress, entityName); + return transferInProgress(progress, offset, totalCount); } return orElse(); } @@ -1032,10 +1057,12 @@ class _$TransferInProgressImpl abstract class TransferInProgress implements PeerToPeerState { const factory TransferInProgress( {required final double progress, - required final String entityName}) = _$TransferInProgressImpl; + required final int offset, + required final int totalCount}) = _$TransferInProgressImpl; double get progress; - String get entityName; + int get offset; + int get totalCount; @JsonKey(ignore: true) _$$TransferInProgressImplCopyWith<_$TransferInProgressImpl> get copyWith => throw _privateConstructorUsedError; @@ -1092,11 +1119,11 @@ class _$CompletedDataTransferImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, @@ -1109,10 +1136,12 @@ class _$CompletedDataTransferImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress, String entityName)? transferInProgress, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress, String entityName)? receivingInProgress, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -1124,10 +1153,12 @@ class _$CompletedDataTransferImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress, String entityName)? transferInProgress, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress, String entityName)? receivingInProgress, + TResult Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -1270,11 +1301,11 @@ class _$FailedToTransferImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, @@ -1287,10 +1318,12 @@ class _$FailedToTransferImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress, String entityName)? transferInProgress, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress, String entityName)? receivingInProgress, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -1302,10 +1335,12 @@ class _$FailedToTransferImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress, String entityName)? transferInProgress, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress, String entityName)? receivingInProgress, + TResult Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -1383,7 +1418,7 @@ abstract class _$$ReceivingInProgressImplCopyWith<$Res> { $Res Function(_$ReceivingInProgressImpl) then) = __$$ReceivingInProgressImplCopyWithImpl<$Res>; @useResult - $Res call({double progress, String entityName}); + $Res call({double progress, int offset, int totalCount}); } /// @nodoc @@ -1398,17 +1433,22 @@ class __$$ReceivingInProgressImplCopyWithImpl<$Res> @override $Res call({ Object? progress = null, - Object? entityName = null, + Object? offset = null, + Object? totalCount = null, }) { return _then(_$ReceivingInProgressImpl( progress: null == progress ? _value.progress : progress // ignore: cast_nullable_to_non_nullable as double, - entityName: null == entityName - ? _value.entityName - : entityName // ignore: cast_nullable_to_non_nullable - as String, + offset: null == offset + ? _value.offset + : offset // ignore: cast_nullable_to_non_nullable + as int, + totalCount: null == totalCount + ? _value.totalCount + : totalCount // ignore: cast_nullable_to_non_nullable + as int, )); } } @@ -1419,16 +1459,18 @@ class _$ReceivingInProgressImpl with DiagnosticableTreeMixin implements ReceivingInProgress { const _$ReceivingInProgressImpl( - {required this.progress, required this.entityName}); + {required this.progress, required this.offset, required this.totalCount}); @override final double progress; @override - final String entityName; + final int offset; + @override + final int totalCount; @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'PeerToPeerState.receivingInProgress(progress: $progress, entityName: $entityName)'; + return 'PeerToPeerState.receivingInProgress(progress: $progress, offset: $offset, totalCount: $totalCount)'; } @override @@ -1437,7 +1479,8 @@ class _$ReceivingInProgressImpl properties ..add(DiagnosticsProperty('type', 'PeerToPeerState.receivingInProgress')) ..add(DiagnosticsProperty('progress', progress)) - ..add(DiagnosticsProperty('entityName', entityName)); + ..add(DiagnosticsProperty('offset', offset)) + ..add(DiagnosticsProperty('totalCount', totalCount)); } @override @@ -1447,12 +1490,13 @@ class _$ReceivingInProgressImpl other is _$ReceivingInProgressImpl && (identical(other.progress, progress) || other.progress == progress) && - (identical(other.entityName, entityName) || - other.entityName == entityName)); + (identical(other.offset, offset) || other.offset == offset) && + (identical(other.totalCount, totalCount) || + other.totalCount == totalCount)); } @override - int get hashCode => Object.hash(runtimeType, progress, entityName); + int get hashCode => Object.hash(runtimeType, progress, offset, totalCount); @JsonKey(ignore: true) @override @@ -1466,16 +1510,16 @@ class _$ReceivingInProgressImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, }) { - return receivingInProgress(progress, entityName); + return receivingInProgress(progress, offset, totalCount); } @override @@ -1483,14 +1527,16 @@ class _$ReceivingInProgressImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress, String entityName)? transferInProgress, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress, String entityName)? receivingInProgress, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { - return receivingInProgress?.call(progress, entityName); + return receivingInProgress?.call(progress, offset, totalCount); } @override @@ -1498,16 +1544,18 @@ class _$ReceivingInProgressImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress, String entityName)? transferInProgress, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress, String entityName)? receivingInProgress, + TResult Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), }) { if (receivingInProgress != null) { - return receivingInProgress(progress, entityName); + return receivingInProgress(progress, offset, totalCount); } return orElse(); } @@ -1566,10 +1614,12 @@ class _$ReceivingInProgressImpl abstract class ReceivingInProgress implements PeerToPeerState { const factory ReceivingInProgress( {required final double progress, - required final String entityName}) = _$ReceivingInProgressImpl; + required final int offset, + required final int totalCount}) = _$ReceivingInProgressImpl; double get progress; - String get entityName; + int get offset; + int get totalCount; @JsonKey(ignore: true) _$$ReceivingInProgressImplCopyWith<_$ReceivingInProgressImpl> get copyWith => throw _privateConstructorUsedError; @@ -1621,11 +1671,11 @@ class _$DataReceivedImpl with DiagnosticableTreeMixin implements DataReceived { TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, @@ -1638,10 +1688,12 @@ class _$DataReceivedImpl with DiagnosticableTreeMixin implements DataReceived { TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress, String entityName)? transferInProgress, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress, String entityName)? receivingInProgress, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -1653,10 +1705,12 @@ class _$DataReceivedImpl with DiagnosticableTreeMixin implements DataReceived { TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress, String entityName)? transferInProgress, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress, String entityName)? receivingInProgress, + TResult Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), @@ -1799,11 +1853,11 @@ class _$FailedDataTransferImpl TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) transferInProgress, required TResult Function() completedDataTransfer, required TResult Function(String error) failedToTransfer, - required TResult Function(double progress, String entityName) + required TResult Function(double progress, int offset, int totalCount) receivingInProgress, required TResult Function() dataReceived, required TResult Function(String error) failedToReceive, @@ -1816,10 +1870,12 @@ class _$FailedDataTransferImpl TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, - TResult? Function(double progress, String entityName)? transferInProgress, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, TResult? Function()? completedDataTransfer, TResult? Function(String error)? failedToTransfer, - TResult? Function(double progress, String entityName)? receivingInProgress, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult? Function()? dataReceived, TResult? Function(String error)? failedToReceive, }) { @@ -1831,10 +1887,12 @@ class _$FailedDataTransferImpl TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(double progress, String entityName)? transferInProgress, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, TResult Function()? completedDataTransfer, TResult Function(String error)? failedToTransfer, - TResult Function(double progress, String entityName)? receivingInProgress, + TResult Function(double progress, int offset, int totalCount)? + receivingInProgress, TResult Function()? dataReceived, TResult Function(String error)? failedToReceive, required TResult orElse(), diff --git a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart index ee4787e15e..2a3fde44db 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart @@ -296,28 +296,28 @@ class BeneficiaryDownSyncBloc await file.writeAsString( jsonEncode({})); // Initialize with an empty JSON object } + var downSyncModel = response["DownsyncCriteria"]; + // Create a unique key using just the offset + String uniqueKey = '${downSyncModel["offset"]}'; + response.removeWhere((key, value) => key == 'DownsyncCriteria'); - // Merge new response with stored data - response.forEach((key, value) { - if (key != "DownsyncCriteria") { - if (storedData.containsKey(key)) { - final existingList = storedData[key] as List? ?? []; - final newList = value as List? ?? []; - - final mergedList = [ - ...existingList, - ...newList.where((newItem) => existingList - .every((existingItem) => existingItem['id'] != newItem['id'])) - ]; - storedData[key] = mergedList; - } else { - storedData[key] = value; - } - } - }); + // Prepare data to insert + Map data = { + "totalCount": downSyncModel["totalCount"], + "response": response, + "boundaryCode": selectedBoundaryCode, + }; + + // Store the data under the unique key + storedData[uniqueKey] = data; + + // Convert map to JSON string + String storedDataString = jsonEncode(storedData); + + debugPrint("Stored data: $storedDataString"); - // Write the merged data back to the file - await file.writeAsString(jsonEncode(storedData)); + // Write the updated data back to the file + await file.writeAsString(storedDataString); if (kDebugMode) { print("Data successfully written to ${file.path}"); diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart index 6938526845..a20d947b83 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -15,6 +15,7 @@ import '../../blocs/peer_to_peer/peer_to_peer.dart'; import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../widgets/localized.dart'; +import '../../widgets/peer_to_peer/file_transfer_animation.dart'; import '../../widgets/showcase/showcase_wrappers.dart'; @RoutePage() @@ -45,13 +46,15 @@ class _DataReceiverPageState extends LocalizedState { nearbyService.stateChangedSubscription(callback: (devices) { for (var device in devices) { if (device.state == SessionState.notConnected) { - context.router.maybePop(); - DigitToast.show(context, - options: DigitToastOptions( - localizations.translate( - '${device.deviceName} ${SessionState.notConnected.name}'), - true, - Theme.of(context))); + if (mounted) { + context.router.maybePop(); + DigitToast.show(context, + options: DigitToastOptions( + localizations.translate( + '${device.deviceName} ${SessionState.notConnected.name}'), + true, + Theme.of(context))); + } } } }); @@ -90,7 +93,9 @@ class _DataReceiverPageState extends LocalizedState { Button( type: ButtonType.secondary, mainAxisSize: MainAxisSize.max, - onPressed: () {}, + onPressed: () { + context.router.maybePop(); + }, label: localizations .translate(i18.common.coreCommonCancel), size: ButtonSize.large, @@ -129,7 +134,7 @@ class _DataReceiverPageState extends LocalizedState { .height * 0.15, lineWidth: kPadding * 1.5, - animation: false, + animation: true, percent: 0, // Update this dynamically for progress center: const Text( @@ -151,30 +156,17 @@ class _DataReceiverPageState extends LocalizedState { mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.smartphone, - size: 40, - color: DigitTheme.instance - .colors.light.primary2), - const SizedBox(width: 8), - const Text( - 'Receiving from', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500), - ), - const SizedBox(width: 8), - Icon(Icons.smartphone, - size: 40, - color: DigitTheme.instance - .colors.light.primary2), + FileTransferAnimation(), // Add animation here ], ), Wrap( spacing: 8.0, runSpacing: 4.0, children: [ - buildDeviceChip(), + // buildDeviceChip(), Container( + padding: const EdgeInsets.all( + kPadding), decoration: BoxDecoration( border: Border.all( color: DigitTheme @@ -200,14 +192,15 @@ class _DataReceiverPageState extends LocalizedState { ], ), ), - receivingInProgress: (progress, receivingEntity) { + receivingInProgress: + (progress, offset, totalCount) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text('Receiving $receivingEntity'), + Text('Receiving $offset / $totalCount'), const SizedBox(height: 16), CircularPercentIndicator( radius: @@ -236,22 +229,7 @@ class _DataReceiverPageState extends LocalizedState { mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.smartphone, - size: 40, - color: DigitTheme.instance.colors - .light.primary2), - const SizedBox(width: 8), - const Text( - 'Receiving from', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500), - ), - const SizedBox(width: 8), - Icon(Icons.smartphone, - size: 40, - color: DigitTheme.instance.colors - .light.primary2), + FileTransferAnimation(), // Add animation here ], ), Wrap( @@ -259,7 +237,10 @@ class _DataReceiverPageState extends LocalizedState { runSpacing: 4.0, children: [ buildDeviceChip(), + const SizedBox(width: 8), Container( + padding: const EdgeInsets.all( + kPadding), decoration: BoxDecoration( border: Border.all( color: DigitTheme.instance @@ -319,6 +300,7 @@ class _DataReceiverPageState extends LocalizedState { } else if (snapshot.hasData) { // Display the device name when available return Container( + padding: const EdgeInsets.all(kPadding), decoration: BoxDecoration( border: Border.all( color: DigitTheme.instance.colors.light.primary1Bg, diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart index 753e07ed06..5b22b64560 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart @@ -44,6 +44,7 @@ class _DataShareHomeState extends LocalizedState { height: MediaQuery.of(context).size.height * 0.2, child: DigitCard( margin: const EdgeInsets.all(kPadding * 2), + inline: true, onPressed: () { context.router .push(DevicesListRoute(deviceType: DeviceType.sender)); @@ -67,6 +68,7 @@ class _DataShareHomeState extends LocalizedState { width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height * 0.2, child: DigitCard( + inline: true, margin: const EdgeInsets.all(kPadding * 2), onPressed: () { context.router diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart index 5d0a0edda2..3dff9128df 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -15,6 +15,7 @@ import '../../blocs/peer_to_peer/peer_to_peer.dart'; import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../widgets/localized.dart'; +import '../../widgets/peer_to_peer/file_transfer_animation.dart'; import '../../widgets/showcase/showcase_wrappers.dart'; @RoutePage() @@ -45,13 +46,15 @@ class _DataTransferScreenState extends LocalizedState { nearbyService.stateChangedSubscription(callback: (devices) { for (var device in devices) { if (device.state == SessionState.notConnected) { - context.router.maybePop(); - DigitToast.show(context, - options: DigitToastOptions( - localizations.translate( - '${device.deviceName} ${SessionState.notConnected.name}'), - true, - Theme.of(context))); + if (mounted) { + context.router.maybePop(); + DigitToast.show(context, + options: DigitToastOptions( + localizations.translate( + '${device.deviceName} ${SessionState.notConnected.name}'), + true, + Theme.of(context))); + } } } }); @@ -59,6 +62,7 @@ class _DataTransferScreenState extends LocalizedState { @override void dispose() { + widget.nearbyService.stopAdvertisingPeer(); super.dispose(); } @@ -88,7 +92,9 @@ class _DataTransferScreenState extends LocalizedState { Button( type: ButtonType.secondary, mainAxisSize: MainAxisSize.max, - onPressed: () {}, + onPressed: () { + context.router.maybePop(); + }, label: localizations.translate(i18.common.coreCommonCancel), size: ButtonSize.large, ), @@ -122,7 +128,7 @@ class _DataTransferScreenState extends LocalizedState { radius: MediaQuery.of(context).size.height * 0.15, lineWidth: kPadding * 1.5, - animation: false, + animation: true, percent: 0, // Update this dynamically for progress center: const Text( @@ -141,18 +147,18 @@ class _DataTransferScreenState extends LocalizedState { ], ), ), - transferInProgress: (progress, sendingEntity) => + transferInProgress: (progress, offset, totalCount) => Column( mainAxisSize: MainAxisSize.max, children: [ const SizedBox(height: 16), - Text('Transferring $sendingEntity'), + Text('Transferring $offset / $totalCount'), const SizedBox(height: 16), CircularPercentIndicator( radius: MediaQuery.of(context).size.height * 0.15, lineWidth: kPadding * 1.5, - animation: false, + animation: true, percent: progress, // Update this dynamically for progress center: Text( @@ -172,27 +178,14 @@ class _DataTransferScreenState extends LocalizedState { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.smartphone, - size: 40, - color: DigitTheme - .instance.colors.light.primary2), - const SizedBox(width: 8), - const Text( - 'Transferring to', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500), - ), - const SizedBox(width: 8), - Icon(Icons.smartphone, - size: 40, - color: DigitTheme - .instance.colors.light.primary2), + FileTransferAnimation(), // Add animation here ], ), Wrap(spacing: 8.0, runSpacing: 4.0, children: [ - buildDeviceChip(), + // buildDeviceChip(), + const SizedBox(width: 8), Container( + padding: const EdgeInsets.all(kPadding), decoration: BoxDecoration( border: Border.all( color: DigitTheme @@ -267,6 +260,7 @@ class _DataTransferScreenState extends LocalizedState { } else if (snapshot.hasData) { // Display the device name when available return Container( + padding: const EdgeInsets.all(kPadding), decoration: BoxDecoration( border: Border.all( color: DigitTheme.instance.colors.light.primary1Bg, diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart index 7d753d2ea5..287e24862c 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -8,7 +8,6 @@ import 'package:digit_components/widgets/atoms/digit_toaster.dart'; import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/digit_extended_theme.dart'; import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; @@ -31,26 +30,24 @@ class DevicesListPage extends LocalizedStatefulWidget { class DevicesListPageState extends LocalizedState with TickerProviderStateMixin { - List devices = []; - List connectedDevices = []; + final List devices = []; + final List connectedDevices = []; + late final Device senderDeviceDetails; late NearbyService nearbyService; - late StreamSubscription subscription; + late StreamSubscription stateSubscription; late AnimationController _controller; late AnimationController _radarController; - bool isInit = false; - double rippleRadius = 0; - @override void initState() { super.initState(); - createAnimation(); - init(); + createAnimations(); + initializeNearbyService(); } @override void dispose() { - subscription.cancel(); + stateSubscription.cancel(); nearbyService.stopBrowsingForPeers(); nearbyService.stopAdvertisingPeer(); _controller.dispose(); @@ -58,7 +55,6 @@ class DevicesListPageState extends LocalizedState super.dispose(); } - @override @override Widget build(BuildContext context) { final theme = Theme.of(context); @@ -71,64 +67,27 @@ class DevicesListPageState extends LocalizedState backgroundColor: DigitTheme.instance.colors.light.primary1Bg, enableFixedButton: true, footer: DigitCard( - margin: const EdgeInsets.only(top: spacer2), - padding: const EdgeInsets.all(spacer2), + margin: const EdgeInsets.only(top: 16.0), + padding: const EdgeInsets.all(16.0), children: [ - if (widget.deviceType == DeviceType.sender) - Button( - onPressed: () { - if (connectedDevices.isNotEmpty) { - context.router.push(DataTransferRoute( - connectedDevices: connectedDevices, - nearbyService: nearbyService, - )); - } else { - DigitToast.show(context, - options: DigitToastOptions( - localizations - .translate(i18.dataShare.noDevicesConnected), - true, - theme)); - } - }, - type: ButtonType.primary, - label: localizations.translate(i18.dataShare.sendAction), - size: ButtonSize.large, - mainAxisSize: MainAxisSize.max, - ), - if (widget.deviceType == DeviceType.receiver) - Button( - onPressed: () { - if (connectedDevices.isNotEmpty) { - context.router.push(DataReceiverRoute( - connectedDevice: connectedDevices.first, - nearbyService: nearbyService, - )); - } else { - DigitToast.show(context, - options: DigitToastOptions( - localizations - .translate(i18.dataShare.noDevicesConnected), - true, - theme)); - } - }, - type: ButtonType.primary, - label: localizations.translate(i18.dataShare.receiveAction), - size: ButtonSize.large, - mainAxisSize: MainAxisSize.max, - ), + Button( + onPressed: handleFooterButtonPress, + type: ButtonType.primary, + label: widget.deviceType == DeviceType.sender + ? localizations.translate(i18.dataShare.sendAction) + : localizations.translate(i18.dataShare.receiveAction), + size: ButtonSize.large, + mainAxisSize: MainAxisSize.max, + ), ], ), slivers: [ SliverToBoxAdapter( child: Column( children: [ - const BackNavigationHelpHeaderWidget( - showHelp: true, - ), + const BackNavigationHelpHeaderWidget(showHelp: true), Padding( - padding: const EdgeInsets.all(kPadding), + padding: const EdgeInsets.all(16.0), child: Align( alignment: Alignment.topLeft, child: Text( @@ -137,59 +96,7 @@ class DevicesListPageState extends LocalizedState ), ), ), - Container( - height: screenHeight * 0.6, - width: screenWidth * 0.9, - margin: const EdgeInsets.all(kPadding), - decoration: BoxDecoration( - color: DigitTheme.instance.colors.light.primary2, - borderRadius: BorderRadius.circular(kPadding), - ), - child: Stack( - alignment: Alignment.center, - children: [ - // Radar Circles - ...List.generate(3, (index) { - return Container( - width: screenWidth * 0.5 + (index * 50), - height: screenHeight * 0.3 + (index * 50), - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: DigitTheme.instance.colors.light.primary1Bg - .withOpacity(0.3), - ), - ), - ); - }), - // Radar Sweep - AnimatedBuilder( - animation: _controller, - builder: (context, child) { - return Transform.rotate( - angle: _controller.value * 2 * pi, - child: Container( - width: screenWidth * 0.9, - height: screenHeight * 0.6, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: SweepGradient( - colors: [ - Colors.white.withOpacity(0.3), - Colors.transparent, - ], - stops: const [0.7, 1.0], - ), - ), - ), - ); - }, - ), - ..._generateRandomDevicePositions( - devices, screenWidth * 0.9, screenHeight * 0.6), - ], - ), - ) + buildRadarScreen(screenWidth, screenHeight), ], ), ) @@ -198,48 +105,81 @@ class DevicesListPageState extends LocalizedState ); } - List _generateRandomDevicePositions( - List devices, double width, double height) { + Widget buildRadarScreen(double width, double height) { + return Container( + height: height * 0.6, + width: width * 0.9, + margin: const EdgeInsets.all(16.0), + decoration: BoxDecoration( + color: DigitTheme.instance.colors.light.primary2, + borderRadius: BorderRadius.circular(16.0), + ), + child: Stack( + alignment: Alignment.center, + children: [ + ...List.generate(3, (index) { + return Container( + width: width * 0.5 + (index * 50), + height: height * 0.3 + (index * 50), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: DigitTheme.instance.colors.light.primary1Bg + .withOpacity(0.3), + ), + ), + ); + }), + AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return Transform.rotate( + angle: _controller.value * 2 * pi, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: SweepGradient( + colors: [ + Colors.white.withOpacity(0.3), + Colors.transparent, + ], + stops: const [0.7, 1.0], + ), + ), + ), + ); + }, + ), + ...generateDeviceWidgets(width * 0.9, height * 0.6), + ], + ), + ); + } + + List generateDeviceWidgets(double width, double height) { final random = Random(); - return widget.deviceType == DeviceType.receiver - ? connectedDevices.asMap().entries.map((entry) { - // Use the device index to offset the randomization for uniqueness - final angle = random.nextDouble() * 2 * pi + - entry.key * 0.1; // slight offset for uniqueness - final radius = random.nextDouble() * rippleRadius; - final x = radius * cos(angle); - final y = radius * sin(angle); + final devicesToShow = + widget.deviceType == DeviceType.receiver ? connectedDevices : devices; - return Positioned( - left: width / 2 + x - 20, // Adjust based on the container size - top: height / 2 + y - 20, - child: _buildDeviceWidget(entry.value), - ); - }).toList() - : devices.asMap().entries.map((entry) { - final angle = random.nextDouble() * 2 * pi + - entry.key * 0.1; // slight offset for uniqueness - final radius = (random.nextDouble() * rippleRadius) + - 20; // Ensure enough space between devices - final x = radius * cos(angle); - final y = radius * sin(angle); + return devicesToShow.asMap().entries.map((entry) { + final angle = random.nextDouble() * 2 * pi + entry.key * 0.1; + final radius = 50 + random.nextDouble() * 100; + final x = radius * cos(angle); + final y = radius * sin(angle); - return Positioned( - left: width / 2 + x - 20, - top: height / 2 + y - 20, - child: _buildDeviceWidget(entry.value), - ); - }).toList(); + return Positioned( + left: width / 2 + x - 20, + top: height / 2 + y - 20, + child: buildDeviceWidget(entry.value), + ); + }).toList(); } - // Build each device widget with icon and name - Widget _buildDeviceWidget(Device device) { - return device.state == SessionState.connecting - ? const CircularProgressIndicator() - : GestureDetector( - onTap: () { - _onButtonClicked(device); - }, + Widget buildDeviceWidget(Device device) { + return device.state == SessionState.connected || + device.state == SessionState.notConnected + ? GestureDetector( + onTap: () => handleDeviceTap(device), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -288,7 +228,45 @@ class DevicesListPageState extends LocalizedState ), ], ), - ); + ) + : const CircularProgressIndicator(); + } + + void handleFooterButtonPress() { + if (connectedDevices.isEmpty) { + DigitToast.show( + context, + options: DigitToastOptions( + localizations.translate(i18.dataShare.noDevicesConnected), + true, + Theme.of(context), + ), + ); + return; + } + + if (widget.deviceType == DeviceType.sender) { + context.router.push(DataTransferRoute( + connectedDevices: connectedDevices, + nearbyService: nearbyService, + )); + } else { + context.router.push(DataReceiverRoute( + connectedDevice: connectedDevices.first, + nearbyService: nearbyService, + )); + } + } + + void handleDeviceTap(Device device) { + if (device.state == SessionState.notConnected) { + nearbyService.invitePeer( + deviceID: device.deviceId, + deviceName: device.deviceName, + ); + } else if (device.state == SessionState.connected) { + nearbyService.disconnectPeer(deviceID: device.deviceId); + } } String getStateName(SessionState state) { @@ -310,125 +288,70 @@ class DevicesListPageState extends LocalizedState return DigitTheme.instance.colors.light.alertWarning; case SessionState.connecting: return DigitTheme.instance.colors.light.alertWarning; - default: + case SessionState.connected: return DigitTheme.instance.colors.light.alertSuccess; + default: + return Colors.grey; } } - int getItemCount() { - if (widget.deviceType == DeviceType.receiver) { - return connectedDevices.length; - } else { - return devices.length; - } + void createAnimations() { + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 10), + )..repeat(); + _radarController = AnimationController( + vsync: this, + duration: const Duration(seconds: 10), + )..repeat(); } - _onButtonClicked(Device device) { - switch (device.state) { - case SessionState.notConnected: - nearbyService.invitePeer( - deviceID: device.deviceId, - deviceName: device.deviceName, - ); - break; - case SessionState.connected: - nearbyService.disconnectPeer(deviceID: device.deviceId); - break; - case SessionState.connecting: - break; - } - } + Future initializeNearbyService() async { + final deviceInfo = DeviceInfoPlugin(); + final deviceId = Platform.isAndroid + ? (await deviceInfo.androidInfo).model + : (await deviceInfo.iosInfo).localizedModel; - void init() async { nearbyService = NearbyService(); - String deviceId = ''; - DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - final Set navigatedDevices = {}; - - if (Platform.isAndroid) { - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - deviceId = androidInfo.model; - } - if (Platform.isIOS) { - IosDeviceInfo iosInfo = await deviceInfo.iosInfo; - deviceId = iosInfo.localizedModel; - } await nearbyService.init( - serviceType: 'mpconn', // TODO: Replace with Digit service type - deviceName: deviceId, - strategy: Strategy.Wi_Fi_P2P, - callback: (isRunning) async { - if (isRunning) { - if (widget.deviceType == DeviceType.sender) { - await nearbyService.stopBrowsingForPeers(); - await Future.delayed(const Duration(microseconds: 200)); - await nearbyService.startBrowsingForPeers(); - } else { - await nearbyService.stopAdvertisingPeer(); - await nearbyService.stopBrowsingForPeers(); - await Future.delayed(const Duration(microseconds: 200)); - await nearbyService.startAdvertisingPeer(); - await nearbyService.startBrowsingForPeers(); - } - } - }); - subscription = - nearbyService.stateChangedSubscription(callback: (devicesList) { - if (devicesList.isNotEmpty) { - for (var device in devicesList) { - var element = device; - - if (kDebugMode) { - print( - "deviceId: ${element.deviceId} | deviceName: ${element.deviceName} | state: ${element.state}"); + serviceType: 'mpconn', + deviceName: deviceId, + strategy: Strategy.Wi_Fi_P2P, + callback: (isRunning) async { + if (isRunning) { + if (widget.deviceType == DeviceType.sender) { + await nearbyService.startBrowsingForPeers(); + } else { + await nearbyService.startAdvertisingPeer(); } + } + }, + ); - // Handle Android-specific browsing - if (Platform.isAndroid) { - if (element.state == SessionState.connected) { - DigitToast.show(context, - options: DigitToastOptions( - localizations - .translate('${element.deviceName} is connected'), - false, - Theme.of(context))); - } else if (element.state == SessionState.notConnected) { - nearbyService.startBrowsingForPeers(); - navigatedDevices.remove( - element.deviceId); // Allow re-navigation if disconnected - } + stateSubscription = nearbyService.stateChangedSubscription( + callback: (devicesList) { + setState(() { + // Clear the existing lists to avoid stale data + devices.clear(); + connectedDevices.clear(); + // Deduplicate the devices list + final uniqueDevices = {}; + // Separate devices based on their connection state + for (var device in devicesList) { + uniqueDevices[device.deviceId] = + device; // Replace entries with the same deviceId } - setState(() { - // Deduplicate the devices list - final uniqueDevices = - {}; // Use a map for deduplication - for (var device in devicesList) { - uniqueDevices[device.deviceId] = - device; // Replace entries with the same deviceId - } + // Update the devices list and connected devices + devices + ..clear() + ..addAll(uniqueDevices.values); // Add only unique devices - // Update the devices list and connected devices - devices - ..clear() - ..addAll(uniqueDevices.values); // Add only unique devices - - connectedDevices - ..clear() - ..addAll(devices.where((d) => d.state == SessionState.connected)); - }); - } - } - }); - } - - void createAnimation() { - _controller = - AnimationController(vsync: this, duration: const Duration(seconds: 10)) - ..repeat(); - _radarController = AnimationController( - duration: const Duration(seconds: 10), - vsync: this, - )..repeat(reverse: false); + connectedDevices + ..clear() + ..addAll(devices.where((d) => d.state == SessionState.connected)); + }); + }, + ); } } diff --git a/apps/health_campaign_field_worker_app/lib/widgets/peer_to_peer/file_transfer_animation.dart b/apps/health_campaign_field_worker_app/lib/widgets/peer_to_peer/file_transfer_animation.dart new file mode 100644 index 0000000000..eee2f5c1df --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/widgets/peer_to_peer/file_transfer_animation.dart @@ -0,0 +1,76 @@ +import 'package:digit_ui_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +class FileTransferAnimation extends StatefulWidget { + @override + _FileTransferAnimationState createState() => _FileTransferAnimationState(); +} + +class _FileTransferAnimationState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation _animation; + + @override + void initState() { + super.initState(); + + // Initialize the AnimationController + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 2), + )..repeat(); // Repeat animation indefinitely + + // Define the animation (from 0 to 1) + _animation = Tween(begin: 0, end: 1).animate( + CurvedAnimation(parent: _controller, curve: Curves.easeInOut), + ); + } + + @override + void dispose() { + // Dispose of the controller to avoid memory leaks + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + // Animation widget + return SizedBox( + height: 100, + child: Stack( + alignment: Alignment.center, + children: [ + // Static Phone Icons + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.smartphone, + size: 50, color: DigitTheme.instance.colors.light.primary2), + const SizedBox(width: 100), // Distance between the two phones + Icon(Icons.smartphone, + size: 50, color: DigitTheme.instance.colors.light.primary2), + ], + ), + // Moving file icon + AnimatedBuilder( + animation: _animation, + builder: (context, child) { + return Positioned( + left: 50.0 + + (_animation.value * + 100), // Move horizontally between phones + child: Icon( + Icons.insert_drive_file, + size: 24, + color: DigitTheme.instance.colors.light.textSecondary, + ), + ); + }, + ), + ], + ), + ); + } +} diff --git a/packages/attendance_management/pubspec.lock b/packages/attendance_management/pubspec.lock index de4b65da02..d368b888ab 100644 --- a/packages/attendance_management/pubspec.lock +++ b/packages/attendance_management/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "64.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + url: "https://pub.dev" + source: hosted + version: "1.3.25" analyzer: dependency: transitive description: @@ -362,21 +370,20 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.1" - digit_components: + digit_data_model: dependency: "direct main" description: - path: "../digit_components" + path: "../digit_data_model" relative: true source: path - version: "1.0.2+1" - digit_data_model: - dependency: "direct main" - description: - name: digit_data_model - sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" - url: "https://pub.dev" - source: hosted version: "1.0.5-dev.1" + digit_firebase_services: + dependency: "direct overridden" + description: + path: "../digit_firebase_services" + relative: true + source: path + version: "0.0.1" digit_ui_components: dependency: "direct main" description: @@ -497,6 +504,46 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + url: "https://pub.dev" + source: hosted + version: "2.27.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: b94b217e3ad745e784960603d33d99471621ecca151c99c670869b76e50ad2a6 + url: "https://pub.dev" + source: hosted + version: "5.3.1" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + url: "https://pub.dev" + source: hosted + version: "2.11.5" + firebase_crashlytics: + dependency: transitive + description: + name: firebase_crashlytics + sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 + url: "https://pub.dev" + source: hosted + version: "3.4.18" + firebase_crashlytics_platform_interface: + dependency: transitive + description: + name: firebase_crashlytics_platform_interface + sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 + url: "https://pub.dev" + source: hosted + version: "3.6.25" fixnum: dependency: transitive description: From 23266f9df24f1cea843d6b1986099625fc3762c6 Mon Sep 17 00:00:00 2001 From: Naveen Renati <154230258+naveenr-egov@users.noreply.github.com> Date: Mon, 30 Dec 2024 10:59:12 +0530 Subject: [PATCH 08/16] Final acknowledgment fixes --- .../lib/blocs/peer_to_peer/peer_to_peer.dart | 9 +- .../project_beneficiaries_downsync.dart | 14 +- .../lib/pages/peer_to_peer/data_receiver.dart | 18 +- .../lib/pages/peer_to_peer/data_transfer.dart | 14 +- .../pubspec.lock | 32 +- packages/attendance_management/pubspec.lock | 62 +-- packages/closed_household/pubspec.lock | 62 +-- packages/complaints/example/pubspec.lock | 9 +- packages/complaints/pubspec.lock | 71 +-- packages/digit_components/pubspec.lock | 31 -- packages/digit_dss/pubspec.lock | 463 +++++++++++++++++- packages/digit_firebase_services/pubspec.lock | 392 +-------------- packages/digit_location_tracker/pubspec.lock | 57 ++- packages/forms_engine/pubspec.lock | 11 +- packages/inventory_management/pubspec.lock | 7 +- packages/referral_reconciliation/pubspec.lock | 69 +-- packages/registration_delivery/pubspec.lock | 62 +-- packages/survey_form/pubspec.lock | 62 +-- 18 files changed, 599 insertions(+), 846 deletions(-) diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart index c178b94cfe..7f89efc049 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -38,6 +38,7 @@ class PeerToPeerBloc extends Bloc { int totalCount = 0; String entityType = ''; late Device connectedDevice; + PeerToPeerBloc({ required this.individualLocalRepository, required this.householdLocalRepository, @@ -122,12 +123,6 @@ class PeerToPeerBloc extends Bloc { } } - // Wait for final confirmation for the entity - await waitForConfirmation( - event.nearbyService, - confirmationType: "final", - ); - // Send final acknowledgment to all devices for (var device in event.connectedDevice) { await event.nearbyService.sendMessage( @@ -255,6 +250,7 @@ class PeerToPeerBloc extends Bloc { "message": "All entities received and processed successfully.", }), ); + emit(const PeerToPeerState.dataReceived()); } } catch (e) { debugPrint("Error processing received data: $e"); @@ -310,6 +306,7 @@ class PeerToPeerEvent with _$PeerToPeerEvent { const factory PeerToPeerEvent.dataTransfer( {required NearbyService nearbyService, required List connectedDevice}) = DataTransferEvent; + const factory PeerToPeerEvent.dataReceiver( {required NearbyService nearbyService, required dynamic data}) = DataReceiverEvent; diff --git a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart index 2a3fde44db..c10ef820ab 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart @@ -44,6 +44,7 @@ class BeneficiaryDownSyncBloc sideEffectLocalRepository; final LocalRepository referralLocalRepository; + BeneficiaryDownSyncBloc({ required this.individualLocalRepository, required this.downSyncRemoteRepository, @@ -160,8 +161,9 @@ class BeneficiaryDownSyncBloc // [TODO: Move the function DiskSpace.getFreeDiskSpace to utils diskSpace = await DiskSpace .getFreeDiskSpace; // Returns the device available space in MB + var serverData = (event.initialServerCount * 150 * 1); // diskSpace in MB * 1000 comparison with serverTotalCount * 150KB * Number of entities * 2 - if ((diskSpace ?? 0) * 1000 < (event.initialServerCount * 150 * 2)) { + if ((diskSpace ?? 0) * 1000 < serverData) { emit(const BeneficiaryDownSyncState.insufficientStorage()); } else { try { @@ -372,9 +374,11 @@ class BeneficiaryDownSyncState with _$BeneficiaryDownSyncState { int syncedCount, int totalCount, ) = _DownSyncInProgressState; + const factory BeneficiaryDownSyncState.success( DownsyncModel downSyncResult, ) = _DownSyncSuccessState; + const factory BeneficiaryDownSyncState.getBatchSize( int batchSize, String projectId, @@ -382,21 +386,29 @@ class BeneficiaryDownSyncState with _$BeneficiaryDownSyncState { int pendingSyncCount, String boundaryName, ) = _DownSyncGetBatchSizeState; + const factory BeneficiaryDownSyncState.loading(bool isPop) = _DownSyncLoadingState; + const factory BeneficiaryDownSyncState.insufficientStorage() = _DownSyncInsufficientStorageState; + const factory BeneficiaryDownSyncState.dataFound( int initialServerCount, int batchSize, ) = _DownSyncDataFoundState; + const factory BeneficiaryDownSyncState.resetState() = _DownSyncResetState; + const factory BeneficiaryDownSyncState.totalCountCheckFailed() = _DownSynnCountCheckFailedState; + const factory BeneficiaryDownSyncState.failed() = _DownSyncFailureState; + const factory BeneficiaryDownSyncState.report( List downsyncCriteriaList, ) = _DownSyncReportState; + const factory BeneficiaryDownSyncState.pendingSync() = _DownSyncPendingSyncState; } diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart index a20d947b83..eb1cf7edba 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -22,6 +22,7 @@ import '../../widgets/showcase/showcase_wrappers.dart'; class DataReceiverPage extends LocalizedStatefulWidget { final Device connectedDevice; final NearbyService nearbyService; + const DataReceiverPage( {super.key, required this.connectedDevice, required this.nearbyService}); @@ -77,7 +78,8 @@ class _DataReceiverPageState extends LocalizedState { child: BlocListener( listener: (context, state) { if (state is DataReceived) { - context.router.push(AcknowledgementRoute()); + context.router + .popAndPush(AcknowledgementRoute(isDataRecordSuccess: true)); } }, child: BlocBuilder( @@ -135,8 +137,8 @@ class _DataReceiverPageState extends LocalizedState { 0.15, lineWidth: kPadding * 1.5, animation: true, - percent: - 0, // Update this dynamically for progress + percent: 0, + // Update this dynamically for progress center: const Text( '0 %', style: TextStyle( @@ -156,7 +158,8 @@ class _DataReceiverPageState extends LocalizedState { mainAxisAlignment: MainAxisAlignment.center, children: [ - FileTransferAnimation(), // Add animation here + FileTransferAnimation(), + // Add animation here ], ), Wrap( @@ -208,8 +211,8 @@ class _DataReceiverPageState extends LocalizedState { 0.15, lineWidth: kPadding * 1.5, animation: false, - percent: - progress, // Update this dynamically for progress + percent: progress, + // Update this dynamically for progress center: Text( '${(progress * 100).toStringAsFixed(1)} %', style: const TextStyle( @@ -229,7 +232,8 @@ class _DataReceiverPageState extends LocalizedState { mainAxisAlignment: MainAxisAlignment.center, children: [ - FileTransferAnimation(), // Add animation here + FileTransferAnimation(), + // Add animation here ], ), Wrap( diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart index 3dff9128df..70c165135b 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -76,7 +76,8 @@ class _DataTransferScreenState extends LocalizedState { child: BlocListener( listener: (context, state) { if (state is CompletedDataTransfer) { - context.router.push(AcknowledgementRoute()); + context.router + .popAndPush(AcknowledgementRoute(isDataRecordSuccess: true)); } }, child: BlocBuilder( @@ -129,8 +130,8 @@ class _DataTransferScreenState extends LocalizedState { MediaQuery.of(context).size.height * 0.15, lineWidth: kPadding * 1.5, animation: true, - percent: - 0, // Update this dynamically for progress + percent: 0, + // Update this dynamically for progress center: const Text( '0 %', style: TextStyle( @@ -159,8 +160,8 @@ class _DataTransferScreenState extends LocalizedState { MediaQuery.of(context).size.height * 0.15, lineWidth: kPadding * 1.5, animation: true, - percent: - progress, // Update this dynamically for progress + percent: progress, + // Update this dynamically for progress center: Text( '${(progress * 100).toStringAsFixed(1)} %', style: const TextStyle( @@ -178,7 +179,8 @@ class _DataTransferScreenState extends LocalizedState { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - FileTransferAnimation(), // Add animation here + FileTransferAnimation(), + // Add animation here ], ), Wrap(spacing: 8.0, runSpacing: 4.0, children: [ diff --git a/apps/health_campaign_field_worker_app/pubspec.lock b/apps/health_campaign_field_worker_app/pubspec.lock index a215a1a0ee..881d89e86b 100644 --- a/apps/health_campaign_field_worker_app/pubspec.lock +++ b/apps/health_campaign_field_worker_app/pubspec.lock @@ -506,9 +506,10 @@ packages: digit_components: dependency: "direct main" description: - path: "../../packages/digit_components" - relative: true - source: path + name: digit_components + sha256: "07b585e5d8010639366da72a4a8b215ce9b8790c75b2162b66af3cea57ca35d9" + url: "https://pub.dev" + source: hosted version: "1.0.2+1" digit_data_model: dependency: "direct main" @@ -527,17 +528,19 @@ packages: digit_firebase_services: dependency: "direct main" description: - path: "../../packages/digit_firebase_services" - relative: true - source: path + name: digit_firebase_services + sha256: ce76521d797e123b6fc95c9dfad7d4a918a93b97f57aecd0e1d517b46190909d + url: "https://pub.dev" + source: hosted version: "0.0.1" digit_location_tracker: dependency: "direct main" description: - path: "../../packages/digit_location_tracker" - relative: true - source: path - version: "0.0.1-dev.1" + name: digit_location_tracker + sha256: ee5531b9b9442820d48d1ddd86177602eb425f742b0d9c29b57325ef157fa886 + url: "https://pub.dev" + source: hosted + version: "0.0.1-dev.2" digit_scanner: dependency: "direct main" description: @@ -548,9 +551,10 @@ packages: digit_showcase: dependency: "direct main" description: - path: "../../packages/digit_showcase" - relative: true - source: path + name: digit_showcase + sha256: "75b67298f1860ad757827b15af752b677f934b5275b887e36b15e25a5285e498" + url: "https://pub.dev" + source: hosted version: "1.0.0" digit_ui_components: dependency: "direct main" @@ -2414,5 +2418,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <=3.9.0" + dart: ">=3.2.3 <3.9.0" flutter: ">=3.16.0" diff --git a/packages/attendance_management/pubspec.lock b/packages/attendance_management/pubspec.lock index d368b888ab..461317ac1a 100644 --- a/packages/attendance_management/pubspec.lock +++ b/packages/attendance_management/pubspec.lock @@ -9,14 +9,6 @@ packages: url: "https://pub.dev" source: hosted version: "64.0.0" - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" - url: "https://pub.dev" - source: hosted - version: "1.3.25" analyzer: dependency: transitive description: @@ -373,17 +365,11 @@ packages: digit_data_model: dependency: "direct main" description: - path: "../digit_data_model" - relative: true - source: path + name: digit_data_model + sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" + url: "https://pub.dev" + source: hosted version: "1.0.5-dev.1" - digit_firebase_services: - dependency: "direct overridden" - description: - path: "../digit_firebase_services" - relative: true - source: path - version: "0.0.1" digit_ui_components: dependency: "direct main" description: @@ -504,46 +490,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" - firebase_core: - dependency: transitive - description: - name: firebase_core - sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" - url: "https://pub.dev" - source: hosted - version: "2.27.0" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: b94b217e3ad745e784960603d33d99471621ecca151c99c670869b76e50ad2a6 - url: "https://pub.dev" - source: hosted - version: "5.3.1" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 - url: "https://pub.dev" - source: hosted - version: "2.11.5" - firebase_crashlytics: - dependency: transitive - description: - name: firebase_crashlytics - sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 - url: "https://pub.dev" - source: hosted - version: "3.4.18" - firebase_crashlytics_platform_interface: - dependency: transitive - description: - name: firebase_crashlytics_platform_interface - sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 - url: "https://pub.dev" - source: hosted - version: "3.6.25" fixnum: dependency: transitive description: diff --git a/packages/closed_household/pubspec.lock b/packages/closed_household/pubspec.lock index d58e8b6794..76890865c8 100644 --- a/packages/closed_household/pubspec.lock +++ b/packages/closed_household/pubspec.lock @@ -9,14 +9,6 @@ packages: url: "https://pub.dev" source: hosted version: "61.0.0" - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" - url: "https://pub.dev" - source: hosted - version: "1.3.25" analyzer: dependency: transitive description: @@ -421,17 +413,11 @@ packages: digit_data_model: dependency: "direct main" description: - path: "../digit_data_model" - relative: true - source: path + name: digit_data_model + sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" + url: "https://pub.dev" + source: hosted version: "1.0.5-dev.1" - digit_firebase_services: - dependency: "direct overridden" - description: - path: "../digit_firebase_services" - relative: true - source: path - version: "0.0.1" digit_scanner: dependency: "direct main" description: @@ -576,46 +562,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" - firebase_core: - dependency: transitive - description: - name: firebase_core - sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" - url: "https://pub.dev" - source: hosted - version: "2.27.0" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 - url: "https://pub.dev" - source: hosted - version: "5.3.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 - url: "https://pub.dev" - source: hosted - version: "2.11.5" - firebase_crashlytics: - dependency: transitive - description: - name: firebase_crashlytics - sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 - url: "https://pub.dev" - source: hosted - version: "3.4.18" - firebase_crashlytics_platform_interface: - dependency: transitive - description: - name: firebase_crashlytics_platform_interface - sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 - url: "https://pub.dev" - source: hosted - version: "3.6.25" fixnum: dependency: transitive description: diff --git a/packages/complaints/example/pubspec.lock b/packages/complaints/example/pubspec.lock index 22d3a4b45f..2f64870891 100644 --- a/packages/complaints/example/pubspec.lock +++ b/packages/complaints/example/pubspec.lock @@ -227,9 +227,10 @@ packages: digit_components: dependency: "direct main" description: - path: "../../digit_components" - relative: true - source: path + name: digit_components + sha256: "07b585e5d8010639366da72a4a8b215ce9b8790c75b2162b66af3cea57ca35d9" + url: "https://pub.dev" + source: hosted version: "1.0.2+1" digit_data_model: dependency: transitive @@ -1068,5 +1069,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" + dart: ">=3.2.0 <3.9.0" flutter: ">=3.16.0" diff --git a/packages/complaints/pubspec.lock b/packages/complaints/pubspec.lock index 7fdffffec4..e451fcd62b 100644 --- a/packages/complaints/pubspec.lock +++ b/packages/complaints/pubspec.lock @@ -9,14 +9,6 @@ packages: url: "https://pub.dev" source: hosted version: "64.0.0" - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" - url: "https://pub.dev" - source: hosted - version: "1.3.25" analyzer: dependency: transitive description: @@ -277,24 +269,19 @@ packages: digit_components: dependency: "direct main" description: - path: "../digit_components" - relative: true - source: path + name: digit_components + sha256: "07b585e5d8010639366da72a4a8b215ce9b8790c75b2162b66af3cea57ca35d9" + url: "https://pub.dev" + source: hosted version: "1.0.2+1" digit_data_model: dependency: "direct main" description: - path: "../digit_data_model" - relative: true - source: path + name: digit_data_model + sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" + url: "https://pub.dev" + source: hosted version: "1.0.5-dev.1" - digit_firebase_services: - dependency: "direct overridden" - description: - path: "../digit_firebase_services" - relative: true - source: path - version: "0.0.1" dio: dependency: "direct main" description: @@ -359,46 +346,6 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" - firebase_core: - dependency: transitive - description: - name: firebase_core - sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" - url: "https://pub.dev" - source: hosted - version: "2.27.0" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 - url: "https://pub.dev" - source: hosted - version: "5.3.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 - url: "https://pub.dev" - source: hosted - version: "2.11.5" - firebase_crashlytics: - dependency: transitive - description: - name: firebase_crashlytics - sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 - url: "https://pub.dev" - source: hosted - version: "3.4.18" - firebase_crashlytics_platform_interface: - dependency: transitive - description: - name: firebase_crashlytics_platform_interface - sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 - url: "https://pub.dev" - source: hosted - version: "3.6.25" fixnum: dependency: transitive description: @@ -1268,5 +1215,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" + dart: ">=3.2.0 <3.9.0" flutter: ">=3.16.0" diff --git a/packages/digit_components/pubspec.lock b/packages/digit_components/pubspec.lock index e9d52e3a2c..7c84c45c4f 100644 --- a/packages/digit_components/pubspec.lock +++ b/packages/digit_components/pubspec.lock @@ -17,14 +17,6 @@ packages: url: "https://pub.dev" source: hosted version: "6.2.0" - ansicolor: - dependency: transitive - description: - name: ansicolor - sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" - url: "https://pub.dev" - source: hosted - version: "2.0.3" archive: dependency: transitive description: @@ -209,21 +201,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" - dart_mappable: - dependency: transitive - description: - name: dart_mappable - sha256: "47269caf2060533c29b823ff7fa9706502355ffcb61e7f2a374e3a0fb2f2c3f0" - url: "https://pub.dev" - source: hosted - version: "4.2.2" - dart_mappable_builder: - dependency: "direct overridden" - description: - path: "../dart_mappable_builder" - relative: true - source: path - version: "4.2.0" dart_style: dependency: transitive description: @@ -932,14 +909,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - type_plus: - dependency: transitive - description: - name: type_plus - sha256: d5d1019471f0d38b91603adb9b5fd4ce7ab903c879d2fbf1a3f80a630a03fcc9 - url: "https://pub.dev" - source: hosted - version: "2.1.1" typed_data: dependency: transitive description: diff --git a/packages/digit_dss/pubspec.lock b/packages/digit_dss/pubspec.lock index cedd551475..d7acdbc803 100644 --- a/packages/digit_dss/pubspec.lock +++ b/packages/digit_dss/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "61.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + url: "https://pub.dev" + source: hosted + version: "1.3.25" analyzer: dependency: transitive description: @@ -60,11 +68,10 @@ packages: attendance_management: dependency: "direct main" description: - name: attendance_management - sha256: f1b4373e8d0d9f8227ede0d25d4141f0d16d18ac2525c0347b844098cdab080f - url: "https://pub.dev" - source: hosted - version: "1.0.2+1" + path: "../attendance_management" + relative: true + source: path + version: "1.0.3-dev.1" auto_route: dependency: "direct main" description: @@ -169,6 +176,46 @@ packages: url: "https://pub.dev" source: hosted version: "8.9.2" + camera: + dependency: transitive + description: + name: camera + sha256: "9499cbc2e51d8eb0beadc158b288380037618ce4e30c9acbc4fae1ac3ecb5797" + url: "https://pub.dev" + source: hosted + version: "0.10.5+9" + camera_android: + dependency: transitive + description: + name: camera_android + sha256: b350ac087f111467e705b2b76cc1322f7f5bdc122aa83b4b243b0872f390d229 + url: "https://pub.dev" + source: hosted + version: "0.10.9+2" + camera_avfoundation: + dependency: transitive + description: + name: camera_avfoundation + sha256: "608b56b0880722f703871329c4d7d4c2f379c8e2936940851df7fc041abc6f51" + url: "https://pub.dev" + source: hosted + version: "0.9.13+10" + camera_platform_interface: + dependency: transitive + description: + name: camera_platform_interface + sha256: b3ede1f171532e0d83111fe0980b46d17f1aa9788a07a2fbed07366bbdbb9061 + url: "https://pub.dev" + source: hosted + version: "2.8.0" + camera_web: + dependency: transitive + description: + name: camera_web + sha256: b9235ec0a2ce949daec546f1f3d86f05c3921ed31c7d9ab6b7c03214d152fc2d + url: "https://pub.dev" + source: hosted + version: "0.3.4" characters: dependency: transitive description: @@ -257,6 +304,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e + url: "https://pub.dev" + source: hosted + version: "0.3.3+8" crypto: dependency: transitive description: @@ -265,6 +320,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" cupertino_icons: dependency: transitive description: @@ -342,7 +405,22 @@ packages: path: "../digit_data_model" relative: true source: path - version: "1.0.4" + version: "1.0.5-dev.1" + digit_firebase_services: + dependency: "direct overridden" + description: + path: "../digit_firebase_services" + relative: true + source: path + version: "0.0.1" + digit_ui_components: + dependency: transitive + description: + name: digit_ui_components + sha256: e38f163515aa6a6c5283754e741b21f33fb3a6c0a1fc171a1e4e6620510d46ae + url: "https://pub.dev" + source: hosted + version: "0.0.1+7" dio: dependency: "direct main" description: @@ -359,6 +437,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + dotted_border: + dependency: transitive + description: + name: dotted_border + sha256: "108837e11848ca776c53b30bc870086f84b62ed6e01c503ed976e8f8c7df9c04" + url: "https://pub.dev" + source: hosted + version: "2.1.0" drift: dependency: transitive description: @@ -415,6 +501,86 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.4" + file_picker: + dependency: transitive + description: + name: file_picker + sha256: d1d0ac3966b36dc3e66eeefb40280c17feb87fa2099c6e22e6a1fc959327bd03 + url: "https://pub.dev" + source: hosted + version: "8.0.0+1" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 + url: "https://pub.dev" + source: hosted + version: "0.9.4" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + url: "https://pub.dev" + source: hosted + version: "2.27.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf + url: "https://pub.dev" + source: hosted + version: "5.4.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + url: "https://pub.dev" + source: hosted + version: "2.11.5" + firebase_crashlytics: + dependency: transitive + description: + name: firebase_crashlytics + sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 + url: "https://pub.dev" + source: hosted + version: "3.4.18" + firebase_crashlytics_platform_interface: + dependency: transitive + description: + name: firebase_crashlytics_platform_interface + sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 + url: "https://pub.dev" + source: hosted + version: "3.6.25" fixnum: dependency: transitive description: @@ -436,6 +602,30 @@ packages: url: "https://pub.dev" source: hosted version: "8.1.6" + flutter_dropzone: + dependency: transitive + description: + name: flutter_dropzone + sha256: b399c60411f9bf9c4c2f97933c6a3a185859e75aade8897831e76cee4346c8e1 + url: "https://pub.dev" + source: hosted + version: "3.0.7" + flutter_dropzone_platform_interface: + dependency: transitive + description: + name: flutter_dropzone_platform_interface + sha256: "96d2c51c86063ba150551c3b40fd26c5a18785bee071c0c751502d28a545df3b" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + flutter_dropzone_web: + dependency: transitive + description: + name: flutter_dropzone_web + sha256: c5a0fdb63b7216352a01761ec1b6eba1982e49541e60675735e2d3d95e207b19 + url: "https://pub.dev" + source: hosted + version: "3.0.13" flutter_focus_watcher: dependency: transitive description: @@ -500,6 +690,19 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" + url: "https://pub.dev" + source: hosted + version: "2.0.19" flutter_spinkit: dependency: transitive description: @@ -508,14 +711,22 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.1" + flutter_styled_toast: + dependency: transitive + description: + name: flutter_styled_toast + sha256: e667f13a665820eb0fa8506547e47eacbcddf1948d6d3036cfd3b089bd4b0516 + url: "https://pub.dev" + source: hosted + version: "2.2.1" flutter_svg: dependency: "direct main" description: name: flutter_svg - sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" url: "https://pub.dev" source: hosted - version: "2.0.9" + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -566,6 +777,54 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.0" + geolocator: + dependency: transitive + description: + name: geolocator + sha256: f4efb8d3c4cdcad2e226af9661eb1a0dd38c71a9494b22526f9da80ab79520e5 + url: "https://pub.dev" + source: hosted + version: "10.1.1" + geolocator_android: + dependency: transitive + description: + name: geolocator_android + sha256: "93906636752ea4d4e778afa981fdfe7409f545b3147046300df194330044d349" + url: "https://pub.dev" + source: hosted + version: "4.3.1" + geolocator_apple: + dependency: transitive + description: + name: geolocator_apple + sha256: "6154ea2682563f69fc0125762ed7e91e7ed85d0b9776595653be33918e064807" + url: "https://pub.dev" + source: hosted + version: "2.3.8+1" + geolocator_platform_interface: + dependency: transitive + description: + name: geolocator_platform_interface + sha256: "386ce3d9cce47838355000070b1d0b13efb5bc430f8ecda7e9238c8409ace012" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + geolocator_web: + dependency: transitive + description: + name: geolocator_web + sha256: "102e7da05b48ca6bf0a5bda0010f886b171d1a08059f01bfe02addd0175ebece" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + geolocator_windows: + dependency: transitive + description: + name: geolocator_windows + sha256: "53da08937d07c24b0d9952eb57a3b474e29aae2abf9dd717f7e1230995f13f0e" + url: "https://pub.dev" + source: hosted + version: "0.2.3" glob: dependency: transitive description: @@ -578,10 +837,10 @@ packages: dependency: transitive description: name: google_fonts - sha256: "6b6f10f0ce3c42f6552d1c70d2c28d764cf22bb487f50f66cca31dcd5194f4d6" + sha256: "2776c66b3e97c6cdd58d1bd3281548b074b64f1fd5c8f82391f7456e38849567" url: "https://pub.dev" source: hosted - version: "4.0.4" + version: "4.0.5" graphs: dependency: transitive description: @@ -598,14 +857,22 @@ packages: url: "https://pub.dev" source: hosted version: "4.3.1" + html: + dependency: transitive + description: + name: html + sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec" + url: "https://pub.dev" + source: hosted + version: "0.15.5" http: dependency: transitive description: name: http - sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba url: "https://pub.dev" source: hosted - version: "0.13.6" + version: "1.2.0" http_multi_server: dependency: transitive description: @@ -622,6 +889,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image_picker: + dependency: transitive + description: + name: image_picker + sha256: "1f498d086203360cca099d20ffea2963f48c39ce91bdd8a3b6d4a045786b02c8" + url: "https://pub.dev" + source: hosted + version: "1.0.8" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "844c6da4e4f2829dffdab97816bca09d0e0977e8dcef7450864aba4e07967a58" + url: "https://pub.dev" + source: hosted + version: "0.8.9+6" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: e2423c53a68b579a7c37a1eda967b8ae536c3d98518e5db95ca1fe5719a730a3 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3 + url: "https://pub.dev" + source: hosted + version: "0.8.9+1" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: fa4e815e6fcada50e35718727d83ba1c92f1edf95c0b4436554cec301b56233b + url: "https://pub.dev" + source: hosted + version: "2.9.3" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" intl: dependency: "direct main" description: @@ -838,6 +1169,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_drawing: + dependency: transitive + description: + name: path_drawing + sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 + url: "https://pub.dev" + source: hosted + version: "1.0.1" path_parsing: dependency: transitive description: @@ -1187,6 +1526,86 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + universal_html: + dependency: transitive + description: + name: universal_html + sha256: "56536254004e24d9d8cfdb7dbbf09b74cf8df96729f38a2f5c238163e3d58971" + url: "https://pub.dev" + source: hosted + version: "2.2.4" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + url_launcher: + dependency: transitive + description: + name: url_launcher + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "17cd5e205ea615e2c6ea7a77323a11712dffa0720a8a90540db57a01347f9ad9" + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + url: "https://pub.dev" + source: hosted + version: "6.2.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + url: "https://pub.dev" + source: hosted + version: "3.1.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b + url: "https://pub.dev" + source: hosted + version: "2.2.3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" + url: "https://pub.dev" + source: hosted + version: "3.1.2" uuid: dependency: transitive description: @@ -1199,26 +1618,26 @@ packages: dependency: transitive description: name: vector_graphics - sha256: "4ac59808bbfca6da38c99f415ff2d3a5d7ca0a6b4809c71d9cf30fba5daf9752" + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" url: "https://pub.dev" source: hosted - version: "1.1.10+1" + version: "1.1.11+1" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: f3247e7ab0ec77dc759263e68394990edc608fb2b480b80db8aa86ed09279e33 + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da url: "https://pub.dev" source: hosted - version: "1.1.10+1" + version: "1.1.11+1" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "18489bdd8850de3dd7ca8a34e0c446f719ec63e2bab2e7a8cc66a9028dd76c5a" + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" url: "https://pub.dev" source: hosted - version: "1.1.10+1" + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -1227,6 +1646,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + visibility_detector: + dependency: transitive + description: + name: visibility_detector + sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + url: "https://pub.dev" + source: hosted + version: "0.4.0+2" vm_service: dependency: transitive description: diff --git a/packages/digit_firebase_services/pubspec.lock b/packages/digit_firebase_services/pubspec.lock index bf1e0562eb..cea3a2c324 100644 --- a/packages/digit_firebase_services/pubspec.lock +++ b/packages/digit_firebase_services/pubspec.lock @@ -1,14 +1,6 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 - url: "https://pub.dev" - source: hosted - version: "64.0.0" _flutterfire_internals: dependency: transitive description: @@ -17,30 +9,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.25" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" - url: "https://pub.dev" - source: hosted - version: "6.2.0" - ansicolor: - dependency: transitive - description: - name: ansicolor - sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" - url: "https://pub.dev" - source: hosted - version: "2.0.3" - args: - dependency: transitive - description: - name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" - url: "https://pub.dev" - source: hosted - version: "2.5.0" async: dependency: transitive description: @@ -49,14 +17,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" - bloc: - dependency: transitive - description: - name: bloc - sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e" - url: "https://pub.dev" - source: hosted - version: "8.1.4" boolean_selector: dependency: transitive description: @@ -65,14 +25,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" - build: - dependency: transitive - description: - name: build - sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" - url: "https://pub.dev" - source: hosted - version: "2.4.1" characters: dependency: transitive description: @@ -97,92 +49,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" - convert: - dependency: transitive - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" - crypto: - dependency: transitive - description: - name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab - url: "https://pub.dev" - source: hosted - version: "3.0.3" - dart_mappable: - dependency: transitive - description: - name: dart_mappable - sha256: f69a961ae8589724ebb542e588f228ae844c5f78028899cbe2cc718977c1b382 - url: "https://pub.dev" - source: hosted - version: "4.3.0" - dart_mappable_builder: - dependency: "direct overridden" - description: - path: "../dart_mappable_builder" - relative: true - source: path - version: "4.2.0" - dart_style: - dependency: transitive - description: - name: dart_style - sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" - url: "https://pub.dev" - source: hosted - version: "2.3.6" - db_viewer: - dependency: transitive - description: - name: db_viewer - sha256: "5f7e3cfcde9663321797d8f6f0c876f7c13f0825a2e77ec1ef065656797144d9" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - digit_data_model: - dependency: "direct overridden" - description: - path: "../digit_data_model" - relative: true - source: path - version: "1.0.4" - dio: - dependency: transitive - description: - name: dio - sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260" - url: "https://pub.dev" - source: hosted - version: "5.7.0" - dio_web_adapter: - dependency: transitive - description: - name: dio_web_adapter - sha256: "36c5b2d79eb17cdae41e974b7a8284fec631651d2a6f39a8a2ff22327e90aeac" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - drift: - dependency: transitive - description: - name: drift - sha256: b50a8342c6ddf05be53bda1d246404cbad101b64dc73e8d6d1ac1090d119b4e2 - url: "https://pub.dev" - source: hosted - version: "2.15.0" - drift_db_viewer: - dependency: transitive - description: - name: drift_db_viewer - sha256: "5ea77858c52b55460a1e8f34ab5f88324621d486717d876fd745765fbc227f3f" - url: "https://pub.dev" - source: hosted - version: "2.1.0" fake_async: dependency: transitive description: @@ -191,22 +57,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" - ffi: - dependency: transitive - description: - name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" firebase_core: dependency: "direct main" description: @@ -252,14 +102,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_bloc: - dependency: transitive - description: - name: flutter_bloc - sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a - url: "https://pub.dev" - source: hosted - version: "8.1.6" flutter_lints: dependency: "direct dev" description: @@ -278,46 +120,6 @@ packages: description: flutter source: sdk version: "0.0.0" - freezed_annotation: - dependency: transitive - description: - name: freezed_annotation - sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 - url: "https://pub.dev" - source: hosted - version: "2.4.4" - glob: - dependency: transitive - description: - name: glob - sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" - source: hosted - version: "4.0.2" - isar: - dependency: transitive - description: - name: isar - sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea" - url: "https://pub.dev" - source: hosted - version: "3.1.0+1" - isar_flutter_libs: - dependency: transitive - description: - name: isar_flutter_libs - sha256: bc6768cc4b9c61aabff77152e7f33b4b17d2fc93134f7af1c3dd51500fe8d5e8 - url: "https://pub.dev" - source: hosted - version: "3.1.0+1" js: dependency: transitive description: @@ -326,14 +128,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" - source: hosted - version: "4.9.0" lints: dependency: transitive description: @@ -342,14 +136,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" - logging: - dependency: transitive - description: - name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.dev" - source: hosted - version: "1.2.0" matcher: dependency: transitive description: @@ -374,30 +160,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" - mocktail: - dependency: transitive - description: - name: mocktail - sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8" - url: "https://pub.dev" - source: hosted - version: "1.0.4" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - package_config: - dependency: transitive - description: - name: package_config - sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" - url: "https://pub.dev" - source: hosted - version: "2.1.0" path: dependency: transitive description: @@ -406,62 +168,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 - url: "https://pub.dev" - source: hosted - version: "2.1.4" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d - url: "https://pub.dev" - source: hosted - version: "2.2.4" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" plugin_platform_interface: dependency: transitive description: @@ -470,43 +176,11 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - provider: - dependency: transitive - description: - name: provider - sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c - url: "https://pub.dev" - source: hosted - version: "6.1.2" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - recase: - dependency: transitive - description: - name: recase - sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 - url: "https://pub.dev" - source: hosted - version: "4.1.0" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" - source_gen: - dependency: transitive - description: - name: source_gen - sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" - url: "https://pub.dev" - source: hosted - version: "1.5.0" source_span: dependency: transitive description: @@ -515,22 +189,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" - sqlite3: - dependency: transitive - description: - name: sqlite3 - sha256: "072128763f1547e3e9b4735ce846bfd226d68019ccda54db4cd427b12dfdedc9" - url: "https://pub.dev" - source: hosted - version: "2.4.0" - sqlite3_flutter_libs: - dependency: transitive - description: - name: sqlite3_flutter_libs - sha256: "7ae52b23366e5295005022e62fa093f64bfe190810223ea0ebf733a4cd140bce" - url: "https://pub.dev" - source: hosted - version: "0.5.26" stack_trace: dependency: transitive description: @@ -571,30 +229,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.1" - type_plus: - dependency: transitive - description: - name: type_plus - sha256: d5d1019471f0d38b91603adb9b5fd4ce7ab903c879d2fbf1a3f80a630a03fcc9 - url: "https://pub.dev" - source: hosted - version: "2.1.1" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://pub.dev" - source: hosted - version: "1.3.2" - uuid: - dependency: transitive - description: - name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" - url: "https://pub.dev" - source: hosted - version: "3.0.7" vector_math: dependency: transitive description: @@ -603,14 +237,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - watcher: - dependency: transitive - description: - name: watcher - sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" - url: "https://pub.dev" - source: hosted - version: "1.1.0" web: dependency: transitive description: @@ -619,22 +245,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d - url: "https://pub.dev" - source: hosted - version: "1.0.4" - yaml: - dependency: transitive - description: - name: yaml - sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" - url: "https://pub.dev" - source: hosted - version: "3.1.2" sdks: dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + flutter: ">=3.3.0" diff --git a/packages/digit_location_tracker/pubspec.lock b/packages/digit_location_tracker/pubspec.lock index ddd73fe05c..7d97e1b9ec 100644 --- a/packages/digit_location_tracker/pubspec.lock +++ b/packages/digit_location_tracker/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "64.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + url: "https://pub.dev" + source: hosted + version: "1.3.25" analyzer: dependency: transitive description: @@ -142,7 +150,14 @@ packages: path: "../digit_data_model" relative: true source: path - version: "1.0.4" + version: "1.0.5-dev.1" + digit_firebase_services: + dependency: "direct overridden" + description: + path: "../digit_firebase_services" + relative: true + source: path + version: "0.0.1" dio: dependency: transitive description: @@ -199,6 +214,46 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + url: "https://pub.dev" + source: hosted + version: "2.27.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf + url: "https://pub.dev" + source: hosted + version: "5.4.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + url: "https://pub.dev" + source: hosted + version: "2.11.5" + firebase_crashlytics: + dependency: transitive + description: + name: firebase_crashlytics + sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 + url: "https://pub.dev" + source: hosted + version: "3.4.18" + firebase_crashlytics_platform_interface: + dependency: transitive + description: + name: firebase_crashlytics_platform_interface + sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 + url: "https://pub.dev" + source: hosted + version: "3.6.25" flutter: dependency: "direct main" description: flutter diff --git a/packages/forms_engine/pubspec.lock b/packages/forms_engine/pubspec.lock index 1fbd7a910f..02ab6b24de 100644 --- a/packages/forms_engine/pubspec.lock +++ b/packages/forms_engine/pubspec.lock @@ -228,11 +228,10 @@ packages: digit_components: dependency: "direct main" description: - name: digit_components - sha256: "8e5d120f2c16c0d8ffaf4d0de1218da5e492061d6bb9245214589fb1ea5ec09e" - url: "https://pub.dev" - source: hosted - version: "0.0.3+16" + path: "../digit_components" + relative: true + source: path + version: "1.0.2+1" easy_stepper: dependency: transitive description: @@ -1014,5 +1013,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <3.9.0" + dart: ">=3.2.0 <4.0.0" flutter: ">=3.16.0" diff --git a/packages/inventory_management/pubspec.lock b/packages/inventory_management/pubspec.lock index 1bb76bac87..f466306d20 100644 --- a/packages/inventory_management/pubspec.lock +++ b/packages/inventory_management/pubspec.lock @@ -413,10 +413,9 @@ packages: digit_scanner: dependency: "direct main" description: - name: digit_scanner - sha256: "9862c4885465bb1942e36dc9b42596c201648db9b0f5ffb8ad768e2409fc2742" - url: "https://pub.dev" - source: hosted + path: "../digit_scanner" + relative: true + source: path version: "1.0.3+1" dio: dependency: transitive diff --git a/packages/referral_reconciliation/pubspec.lock b/packages/referral_reconciliation/pubspec.lock index cbee32ec63..880efe553b 100644 --- a/packages/referral_reconciliation/pubspec.lock +++ b/packages/referral_reconciliation/pubspec.lock @@ -9,14 +9,6 @@ packages: url: "https://pub.dev" source: hosted version: "61.0.0" - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" - url: "https://pub.dev" - source: hosted - version: "1.3.25" analyzer: dependency: transitive description: @@ -421,24 +413,17 @@ packages: digit_data_model: dependency: "direct main" description: - path: "../digit_data_model" - relative: true - source: path + name: digit_data_model + sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" + url: "https://pub.dev" + source: hosted version: "1.0.5-dev.1" - digit_firebase_services: - dependency: "direct overridden" - description: - path: "../digit_firebase_services" - relative: true - source: path - version: "0.0.1" digit_scanner: dependency: "direct main" description: - name: digit_scanner - sha256: "9862c4885465bb1942e36dc9b42596c201648db9b0f5ffb8ad768e2409fc2742" - url: "https://pub.dev" - source: hosted + path: "../digit_scanner" + relative: true + source: path version: "1.0.3+1" digit_ui_components: dependency: "direct main" @@ -560,46 +545,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" - firebase_core: - dependency: transitive - description: - name: firebase_core - sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" - url: "https://pub.dev" - source: hosted - version: "2.27.0" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 - url: "https://pub.dev" - source: hosted - version: "5.3.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 - url: "https://pub.dev" - source: hosted - version: "2.11.5" - firebase_crashlytics: - dependency: transitive - description: - name: firebase_crashlytics - sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 - url: "https://pub.dev" - source: hosted - version: "3.4.18" - firebase_crashlytics_platform_interface: - dependency: transitive - description: - name: firebase_crashlytics_platform_interface - sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 - url: "https://pub.dev" - source: hosted - version: "3.6.25" fixnum: dependency: transitive description: diff --git a/packages/registration_delivery/pubspec.lock b/packages/registration_delivery/pubspec.lock index f8308b0134..8d83531167 100644 --- a/packages/registration_delivery/pubspec.lock +++ b/packages/registration_delivery/pubspec.lock @@ -9,14 +9,6 @@ packages: url: "https://pub.dev" source: hosted version: "61.0.0" - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" - url: "https://pub.dev" - source: hosted - version: "1.3.25" analyzer: dependency: transitive description: @@ -425,20 +417,12 @@ packages: relative: true source: path version: "1.0.5-dev.1" - digit_firebase_services: - dependency: "direct overridden" - description: - path: "../digit_firebase_services" - relative: true - source: path - version: "0.0.1" digit_scanner: dependency: "direct main" description: - name: digit_scanner - sha256: "9862c4885465bb1942e36dc9b42596c201648db9b0f5ffb8ad768e2409fc2742" - url: "https://pub.dev" - source: hosted + path: "../digit_scanner" + relative: true + source: path version: "1.0.3+1" digit_showcase: dependency: "direct main" @@ -576,46 +560,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" - firebase_core: - dependency: transitive - description: - name: firebase_core - sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" - url: "https://pub.dev" - source: hosted - version: "2.27.0" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 - url: "https://pub.dev" - source: hosted - version: "5.3.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 - url: "https://pub.dev" - source: hosted - version: "2.11.5" - firebase_crashlytics: - dependency: transitive - description: - name: firebase_crashlytics - sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 - url: "https://pub.dev" - source: hosted - version: "3.4.18" - firebase_crashlytics_platform_interface: - dependency: transitive - description: - name: firebase_crashlytics_platform_interface - sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 - url: "https://pub.dev" - source: hosted - version: "3.6.25" fixnum: dependency: transitive description: diff --git a/packages/survey_form/pubspec.lock b/packages/survey_form/pubspec.lock index 2d068be649..ca017de05e 100644 --- a/packages/survey_form/pubspec.lock +++ b/packages/survey_form/pubspec.lock @@ -9,14 +9,6 @@ packages: url: "https://pub.dev" source: hosted version: "64.0.0" - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" - url: "https://pub.dev" - source: hosted - version: "1.3.25" analyzer: dependency: transitive description: @@ -349,17 +341,11 @@ packages: digit_data_model: dependency: "direct main" description: - path: "../digit_data_model" - relative: true - source: path + name: digit_data_model + sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" + url: "https://pub.dev" + source: hosted version: "1.0.5-dev.1" - digit_firebase_services: - dependency: "direct overridden" - description: - path: "../digit_firebase_services" - relative: true - source: path - version: "0.0.1" digit_ui_components: dependency: "direct main" description: @@ -480,46 +466,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+2" - firebase_core: - dependency: transitive - description: - name: firebase_core - sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" - url: "https://pub.dev" - source: hosted - version: "2.27.0" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 - url: "https://pub.dev" - source: hosted - version: "5.3.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 - url: "https://pub.dev" - source: hosted - version: "2.11.5" - firebase_crashlytics: - dependency: transitive - description: - name: firebase_crashlytics - sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 - url: "https://pub.dev" - source: hosted - version: "3.4.18" - firebase_crashlytics_platform_interface: - dependency: transitive - description: - name: firebase_crashlytics_platform_interface - sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 - url: "https://pub.dev" - source: hosted - version: "3.6.25" fixnum: dependency: transitive description: From 9cd3f67e96a8477952bfc90c10ffd85e686b672a Mon Sep 17 00:00:00 2001 From: Naveen Renati <154230258+naveenr-egov@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:02:32 +0530 Subject: [PATCH 09/16] Modified downsync file structure --- .../lib/blocs/peer_to_peer/peer_to_peer.dart | 121 ++-- .../peer_to_peer/peer_to_peer.freezed.dart | 85 ++- .../project_beneficiaries_downsync.dart | 10 +- .../lib/pages/peer_to_peer/data_receiver.dart | 2 +- .../lib/pages/peer_to_peer/data_transfer.dart | 15 +- .../lib/pages/peer_to_peer/devices_list.dart | 5 +- .../peer_to_peer/peer_to_peer_wrapper.dart | 5 +- packages/auto_route/pubspec.lock | 541 ------------------ packages/referral_reconciliation/pubspec.lock | 14 +- packages/registration_delivery/pubspec.lock | 21 +- 10 files changed, 202 insertions(+), 617 deletions(-) delete mode 100644 packages/auto_route/pubspec.lock diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart index 7f89efc049..55f123332a 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -12,6 +12,7 @@ import 'package:path_provider/path_provider.dart'; import 'package:registration_delivery/registration_delivery.dart'; import '../../data/repositories/sync/remote_type.dart'; +import '../../models/downsync/downsync.dart'; import '../../utils/utils.dart'; part 'peer_to_peer.freezed.dart'; @@ -32,22 +33,26 @@ class PeerToPeerBloc extends Bloc { sideEffectLocalRepository; final LocalRepository referralLocalRepository; + final LocalRepository + downSyncLocalRepository; List receivedData = []; int receivedBytes = 0; int totalCount = 0; String entityType = ''; late Device connectedDevice; - - PeerToPeerBloc({ - required this.individualLocalRepository, - required this.householdLocalRepository, - required this.householdMemberLocalRepository, - required this.projectBeneficiaryLocalRepository, - required this.taskLocalRepository, - required this.sideEffectLocalRepository, - required this.referralLocalRepository, - }) : super(const PeerToPeerInitial()) { + late String selectedBoundaryCode; + + PeerToPeerBloc( + {required this.individualLocalRepository, + required this.householdLocalRepository, + required this.householdMemberLocalRepository, + required this.projectBeneficiaryLocalRepository, + required this.taskLocalRepository, + required this.sideEffectLocalRepository, + required this.referralLocalRepository, + required this.downSyncLocalRepository}) + : super(const PeerToPeerInitial()) { on(_handleSendEntities); on(_handleReceiveEntities); } @@ -61,7 +66,8 @@ class PeerToPeerBloc extends Bloc { progress: 0, offset: 0, totalCount: 0)); final downloadsDirectory = await getDownloadsDirectory(); - final file = File('${downloadsDirectory!.path}/down_sync_data.json'); + final file = File( + '${downloadsDirectory!.path}/${event.selectedProject}/${event.selectedBoundaryCode}/down_sync_data.json'); if (await file.exists()) { final fileStream = file.openRead(); @@ -88,6 +94,16 @@ class PeerToPeerBloc extends Bloc { .map((e) => offsetData[e]) .toList(); + var selectedBoundaryCode = offsetData.keys + .where((element) => element == 'boundaryCode') + .map((e) => offsetData[e]) + .firstOrNull; + + var selectedBoundaryName = offsetData.keys + .where((element) => element == 'boundaryName') + .map((e) => offsetData[e]) + .firstOrNull; + totalCount = offsetData.keys .where((element) => element == 'totalCount') .map((e) => offsetData[e]) @@ -102,6 +118,8 @@ class PeerToPeerBloc extends Bloc { device.deviceId, jsonEncode({ "type": "chunk", + "selectedBoundaryCode": selectedBoundaryCode, + "selectedBoundaryName": selectedBoundaryName, "message": compressJson(entityResponse), "offset": offsetValue, "totalData": totalCount, @@ -144,6 +162,9 @@ class PeerToPeerBloc extends Bloc { emit(const PeerToPeerState.completedDataTransfer()); } + } else { + emit(const PeerToPeerState.failedToTransfer( + error: "File doesn't exist")); } } catch (e) { emit(PeerToPeerState.failedToTransfer(error: e.toString())); @@ -185,30 +206,47 @@ class PeerToPeerBloc extends Bloc { // Process chunk int offset = receivedJson["offset"]; int totalCount = receivedJson["totalData"]; + selectedBoundaryCode = receivedJson["selectedBoundaryCode"]; final compressedMessage = receivedJson["message"]; final entityList = decompressJson(compressedMessage).entries; for (var entity in entityList) { entityType = entity.key; - final List entityResponse = entity.value ?? []; - final entityList = - entityResponse.whereType>().toList(); - // Save chunk to database immediately - final local = RepositoryType.getLocalForType( - DataModels.getDataModelForEntityName(entityType), - [ - individualLocalRepository, - householdLocalRepository, - householdMemberLocalRepository, - projectBeneficiaryLocalRepository, - taskLocalRepository, - sideEffectLocalRepository, - referralLocalRepository, - ], - ); - // Convert chunk to entity list and save it - createDbRecords(local, entityList, entityType); + if (entityType == 'DownsyncCriteria') { + final existingDownSyncData = + await downSyncLocalRepository.search(DownsyncSearchModel( + locality: selectedBoundaryCode, + )); + + if (existingDownSyncData.isNotEmpty) { + await downSyncLocalRepository + .update(DownsyncModelMapper.fromMap(entity.value)); + } else { + await downSyncLocalRepository + .create(DownsyncModelMapper.fromMap(entity.value)); + } + } else { + final List entityResponse = entity.value ?? []; + final entityList = + entityResponse.whereType>().toList(); + // Save chunk to database immediately + final local = RepositoryType.getLocalForType( + DataModels.getDataModelForEntityName(entityType), + [ + individualLocalRepository, + householdLocalRepository, + householdMemberLocalRepository, + projectBeneficiaryLocalRepository, + taskLocalRepository, + sideEffectLocalRepository, + referralLocalRepository, + ], + ); + + // Convert chunk to entity list and save it + createDbRecords(local, entityList, entityType); + } } // Update progress and clear processed data @@ -235,7 +273,20 @@ class PeerToPeerBloc extends Bloc { }), ); } else if (messageType == "confirmation" && - receivedJson["confirmationType"] == "allEntitiesTransferComplete") { + receivedJson["confirmationType"] == "finalTransfer") { + final existingDownSyncData = + await downSyncLocalRepository.search(DownsyncSearchModel( + locality: selectedBoundaryCode, + )); + + await downSyncLocalRepository.update( + existingDownSyncData.first.copyWith( + offset: 0, + limit: 0, + lastSyncedTime: DateTime.now().millisecondsSinceEpoch, + ), + ); + // Handle overall transfer final acknowledgment emit(const PeerToPeerState.dataReceived()); @@ -245,7 +296,6 @@ class PeerToPeerBloc extends Bloc { jsonEncode({ "type": "confirmation", "confirmationType": "finalAcknowledgment", - "level": "overall", // Differentiator "status": "success", "message": "All entities received and processed successfully.", }), @@ -278,15 +328,18 @@ class PeerToPeerBloc extends Bloc { callback: (data) { try { var receivedJson = jsonDecode(data["message"]); - if (receivedJson["type"] == "confirmation" && - receivedJson["confirmationType"] == confirmationType) { + if (receivedJson["type"] == "confirmation") { if (confirmationType == "chunk" && receivedJson["offset"] == offset) { completer.complete(); + } else if (confirmationType == "finalAcknowledgment") { + completer.complete(); } else if (confirmationType == "final") { completer.complete(); } else if (confirmationType == "failed") { completer.complete(); + emit(const PeerToPeerState.failedToTransfer( + error: "File doesn't exist")); throw "Failed to transfer ${receivedJson['message']}"; } } @@ -305,6 +358,8 @@ class PeerToPeerBloc extends Bloc { class PeerToPeerEvent with _$PeerToPeerEvent { const factory PeerToPeerEvent.dataTransfer( {required NearbyService nearbyService, + required String selectedProject, + required String selectedBoundaryCode, required List connectedDevice}) = DataTransferEvent; const factory PeerToPeerEvent.dataReceiver( diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart index 715ea21f68..1b4a60a031 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart @@ -20,7 +20,10 @@ mixin _$PeerToPeerEvent { @optionalTypeArgs TResult when({ required TResult Function( - NearbyService nearbyService, List connectedDevice) + NearbyService nearbyService, + String selectedProject, + String selectedBoundaryCode, + List connectedDevice) dataTransfer, required TResult Function(NearbyService nearbyService, dynamic data) dataReceiver, @@ -28,15 +31,16 @@ mixin _$PeerToPeerEvent { throw _privateConstructorUsedError; @optionalTypeArgs TResult? whenOrNull({ - TResult? Function( - NearbyService nearbyService, List connectedDevice)? + TResult? Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? dataTransfer, TResult? Function(NearbyService nearbyService, dynamic data)? dataReceiver, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ - TResult Function(NearbyService nearbyService, List connectedDevice)? + TResult Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? dataTransfer, TResult Function(NearbyService nearbyService, dynamic data)? dataReceiver, required TResult orElse(), @@ -108,7 +112,11 @@ abstract class _$$DataTransferEventImplCopyWith<$Res> __$$DataTransferEventImplCopyWithImpl<$Res>; @override @useResult - $Res call({NearbyService nearbyService, List connectedDevice}); + $Res call( + {NearbyService nearbyService, + String selectedProject, + String selectedBoundaryCode, + List connectedDevice}); } /// @nodoc @@ -123,6 +131,8 @@ class __$$DataTransferEventImplCopyWithImpl<$Res> @override $Res call({ Object? nearbyService = null, + Object? selectedProject = null, + Object? selectedBoundaryCode = null, Object? connectedDevice = null, }) { return _then(_$DataTransferEventImpl( @@ -130,6 +140,14 @@ class __$$DataTransferEventImplCopyWithImpl<$Res> ? _value.nearbyService : nearbyService // ignore: cast_nullable_to_non_nullable as NearbyService, + selectedProject: null == selectedProject + ? _value.selectedProject + : selectedProject // ignore: cast_nullable_to_non_nullable + as String, + selectedBoundaryCode: null == selectedBoundaryCode + ? _value.selectedBoundaryCode + : selectedBoundaryCode // ignore: cast_nullable_to_non_nullable + as String, connectedDevice: null == connectedDevice ? _value._connectedDevice : connectedDevice // ignore: cast_nullable_to_non_nullable @@ -145,11 +163,17 @@ class _$DataTransferEventImpl implements DataTransferEvent { const _$DataTransferEventImpl( {required this.nearbyService, + required this.selectedProject, + required this.selectedBoundaryCode, required final List connectedDevice}) : _connectedDevice = connectedDevice; @override final NearbyService nearbyService; + @override + final String selectedProject; + @override + final String selectedBoundaryCode; final List _connectedDevice; @override List get connectedDevice { @@ -160,7 +184,7 @@ class _$DataTransferEventImpl @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'PeerToPeerEvent.dataTransfer(nearbyService: $nearbyService, connectedDevice: $connectedDevice)'; + return 'PeerToPeerEvent.dataTransfer(nearbyService: $nearbyService, selectedProject: $selectedProject, selectedBoundaryCode: $selectedBoundaryCode, connectedDevice: $connectedDevice)'; } @override @@ -169,6 +193,8 @@ class _$DataTransferEventImpl properties ..add(DiagnosticsProperty('type', 'PeerToPeerEvent.dataTransfer')) ..add(DiagnosticsProperty('nearbyService', nearbyService)) + ..add(DiagnosticsProperty('selectedProject', selectedProject)) + ..add(DiagnosticsProperty('selectedBoundaryCode', selectedBoundaryCode)) ..add(DiagnosticsProperty('connectedDevice', connectedDevice)); } @@ -179,12 +205,20 @@ class _$DataTransferEventImpl other is _$DataTransferEventImpl && (identical(other.nearbyService, nearbyService) || other.nearbyService == nearbyService) && + (identical(other.selectedProject, selectedProject) || + other.selectedProject == selectedProject) && + (identical(other.selectedBoundaryCode, selectedBoundaryCode) || + other.selectedBoundaryCode == selectedBoundaryCode) && const DeepCollectionEquality() .equals(other._connectedDevice, _connectedDevice)); } @override - int get hashCode => Object.hash(runtimeType, nearbyService, + int get hashCode => Object.hash( + runtimeType, + nearbyService, + selectedProject, + selectedBoundaryCode, const DeepCollectionEquality().hash(_connectedDevice)); @JsonKey(ignore: true) @@ -198,35 +232,42 @@ class _$DataTransferEventImpl @optionalTypeArgs TResult when({ required TResult Function( - NearbyService nearbyService, List connectedDevice) + NearbyService nearbyService, + String selectedProject, + String selectedBoundaryCode, + List connectedDevice) dataTransfer, required TResult Function(NearbyService nearbyService, dynamic data) dataReceiver, }) { - return dataTransfer(nearbyService, connectedDevice); + return dataTransfer( + nearbyService, selectedProject, selectedBoundaryCode, connectedDevice); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function( - NearbyService nearbyService, List connectedDevice)? + TResult? Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? dataTransfer, TResult? Function(NearbyService nearbyService, dynamic data)? dataReceiver, }) { - return dataTransfer?.call(nearbyService, connectedDevice); + return dataTransfer?.call( + nearbyService, selectedProject, selectedBoundaryCode, connectedDevice); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(NearbyService nearbyService, List connectedDevice)? + TResult Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? dataTransfer, TResult Function(NearbyService nearbyService, dynamic data)? dataReceiver, required TResult orElse(), }) { if (dataTransfer != null) { - return dataTransfer(nearbyService, connectedDevice); + return dataTransfer(nearbyService, selectedProject, selectedBoundaryCode, + connectedDevice); } return orElse(); } @@ -266,10 +307,14 @@ class _$DataTransferEventImpl abstract class DataTransferEvent implements PeerToPeerEvent { const factory DataTransferEvent( {required final NearbyService nearbyService, + required final String selectedProject, + required final String selectedBoundaryCode, required final List connectedDevice}) = _$DataTransferEventImpl; @override NearbyService get nearbyService; + String get selectedProject; + String get selectedBoundaryCode; List get connectedDevice; @override @JsonKey(ignore: true) @@ -367,7 +412,10 @@ class _$DataReceiverEventImpl @optionalTypeArgs TResult when({ required TResult Function( - NearbyService nearbyService, List connectedDevice) + NearbyService nearbyService, + String selectedProject, + String selectedBoundaryCode, + List connectedDevice) dataTransfer, required TResult Function(NearbyService nearbyService, dynamic data) dataReceiver, @@ -378,8 +426,8 @@ class _$DataReceiverEventImpl @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function( - NearbyService nearbyService, List connectedDevice)? + TResult? Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? dataTransfer, TResult? Function(NearbyService nearbyService, dynamic data)? dataReceiver, }) { @@ -389,7 +437,8 @@ class _$DataReceiverEventImpl @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(NearbyService nearbyService, List connectedDevice)? + TResult Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? dataTransfer, TResult Function(NearbyService nearbyService, dynamic data)? dataReceiver, required TResult orElse(), diff --git a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart index c10ef820ab..ebc591c95b 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart @@ -209,7 +209,8 @@ class BeneficiaryDownSyncBloc ); // check if the API response is there or it failed if (downSyncResults.isNotEmpty) { - writeToFile(event.boundaryCode, downSyncResults); + writeToFile(event.projectId, event.boundaryCode, + event.boundaryName, downSyncResults); await networkManager .writeToEntityDB(event.boundaryCode, downSyncResults, [ individualLocalRepository, @@ -269,7 +270,9 @@ class BeneficiaryDownSyncBloc } void writeToFile( + String projectId, String selectedBoundaryCode, + String selectedBoundaryName, Map response, ) async { Map storedData = {}; @@ -284,7 +287,8 @@ class BeneficiaryDownSyncBloc } // Define the file path - final file = File('${downloadsDirectory.path}/down_sync_data.json'); + final file = File( + '${downloadsDirectory.path}/$projectId/$selectedBoundaryCode/down_sync_data.json'); // Read existing file content if available if (file.existsSync()) { @@ -301,13 +305,13 @@ class BeneficiaryDownSyncBloc var downSyncModel = response["DownsyncCriteria"]; // Create a unique key using just the offset String uniqueKey = '${downSyncModel["offset"]}'; - response.removeWhere((key, value) => key == 'DownsyncCriteria'); // Prepare data to insert Map data = { "totalCount": downSyncModel["totalCount"], "response": response, "boundaryCode": selectedBoundaryCode, + "boundaryName": selectedBoundaryName }; // Store the data under the unique key diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart index eb1cf7edba..81c1acfd43 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -136,7 +136,7 @@ class _DataReceiverPageState extends LocalizedState { .height * 0.15, lineWidth: kPadding * 1.5, - animation: true, + animation: false, percent: 0, // Update this dynamically for progress center: const Text( diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart index 70c165135b..f34cf6a9de 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -14,6 +14,7 @@ import 'package:percent_indicator/percent_indicator.dart'; import '../../blocs/peer_to_peer/peer_to_peer.dart'; import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; +import '../../utils/utils.dart'; import '../../widgets/localized.dart'; import '../../widgets/peer_to_peer/file_transfer_animation.dart'; import '../../widgets/showcase/showcase_wrappers.dart'; @@ -42,7 +43,9 @@ class _DataTransferScreenState extends LocalizedState { peerToPeerBloc = context.read(); peerToPeerBloc.add(DataTransferEvent( connectedDevice: widget.connectedDevices, - nearbyService: nearbyService)); + nearbyService: nearbyService, + selectedBoundaryCode: context.boundary.code ?? '', + selectedProject: context.selectedProject.id)); nearbyService.stateChangedSubscription(callback: (devices) { for (var device in devices) { if (device.state == SessionState.notConnected) { @@ -129,7 +132,7 @@ class _DataTransferScreenState extends LocalizedState { radius: MediaQuery.of(context).size.height * 0.15, lineWidth: kPadding * 1.5, - animation: true, + animation: false, percent: 0, // Update this dynamically for progress center: const Text( @@ -159,7 +162,7 @@ class _DataTransferScreenState extends LocalizedState { radius: MediaQuery.of(context).size.height * 0.15, lineWidth: kPadding * 1.5, - animation: true, + animation: false, percent: progress, // Update this dynamically for progress center: Text( @@ -214,7 +217,11 @@ class _DataTransferScreenState extends LocalizedState { DataTransferEvent( nearbyService: nearbyService, connectedDevice: - widget.connectedDevices)); + widget.connectedDevices, + selectedBoundaryCode: + context.boundary.code ?? '', + selectedProject: + context.selectedProject.id)); }, size: ButtonSize.large, label: localizations diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart index 287e24862c..991a82515d 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -78,6 +78,7 @@ class DevicesListPageState extends LocalizedState : localizations.translate(i18.dataShare.receiveAction), size: ButtonSize.large, mainAxisSize: MainAxisSize.max, + capitalizeLetters: false, ), ], ), @@ -179,7 +180,9 @@ class DevicesListPageState extends LocalizedState return device.state == SessionState.connected || device.state == SessionState.notConnected ? GestureDetector( - onTap: () => handleDeviceTap(device), + onTap: () { + handleDeviceTap(device); + }, child: Column( mainAxisSize: MainAxisSize.min, children: [ diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/peer_to_peer_wrapper.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/peer_to_peer_wrapper.dart index bb8f63a637..344e92898f 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/peer_to_peer_wrapper.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/peer_to_peer_wrapper.dart @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:registration_delivery/registration_delivery.dart'; import '../../blocs/peer_to_peer/peer_to_peer.dart'; +import '../../models/downsync/downsync.dart'; import '../../router/app_router.dart'; @RoutePage() @@ -36,6 +37,8 @@ class PeerToPeerWrapperPage extends StatelessWidget sideEffectLocalRepository: context.read< LocalRepository>(), referralLocalRepository: context - .read>())); + .read>(), + downSyncLocalRepository: context + .read>())); } } diff --git a/packages/auto_route/pubspec.lock b/packages/auto_route/pubspec.lock deleted file mode 100644 index 0d28f4bc7a..0000000000 --- a/packages/auto_route/pubspec.lock +++ /dev/null @@ -1,541 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 - url: "https://pub.dev" - source: hosted - version: "64.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" - url: "https://pub.dev" - source: hosted - version: "6.2.0" - args: - dependency: transitive - description: - name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" - url: "https://pub.dev" - source: hosted - version: "2.5.0" - async: - dependency: transitive - description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - auto_route_generator: - dependency: "direct dev" - description: - name: auto_route_generator - sha256: "11067a3bcd643812518fe26c0c9ec073990286cabfd9d74b6da9ef9b913c4d22" - url: "https://pub.dev" - source: hosted - version: "7.3.2" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - build: - dependency: transitive - description: - name: build - sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - build_config: - dependency: transitive - description: - name: build_config - sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 - url: "https://pub.dev" - source: hosted - version: "1.1.1" - build_daemon: - dependency: transitive - description: - name: build_daemon - sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" - url: "https://pub.dev" - source: hosted - version: "4.0.1" - build_resolvers: - dependency: transitive - description: - name: build_resolvers - sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" - url: "https://pub.dev" - source: hosted - version: "2.4.2" - build_runner: - dependency: "direct dev" - description: - name: build_runner - sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" - url: "https://pub.dev" - source: hosted - version: "2.4.9" - build_runner_core: - dependency: transitive - description: - name: build_runner_core - sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" - url: "https://pub.dev" - source: hosted - version: "7.3.0" - built_collection: - dependency: transitive - description: - name: built_collection - sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.dev" - source: hosted - version: "5.1.1" - built_value: - dependency: transitive - description: - name: built_value - sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb - url: "https://pub.dev" - source: hosted - version: "8.9.2" - characters: - dependency: transitive - description: - name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff - url: "https://pub.dev" - source: hosted - version: "2.0.3" - clock: - dependency: transitive - description: - name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" - source: hosted - version: "1.1.1" - code_builder: - dependency: transitive - description: - name: code_builder - sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 - url: "https://pub.dev" - source: hosted - version: "4.10.0" - collection: - dependency: "direct main" - description: - name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a - url: "https://pub.dev" - source: hosted - version: "1.18.0" - convert: - dependency: transitive - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" - crypto: - dependency: transitive - description: - name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab - url: "https://pub.dev" - source: hosted - version: "3.0.3" - dart_style: - dependency: transitive - description: - name: dart_style - sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" - url: "https://pub.dev" - source: hosted - version: "2.3.6" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" - source: hosted - version: "1.3.1" - file: - dependency: transitive - description: - name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" - url: "https://pub.dev" - source: hosted - version: "7.0.0" - fixnum: - dependency: transitive - description: - name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - glob: - dependency: transitive - description: - name: glob - sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - graphs: - dependency: transitive - description: - name: graphs - sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 - url: "https://pub.dev" - source: hosted - version: "2.3.1" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" - source: hosted - version: "4.0.2" - io: - dependency: transitive - description: - name: io - sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" - url: "https://pub.dev" - source: hosted - version: "1.0.4" - js: - dependency: transitive - description: - name: js - sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf - url: "https://pub.dev" - source: hosted - version: "0.7.1" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" - source: hosted - version: "4.9.0" - lints: - dependency: transitive - description: - name: lints - sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 - url: "https://pub.dev" - source: hosted - version: "3.0.0" - logging: - dependency: transitive - description: - name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" - url: "https://pub.dev" - source: hosted - version: "0.12.16" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" - url: "https://pub.dev" - source: hosted - version: "0.5.0" - meta: - dependency: "direct main" - description: - name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e - url: "https://pub.dev" - source: hosted - version: "1.10.0" - mime: - dependency: transitive - description: - name: mime - sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" - url: "https://pub.dev" - source: hosted - version: "1.0.6" - mockito: - dependency: "direct dev" - description: - name: mockito - sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" - url: "https://pub.dev" - source: hosted - version: "5.4.4" - package_config: - dependency: transitive - description: - name: package_config - sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - path: - dependency: "direct main" - description: - name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" - url: "https://pub.dev" - source: hosted - version: "1.8.3" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 - url: "https://pub.dev" - source: hosted - version: "6.0.2" - pool: - dependency: transitive - description: - name: pool - sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" - url: "https://pub.dev" - source: hosted - version: "1.5.1" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - shelf: - dependency: transitive - description: - name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 - url: "https://pub.dev" - source: hosted - version: "1.4.1" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" - url: "https://pub.dev" - source: hosted - version: "1.0.4" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_gen: - dependency: transitive - description: - name: source_gen - sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" - url: "https://pub.dev" - source: hosted - version: "1.5.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.dev" - source: hosted - version: "1.10.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" - url: "https://pub.dev" - source: hosted - version: "1.11.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.dev" - source: hosted - version: "2.1.2" - stream_transform: - dependency: transitive - description: - name: stream_transform - sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - test_api: - dependency: transitive - description: - name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" - url: "https://pub.dev" - source: hosted - version: "0.6.1" - timing: - dependency: transitive - description: - name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://pub.dev" - source: hosted - version: "1.3.2" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - watcher: - dependency: transitive - description: - name: watcher - sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - web: - dependency: transitive - description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 - url: "https://pub.dev" - source: hosted - version: "0.3.0" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b - url: "https://pub.dev" - source: hosted - version: "2.4.0" - xml: - dependency: transitive - description: - name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://pub.dev" - source: hosted - version: "6.5.0" - yaml: - dependency: transitive - description: - name: yaml - sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" - url: "https://pub.dev" - source: hosted - version: "3.1.2" -sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" diff --git a/packages/referral_reconciliation/pubspec.lock b/packages/referral_reconciliation/pubspec.lock index 880efe553b..61b85de941 100644 --- a/packages/referral_reconciliation/pubspec.lock +++ b/packages/referral_reconciliation/pubspec.lock @@ -421,9 +421,10 @@ packages: digit_scanner: dependency: "direct main" description: - path: "../digit_scanner" - relative: true - source: path + name: digit_scanner + sha256: "9862c4885465bb1942e36dc9b42596c201648db9b0f5ffb8ad768e2409fc2742" + url: "https://pub.dev" + source: hosted version: "1.0.3+1" digit_ui_components: dependency: "direct main" @@ -1461,9 +1462,10 @@ packages: survey_form: dependency: "direct main" description: - path: "../survey_form" - relative: true - source: path + name: survey_form + sha256: "52532fb3fae06883828d22f870045587bf7122f67cb4de236c82ad4d6de1d7d7" + url: "https://pub.dev" + source: hosted version: "0.0.1-dev.2" synchronized: dependency: transitive diff --git a/packages/registration_delivery/pubspec.lock b/packages/registration_delivery/pubspec.lock index 8d83531167..f43c0acdf2 100644 --- a/packages/registration_delivery/pubspec.lock +++ b/packages/registration_delivery/pubspec.lock @@ -413,16 +413,18 @@ packages: digit_data_model: dependency: "direct main" description: - path: "../digit_data_model" - relative: true - source: path + name: digit_data_model + sha256: "63c878bfe49e3e8db190dd5cd35d7a7b93b2e3b6663cebaaee25ff0089c1112b" + url: "https://pub.dev" + source: hosted version: "1.0.5-dev.1" digit_scanner: dependency: "direct main" description: - path: "../digit_scanner" - relative: true - source: path + name: digit_scanner + sha256: "9862c4885465bb1942e36dc9b42596c201648db9b0f5ffb8ad768e2409fc2742" + url: "https://pub.dev" + source: hosted version: "1.0.3+1" digit_showcase: dependency: "direct main" @@ -1484,9 +1486,10 @@ packages: survey_form: dependency: "direct main" description: - path: "../survey_form" - relative: true - source: path + name: survey_form + sha256: "52532fb3fae06883828d22f870045587bf7122f67cb4de236c82ad4d6de1d7d7" + url: "https://pub.dev" + source: hosted version: "0.0.1-dev.2" synchronized: dependency: transitive From 76db7e7237b5f93f66e3d88140472786b218aa96 Mon Sep 17 00:00:00 2001 From: Naveen Renati <154230258+naveenr-egov@users.noreply.github.com> Date: Fri, 3 Jan 2025 11:51:47 +0530 Subject: [PATCH 10/16] Merge conflicts --- .../lib/blocs/peer_to_peer/peer_to_peer.dart | 7 +- .../project_beneficiaries_downsync.dart | 12 +- .../lib/data/sync_service_mapper.dart | 105 +++++++++--------- .../lib/pages/peer_to_peer/data_receiver.dart | 6 +- .../lib/pages/peer_to_peer/data_transfer.dart | 12 +- .../lib/pages/peer_to_peer/devices_list.dart | 8 +- .../lib/router/app_router.dart | 26 ++++- .../pubspec.lock | 17 +++ .../digit_components/example/pubspec.lock | 2 +- packages/digit_location_tracker/pubspec.lock | 2 +- packages/forms_engine/pubspec.lock | 2 +- 11 files changed, 118 insertions(+), 81 deletions(-) diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart index 55f123332a..f7e6a5b9eb 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -10,10 +10,10 @@ import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:path_provider/path_provider.dart'; import 'package:registration_delivery/registration_delivery.dart'; +import 'package:sync_service/data/repositories/sync/remote_type.dart'; -import '../../data/repositories/sync/remote_type.dart'; +import '../../data/sync_service_mapper.dart'; import '../../models/downsync/downsync.dart'; -import '../../utils/utils.dart'; part 'peer_to_peer.freezed.dart'; @@ -244,8 +244,7 @@ class PeerToPeerBloc extends Bloc { ], ); - // Convert chunk to entity list and save it - createDbRecords(local, entityList, entityType); + SyncServiceMapper().createDbRecords(local, entityList, entityType); } } diff --git a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart index 246b20e67a..d0151f14c3 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/projects_beneficiary_downsync/project_beneficiaries_downsync.dart @@ -33,16 +33,17 @@ class BeneficiaryDownSyncBloc downSyncLocalRepository; final BandwidthCheckRepository bandwidthCheckRepository; final LocalRepository - householdLocalRepository; + householdLocalRepository; final LocalRepository - householdMemberLocalRepository; + householdMemberLocalRepository; final LocalRepository - projectBeneficiaryLocalRepository; + projectBeneficiaryLocalRepository; final LocalRepository taskLocalRepository; final LocalRepository - sideEffectLocalRepository; + sideEffectLocalRepository; final LocalRepository referralLocalRepository; + BeneficiaryDownSyncBloc({ required this.individualLocalRepository, required this.downSyncRemoteRepository, @@ -209,8 +210,7 @@ class BeneficiaryDownSyncBloc event.boundaryName, downSyncResults); await SyncServiceSingleton() .entityMapper - ? - .writeToEntityDB(event.boundaryCode, downSyncResults, [ + ?.writeToEntityDB(downSyncResults, [ individualLocalRepository, householdLocalRepository, householdMemberLocalRepository, diff --git a/apps/health_campaign_field_worker_app/lib/data/sync_service_mapper.dart b/apps/health_campaign_field_worker_app/lib/data/sync_service_mapper.dart index 92b9957ee9..959ebd6bf0 100644 --- a/apps/health_campaign_field_worker_app/lib/data/sync_service_mapper.dart +++ b/apps/health_campaign_field_worker_app/lib/data/sync_service_mapper.dart @@ -15,9 +15,9 @@ import '../utils/environment_config.dart'; class SyncServiceMapper extends SyncEntityMapperListener { @override FutureOr writeToEntityDB( - Map response, - List> - localRepositories) async { + Map response, + List localRepositories, + ) async { try { for (int i = 0; i <= response.keys.length - 1; i++) { if (response.keys.elementAt(i) != 'DownsyncCriteria') { @@ -31,53 +31,8 @@ class SyncServiceMapper extends SyncEntityMapperListener { final entityList = entityResponse.whereType>().toList(); - switch (response.keys.elementAt(i)) { - case "Individuals": - final entity = entityList - .map((e) => IndividualModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "Households": - final entity = entityList - .map((e) => HouseholdModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "HouseholdMembers": - final entity = entityList - .map( - (e) => HouseholdMemberModelMapper.fromJson( - jsonEncode(e), - ), - ) - .toList(); - await local.bulkCreate(entity); - case "ProjectBeneficiaries": - final entity = entityList - .map((e) => - ProjectBeneficiaryModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "Tasks": - final entity = entityList - .map((e) => TaskModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "SideEffects": - final entity = entityList - .map((e) => SideEffectModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - case "Referrals": - final entity = entityList - .map((e) => ReferralModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - default: - final entity = entityList - .map((e) => EntityModelMapper.fromJson(jsonEncode(e))) - .toList(); - await local.bulkCreate(entity); - } + var key = response.keys.elementAt(i); + createDbRecords(local, entityList, key); } } } catch (e) { @@ -85,6 +40,56 @@ class SyncServiceMapper extends SyncEntityMapperListener { } } + void createDbRecords(LocalRepository local, + List> entityList, String key) async { + switch (key) { + case "Individuals": + final entity = entityList + .map((e) => IndividualModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "Households": + final entity = entityList + .map((e) => HouseholdModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "HouseholdMembers": + final entity = entityList + .map( + (e) => HouseholdMemberModelMapper.fromJson( + jsonEncode(e), + ), + ) + .toList(); + await local.bulkCreate(entity); + case "ProjectBeneficiaries": + final entity = entityList + .map((e) => ProjectBeneficiaryModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "Tasks": + final entity = entityList + .map((e) => TaskModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "SideEffects": + final entity = entityList + .map((e) => SideEffectModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + case "Referrals": + final entity = entityList + .map((e) => ReferralModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + default: + final entity = entityList + .map((e) => EntityModelMapper.fromJson(jsonEncode(e))) + .toList(); + await local.bulkCreate(entity); + } + } + @override int getSyncCount(List opLogs) { int count = opLogs.where((element) { diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart index 81c1acfd43..0819289a5f 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -92,15 +92,15 @@ class _DataReceiverPageState extends LocalizedState { margin: const EdgeInsets.only(top: spacer2), padding: const EdgeInsets.all(spacer2), children: [ - Button( - type: ButtonType.secondary, + DigitButton( + type: DigitButtonType.secondary, mainAxisSize: MainAxisSize.max, onPressed: () { context.router.maybePop(); }, label: localizations .translate(i18.common.coreCommonCancel), - size: ButtonSize.large, + size: DigitButtonSize.large, ), ]), slivers: [ diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart index f34cf6a9de..d422f874b7 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -93,14 +93,14 @@ class _DataTransferScreenState extends LocalizedState { margin: const EdgeInsets.only(top: spacer2), padding: const EdgeInsets.all(spacer2), children: [ - Button( - type: ButtonType.secondary, + DigitButton( + type: DigitButtonType.secondary, mainAxisSize: MainAxisSize.max, onPressed: () { context.router.maybePop(); }, label: localizations.translate(i18.common.coreCommonCancel), - size: ButtonSize.large, + size: DigitButtonSize.large, ), ]), slivers: [ @@ -211,7 +211,7 @@ class _DataTransferScreenState extends LocalizedState { ], ), failedToTransfer: (error) => Center( - child: Button( + child: DigitButton( onPressed: () { context.read().add( DataTransferEvent( @@ -223,10 +223,10 @@ class _DataTransferScreenState extends LocalizedState { selectedProject: context.selectedProject.id)); }, - size: ButtonSize.large, + size: DigitButtonSize.large, label: localizations .translate(i18.common.coreCommonRetry), - type: ButtonType.primary, + type: DigitButtonType.primary, ), ), )), diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart index 991a82515d..6308874109 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -65,18 +65,18 @@ class DevicesListPageState extends LocalizedState return Scaffold( body: ScrollableContent( backgroundColor: DigitTheme.instance.colors.light.primary1Bg, - enableFixedButton: true, + enableFixedDigitButton: true, footer: DigitCard( margin: const EdgeInsets.only(top: 16.0), padding: const EdgeInsets.all(16.0), children: [ - Button( + DigitButton( onPressed: handleFooterButtonPress, - type: ButtonType.primary, + type: DigitButtonType.primary, label: widget.deviceType == DeviceType.sender ? localizations.translate(i18.dataShare.sendAction) : localizations.translate(i18.dataShare.receiveAction), - size: ButtonSize.large, + size: DigitButtonSize.large, mainAxisSize: MainAxisSize.max, capitalizeLetters: false, ), diff --git a/apps/health_campaign_field_worker_app/lib/router/app_router.dart b/apps/health_campaign_field_worker_app/lib/router/app_router.dart index f588a1f498..64e345d21f 100644 --- a/apps/health_campaign_field_worker_app/lib/router/app_router.dart +++ b/apps/health_campaign_field_worker_app/lib/router/app_router.dart @@ -1,21 +1,16 @@ import 'package:attendance_management/router/attendance_router.dart'; -import 'package:attendance_management/router/attendance_router.gm.dart'; import 'package:auto_route/auto_route.dart'; import 'package:closed_household/router/closed_household_router.dart'; -import 'package:closed_household/router/closed_household_router.gm.dart'; import 'package:complaints/router/complaints_router.dart'; import 'package:complaints/router/complaints_router.gm.dart'; import 'package:digit_data_model/data_model.dart'; -import 'package:digit_data_model/data_model.dart'; import 'package:digit_dss/router/dashboard_router.dart'; import 'package:digit_dss/router/dashboard_router.gm.dart'; import 'package:digit_scanner/router/digit_scanner_router.dart'; import 'package:digit_scanner/router/digit_scanner_router.gm.dart'; import 'package:flutter/material.dart'; import 'package:inventory_management/router/inventory_router.dart'; -import 'package:inventory_management/router/inventory_router.gm.dart'; import 'package:referral_reconciliation/router/referral_reconciliation_router.dart'; -import 'package:referral_reconciliation/router/referral_reconciliation_router.gm.dart'; import 'package:registration_delivery/router/registration_delivery_router.dart'; import 'package:registration_delivery/router/registration_delivery_router.gm.dart'; import 'package:survey_form/router/survey_form_router.dart'; @@ -28,6 +23,11 @@ import '../pages/boundary_selection.dart'; import '../pages/home.dart'; import '../pages/language_selection.dart'; import '../pages/login.dart'; +import '../pages/peer_to_peer/data_receiver.dart'; +import '../pages/peer_to_peer/data_share_home.dart'; +import '../pages/peer_to_peer/data_transfer.dart'; +import '../pages/peer_to_peer/devices_list.dart'; +import '../pages/peer_to_peer/peer_to_peer_wrapper.dart'; import '../pages/profile.dart'; import '../pages/project_facility_selection.dart'; import '../pages/project_selection.dart'; @@ -201,6 +201,22 @@ class AppRouter extends _$AppRouter { // Referral Reconciliation Route ...ReferralReconciliationRoute().routes, + + AutoRoute( + page: DataShareHomeRoute.page, + path: 'data-share-home', + ), + AutoRoute( + page: PeerToPeerWrapperRoute.page, + path: 'peer-to-peer-wrapper', + children: [ + AutoRoute( + page: DevicesListRoute.page, + path: 'devices-list', + initial: true), + AutoRoute(page: DataTransferRoute.page, path: 'data-transfer'), + AutoRoute(page: DataReceiverRoute.page, path: 'data-receiver'), + ]), ], ) ]; diff --git a/apps/health_campaign_field_worker_app/pubspec.lock b/apps/health_campaign_field_worker_app/pubspec.lock index 88ebc49aa4..45ec1ccfa9 100644 --- a/apps/health_campaign_field_worker_app/pubspec.lock +++ b/apps/health_campaign_field_worker_app/pubspec.lock @@ -953,6 +953,15 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_nearby_connections: + dependency: "direct main" + description: + path: "." + ref: master + resolved-ref: "9ead63aa7e01f7603a453368de1ee2b4dc009ed6" + url: "https://github.com/champeauxr/flutter_nearby_connections" + source: git + version: "1.1.2" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -1669,6 +1678,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + percent_indicator: + dependency: "direct main" + description: + name: percent_indicator + sha256: "0d77d5c6fa9b7f60202cedf748b568ba9ba38d3f30405d6ceae4da76f5185462" + url: "https://pub.dev" + source: hosted + version: "4.2.4" permission_handler: dependency: "direct main" description: diff --git a/packages/digit_components/example/pubspec.lock b/packages/digit_components/example/pubspec.lock index d3c1ce88c8..60b6f7b8fe 100644 --- a/packages/digit_components/example/pubspec.lock +++ b/packages/digit_components/example/pubspec.lock @@ -231,7 +231,7 @@ packages: path: ".." relative: true source: path - version: "1.0.2+1" + version: "1.0.3" easy_stepper: dependency: transitive description: diff --git a/packages/digit_location_tracker/pubspec.lock b/packages/digit_location_tracker/pubspec.lock index d425cd3822..f1ca40a52a 100644 --- a/packages/digit_location_tracker/pubspec.lock +++ b/packages/digit_location_tracker/pubspec.lock @@ -142,7 +142,7 @@ packages: path: "../digit_data_model" relative: true source: path - version: "1.0.5" + version: "1.0.5+1" digit_firebase_services: dependency: "direct overridden" description: diff --git a/packages/forms_engine/pubspec.lock b/packages/forms_engine/pubspec.lock index b3553cb931..7359a844b5 100644 --- a/packages/forms_engine/pubspec.lock +++ b/packages/forms_engine/pubspec.lock @@ -231,7 +231,7 @@ packages: path: "../digit_components" relative: true source: path - version: "1.0.2+1" + version: "1.0.3" easy_stepper: dependency: transitive description: From 197820924fb410e877c2456730398fa9e57323dc Mon Sep 17 00:00:00 2001 From: Naveen Renati <154230258+naveenr-egov@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:45:31 +0530 Subject: [PATCH 11/16] Added message model and moved to enums --- .../lib/blocs/peer_to_peer/peer_to_peer.dart | 136 ++++++------ .../lib/models/data_model.init.dart | 22 +- .../entities/peer_to_peer/message_types.dart | 35 ++++ .../peer_to_peer/message_types.mapper.dart | 161 +++++++++++++++ .../peer_to_peer/peer_to_peer_message.dart | 25 +++ .../peer_to_peer_message.mapper.dart | 194 ++++++++++++++++++ .../lib/router/app_router.dart | 1 + 7 files changed, 496 insertions(+), 78 deletions(-) create mode 100644 apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.dart create mode 100644 apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.mapper.dart create mode 100644 apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/peer_to_peer_message.dart create mode 100644 apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/peer_to_peer_message.mapper.dart diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart index f7e6a5b9eb..af96a25c05 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -14,6 +14,8 @@ import 'package:sync_service/data/repositories/sync/remote_type.dart'; import '../../data/sync_service_mapper.dart'; import '../../models/downsync/downsync.dart'; +import '../../models/entities/peer_to_peer/message_types.dart'; +import '../../models/entities/peer_to_peer/peer_to_peer_message.dart'; part 'peer_to_peer.freezed.dart'; @@ -41,7 +43,7 @@ class PeerToPeerBloc extends Bloc { int totalCount = 0; String entityType = ''; late Device connectedDevice; - late String selectedBoundaryCode; + late String? selectedBoundaryCode; PeerToPeerBloc( {required this.individualLocalRepository, @@ -99,11 +101,6 @@ class PeerToPeerBloc extends Bloc { .map((e) => offsetData[e]) .firstOrNull; - var selectedBoundaryName = offsetData.keys - .where((element) => element == 'boundaryName') - .map((e) => offsetData[e]) - .firstOrNull; - totalCount = offsetData.keys .where((element) => element == 'totalCount') .map((e) => offsetData[e]) @@ -116,21 +113,20 @@ class PeerToPeerBloc extends Bloc { for (var device in event.connectedDevice) { await event.nearbyService.sendMessage( device.deviceId, - jsonEncode({ - "type": "chunk", - "selectedBoundaryCode": selectedBoundaryCode, - "selectedBoundaryName": selectedBoundaryName, - "message": compressJson(entityResponse), - "offset": offsetValue, - "totalData": totalCount, - }), + PeerToPeerMessageModel( + messageType: MessageTypes.chunk.toValue(), + selectedBoundaryCode: selectedBoundaryCode, + message: compressJson(entityResponse), + offset: offsetValue, + totalCount: totalCount) + .toJson(), ); } // Wait for confirmation before proceeding await waitForConfirmation( event.nearbyService, - confirmationType: "chunk", + confirmationType: ConfirmationTypes.chunk.toValue(), offset: offsetValue, ); @@ -145,19 +141,19 @@ class PeerToPeerBloc extends Bloc { for (var device in event.connectedDevice) { await event.nearbyService.sendMessage( device.deviceId, - jsonEncode({ - "type": "confirmation", - "confirmationType": "finalTransfer", - "status": "completed", - "message": "All entities have been sent successfully.", - }), + PeerToPeerMessageModel( + messageType: MessageTypes.confirmation.toValue(), + message: "All entities have been sent successfully.", + confirmationType: ConfirmationTypes.finalTransfer.toValue(), + status: MessageStatus.completed.toValue(), + ).toJson(), ); } // Wait for receiver's overall acknowledgment await waitForConfirmation( event.nearbyService, - confirmationType: "finalAcknowledgment", + confirmationType: ConfirmationTypes.finalAcknowledgment.toValue(), ); emit(const PeerToPeerState.completedDataTransfer()); @@ -199,15 +195,15 @@ class PeerToPeerBloc extends Bloc { PeerToPeerEmitter emit, ) async { try { - var receivedJson = jsonDecode(event.data["message"]); - var messageType = receivedJson["type"]; + PeerToPeerMessageModel messageModel = + PeerToPeerMessageModelMapper.fromJson(event.data["message"]); - if (messageType == "chunk") { + if (messageModel.messageType == MessageTypes.chunk.toValue()) { // Process chunk - int offset = receivedJson["offset"]; - int totalCount = receivedJson["totalData"]; - selectedBoundaryCode = receivedJson["selectedBoundaryCode"]; - final compressedMessage = receivedJson["message"]; + int? offset = messageModel.offset; + int? totalCount = messageModel.totalCount; + selectedBoundaryCode = messageModel.selectedBoundaryCode; + final compressedMessage = messageModel.message; final entityList = decompressJson(compressedMessage).entries; for (var entity in entityList) { @@ -249,8 +245,8 @@ class PeerToPeerBloc extends Bloc { } // Update progress and clear processed data - receivedBytes = offset; - double progress = receivedBytes / totalCount; + receivedBytes = offset!; + double progress = receivedBytes / totalCount!; // Emit progress emit(PeerToPeerState.receivingInProgress( @@ -261,18 +257,19 @@ class PeerToPeerBloc extends Bloc { // Send chunk acknowledgment await event.nearbyService.sendMessage( - event.data["deviceId"], - jsonEncode({ - "type": "confirmation", - "confirmationType": "chunk", - "status": "received", - "offset": offset, - "progress": progress, - "message": "Chunk received and saved successfully.", - }), - ); - } else if (messageType == "confirmation" && - receivedJson["confirmationType"] == "finalTransfer") { + event.data["deviceId"], + PeerToPeerMessageModel( + messageType: MessageTypes.confirmation.toValue(), + confirmationType: ConfirmationTypes.chunk.toValue(), + status: MessageStatus.received.toValue(), + progress: progress, + offset: offset, + message: "Chunk received and saved successfully.") + .toJson()); + } else if (messageModel.messageType == + MessageTypes.confirmation.toValue() && + messageModel.confirmationType == + ConfirmationTypes.finalTransfer.toValue()) { final existingDownSyncData = await downSyncLocalRepository.search(DownsyncSearchModel( locality: selectedBoundaryCode, @@ -286,33 +283,28 @@ class PeerToPeerBloc extends Bloc { ), ); - // Handle overall transfer final acknowledgment - emit(const PeerToPeerState.dataReceived()); - // Send overall transfer acknowledgment await event.nearbyService.sendMessage( - event.data["deviceId"], - jsonEncode({ - "type": "confirmation", - "confirmationType": "finalAcknowledgment", - "status": "success", - "message": "All entities received and processed successfully.", - }), - ); + event.data["deviceId"], + PeerToPeerMessageModel( + messageType: MessageTypes.confirmation.toValue(), + message: "All entities received and processed successfully.", + confirmationType: ConfirmationTypes.finalAcknowledgment.toValue(), + status: MessageStatus.success.toValue(), + ).toJson()); emit(const PeerToPeerState.dataReceived()); } } catch (e) { debugPrint("Error processing received data: $e"); emit(PeerToPeerState.failedToReceive(error: e.toString())); await event.nearbyService.sendMessage( - event.data["deviceId"], - jsonEncode({ - "type": "confirmation", - "confirmationType": "failed", - "status": "fail", - "message": "$e", - }), - ); + event.data["deviceId"], + PeerToPeerMessageModel( + messageType: MessageTypes.confirmation.toValue(), + message: "$e", + confirmationType: ConfirmationTypes.failed.toValue(), + status: MessageStatus.fail.toValue(), + ).toJson()); } } @@ -326,20 +318,24 @@ class PeerToPeerBloc extends Bloc { final subscription = nearbyService.dataReceivedSubscription( callback: (data) { try { - var receivedJson = jsonDecode(data["message"]); - if (receivedJson["type"] == "confirmation") { - if (confirmationType == "chunk" && - receivedJson["offset"] == offset) { + PeerToPeerMessageModel messageModel = + PeerToPeerMessageModelMapper.fromJson(data["message"]); + + if (messageModel.messageType == MessageTypes.confirmation.toValue()) { + if (confirmationType == ConfirmationTypes.chunk.toValue() && + messageModel.offset == offset) { completer.complete(); - } else if (confirmationType == "finalAcknowledgment") { + } else if (confirmationType == + ConfirmationTypes.finalAcknowledgment.toValue()) { completer.complete(); - } else if (confirmationType == "final") { + } else if (confirmationType == + ConfirmationTypes.finalTransfer.toValue()) { completer.complete(); - } else if (confirmationType == "failed") { + } else if (confirmationType == ConfirmationTypes.failed.toValue()) { completer.complete(); emit(const PeerToPeerState.failedToTransfer( error: "File doesn't exist")); - throw "Failed to transfer ${receivedJson['message']}"; + throw "Failed to transfer ${messageModel.message}"; } } } catch (e) { diff --git a/apps/health_campaign_field_worker_app/lib/models/data_model.init.dart b/apps/health_campaign_field_worker_app/lib/models/data_model.init.dart index c79ba0096a..9774019fc3 100644 --- a/apps/health_campaign_field_worker_app/lib/models/data_model.init.dart +++ b/apps/health_campaign_field_worker_app/lib/models/data_model.init.dart @@ -7,10 +7,12 @@ import 'downsync/downsync.dart' as p0; import 'entities/additional_fields_type.dart' as p1; import 'entities/mdms_master_enums.dart' as p2; import 'entities/mdms_module_enums.dart' as p3; -import 'entities/roles.dart' as p4; -import 'entities/roles_type.dart' as p5; -import 'entities/scanner_type.dart' as p6; -import 'entities/status.dart' as p7; +import 'entities/peer_to_peer/message_types.dart' as p4; +import 'entities/peer_to_peer/peer_to_peer_message.dart' as p5; +import 'entities/roles.dart' as p6; +import 'entities/roles_type.dart' as p7; +import 'entities/scanner_type.dart' as p8; +import 'entities/status.dart' as p9; void initializeMappers() { p0.DownsyncSearchModelMapper.ensureInitialized(); @@ -19,8 +21,12 @@ void initializeMappers() { p1.AdditionalFieldsTypeMapper.ensureInitialized(); p2.MasterEnumsMapper.ensureInitialized(); p3.ModuleEnumsMapper.ensureInitialized(); - p4.RolesMapper.ensureInitialized(); - p5.RolesTypeMapper.ensureInitialized(); - p6.ScannerTypeMapper.ensureInitialized(); - p7.StatusMapper.ensureInitialized(); + p4.MessageTypesMapper.ensureInitialized(); + p4.ConfirmationTypesMapper.ensureInitialized(); + p4.MessageStatusMapper.ensureInitialized(); + p5.PeerToPeerMessageModelMapper.ensureInitialized(); + p6.RolesMapper.ensureInitialized(); + p7.RolesTypeMapper.ensureInitialized(); + p8.ScannerTypeMapper.ensureInitialized(); + p9.StatusMapper.ensureInitialized(); } diff --git a/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.dart b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.dart new file mode 100644 index 0000000000..c394fa30ce --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.dart @@ -0,0 +1,35 @@ +import 'package:dart_mappable/dart_mappable.dart'; + +part 'message_types.mapper.dart'; + +@MappableEnum(caseStyle: CaseStyle.upperCase) +enum MessageTypes { + @MappableValue("confirmation") + confirmation, + @MappableValue("chunk") + chunk +} + +@MappableEnum(caseStyle: CaseStyle.upperCase) +enum ConfirmationTypes { + @MappableValue("finalTransfer") + finalTransfer, + @MappableValue("chunk") + chunk, + @MappableValue("failed") + failed, + @MappableValue("finalAcknowledgment") + finalAcknowledgment, +} + +@MappableEnum(caseStyle: CaseStyle.upperCase) +enum MessageStatus { + @MappableValue("success") + success, + @MappableValue("fail") + fail, + @MappableValue("received") + received, + @MappableValue("completed") + completed, +} diff --git a/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.mapper.dart b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.mapper.dart new file mode 100644 index 0000000000..a4eef2bf0d --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.mapper.dart @@ -0,0 +1,161 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, unnecessary_cast, override_on_non_overriding_member +// ignore_for_file: strict_raw_type, inference_failure_on_untyped_parameter + +part of 'message_types.dart'; + +class MessageTypesMapper extends EnumMapper { + MessageTypesMapper._(); + + static MessageTypesMapper? _instance; + static MessageTypesMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = MessageTypesMapper._()); + } + return _instance!; + } + + static MessageTypes fromValue(dynamic value) { + ensureInitialized(); + return MapperContainer.globals.fromValue(value); + } + + @override + MessageTypes decode(dynamic value) { + switch (value) { + case "confirmation": + return MessageTypes.confirmation; + case "chunk": + return MessageTypes.chunk; + default: + throw MapperException.unknownEnumValue(value); + } + } + + @override + dynamic encode(MessageTypes self) { + switch (self) { + case MessageTypes.confirmation: + return "confirmation"; + case MessageTypes.chunk: + return "chunk"; + } + } +} + +extension MessageTypesMapperExtension on MessageTypes { + dynamic toValue() { + MessageTypesMapper.ensureInitialized(); + return MapperContainer.globals.toValue(this); + } +} + +class ConfirmationTypesMapper extends EnumMapper { + ConfirmationTypesMapper._(); + + static ConfirmationTypesMapper? _instance; + static ConfirmationTypesMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = ConfirmationTypesMapper._()); + } + return _instance!; + } + + static ConfirmationTypes fromValue(dynamic value) { + ensureInitialized(); + return MapperContainer.globals.fromValue(value); + } + + @override + ConfirmationTypes decode(dynamic value) { + switch (value) { + case "finalTransfer": + return ConfirmationTypes.finalTransfer; + case "chunk": + return ConfirmationTypes.chunk; + case "failed": + return ConfirmationTypes.failed; + case "finalAcknowledgment": + return ConfirmationTypes.finalAcknowledgment; + default: + throw MapperException.unknownEnumValue(value); + } + } + + @override + dynamic encode(ConfirmationTypes self) { + switch (self) { + case ConfirmationTypes.finalTransfer: + return "finalTransfer"; + case ConfirmationTypes.chunk: + return "chunk"; + case ConfirmationTypes.failed: + return "failed"; + case ConfirmationTypes.finalAcknowledgment: + return "finalAcknowledgment"; + } + } +} + +extension ConfirmationTypesMapperExtension on ConfirmationTypes { + dynamic toValue() { + ConfirmationTypesMapper.ensureInitialized(); + return MapperContainer.globals.toValue(this); + } +} + +class MessageStatusMapper extends EnumMapper { + MessageStatusMapper._(); + + static MessageStatusMapper? _instance; + static MessageStatusMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = MessageStatusMapper._()); + } + return _instance!; + } + + static MessageStatus fromValue(dynamic value) { + ensureInitialized(); + return MapperContainer.globals.fromValue(value); + } + + @override + MessageStatus decode(dynamic value) { + switch (value) { + case "success": + return MessageStatus.success; + case "fail": + return MessageStatus.fail; + case "received": + return MessageStatus.received; + case "completed": + return MessageStatus.completed; + default: + throw MapperException.unknownEnumValue(value); + } + } + + @override + dynamic encode(MessageStatus self) { + switch (self) { + case MessageStatus.success: + return "success"; + case MessageStatus.fail: + return "fail"; + case MessageStatus.received: + return "received"; + case MessageStatus.completed: + return "completed"; + } + } +} + +extension MessageStatusMapperExtension on MessageStatus { + dynamic toValue() { + MessageStatusMapper.ensureInitialized(); + return MapperContainer.globals.toValue(this); + } +} diff --git a/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/peer_to_peer_message.dart b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/peer_to_peer_message.dart new file mode 100644 index 0000000000..7efbd31aea --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/peer_to_peer_message.dart @@ -0,0 +1,25 @@ +import 'package:dart_mappable/dart_mappable.dart'; + +part 'peer_to_peer_message.mapper.dart'; + +@MappableClass(ignoreNull: true, discriminatorValue: MappableClass.useAsDefault) +class PeerToPeerMessageModel with PeerToPeerMessageModelMappable { + final String messageType; + final String? confirmationType; + final String? status; + final String message; + final String? selectedBoundaryCode; + final int? offset; + final int? totalCount; + final double? progress; + + PeerToPeerMessageModel( + {required this.messageType, + this.confirmationType, + this.status, + required this.message, + this.selectedBoundaryCode, + this.offset, + this.totalCount, + this.progress}); +} diff --git a/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/peer_to_peer_message.mapper.dart b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/peer_to_peer_message.mapper.dart new file mode 100644 index 0000000000..9b0823bfbf --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/peer_to_peer_message.mapper.dart @@ -0,0 +1,194 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, unnecessary_cast, override_on_non_overriding_member +// ignore_for_file: strict_raw_type, inference_failure_on_untyped_parameter + +part of 'peer_to_peer_message.dart'; + +class PeerToPeerMessageModelMapper + extends ClassMapperBase { + PeerToPeerMessageModelMapper._(); + + static PeerToPeerMessageModelMapper? _instance; + static PeerToPeerMessageModelMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = PeerToPeerMessageModelMapper._()); + } + return _instance!; + } + + @override + final String id = 'PeerToPeerMessageModel'; + + static String _$messageType(PeerToPeerMessageModel v) => v.messageType; + static const Field _f$messageType = + Field('messageType', _$messageType); + static String? _$confirmationType(PeerToPeerMessageModel v) => + v.confirmationType; + static const Field _f$confirmationType = + Field('confirmationType', _$confirmationType, opt: true); + static String? _$status(PeerToPeerMessageModel v) => v.status; + static const Field _f$status = + Field('status', _$status, opt: true); + static String _$message(PeerToPeerMessageModel v) => v.message; + static const Field _f$message = + Field('message', _$message); + static String? _$selectedBoundaryCode(PeerToPeerMessageModel v) => + v.selectedBoundaryCode; + static const Field _f$selectedBoundaryCode = + Field('selectedBoundaryCode', _$selectedBoundaryCode, opt: true); + static int? _$offset(PeerToPeerMessageModel v) => v.offset; + static const Field _f$offset = + Field('offset', _$offset, opt: true); + static int? _$totalCount(PeerToPeerMessageModel v) => v.totalCount; + static const Field _f$totalCount = + Field('totalCount', _$totalCount, opt: true); + static double? _$progress(PeerToPeerMessageModel v) => v.progress; + static const Field _f$progress = + Field('progress', _$progress, opt: true); + + @override + final MappableFields fields = const { + #messageType: _f$messageType, + #confirmationType: _f$confirmationType, + #status: _f$status, + #message: _f$message, + #selectedBoundaryCode: _f$selectedBoundaryCode, + #offset: _f$offset, + #totalCount: _f$totalCount, + #progress: _f$progress, + }; + @override + final bool ignoreNull = true; + + static PeerToPeerMessageModel _instantiate(DecodingData data) { + return PeerToPeerMessageModel( + messageType: data.dec(_f$messageType), + confirmationType: data.dec(_f$confirmationType), + status: data.dec(_f$status), + message: data.dec(_f$message), + selectedBoundaryCode: data.dec(_f$selectedBoundaryCode), + offset: data.dec(_f$offset), + totalCount: data.dec(_f$totalCount), + progress: data.dec(_f$progress)); + } + + @override + final Function instantiate = _instantiate; + + static PeerToPeerMessageModel fromMap(Map map) { + return ensureInitialized().decodeMap(map); + } + + static PeerToPeerMessageModel fromJson(String json) { + return ensureInitialized().decodeJson(json); + } +} + +mixin PeerToPeerMessageModelMappable { + String toJson() { + return PeerToPeerMessageModelMapper.ensureInitialized() + .encodeJson(this as PeerToPeerMessageModel); + } + + Map toMap() { + return PeerToPeerMessageModelMapper.ensureInitialized() + .encodeMap(this as PeerToPeerMessageModel); + } + + PeerToPeerMessageModelCopyWith + get copyWith => _PeerToPeerMessageModelCopyWithImpl( + this as PeerToPeerMessageModel, $identity, $identity); + @override + String toString() { + return PeerToPeerMessageModelMapper.ensureInitialized() + .stringifyValue(this as PeerToPeerMessageModel); + } + + @override + bool operator ==(Object other) { + return PeerToPeerMessageModelMapper.ensureInitialized() + .equalsValue(this as PeerToPeerMessageModel, other); + } + + @override + int get hashCode { + return PeerToPeerMessageModelMapper.ensureInitialized() + .hashValue(this as PeerToPeerMessageModel); + } +} + +extension PeerToPeerMessageModelValueCopy<$R, $Out> + on ObjectCopyWith<$R, PeerToPeerMessageModel, $Out> { + PeerToPeerMessageModelCopyWith<$R, PeerToPeerMessageModel, $Out> + get $asPeerToPeerMessageModel => + $base.as((v, t, t2) => _PeerToPeerMessageModelCopyWithImpl(v, t, t2)); +} + +abstract class PeerToPeerMessageModelCopyWith< + $R, + $In extends PeerToPeerMessageModel, + $Out> implements ClassCopyWith<$R, $In, $Out> { + $R call( + {String? messageType, + String? confirmationType, + String? status, + String? message, + String? selectedBoundaryCode, + int? offset, + int? totalCount, + double? progress}); + PeerToPeerMessageModelCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>( + Then<$Out2, $R2> t); +} + +class _PeerToPeerMessageModelCopyWithImpl<$R, $Out> + extends ClassCopyWithBase<$R, PeerToPeerMessageModel, $Out> + implements + PeerToPeerMessageModelCopyWith<$R, PeerToPeerMessageModel, $Out> { + _PeerToPeerMessageModelCopyWithImpl(super.value, super.then, super.then2); + + @override + late final ClassMapperBase $mapper = + PeerToPeerMessageModelMapper.ensureInitialized(); + @override + $R call( + {String? messageType, + Object? confirmationType = $none, + Object? status = $none, + String? message, + Object? selectedBoundaryCode = $none, + Object? offset = $none, + Object? totalCount = $none, + Object? progress = $none}) => + $apply(FieldCopyWithData({ + if (messageType != null) #messageType: messageType, + if (confirmationType != $none) #confirmationType: confirmationType, + if (status != $none) #status: status, + if (message != null) #message: message, + if (selectedBoundaryCode != $none) + #selectedBoundaryCode: selectedBoundaryCode, + if (offset != $none) #offset: offset, + if (totalCount != $none) #totalCount: totalCount, + if (progress != $none) #progress: progress + })); + @override + PeerToPeerMessageModel $make(CopyWithData data) => PeerToPeerMessageModel( + messageType: data.get(#messageType, or: $value.messageType), + confirmationType: + data.get(#confirmationType, or: $value.confirmationType), + status: data.get(#status, or: $value.status), + message: data.get(#message, or: $value.message), + selectedBoundaryCode: + data.get(#selectedBoundaryCode, or: $value.selectedBoundaryCode), + offset: data.get(#offset, or: $value.offset), + totalCount: data.get(#totalCount, or: $value.totalCount), + progress: data.get(#progress, or: $value.progress)); + + @override + PeerToPeerMessageModelCopyWith<$R2, PeerToPeerMessageModel, $Out2> + $chain<$R2, $Out2>(Then<$Out2, $R2> t) => + _PeerToPeerMessageModelCopyWithImpl($value, $cast, t); +} diff --git a/apps/health_campaign_field_worker_app/lib/router/app_router.dart b/apps/health_campaign_field_worker_app/lib/router/app_router.dart index 64e345d21f..9f56755311 100644 --- a/apps/health_campaign_field_worker_app/lib/router/app_router.dart +++ b/apps/health_campaign_field_worker_app/lib/router/app_router.dart @@ -9,6 +9,7 @@ import 'package:digit_dss/router/dashboard_router.gm.dart'; import 'package:digit_scanner/router/digit_scanner_router.dart'; import 'package:digit_scanner/router/digit_scanner_router.gm.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; import 'package:inventory_management/router/inventory_router.dart'; import 'package:referral_reconciliation/router/referral_reconciliation_router.dart'; import 'package:registration_delivery/router/registration_delivery_router.dart'; From 8c6626191b2a5bfeb9309d4a093549a7f4858414 Mon Sep 17 00:00:00 2001 From: Naveen Renati <154230258+naveenr-egov@users.noreply.github.com> Date: Mon, 17 Feb 2025 10:37:30 +0530 Subject: [PATCH 12/16] unlocalized codes display fix during login and logout --- .../lib/blocs/localization/app_localization.dart | 6 ++++-- .../lib/pages/language_selection.dart | 9 +++------ apps/health_campaign_field_worker_app/pubspec.lock | 7 +++---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/apps/health_campaign_field_worker_app/lib/blocs/localization/app_localization.dart b/apps/health_campaign_field_worker_app/lib/blocs/localization/app_localization.dart index 44046ce48c..7d883212c1 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/localization/app_localization.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/localization/app_localization.dart @@ -23,11 +23,13 @@ class AppLocalizations { AppLocalizationsDelegate(config, sql); Future load() async { - _localizedStrings.clear(); - final listOfLocalizations = await LocalizationLocalRepository().returnLocalizationFromSQL(sql); + if (listOfLocalizations.isNotEmpty) { + _localizedStrings.clear(); + } + _localizedStrings.addAll(listOfLocalizations); return true; diff --git a/apps/health_campaign_field_worker_app/lib/pages/language_selection.dart b/apps/health_campaign_field_worker_app/lib/pages/language_selection.dart index 2a3d446b18..abbef4b340 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/language_selection.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/language_selection.dart @@ -2,6 +2,7 @@ import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/digit_extended_theme.dart'; import 'package:digit_ui_components/theme/spacers.dart'; import 'package:digit_ui_components/utils/component_utils.dart'; +import 'package:digit_ui_components/widgets/atoms/digit_loader.dart'; import 'package:digit_ui_components/widgets/molecules/language_selection_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -59,14 +60,10 @@ class _LanguageSelectionPageState extends State { listener: (context, state) { if (state.loading && !isDialogVisible) { isDialogVisible = true; - DigitComponentsUtils.showDialog( - context, - "", - DialogType.inProgress, - ); + DigitLoaders.overlayLoader(context: context); } else if (!state.loading && isDialogVisible) { isDialogVisible = false; - DigitComponentsUtils.hideDialog(context); + Navigator.of(context, rootNavigator: true).pop(); } if (!state.loading && !isDialogVisible && diff --git a/apps/health_campaign_field_worker_app/pubspec.lock b/apps/health_campaign_field_worker_app/pubspec.lock index d65cc86d58..6692acf941 100644 --- a/apps/health_campaign_field_worker_app/pubspec.lock +++ b/apps/health_campaign_field_worker_app/pubspec.lock @@ -1808,10 +1808,9 @@ packages: registration_delivery: dependency: "direct main" description: - name: registration_delivery - sha256: "4354d586163faa46a1880a72dfcc380025599d370a194e6f14a7bba68f17906c" - url: "https://pub.dev" - source: hosted + path: "../../packages/registration_delivery" + relative: true + source: path version: "1.0.6" rxdart: dependency: transitive From f4f127032db5050a61b825039e2e8d29636fdbe1 Mon Sep 17 00:00:00 2001 From: Naveen Renati <154230258+naveenr-egov@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:06:08 +0530 Subject: [PATCH 13/16] Added PRODUCT as enum in beneficiary_type.dart --- packages/complaints/example/pubspec.lock | 12 ++++++------ packages/complaints/pubspec.lock | 4 ++-- packages/complaints/pubspec.yaml | 2 +- .../lib/models/entities/beneficiary_type.dart | 11 ++++++++--- .../lib/models/entities/beneficiary_type.mapper.dart | 4 ++++ 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/packages/complaints/example/pubspec.lock b/packages/complaints/example/pubspec.lock index 7b7c41616e..4e7c4caaa0 100644 --- a/packages/complaints/example/pubspec.lock +++ b/packages/complaints/example/pubspec.lock @@ -324,10 +324,10 @@ packages: dependency: transitive description: name: drift - sha256: c2d073d35ad441730812f4ea05b5dd031fb81c5f9786a4f5fb77ecd6307b6f74 + sha256: "6acedc562ffeed308049f78fb1906abad3d65714580b6745441ee6d50ec564cd" url: "https://pub.dev" source: hosted - version: "2.22.1" + version: "2.18.0" fake_async: dependency: transitive description: @@ -1069,10 +1069,10 @@ packages: dependency: transitive description: name: sqlite3 - sha256: bb174b3ec2527f9c5f680f73a89af8149dd99782fbb56ea88ad0807c5638f2ed + sha256: fde692580bee3379374af1f624eb3e113ab2865ecb161dbe2d8ac2de9735dbdb url: "https://pub.dev" source: hosted - version: "2.4.7" + version: "2.4.5" sqlite3_flutter_libs: dependency: transitive description: @@ -1301,10 +1301,10 @@ packages: dependency: transitive description: name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "0.5.1" web_socket_channel: dependency: transitive description: diff --git a/packages/complaints/pubspec.lock b/packages/complaints/pubspec.lock index 18ec5967db..379797c1e6 100644 --- a/packages/complaints/pubspec.lock +++ b/packages/complaints/pubspec.lock @@ -358,10 +358,10 @@ packages: dependency: "direct main" description: name: drift - sha256: "4e0ffee40d23f0b809e6cff1ad202886f51d629649073ed42d9cd1d194ea943e" + sha256: "6acedc562ffeed308049f78fb1906abad3d65714580b6745441ee6d50ec564cd" url: "https://pub.dev" source: hosted - version: "2.19.1+1" + version: "2.18.0" fake_async: dependency: transitive description: diff --git a/packages/complaints/pubspec.yaml b/packages/complaints/pubspec.yaml index b129ba7c29..d3e501eee4 100644 --- a/packages/complaints/pubspec.yaml +++ b/packages/complaints/pubspec.yaml @@ -26,7 +26,7 @@ dependencies: recase: ^4.1.0 flutter_svg: ^2.0.8 path_provider: ^2.0.11 - drift: ^2.0.0 + drift: ^2.18.0 dio: ^5.1.2 diff --git a/packages/digit_data_model/lib/models/entities/beneficiary_type.dart b/packages/digit_data_model/lib/models/entities/beneficiary_type.dart index f6ee614a6f..b924b33282 100644 --- a/packages/digit_data_model/lib/models/entities/beneficiary_type.dart +++ b/packages/digit_data_model/lib/models/entities/beneficiary_type.dart @@ -2,9 +2,14 @@ import 'package:dart_mappable/dart_mappable.dart'; part 'beneficiary_type.mapper.dart'; + @MappableEnum(caseStyle: CaseStyle.upperCase) enum BeneficiaryType { - @MappableValue("INDIVIDUAL") individual, - @MappableValue("HOUSEHOLD") household, + @MappableValue("INDIVIDUAL") + individual, + @MappableValue("HOUSEHOLD") + household, + @MappableValue("PRODUCT") + product, ; -} \ No newline at end of file +} diff --git a/packages/digit_data_model/lib/models/entities/beneficiary_type.mapper.dart b/packages/digit_data_model/lib/models/entities/beneficiary_type.mapper.dart index 349f9b2d50..f9f1ee40e2 100644 --- a/packages/digit_data_model/lib/models/entities/beneficiary_type.mapper.dart +++ b/packages/digit_data_model/lib/models/entities/beneficiary_type.mapper.dart @@ -29,6 +29,8 @@ class BeneficiaryTypeMapper extends EnumMapper { return BeneficiaryType.individual; case "HOUSEHOLD": return BeneficiaryType.household; + case "PRODUCT": + return BeneficiaryType.product; default: throw MapperException.unknownEnumValue(value); } @@ -41,6 +43,8 @@ class BeneficiaryTypeMapper extends EnumMapper { return "INDIVIDUAL"; case BeneficiaryType.household: return "HOUSEHOLD"; + case BeneficiaryType.product: + return "PRODUCT"; } } } From a5d2b6c97e318a4ccfd781c2ec39560a9f54647a Mon Sep 17 00:00:00 2001 From: Naveen Renati <154230258+naveenr-egov@users.noreply.github.com> Date: Tue, 18 Feb 2025 11:53:59 +0530 Subject: [PATCH 14/16] fetching sender device details --- .../lib/models/data_model.init.dart | 3 +- .../lib/pages/home.dart | 7 +-- .../lib/pages/peer_to_peer/data_receiver.dart | 54 +++--------------- .../lib/pages/peer_to_peer/data_transfer.dart | 23 +++++--- .../lib/pages/peer_to_peer/devices_list.dart | 57 ++++++++++++++++--- 5 files changed, 74 insertions(+), 70 deletions(-) diff --git a/apps/health_campaign_field_worker_app/lib/models/data_model.init.dart b/apps/health_campaign_field_worker_app/lib/models/data_model.init.dart index 0bec643d71..6e386db776 100644 --- a/apps/health_campaign_field_worker_app/lib/models/data_model.init.dart +++ b/apps/health_campaign_field_worker_app/lib/models/data_model.init.dart @@ -11,7 +11,7 @@ import 'entities/peer_to_peer/message_types.dart' as p4; import 'entities/peer_to_peer/peer_to_peer_message.dart' as p5; import 'entities/roles.dart' as p6; import 'entities/roles_type.dart' as p7; -import 'entities/status.dart' as p9; +import 'entities/scanner_type.dart' as p8; void initializeMappers() { p0.DownsyncSearchModelMapper.ensureInitialized(); @@ -27,5 +27,4 @@ void initializeMappers() { p6.RolesMapper.ensureInitialized(); p7.RolesTypeMapper.ensureInitialized(); p8.ScannerTypeMapper.ensureInitialized(); - p9.StatusMapper.ensureInitialized(); } diff --git a/apps/health_campaign_field_worker_app/lib/pages/home.dart b/apps/health_campaign_field_worker_app/lib/pages/home.dart index 84a1e495ee..0f45da4e5c 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/home.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/home.dart @@ -614,10 +614,9 @@ class _HomePageState extends LocalizedState { .map((label) => homeItemsShowcaseMap[label]!) .toList(); - - if (envConfig.variables.envType == EnvType.demo && kReleaseMode) { - filteredLabels.remove(i18.home.db); - } + if (envConfig.variables.envType == EnvType.demo && kReleaseMode) { + filteredLabels.remove(i18.home.db); + } filteredLabels.add(i18.home.dataShare); // TODO: Role action mapping diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart index 0819289a5f..f280e1d7c5 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:attendance_management/widgets/back_navigation_help_header.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:digit_components/widgets/atoms/digit_toaster.dart'; import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/digit_extended_theme.dart'; import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; @@ -49,12 +48,12 @@ class _DataReceiverPageState extends LocalizedState { if (device.state == SessionState.notConnected) { if (mounted) { context.router.maybePop(); - DigitToast.show(context, - options: DigitToastOptions( - localizations.translate( - '${device.deviceName} ${SessionState.notConnected.name}'), - true, - Theme.of(context))); + Toast.showToast( + context, + message: localizations.translate( + '${device.deviceName} ${SessionState.notConnected.name}'), + type: ToastType.error, + ); } } } @@ -79,7 +78,7 @@ class _DataReceiverPageState extends LocalizedState { listener: (context, state) { if (state is DataReceived) { context.router - .popAndPush(AcknowledgementRoute(isDataRecordSuccess: true)); + .popAndPush(AcknowledgementRoute(isDataRecordSuccess: false)); } }, child: BlocBuilder( @@ -240,8 +239,6 @@ class _DataReceiverPageState extends LocalizedState { spacing: 8.0, runSpacing: 4.0, children: [ - buildDeviceChip(), - const SizedBox(width: 8), Container( padding: const EdgeInsets.all( kPadding), @@ -287,41 +284,4 @@ class _DataReceiverPageState extends LocalizedState { } return deviceId; } - - Widget buildDeviceChip() { - return FutureBuilder( - future: getCurrentDeviceName(), // Call your async method here - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - // Show a loading indicator while the future is being resolved - return const CircularProgressIndicator(); - } else if (snapshot.hasError) { - // Handle error case - return Chip( - label: Text(localizations.translate(i18.common.coreCommonNA)), - backgroundColor: DigitTheme.instance.colors.light.primary1Bg, - ); - } else if (snapshot.hasData) { - // Display the device name when available - return Container( - padding: const EdgeInsets.all(kPadding), - decoration: BoxDecoration( - border: Border.all( - color: DigitTheme.instance.colors.light.primary1Bg, - ), - borderRadius: BorderRadius.circular(kPadding), - ), - child: Text( - snapshot.data!, - style: TextStyle( - color: DigitTheme.instance.colors.light.primary2, - ), - ), - ); - } else { - return const SizedBox.shrink(); // Handle unexpected case - } - }, - ); - } } diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart index d422f874b7..c7bf899a24 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:attendance_management/widgets/back_navigation_help_header.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:digit_components/widgets/atoms/digit_toaster.dart'; import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/digit_extended_theme.dart'; import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; @@ -51,12 +50,12 @@ class _DataTransferScreenState extends LocalizedState { if (device.state == SessionState.notConnected) { if (mounted) { context.router.maybePop(); - DigitToast.show(context, - options: DigitToastOptions( - localizations.translate( - '${device.deviceName} ${SessionState.notConnected.name}'), - true, - Theme.of(context))); + Toast.showToast( + context, + message: localizations.translate( + '${device.deviceName} ${SessionState.notConnected.name}'), + type: ToastType.error, + ); } } } @@ -80,7 +79,15 @@ class _DataTransferScreenState extends LocalizedState { listener: (context, state) { if (state is CompletedDataTransfer) { context.router - .popAndPush(AcknowledgementRoute(isDataRecordSuccess: true)); + .popAndPush(AcknowledgementRoute(isDataRecordSuccess: false)); + } + if (state is FailedDataTransfer) { + Toast.showToast( + context, + message: localizations.translate(state.error), + type: ToastType.error, + position: ToastPosition.aboveOneButtonFooter, + ); } }, child: BlocBuilder( diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart index 6308874109..a4ba6ef558 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -4,9 +4,9 @@ import 'dart:math'; import 'package:attendance_management/widgets/back_navigation_help_header.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:digit_components/widgets/atoms/digit_toaster.dart'; import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:digit_ui_components/widgets/atoms/digit_loader.dart'; import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; @@ -37,12 +37,17 @@ class DevicesListPageState extends LocalizedState late StreamSubscription stateSubscription; late AnimationController _controller; late AnimationController _radarController; + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + late Device senderDevice; + String? deviceName; @override void initState() { super.initState(); createAnimations(); initializeNearbyService(); + senderDevice = Device('', '', 0); + fetchSenderDeviceDetails(); } @override @@ -159,8 +164,11 @@ class DevicesListPageState extends LocalizedState List generateDeviceWidgets(double width, double height) { final random = Random(); - final devicesToShow = - widget.deviceType == DeviceType.receiver ? connectedDevices : devices; + final devicesToShow = widget.deviceType == DeviceType.receiver + ? senderDevice.deviceId.isNotEmpty + ? [senderDevice] + : [] + : devices; return devicesToShow.asMap().entries.map((entry) { final angle = random.nextDouble() * 2 * pi + entry.key * 0.1; @@ -237,13 +245,10 @@ class DevicesListPageState extends LocalizedState void handleFooterButtonPress() { if (connectedDevices.isEmpty) { - DigitToast.show( + Toast.showToast( context, - options: DigitToastOptions( - localizations.translate(i18.dataShare.noDevicesConnected), - true, - Theme.of(context), - ), + message: localizations.translate(i18.dataShare.noDevicesConnected), + type: ToastType.error, ); return; } @@ -263,6 +268,7 @@ class DevicesListPageState extends LocalizedState void handleDeviceTap(Device device) { if (device.state == SessionState.notConnected) { + DigitLoaders.overlayLoader(context: context); nearbyService.invitePeer( deviceID: device.deviceId, deviceName: device.deviceName, @@ -279,6 +285,9 @@ class DevicesListPageState extends LocalizedState case SessionState.connecting: return SessionState.connecting.name.toUpperCase(); case SessionState.connected: + if (widget.deviceType == DeviceType.sender) { + Navigator.of(context, rootNavigator: true).pop(); + } return SessionState.connected.name.toUpperCase(); default: return "UNKNOWN"; @@ -354,7 +363,37 @@ class DevicesListPageState extends LocalizedState ..clear() ..addAll(devices.where((d) => d.state == SessionState.connected)); }); + if (connectedDevices.isNotEmpty) { + if (widget.deviceType == DeviceType.sender) { + for (var e in connectedDevices) { + var senderDevice = deviceName ?? ''; + nearbyService.sendMessage(e.deviceId, senderDevice); + } + } + nearbyService.dataReceivedSubscription(callback: (data) { + print('received ${data['message']}'); + // senderDevice = data['message']; + }); + } }, ); } + + Future getSenderDeviceName() async { + var deviceId = ''; + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + deviceId = androidInfo.model; + } + if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + deviceId = iosInfo.localizedModel; + } + return deviceId; + } + + void fetchSenderDeviceDetails() async { + deviceName = await getSenderDeviceName(); + setState(() {}); + } } From 49fce8b46efd8557194d3ae103b6dab7d3fbd48f Mon Sep 17 00:00:00 2001 From: Naveen Renati <154230258+naveenr-egov@users.noreply.github.com> Date: Tue, 18 Feb 2025 18:03:27 +0530 Subject: [PATCH 15/16] added check to validate selected project and boundary added new handshake message type for the validation --- .../lib/blocs/peer_to_peer/peer_to_peer.dart | 120 +++++--- .../peer_to_peer/peer_to_peer.freezed.dart | 93 ++++-- .../entities/peer_to_peer/message_types.dart | 6 +- .../peer_to_peer/message_types.mapper.dart | 8 + .../lib/pages/peer_to_peer/data_receiver.dart | 274 +++++++++--------- .../pages/peer_to_peer/data_share_home.dart | 4 +- .../lib/pages/peer_to_peer/devices_list.dart | 48 +-- 7 files changed, 321 insertions(+), 232 deletions(-) diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart index af96a25c05..480de9d3c4 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -106,34 +106,53 @@ class PeerToPeerBloc extends Bloc { .map((e) => offsetData[e]) .toList() .first; + for (var device in event.connectedDevice) { + await event.nearbyService.sendMessage( + device.deviceId, + PeerToPeerMessageModel( + messageType: MessageTypes.handShake.toValue(), + selectedBoundaryCode: event.selectedBoundaryCode, + message: event.selectedProject, + ).toJson(), + ); - for (var entity in entityData) { - Map entityResponse = entity; - - for (var device in event.connectedDevice) { - await event.nearbyService.sendMessage( - device.deviceId, - PeerToPeerMessageModel( - messageType: MessageTypes.chunk.toValue(), - selectedBoundaryCode: selectedBoundaryCode, - message: compressJson(entityResponse), - offset: offsetValue, - totalCount: totalCount) - .toJson(), - ); - } - - // Wait for confirmation before proceeding - await waitForConfirmation( + bool handshakeSuccessful = await waitForConfirmation( event.nearbyService, - confirmationType: ConfirmationTypes.chunk.toValue(), - offset: offsetValue, + confirmationType: ConfirmationTypes.handShake.toValue(), ); - emit(PeerToPeerState.transferInProgress( - progress: offsetValue / totalCount, + if (handshakeSuccessful) { + emit(const PeerToPeerState.failedToTransfer( + error: "Handshake failed. Stopping transfer.")); + return; + } else { + for (var entity in entityData) { + Map entityResponse = entity; + + await event.nearbyService.sendMessage( + device.deviceId, + PeerToPeerMessageModel( + messageType: MessageTypes.chunk.toValue(), + selectedBoundaryCode: selectedBoundaryCode, + message: compressJson(entityResponse), + offset: offsetValue, + totalCount: totalCount) + .toJson(), + ); + } + + // Wait for confirmation before proceeding + await waitForConfirmation( + event.nearbyService, + confirmationType: ConfirmationTypes.chunk.toValue(), offset: offsetValue, - totalCount: totalCount)); + ); + + emit(PeerToPeerState.transferInProgress( + progress: offsetValue / totalCount, + offset: offsetValue, + totalCount: totalCount)); + } } } @@ -161,6 +180,7 @@ class PeerToPeerBloc extends Bloc { } else { emit(const PeerToPeerState.failedToTransfer( error: "File doesn't exist")); + return; } } catch (e) { emit(PeerToPeerState.failedToTransfer(error: e.toString())); @@ -198,7 +218,33 @@ class PeerToPeerBloc extends Bloc { PeerToPeerMessageModel messageModel = PeerToPeerMessageModelMapper.fromJson(event.data["message"]); - if (messageModel.messageType == MessageTypes.chunk.toValue()) { + if (messageModel.messageType == MessageTypes.handShake.toValue()) { + // First message contains boundary and project + if (messageModel.selectedBoundaryCode == event.selectedBoundaryCode && + messageModel.message == event.projectId) { + // Send acknowledgment to proceed + await event.nearbyService.sendMessage( + event.data["deviceId"], + PeerToPeerMessageModel( + messageType: MessageTypes.confirmation.toValue(), + message: "Handshake successful. Proceeding with transfer.", + confirmationType: ConfirmationTypes.handShake.toValue(), + status: MessageStatus.success.toValue(), + ).toJson()); + } else { + // Send failure message and stop transfer + await event.nearbyService.sendMessage( + event.data["deviceId"], + PeerToPeerMessageModel( + messageType: MessageTypes.confirmation.toValue(), + message: "Handshake failed. Boundary or project mismatch.", + confirmationType: ConfirmationTypes.failed.toValue(), + status: MessageStatus.fail.toValue(), + ).toJson()); + emit(const PeerToPeerState.failedToReceive( + error: "Boundary or project mismatch.")); + } + } else if (messageModel.messageType == MessageTypes.chunk.toValue()) { // Process chunk int? offset = messageModel.offset; int? totalCount = messageModel.totalCount; @@ -308,12 +354,12 @@ class PeerToPeerBloc extends Bloc { } } - Future waitForConfirmation( + Future waitForConfirmation( NearbyService nearbyService, { required String confirmationType, int? offset, }) async { - final completer = Completer(); + final completer = Completer(); final subscription = nearbyService.dataReceivedSubscription( callback: (data) { @@ -324,28 +370,28 @@ class PeerToPeerBloc extends Bloc { if (messageModel.messageType == MessageTypes.confirmation.toValue()) { if (confirmationType == ConfirmationTypes.chunk.toValue() && messageModel.offset == offset) { - completer.complete(); + completer.complete(true); } else if (confirmationType == - ConfirmationTypes.finalAcknowledgment.toValue()) { - completer.complete(); - } else if (confirmationType == - ConfirmationTypes.finalTransfer.toValue()) { - completer.complete(); + ConfirmationTypes.finalAcknowledgment.toValue() || + confirmationType == ConfirmationTypes.finalTransfer.toValue() || + confirmationType == ConfirmationTypes.handShake.toValue()) { + completer.complete(true); } else if (confirmationType == ConfirmationTypes.failed.toValue()) { - completer.complete(); + completer.complete(false); emit(const PeerToPeerState.failedToTransfer( error: "File doesn't exist")); - throw "Failed to transfer ${messageModel.message}"; } } } catch (e) { debugPrint("Error processing confirmation: $e"); + completer.complete(false); } }, ); - await completer.future; + bool result = await completer.future; subscription.cancel(); + return result; } } @@ -358,7 +404,9 @@ class PeerToPeerEvent with _$PeerToPeerEvent { required List connectedDevice}) = DataTransferEvent; const factory PeerToPeerEvent.dataReceiver( - {required NearbyService nearbyService, + {required String projectId, + required String selectedBoundaryCode, + required NearbyService nearbyService, required dynamic data}) = DataReceiverEvent; } diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart index 1b4a60a031..6bc18c95ff 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart @@ -17,6 +17,7 @@ final _privateConstructorUsedError = UnsupportedError( /// @nodoc mixin _$PeerToPeerEvent { NearbyService get nearbyService => throw _privateConstructorUsedError; + String get selectedBoundaryCode => throw _privateConstructorUsedError; @optionalTypeArgs TResult when({ required TResult Function( @@ -25,7 +26,8 @@ mixin _$PeerToPeerEvent { String selectedBoundaryCode, List connectedDevice) dataTransfer, - required TResult Function(NearbyService nearbyService, dynamic data) + required TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data) dataReceiver, }) => throw _privateConstructorUsedError; @@ -34,7 +36,9 @@ mixin _$PeerToPeerEvent { TResult? Function(NearbyService nearbyService, String selectedProject, String selectedBoundaryCode, List connectedDevice)? dataTransfer, - TResult? Function(NearbyService nearbyService, dynamic data)? dataReceiver, + TResult? Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, }) => throw _privateConstructorUsedError; @optionalTypeArgs @@ -42,7 +46,9 @@ mixin _$PeerToPeerEvent { TResult Function(NearbyService nearbyService, String selectedProject, String selectedBoundaryCode, List connectedDevice)? dataTransfer, - TResult Function(NearbyService nearbyService, dynamic data)? dataReceiver, + TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, required TResult orElse(), }) => throw _privateConstructorUsedError; @@ -77,7 +83,7 @@ abstract class $PeerToPeerEventCopyWith<$Res> { PeerToPeerEvent value, $Res Function(PeerToPeerEvent) then) = _$PeerToPeerEventCopyWithImpl<$Res, PeerToPeerEvent>; @useResult - $Res call({NearbyService nearbyService}); + $Res call({NearbyService nearbyService, String selectedBoundaryCode}); } /// @nodoc @@ -94,12 +100,17 @@ class _$PeerToPeerEventCopyWithImpl<$Res, $Val extends PeerToPeerEvent> @override $Res call({ Object? nearbyService = null, + Object? selectedBoundaryCode = null, }) { return _then(_value.copyWith( nearbyService: null == nearbyService ? _value.nearbyService : nearbyService // ignore: cast_nullable_to_non_nullable as NearbyService, + selectedBoundaryCode: null == selectedBoundaryCode + ? _value.selectedBoundaryCode + : selectedBoundaryCode // ignore: cast_nullable_to_non_nullable + as String, ) as $Val); } } @@ -237,7 +248,8 @@ class _$DataTransferEventImpl String selectedBoundaryCode, List connectedDevice) dataTransfer, - required TResult Function(NearbyService nearbyService, dynamic data) + required TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data) dataReceiver, }) { return dataTransfer( @@ -250,7 +262,9 @@ class _$DataTransferEventImpl TResult? Function(NearbyService nearbyService, String selectedProject, String selectedBoundaryCode, List connectedDevice)? dataTransfer, - TResult? Function(NearbyService nearbyService, dynamic data)? dataReceiver, + TResult? Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, }) { return dataTransfer?.call( nearbyService, selectedProject, selectedBoundaryCode, connectedDevice); @@ -262,7 +276,9 @@ class _$DataTransferEventImpl TResult Function(NearbyService nearbyService, String selectedProject, String selectedBoundaryCode, List connectedDevice)? dataTransfer, - TResult Function(NearbyService nearbyService, dynamic data)? dataReceiver, + TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, required TResult orElse(), }) { if (dataTransfer != null) { @@ -314,6 +330,7 @@ abstract class DataTransferEvent implements PeerToPeerEvent { @override NearbyService get nearbyService; String get selectedProject; + @override String get selectedBoundaryCode; List get connectedDevice; @override @@ -330,7 +347,11 @@ abstract class _$$DataReceiverEventImplCopyWith<$Res> __$$DataReceiverEventImplCopyWithImpl<$Res>; @override @useResult - $Res call({NearbyService nearbyService, dynamic data}); + $Res call( + {String projectId, + String selectedBoundaryCode, + NearbyService nearbyService, + dynamic data}); } /// @nodoc @@ -344,10 +365,20 @@ class __$$DataReceiverEventImplCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ + Object? projectId = null, + Object? selectedBoundaryCode = null, Object? nearbyService = null, Object? data = freezed, }) { return _then(_$DataReceiverEventImpl( + projectId: null == projectId + ? _value.projectId + : projectId // ignore: cast_nullable_to_non_nullable + as String, + selectedBoundaryCode: null == selectedBoundaryCode + ? _value.selectedBoundaryCode + : selectedBoundaryCode // ignore: cast_nullable_to_non_nullable + as String, nearbyService: null == nearbyService ? _value.nearbyService : nearbyService // ignore: cast_nullable_to_non_nullable @@ -366,8 +397,15 @@ class _$DataReceiverEventImpl with DiagnosticableTreeMixin implements DataReceiverEvent { const _$DataReceiverEventImpl( - {required this.nearbyService, required this.data}); + {required this.projectId, + required this.selectedBoundaryCode, + required this.nearbyService, + required this.data}); + @override + final String projectId; + @override + final String selectedBoundaryCode; @override final NearbyService nearbyService; @override @@ -375,7 +413,7 @@ class _$DataReceiverEventImpl @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'PeerToPeerEvent.dataReceiver(nearbyService: $nearbyService, data: $data)'; + return 'PeerToPeerEvent.dataReceiver(projectId: $projectId, selectedBoundaryCode: $selectedBoundaryCode, nearbyService: $nearbyService, data: $data)'; } @override @@ -383,6 +421,8 @@ class _$DataReceiverEventImpl super.debugFillProperties(properties); properties ..add(DiagnosticsProperty('type', 'PeerToPeerEvent.dataReceiver')) + ..add(DiagnosticsProperty('projectId', projectId)) + ..add(DiagnosticsProperty('selectedBoundaryCode', selectedBoundaryCode)) ..add(DiagnosticsProperty('nearbyService', nearbyService)) ..add(DiagnosticsProperty('data', data)); } @@ -392,14 +432,18 @@ class _$DataReceiverEventImpl return identical(this, other) || (other.runtimeType == runtimeType && other is _$DataReceiverEventImpl && + (identical(other.projectId, projectId) || + other.projectId == projectId) && + (identical(other.selectedBoundaryCode, selectedBoundaryCode) || + other.selectedBoundaryCode == selectedBoundaryCode) && (identical(other.nearbyService, nearbyService) || other.nearbyService == nearbyService) && const DeepCollectionEquality().equals(other.data, data)); } @override - int get hashCode => Object.hash( - runtimeType, nearbyService, const DeepCollectionEquality().hash(data)); + int get hashCode => Object.hash(runtimeType, projectId, selectedBoundaryCode, + nearbyService, const DeepCollectionEquality().hash(data)); @JsonKey(ignore: true) @override @@ -417,10 +461,11 @@ class _$DataReceiverEventImpl String selectedBoundaryCode, List connectedDevice) dataTransfer, - required TResult Function(NearbyService nearbyService, dynamic data) + required TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data) dataReceiver, }) { - return dataReceiver(nearbyService, data); + return dataReceiver(projectId, selectedBoundaryCode, nearbyService, data); } @override @@ -429,9 +474,12 @@ class _$DataReceiverEventImpl TResult? Function(NearbyService nearbyService, String selectedProject, String selectedBoundaryCode, List connectedDevice)? dataTransfer, - TResult? Function(NearbyService nearbyService, dynamic data)? dataReceiver, + TResult? Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, }) { - return dataReceiver?.call(nearbyService, data); + return dataReceiver?.call( + projectId, selectedBoundaryCode, nearbyService, data); } @override @@ -440,11 +488,13 @@ class _$DataReceiverEventImpl TResult Function(NearbyService nearbyService, String selectedProject, String selectedBoundaryCode, List connectedDevice)? dataTransfer, - TResult Function(NearbyService nearbyService, dynamic data)? dataReceiver, + TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, required TResult orElse(), }) { if (dataReceiver != null) { - return dataReceiver(nearbyService, data); + return dataReceiver(projectId, selectedBoundaryCode, nearbyService, data); } return orElse(); } @@ -483,9 +533,14 @@ class _$DataReceiverEventImpl abstract class DataReceiverEvent implements PeerToPeerEvent { const factory DataReceiverEvent( - {required final NearbyService nearbyService, + {required final String projectId, + required final String selectedBoundaryCode, + required final NearbyService nearbyService, required final dynamic data}) = _$DataReceiverEventImpl; + String get projectId; + @override + String get selectedBoundaryCode; @override NearbyService get nearbyService; dynamic get data; diff --git a/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.dart b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.dart index c394fa30ce..e8b824dac6 100644 --- a/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.dart +++ b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.dart @@ -7,7 +7,9 @@ enum MessageTypes { @MappableValue("confirmation") confirmation, @MappableValue("chunk") - chunk + chunk, + @MappableValue("handshake") + handShake } @MappableEnum(caseStyle: CaseStyle.upperCase) @@ -20,6 +22,8 @@ enum ConfirmationTypes { failed, @MappableValue("finalAcknowledgment") finalAcknowledgment, + @MappableValue("handshake") + handShake } @MappableEnum(caseStyle: CaseStyle.upperCase) diff --git a/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.mapper.dart b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.mapper.dart index a4eef2bf0d..7be7d3045f 100644 --- a/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.mapper.dart +++ b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.mapper.dart @@ -29,6 +29,8 @@ class MessageTypesMapper extends EnumMapper { return MessageTypes.confirmation; case "chunk": return MessageTypes.chunk; + case "handshake": + return MessageTypes.handShake; default: throw MapperException.unknownEnumValue(value); } @@ -41,6 +43,8 @@ class MessageTypesMapper extends EnumMapper { return "confirmation"; case MessageTypes.chunk: return "chunk"; + case MessageTypes.handShake: + return "handshake"; } } } @@ -79,6 +83,8 @@ class ConfirmationTypesMapper extends EnumMapper { return ConfirmationTypes.failed; case "finalAcknowledgment": return ConfirmationTypes.finalAcknowledgment; + case "handshake": + return ConfirmationTypes.handShake; default: throw MapperException.unknownEnumValue(value); } @@ -95,6 +101,8 @@ class ConfirmationTypesMapper extends EnumMapper { return "failed"; case ConfirmationTypes.finalAcknowledgment: return "finalAcknowledgment"; + case ConfirmationTypes.handShake: + return "handshake"; } } } diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart index f280e1d7c5..c1273d1ed2 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -13,6 +13,7 @@ import 'package:percent_indicator/percent_indicator.dart'; import '../../blocs/peer_to_peer/peer_to_peer.dart'; import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; +import '../../utils/utils.dart'; import '../../widgets/localized.dart'; import '../../widgets/peer_to_peer/file_transfer_animation.dart'; import '../../widgets/showcase/showcase_wrappers.dart'; @@ -40,8 +41,11 @@ class _DataReceiverPageState extends LocalizedState { nearbyService = widget.nearbyService; peerToPeerBloc = context.read(); nearbyService.dataReceivedSubscription(callback: (data) { - peerToPeerBloc.add( - DataReceiverEvent(nearbyService: widget.nearbyService, data: data)); + peerToPeerBloc.add(DataReceiverEvent( + nearbyService: widget.nearbyService, + data: data, + selectedBoundaryCode: context.boundary.code!, + projectId: context.projectId)); }); nearbyService.stateChangedSubscription(callback: (devices) { for (var device in devices) { @@ -80,6 +84,15 @@ class _DataReceiverPageState extends LocalizedState { context.router .popAndPush(AcknowledgementRoute(isDataRecordSuccess: false)); } + if (state is FailedDataTransfer) { + Toast.showToast( + context, + message: localizations.translate(state.error), + type: ToastType.error, + position: ToastPosition.aboveOneButtonFooter, + ); + context.router.maybePop(); + } }, child: BlocBuilder( builder: (context, state) { @@ -121,150 +134,139 @@ class _DataReceiverPageState extends LocalizedState { color: DigitTheme.instance.colors.light.paperPrimary, margin: const EdgeInsets.all(kPadding), child: state.maybeWhen( - orElse: () => Center( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - const SizedBox(height: 16), - CircularPercentIndicator( - radius: MediaQuery.of(context) - .size - .height * - 0.15, - lineWidth: kPadding * 1.5, - animation: false, - percent: 0, - // Update this dynamically for progress - center: const Text( - '0 %', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold), - ), - - progressBorderColor: DigitTheme - .instance.colors.light.primary1Bg, - progressColor: DigitTheme.instance - .colors.light.alertSuccess, - backgroundColor: DigitTheme - .instance.colors.light.primary1Bg, - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - FileTransferAnimation(), - // Add animation here - ], - ), - Wrap( - spacing: 8.0, - runSpacing: 4.0, - children: [ - // buildDeviceChip(), - Container( - padding: const EdgeInsets.all( - kPadding), - decoration: BoxDecoration( - border: Border.all( - color: DigitTheme - .instance - .colors - .light - .primary1Bg, - ), - borderRadius: - BorderRadius.circular( - kPadding), - ), - child: Text( - widget.connectedDevice - .deviceName, - style: TextStyle( - color: DigitTheme.instance - .colors.light.primary2, - ), - ), - ), - ]), - ], + orElse: () => Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 16), + CircularPercentIndicator( + radius: MediaQuery.of(context).size.height * + 0.15, + lineWidth: kPadding * 1.5, + animation: false, + percent: 0, + // Update this dynamically for progress + center: const Text( + '0 %', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), ), + + progressBorderColor: DigitTheme + .instance.colors.light.primary1Bg, + progressColor: DigitTheme + .instance.colors.light.alertSuccess, + backgroundColor: DigitTheme + .instance.colors.light.primary1Bg, ), - receivingInProgress: - (progress, offset, totalCount) { - return Center( - child: Column( + const SizedBox(height: 16), + Row( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: - CrossAxisAlignment.center, children: [ - Text('Receiving $offset / $totalCount'), - const SizedBox(height: 16), - CircularPercentIndicator( - radius: - MediaQuery.of(context).size.height * - 0.15, - lineWidth: kPadding * 1.5, - animation: false, - percent: progress, - // Update this dynamically for progress - center: Text( - '${(progress * 100).toStringAsFixed(1)} %', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold), + FileTransferAnimation(), + // Add animation here + ], + ), + Wrap( + spacing: 8.0, + runSpacing: 4.0, + children: [ + // buildDeviceChip(), + Container( + padding: + const EdgeInsets.all(kPadding), + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme.instance.colors + .light.primary1Bg, + ), + borderRadius: + BorderRadius.circular(kPadding), + ), + child: Text( + widget.connectedDevice.deviceName, + style: TextStyle( + color: DigitTheme.instance.colors + .light.primary2, + ), + ), ), - - progressBorderColor: DigitTheme - .instance.colors.light.primary1Bg, - progressColor: DigitTheme - .instance.colors.light.alertSuccess, - backgroundColor: DigitTheme - .instance.colors.light.primary1Bg, + ]), + ], + ), + ), + receivingInProgress: + (progress, offset, totalCount) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text('Receiving $offset / $totalCount'), + const SizedBox(height: 16), + CircularPercentIndicator( + radius: + MediaQuery.of(context).size.height * + 0.15, + lineWidth: kPadding * 1.5, + animation: false, + percent: progress, + // Update this dynamically for progress + center: Text( + '${(progress * 100).toStringAsFixed(1)} %', + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: - MainAxisAlignment.center, + + progressBorderColor: DigitTheme + .instance.colors.light.primary1Bg, + progressColor: DigitTheme + .instance.colors.light.alertSuccess, + backgroundColor: DigitTheme + .instance.colors.light.primary1Bg, + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + FileTransferAnimation(), + // Add animation here + ], + ), + Wrap( + spacing: 8.0, + runSpacing: 4.0, children: [ - FileTransferAnimation(), - // Add animation here - ], - ), - Wrap( - spacing: 8.0, - runSpacing: 4.0, - children: [ - Container( - padding: const EdgeInsets.all( - kPadding), - decoration: BoxDecoration( - border: Border.all( - color: DigitTheme.instance - .colors.light.primary1Bg, - ), - borderRadius: - BorderRadius.circular( - kPadding), + Container( + padding: + const EdgeInsets.all(kPadding), + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme.instance + .colors.light.primary1Bg, ), - child: Text( - widget - .connectedDevice.deviceName, - style: TextStyle( - color: DigitTheme.instance - .colors.light.primary2, - ), + borderRadius: + BorderRadius.circular( + kPadding), + ), + child: Text( + widget.connectedDevice.deviceName, + style: TextStyle( + color: DigitTheme.instance + .colors.light.primary2, ), ), - ]), - ], - ), - ); - })), + ), + ]), + ], + ), + ); + }, + )), ])) ]); }, diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart index 5b22b64560..3b8316cbae 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart @@ -1,5 +1,3 @@ -import 'package:attendance_management/widgets/back_navigation_help_header.dart'; -import 'package:attendance_management/widgets/localized.dart'; import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/digit_extended_theme.dart'; import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; @@ -7,6 +5,8 @@ import 'package:flutter/material.dart'; import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; +import '../../widgets/header/back_navigation_help_header.dart'; +import '../../widgets/localized.dart'; import '../../widgets/showcase/showcase_wrappers.dart'; import 'devices_list.dart'; diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart index a4ba6ef558..f86d95d488 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -6,7 +6,6 @@ import 'package:attendance_management/widgets/back_navigation_help_header.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/digit_extended_theme.dart'; -import 'package:digit_ui_components/widgets/atoms/digit_loader.dart'; import 'package:digit_ui_components/widgets/molecules/digit_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; @@ -32,21 +31,18 @@ class DevicesListPageState extends LocalizedState with TickerProviderStateMixin { final List devices = []; final List connectedDevices = []; - late final Device senderDeviceDetails; + late final String senderDeviceDetails; late NearbyService nearbyService; late StreamSubscription stateSubscription; late AnimationController _controller; late AnimationController _radarController; DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - late Device senderDevice; - String? deviceName; @override void initState() { super.initState(); createAnimations(); initializeNearbyService(); - senderDevice = Device('', '', 0); fetchSenderDeviceDetails(); } @@ -164,11 +160,8 @@ class DevicesListPageState extends LocalizedState List generateDeviceWidgets(double width, double height) { final random = Random(); - final devicesToShow = widget.deviceType == DeviceType.receiver - ? senderDevice.deviceId.isNotEmpty - ? [senderDevice] - : [] - : devices; + final devicesToShow = + widget.deviceType == DeviceType.receiver ? connectedDevices : devices; return devicesToShow.asMap().entries.map((entry) { final angle = random.nextDouble() * 2 * pi + entry.key * 0.1; @@ -268,10 +261,9 @@ class DevicesListPageState extends LocalizedState void handleDeviceTap(Device device) { if (device.state == SessionState.notConnected) { - DigitLoaders.overlayLoader(context: context); nearbyService.invitePeer( deviceID: device.deviceId, - deviceName: device.deviceName, + deviceName: senderDeviceDetails, ); } else if (device.state == SessionState.connected) { nearbyService.disconnectPeer(deviceID: device.deviceId); @@ -285,9 +277,6 @@ class DevicesListPageState extends LocalizedState case SessionState.connecting: return SessionState.connecting.name.toUpperCase(); case SessionState.connected: - if (widget.deviceType == DeviceType.sender) { - Navigator.of(context, rootNavigator: true).pop(); - } return SessionState.connected.name.toUpperCase(); default: return "UNKNOWN"; @@ -334,7 +323,7 @@ class DevicesListPageState extends LocalizedState if (widget.deviceType == DeviceType.sender) { await nearbyService.startBrowsingForPeers(); } else { - await nearbyService.startAdvertisingPeer(); + await nearbyService.startAdvertisingPeer(deviceName: deviceId); } } }, @@ -363,37 +352,20 @@ class DevicesListPageState extends LocalizedState ..clear() ..addAll(devices.where((d) => d.state == SessionState.connected)); }); - if (connectedDevices.isNotEmpty) { - if (widget.deviceType == DeviceType.sender) { - for (var e in connectedDevices) { - var senderDevice = deviceName ?? ''; - nearbyService.sendMessage(e.deviceId, senderDevice); - } - } - nearbyService.dataReceivedSubscription(callback: (data) { - print('received ${data['message']}'); - // senderDevice = data['message']; - }); - } }, ); } Future getSenderDeviceName() async { var deviceId = ''; - if (Platform.isAndroid) { - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - deviceId = androidInfo.model; - } - if (Platform.isIOS) { - IosDeviceInfo iosInfo = await deviceInfo.iosInfo; - deviceId = iosInfo.localizedModel; - } + final deviceInfo = DeviceInfoPlugin(); + deviceId = Platform.isAndroid + ? (await deviceInfo.androidInfo).model + : (await deviceInfo.iosInfo).localizedModel; return deviceId; } void fetchSenderDeviceDetails() async { - deviceName = await getSenderDeviceName(); - setState(() {}); + senderDeviceDetails = await getSenderDeviceName(); } } From 3693a0ef40f5ef5b3087d8910ffdd023198732ab Mon Sep 17 00:00:00 2001 From: Naveen Renati <154230258+naveenr-egov@users.noreply.github.com> Date: Wed, 19 Feb 2025 12:24:09 +0530 Subject: [PATCH 16/16] Added localization codes updated ui, and removed boundary check during handshake --- .../lib/blocs/peer_to_peer/peer_to_peer.dart | 26 ++--- .../lib/pages/peer_to_peer/data_receiver.dart | 72 ++++-------- .../pages/peer_to_peer/data_share_home.dart | 15 +-- .../lib/pages/peer_to_peer/data_transfer.dart | 104 +++++++----------- .../lib/pages/peer_to_peer/devices_list.dart | 11 +- .../lib/utils/i18_key_constants.dart | 76 +++++++++++++ .../widgets/showcase/showcase_wrappers.dart | 19 ++-- 7 files changed, 172 insertions(+), 151 deletions(-) diff --git a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart index 480de9d3c4..6daedf8b52 100644 --- a/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -16,6 +16,7 @@ import '../../data/sync_service_mapper.dart'; import '../../models/downsync/downsync.dart'; import '../../models/entities/peer_to_peer/message_types.dart'; import '../../models/entities/peer_to_peer/peer_to_peer_message.dart'; +import '../../utils/i18_key_constants.dart' as i18; part 'peer_to_peer.freezed.dart'; @@ -80,8 +81,7 @@ class PeerToPeerBloc extends Bloc { // Ensure that 'entities' is a Map if (offsets is! Map) { emit(PeerToPeerState.failedToTransfer( - error: - 'Expected a Map, but got ${offsets.runtimeType}')); + error: i18.dataShare.invalidFileError)); return; } @@ -122,8 +122,8 @@ class PeerToPeerBloc extends Bloc { ); if (handshakeSuccessful) { - emit(const PeerToPeerState.failedToTransfer( - error: "Handshake failed. Stopping transfer.")); + emit(PeerToPeerState.failedToTransfer( + error: i18.dataShare.projectMisMatchError)); return; } else { for (var entity in entityData) { @@ -178,8 +178,8 @@ class PeerToPeerBloc extends Bloc { emit(const PeerToPeerState.completedDataTransfer()); } } else { - emit(const PeerToPeerState.failedToTransfer( - error: "File doesn't exist")); + emit(PeerToPeerState.failedToTransfer( + error: i18.dataShare.fileNotFoundError)); return; } } catch (e) { @@ -219,9 +219,7 @@ class PeerToPeerBloc extends Bloc { PeerToPeerMessageModelMapper.fromJson(event.data["message"]); if (messageModel.messageType == MessageTypes.handShake.toValue()) { - // First message contains boundary and project - if (messageModel.selectedBoundaryCode == event.selectedBoundaryCode && - messageModel.message == event.projectId) { + if (messageModel.message == event.projectId) { // Send acknowledgment to proceed await event.nearbyService.sendMessage( event.data["deviceId"], @@ -237,12 +235,12 @@ class PeerToPeerBloc extends Bloc { event.data["deviceId"], PeerToPeerMessageModel( messageType: MessageTypes.confirmation.toValue(), - message: "Handshake failed. Boundary or project mismatch.", + message: "Handshake failed. Project mismatch.", confirmationType: ConfirmationTypes.failed.toValue(), status: MessageStatus.fail.toValue(), ).toJson()); - emit(const PeerToPeerState.failedToReceive( - error: "Boundary or project mismatch.")); + emit(PeerToPeerState.failedToReceive( + error: i18.dataShare.projectMisMatchError)); } } else if (messageModel.messageType == MessageTypes.chunk.toValue()) { // Process chunk @@ -378,8 +376,8 @@ class PeerToPeerBloc extends Bloc { completer.complete(true); } else if (confirmationType == ConfirmationTypes.failed.toValue()) { completer.complete(false); - emit(const PeerToPeerState.failedToTransfer( - error: "File doesn't exist")); + emit(PeerToPeerState.failedToTransfer( + error: i18.dataShare.failedToTransfer)); } } } catch (e) { diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart index c1273d1ed2..5097183a5f 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:attendance_management/widgets/back_navigation_help_header.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:digit_ui_components/digit_components.dart'; @@ -16,7 +14,6 @@ import '../../utils/i18_key_constants.dart' as i18; import '../../utils/utils.dart'; import '../../widgets/localized.dart'; import '../../widgets/peer_to_peer/file_transfer_animation.dart'; -import '../../widgets/showcase/showcase_wrappers.dart'; @RoutePage() class DataReceiverPage extends LocalizedStatefulWidget { @@ -55,7 +52,7 @@ class _DataReceiverPageState extends LocalizedState { Toast.showToast( context, message: localizations.translate( - '${device.deviceName} ${SessionState.notConnected.name}'), + '${device.deviceName} ${SessionState.notConnected.toString().toUpperCase()}'), type: ToastType.error, ); } @@ -119,7 +116,7 @@ class _DataReceiverPageState extends LocalizedState { SliverToBoxAdapter( child: Column(children: [ Padding( - padding: const EdgeInsets.all(kPadding), + padding: const EdgeInsets.all(spacer2), child: Align( alignment: Alignment.topLeft, child: Text( @@ -132,18 +129,18 @@ class _DataReceiverPageState extends LocalizedState { Container( height: MediaQuery.of(context).size.height * 0.6, color: DigitTheme.instance.colors.light.paperPrimary, - margin: const EdgeInsets.all(kPadding), + margin: const EdgeInsets.all(spacer2), child: state.maybeWhen( orElse: () => Center( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - const SizedBox(height: 16), + const SizedBox(height: spacer4), CircularPercentIndicator( radius: MediaQuery.of(context).size.height * 0.15, - lineWidth: kPadding * 1.5, + lineWidth: spacer2 * 1.5, animation: false, percent: 0, // Update this dynamically for progress @@ -161,29 +158,23 @@ class _DataReceiverPageState extends LocalizedState { backgroundColor: DigitTheme .instance.colors.light.primary1Bg, ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FileTransferAnimation(), - // Add animation here - ], - ), + const SizedBox(height: spacer4), + FileTransferAnimation(), Wrap( - spacing: 8.0, - runSpacing: 4.0, + spacing: spacer2, + runSpacing: spacer1, children: [ // buildDeviceChip(), Container( padding: - const EdgeInsets.all(kPadding), + const EdgeInsets.all(spacer2), decoration: BoxDecoration( border: Border.all( color: DigitTheme.instance.colors .light.primary1Bg, ), borderRadius: - BorderRadius.circular(kPadding), + BorderRadius.circular(spacer2), ), child: Text( widget.connectedDevice.deviceName, @@ -204,23 +195,22 @@ class _DataReceiverPageState extends LocalizedState { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text('Receiving $offset / $totalCount'), - const SizedBox(height: 16), + Text(localizations.translate( + '${i18.dataShare.receiving} $offset / $totalCount')), + const SizedBox(height: spacer4), CircularPercentIndicator( radius: MediaQuery.of(context).size.height * 0.15, - lineWidth: kPadding * 1.5, + lineWidth: spacer2 * 1.5, animation: false, percent: progress, // Update this dynamically for progress center: Text( '${(progress * 100).toStringAsFixed(1)} %', style: const TextStyle( - fontSize: 24, fontWeight: FontWeight.bold), ), - progressBorderColor: DigitTheme .instance.colors.light.primary1Bg, progressColor: DigitTheme @@ -228,22 +218,15 @@ class _DataReceiverPageState extends LocalizedState { backgroundColor: DigitTheme .instance.colors.light.primary1Bg, ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - FileTransferAnimation(), - // Add animation here - ], - ), + const SizedBox(height: spacer4), + FileTransferAnimation(), Wrap( - spacing: 8.0, - runSpacing: 4.0, + spacing: spacer2, + runSpacing: spacer1, children: [ Container( padding: - const EdgeInsets.all(kPadding), + const EdgeInsets.all(spacer2), decoration: BoxDecoration( border: Border.all( color: DigitTheme.instance @@ -251,7 +234,7 @@ class _DataReceiverPageState extends LocalizedState { ), borderRadius: BorderRadius.circular( - kPadding), + spacer2), ), child: Text( widget.connectedDevice.deviceName, @@ -273,17 +256,4 @@ class _DataReceiverPageState extends LocalizedState { ), )); } - - Future getCurrentDeviceName() async { - var deviceId = ''; - if (Platform.isAndroid) { - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - deviceId = androidInfo.model; - } - if (Platform.isIOS) { - IosDeviceInfo iosInfo = await deviceInfo.iosInfo; - deviceId = iosInfo.localizedModel; - } - return deviceId; - } } diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart index 3b8316cbae..56d8413212 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart @@ -7,7 +7,6 @@ import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../widgets/header/back_navigation_help_header.dart'; import '../../widgets/localized.dart'; -import '../../widgets/showcase/showcase_wrappers.dart'; import 'devices_list.dart'; @RoutePage() @@ -30,11 +29,11 @@ class _DataShareHomeState extends LocalizedState { ), children: [ Padding( - padding: const EdgeInsets.all(kPadding), + padding: const EdgeInsets.all(spacer2), child: Align( alignment: Alignment.topLeft, child: Text( - localizations.translate(i18.dataShare.sendAction), + localizations.translate(i18.dataShare.dataSharingLabel), style: textTheme.headingM, ), ), @@ -43,7 +42,8 @@ class _DataShareHomeState extends LocalizedState { width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height * 0.2, child: DigitCard( - margin: const EdgeInsets.all(kPadding * 2), + padding: const EdgeInsets.only(top: spacer10), + margin: const EdgeInsets.all(spacer4), inline: true, onPressed: () { context.router @@ -58,7 +58,7 @@ class _DataShareHomeState extends LocalizedState { Center( child: Text( localizations.translate(i18.dataShare.sendAction), - style: TextStyle( + style: textTheme.label.copyWith( color: DigitTheme.instance.colors.light.primary1), ), ) @@ -68,8 +68,9 @@ class _DataShareHomeState extends LocalizedState { width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height * 0.2, child: DigitCard( + padding: const EdgeInsets.only(top: spacer10), inline: true, - margin: const EdgeInsets.all(kPadding * 2), + margin: const EdgeInsets.all(spacer4), onPressed: () { context.router .push(DevicesListRoute(deviceType: DeviceType.receiver)); @@ -83,7 +84,7 @@ class _DataShareHomeState extends LocalizedState { Center( child: Text( localizations.translate(i18.dataShare.receiveAction), - style: TextStyle( + style: textTheme.label.copyWith( color: DigitTheme.instance.colors.light.primary1), ), ) diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart index c7bf899a24..d70c536c98 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -16,7 +16,6 @@ import '../../utils/i18_key_constants.dart' as i18; import '../../utils/utils.dart'; import '../../widgets/localized.dart'; import '../../widgets/peer_to_peer/file_transfer_animation.dart'; -import '../../widgets/showcase/showcase_wrappers.dart'; @RoutePage() class DataTransferPage extends LocalizedStatefulWidget { @@ -88,6 +87,7 @@ class _DataTransferScreenState extends LocalizedState { type: ToastType.error, position: ToastPosition.aboveOneButtonFooter, ); + context.router.maybePop(); } }, child: BlocBuilder( @@ -115,7 +115,7 @@ class _DataTransferScreenState extends LocalizedState { child: Column( children: [ Padding( - padding: const EdgeInsets.all(kPadding), + padding: const EdgeInsets.all(spacer2), child: Align( alignment: Alignment.topLeft, child: Text( @@ -127,26 +127,25 @@ class _DataTransferScreenState extends LocalizedState { Container( height: MediaQuery.of(context).size.height * 0.6, color: DigitTheme.instance.colors.light.paperPrimary, - margin: const EdgeInsets.all(kPadding), + margin: const EdgeInsets.all(spacer2), child: state.maybeWhen( orElse: () => Center( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - const SizedBox(height: 16), + const SizedBox(height: spacer4), CircularPercentIndicator( radius: MediaQuery.of(context).size.height * 0.15, - lineWidth: kPadding * 1.5, + lineWidth: spacer2 * 1.5, animation: false, percent: 0, // Update this dynamically for progress center: const Text( '0 %', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold), + style: + TextStyle(fontWeight: FontWeight.bold), ), progressBorderColor: DigitTheme .instance.colors.light.primary1Bg, @@ -162,20 +161,20 @@ class _DataTransferScreenState extends LocalizedState { Column( mainAxisSize: MainAxisSize.max, children: [ - const SizedBox(height: 16), - Text('Transferring $offset / $totalCount'), - const SizedBox(height: 16), + const SizedBox(height: spacer4), + Text(localizations.translate( + '${i18.dataShare.transferring} $offset / $totalCount')), + const SizedBox(height: spacer4), CircularPercentIndicator( radius: MediaQuery.of(context).size.height * 0.15, - lineWidth: kPadding * 1.5, + lineWidth: spacer2 * 1.5, animation: false, percent: progress, // Update this dynamically for progress center: Text( '${(progress * 100).toStringAsFixed(1)} %', style: const TextStyle( - fontSize: 24, fontWeight: FontWeight.bold), ), progressBorderColor: @@ -185,57 +184,36 @@ class _DataTransferScreenState extends LocalizedState { backgroundColor: DigitTheme.instance.colors.light.primary1Bg, ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FileTransferAnimation(), - // Add animation here - ], - ), - Wrap(spacing: 8.0, runSpacing: 4.0, children: [ - // buildDeviceChip(), - const SizedBox(width: 8), - Container( - padding: const EdgeInsets.all(kPadding), - decoration: BoxDecoration( - border: Border.all( - color: DigitTheme - .instance.colors.light.primary1Bg, - ), - borderRadius: - BorderRadius.circular(kPadding), - ), - child: Text( - widget.connectedDevices.first.deviceName, - style: TextStyle( - color: DigitTheme - .instance.colors.light.primary2, + const SizedBox(height: spacer4), + FileTransferAnimation(), + Wrap( + spacing: spacer2, + runSpacing: spacer1, + children: [ + // buildDeviceChip(), + const SizedBox(width: spacer2), + Container( + padding: const EdgeInsets.all(spacer2), + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme + .instance.colors.light.primary1Bg, + ), + borderRadius: + BorderRadius.circular(spacer2), + ), + child: Text( + widget + .connectedDevices.first.deviceName, + style: TextStyle( + color: DigitTheme + .instance.colors.light.primary2, + ), + ), ), - ), - ), - ]), + ]), ], ), - failedToTransfer: (error) => Center( - child: DigitButton( - onPressed: () { - context.read().add( - DataTransferEvent( - nearbyService: nearbyService, - connectedDevice: - widget.connectedDevices, - selectedBoundaryCode: - context.boundary.code ?? '', - selectedProject: - context.selectedProject.id)); - }, - size: DigitButtonSize.large, - label: localizations - .translate(i18.common.coreCommonRetry), - type: DigitButtonType.primary, - ), - ), )), ], ), @@ -276,12 +254,12 @@ class _DataTransferScreenState extends LocalizedState { } else if (snapshot.hasData) { // Display the device name when available return Container( - padding: const EdgeInsets.all(kPadding), + padding: const EdgeInsets.all(spacer2), decoration: BoxDecoration( border: Border.all( color: DigitTheme.instance.colors.light.primary1Bg, ), - borderRadius: BorderRadius.circular(kPadding), + borderRadius: BorderRadius.circular(spacer2), ), child: Text( snapshot.data!, diff --git a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart index f86d95d488..491a941828 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -13,7 +13,6 @@ import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; import '../../router/app_router.dart'; import '../../utils/i18_key_constants.dart' as i18; import '../../widgets/localized.dart'; -import '../../widgets/showcase/showcase_wrappers.dart'; enum DeviceType { receiver, sender } @@ -191,13 +190,13 @@ class DevicesListPageState extends LocalizedState decoration: BoxDecoration( color: DigitTheme.instance.colors.light.primary1Bg .withOpacity(0.5), - borderRadius: BorderRadius.circular(kPadding), + borderRadius: BorderRadius.circular(spacer2), border: Border.all( color: DigitTheme.instance.colors.light.primary1Bg .withOpacity(0.2), width: 1.5)), child: Padding( - padding: const EdgeInsets.all(kPadding), + padding: const EdgeInsets.all(spacer2), child: Column( children: [ Icon( @@ -218,10 +217,10 @@ class DevicesListPageState extends LocalizedState ), ), Material( - borderRadius: BorderRadius.circular(kPadding), + borderRadius: BorderRadius.circular(spacer2), color: DigitTheme.instance.colors.light.primary1Bg, child: Padding( - padding: const EdgeInsets.all(kPadding / 2), + padding: const EdgeInsets.all(spacer1), child: Text( getStateName(device.state), textAlign: TextAlign.center, @@ -315,7 +314,7 @@ class DevicesListPageState extends LocalizedState nearbyService = NearbyService(); await nearbyService.init( - serviceType: 'mpconn', + serviceType: 'DigitShare', deviceName: deviceId, strategy: Strategy.Wi_Fi_P2P, callback: (isRunning) async { diff --git a/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart b/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart index 5d591bd633..67e8de5909 100644 --- a/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart +++ b/apps/health_campaign_field_worker_app/lib/utils/i18_key_constants.dart @@ -103,6 +103,7 @@ class Common { String get coreCommonYes => 'CORE_COMMON_YES'; String get coreCommonNo => 'CORE_COMMON_NO'; + String get coreCommonGoback => 'CORE_COMMON_GO_BACK'; String get coreCommonRequiredItems => 'CORE_COMMON_REQUIRED_ITEMS'; @@ -112,6 +113,7 @@ class Common { String get maxCharsRequired => 'MAX_CHARS_ALLOWED'; String get maxValue => 'MAX_VALUE_ALLOWED'; + String get minValue => 'MIN_VALUE_ALLOWED'; String get noResultsFound => 'NO_RESULTS_FOUND'; @@ -119,6 +121,7 @@ class Common { String get coreCommonSyncInProgress => 'CORE_COMMON_SYNC_IN_PROGRESS'; String get facilitySearchHeaderLabel => 'FACILITY_SEARCH_HEADER_LABEL'; + String get projectFacilitySearchHeaderLabel => 'PROJECT_FACILITY_SEARCH_HEADER_LABEL'; @@ -129,8 +132,11 @@ class Common { String get noMatchFound => 'CORE_COMMON_NO_MATCH_FOUND'; String get scanBales => 'CORE_COMMON_SCAN_BALES'; + String get ageInMonths => 'AGE_IN_MONTHS_LABEL'; + String get locationCapturing => 'CAPTURING_LOCATION'; + String get profileUpdateSuccess => 'PROFILE_UPDATE_SUCCESS'; } @@ -316,6 +322,7 @@ class StockDetailsIssuedShowcase { String get facilitySearchHeaderLabel => 'FACILITY_SEARCH_HEADER_LABEL'; String get coreCommonDownload => 'CORE_COMMON_DOWNLOAD'; + String get coreCommonDownloadFailed => 'CORE_COMMON_DOWNLOAD_FAILED'; } @@ -561,10 +568,15 @@ class Home { String get warehouseManagerCheckList => 'WAREHOUSE_MANAGER_CHECK_LIST_LABEL'; String get deleteAllLabel => 'HOME_DELETE_ALL_LABEL'; + String get db => 'HOME_DB_LABEL'; + String get dataShare => 'HOME_DATA_SHARE_LABEL'; + String get dashboard => 'HOME_DASHBOARD_LABEL'; + String get beneficiaryReferralLabel => 'HOME_BENEFICIARY_REFERRAL_LABEL'; + String get manageAttendanceLabel => 'HOME_MANAGE_ATTENDANCE_LABEL'; String get closedHouseHoldLabel => 'HOME_CLOSE_HOUSEHOLD_LABEL'; @@ -576,9 +588,26 @@ class DataShare { const DataShare(); String get sendAction => 'SEND_ACTION'; + String get receiveAction => 'RECEIVE_ACTION'; + String get connectedTo => 'CONNECTED_TO'; + String get noDevicesConnected => 'NO_DEVICES_CONNECTED'; + + String get dataSharingLabel => 'DATA_SHARING_LABEL'; + + String get receiving => 'RECEIVING'; + + String get transferring => 'TRANSFERRING'; + + String get projectMisMatchError => 'PROJECT_MISMATCH_ERROR'; + + String get invalidFileError => 'INVALID_FILE_FORMAT_ERROR'; + + String get fileNotFoundError => 'FILE_NOT_FOUND_ERROR'; + + String get failedToTransfer => 'FAILED_TO_TRANSFER'; } class AcknowledgementSuccess { @@ -592,7 +621,9 @@ class AcknowledgementSuccess { String get acknowledgementLabelText => 'ACKNOWLEDGEMENT_SUCCESS_LABEL_TEXT'; String get goToHome => 'GO_TO_HOME_SCREEN'; + String get downloadmoredata => 'DOWNLOAD_MORE_DATA'; + String get dataDownloadedSuccessLabel => 'DATA_DOWNLOADED_SUCCESS_LABEL'; } @@ -699,6 +730,7 @@ class Complaints { String get inboxSyncRequiredLabel => 'COMPLAINTS_INBOX_SYNC_REQUIRED_LABEL'; String get raisedForMyself => 'COMPLAINTS_RAISED_FOR_MYSELF'; + String get validationMinLengthError => 'COMPLAINTS_VALIDATION_MINLENGTH_ERROR'; @@ -743,7 +775,9 @@ class SyncDialog { String get closeButtonLabel => 'SYNC_DIALOG_CLOSE_BUTTON_LABEL'; String get retryButtonLabel => 'SYNC_DIALOG_RETRY_BUTTON_LABEL'; + String get pendingSyncLabel => 'PENDING_SYNC_LABEL'; + String get pendingSyncContent => 'PENDING_SYNC_CONTENT'; } @@ -929,6 +963,7 @@ class IndividualDetails { 'INDIVIDUAL_DETAILS_INVALID_MOBILE_NUMBER'; String get yearsHintText => 'YEARS_HINT_TEXT'; + String get monthsHintText => 'MONTHS_HINT_TEXT'; String get yearsErrorText => 'ERR_YEARS'; @@ -944,28 +979,45 @@ class BeneficiaryDetails { const BeneficiaryDetails(); String get beneficiarysDetailsLabelText => 'BENEFICIARY_DETAILS_LABEL_TEXT'; + String get beneficiarysDetailsEditIconLabelText => 'BENEFICIARY_DETAILS_EDIT_ICON_LABEL_TEXT'; + String get beneficiarysDetailsEditIconLabel => 'BENEFICIARY_DETAILS_EDIT_ICON_LABEL'; + String get beneficiarysDetailsDeleteIconLabel => 'BENEFICIARY_DETAILS_DELETE_ICON_LABEL'; + String get resourcesTobeDelivered => 'RESOURCES_TO_BE_DELIVERED'; + String get resourcesTobeProvided => 'RESOURCES_TO_BE_PROVIDED'; String get beneficiaryAge => 'BENEFICIARY_AGE'; + String get ctaProceed => 'PROCEED'; + String get beneficiaryDoseNo => 'BENEFICIARY_DETAILS_DOSE_NO'; + String get beneficiaryDose => 'BENEFICIARY_DETAILS_DOSE'; + String get beneficiaryStatus => 'BENEFICIARY_DETAILS_STATUS'; + String get beneficiaryResources => 'BENEFICIARY_DETAILS_RESOURCES'; + String get beneficiaryQuantity => 'BENEFICIARY_DETAILS_QUANTITY'; + String get beneficiaryCompletedOn => 'BENEFICIARY_DETAILS_COMPLETED_ON'; + String get beneficiaryDeliveryStrategy => 'BENEFICIARY_DETAILS_DELIVERY_STRATEGY'; + String get beneficiaryCycle => 'BENEFICIARY_DETAILS_CYCLE'; + String get currentCycleLabel => 'BENEFICIARY_DETAILS_CURRENT_CYCLE_LABEL'; + String get fromCurrentLocation => 'FROM_CURRENT_LOCATION'; + String get unableToScan => 'UNABLE_TO_SCAN'; String get scanValidResource => 'SCAN_VALID_RESOURCE'; @@ -993,30 +1045,52 @@ class BeneficiaryDetails { String get scannerDialogPrimaryAction => 'SCANNER_DIALOG_PRIMARY_ACTION'; String get scannerDialogSecondaryAction => 'SCANNER_DIALOG_SECONDARY_ACTION'; + String get beneficiaryHeader => 'BENEFICIARY_HEADER'; + String get deliveryHeader => 'DELIVERY_TABLE_HEADER'; String get proceedWithoutDownloading => 'PROCEED_WITHOUT_DOWNLOADING'; + String get unableToCheckDataInServer => 'FAILED_TO_CHECK_DATA_IN_SERVER'; + String get dataFound => 'DATA_FOUND'; + String get noDataFound => 'NO_DATA_FOUND'; + String get dataFoundContent => 'DATA_FOUND_CONTENT'; + String get noDataFoundContent => 'NO_DATA_FOUND_CONTENT'; + String get dataDownloadInProgress => 'DATA_DOWNLOAD_IN_PROGRESS'; + String get insufficientStorage => 'INSUFFICIENT_STORAGE_WARNING'; + String get downloadreport => 'DOWNLOAD_REPORT'; + String get boundary => 'BOUNDARY'; + String get status => 'STATUS'; + String get downloadedon => 'DOWNLOADED_ON'; + String get recordsdownload => 'RECORDS_DOWNLOAD'; + String get downloadcompleted => 'DOWNLOAD_COMPLETED'; + String get datadownloadreport => 'DATA_DOWNLOAD_REPORT'; + String get download => 'DOWNLOAD'; + String get partialdownloaded => 'PARTIAL_DOWNLOAD'; + String get downloadtime => 'DOWNLOAD_TIME'; + String get totalrecorddownload => 'TOTAL_RECORD_DOWNLOAD'; + String get insufficientStorageContent => 'INSUFFICIENT_STORAGE_WARNING_CONTENT'; + String get recordCycle => 'BENEFICIARY_DETAILS_RECORD_CYCLE'; } @@ -1032,7 +1106,9 @@ class PrivacyPolicy { } String get privacyNoticeText => 'PRIVACY_POLICY_TEXT'; + String get privacyPolicyLinkText => 'PRIVACY_POLICY_LINK_TEXT'; + String get privacyPolicyValidationText => 'PRIVACY_POLICY_VALIDATION_TEXT'; } diff --git a/apps/health_campaign_field_worker_app/lib/widgets/showcase/showcase_wrappers.dart b/apps/health_campaign_field_worker_app/lib/widgets/showcase/showcase_wrappers.dart index a2ac9e3988..f4e92b93d9 100644 --- a/apps/health_campaign_field_worker_app/lib/widgets/showcase/showcase_wrappers.dart +++ b/apps/health_campaign_field_worker_app/lib/widgets/showcase/showcase_wrappers.dart @@ -1,10 +1,9 @@ import 'package:digit_showcase/showcase.dart'; +import 'package:digit_ui_components/theme/spacers.dart'; import 'package:flutter/material.dart'; import '../localized.dart'; -const kPadding = 8.0; - class ShowcaseItemBuilder { final GlobalKey showcaseKey; final String messageLocalizationKey; @@ -46,17 +45,17 @@ class _ShowcaseItemWrapperWidgetState disableScaleAnimation: true, description: localizations.translate(widget.messageLocalizationKey), targetPadding: const EdgeInsets.fromLTRB( - kPadding / 2, - kPadding / 2, - kPadding / 2, - kPadding / 2, + spacer2 / 2, + spacer2 / 2, + spacer2 / 2, + spacer2 / 2, ), child: Container( padding: const EdgeInsets.fromLTRB( - kPadding / 2, - kPadding / 2, - kPadding / 2, - kPadding / 2, + spacer2 / 2, + spacer2 / 2, + spacer2 / 2, + spacer2 / 2, ), child: widget.child, ),