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/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..6daedf8b52 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.dart @@ -0,0 +1,436 @@ +// 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 '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'; +import '../../utils/i18_key_constants.dart' as i18; + +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; + final LocalRepository + downSyncLocalRepository; + + List receivedData = []; + int receivedBytes = 0; + int totalCount = 0; + String entityType = ''; + late Device connectedDevice; + 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); + } + + FutureOr _handleSendEntities( + DataTransferEvent event, + PeerToPeerEmitter emit, + ) async { + try { + emit(const PeerToPeerState.transferInProgress( + progress: 0, offset: 0, totalCount: 0)); + + final downloadsDirectory = await getDownloadsDirectory(); + final file = File( + '${downloadsDirectory!.path}/${event.selectedProject}/${event.selectedBoundaryCode}/down_sync_data.json'); + + 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: i18.dataShare.invalidFileError)); + 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(); + + var selectedBoundaryCode = offsetData.keys + .where((element) => element == 'boundaryCode') + .map((e) => offsetData[e]) + .firstOrNull; + + totalCount = offsetData.keys + .where((element) => element == 'totalCount') + .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(), + ); + + bool handshakeSuccessful = await waitForConfirmation( + event.nearbyService, + confirmationType: ConfirmationTypes.handShake.toValue(), + ); + + if (handshakeSuccessful) { + emit(PeerToPeerState.failedToTransfer( + error: i18.dataShare.projectMisMatchError)); + 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, + ); + + emit(PeerToPeerState.transferInProgress( + progress: offsetValue / totalCount, + offset: offsetValue, + totalCount: totalCount)); + } + } + } + + // Send final acknowledgment to all devices + for (var device in event.connectedDevice) { + await event.nearbyService.sendMessage( + device.deviceId, + 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: ConfirmationTypes.finalAcknowledgment.toValue(), + ); + + emit(const PeerToPeerState.completedDataTransfer()); + } + } else { + emit(PeerToPeerState.failedToTransfer( + error: i18.dataShare.fileNotFoundError)); + return; + } + } catch (e) { + emit(PeerToPeerState.failedToTransfer(error: e.toString())); + } + } + + String compressJson(Map jsonData) { + // Convert JSON data to string + final jsonString = jsonEncode(jsonData); + + // Compress using zlib + final compressedData = zlib.encode(utf8.encode(jsonString)); + + // 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, + PeerToPeerEmitter emit, + ) async { + try { + PeerToPeerMessageModel messageModel = + PeerToPeerMessageModelMapper.fromJson(event.data["message"]); + + if (messageModel.messageType == MessageTypes.handShake.toValue()) { + if (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. Project mismatch.", + confirmationType: ConfirmationTypes.failed.toValue(), + status: MessageStatus.fail.toValue(), + ).toJson()); + emit(PeerToPeerState.failedToReceive( + error: i18.dataShare.projectMisMatchError)); + } + } else if (messageModel.messageType == MessageTypes.chunk.toValue()) { + // Process chunk + 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) { + entityType = entity.key; + + 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, + ], + ); + + SyncServiceMapper().createDbRecords(local, entityList, entityType); + } + } + + // Update progress and clear processed data + receivedBytes = offset!; + double progress = receivedBytes / totalCount!; + + // Emit progress + emit(PeerToPeerState.receivingInProgress( + progress: progress, + offset: offset, + totalCount: totalCount, + )); + + // Send chunk acknowledgment + await event.nearbyService.sendMessage( + 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, + )); + + await downSyncLocalRepository.update( + existingDownSyncData.first.copyWith( + offset: 0, + limit: 0, + lastSyncedTime: DateTime.now().millisecondsSinceEpoch, + ), + ); + + // Send overall transfer acknowledgment + await event.nearbyService.sendMessage( + 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"], + PeerToPeerMessageModel( + messageType: MessageTypes.confirmation.toValue(), + message: "$e", + confirmationType: ConfirmationTypes.failed.toValue(), + status: MessageStatus.fail.toValue(), + ).toJson()); + } + } + + Future waitForConfirmation( + NearbyService nearbyService, { + required String confirmationType, + int? offset, + }) async { + final completer = Completer(); + + final subscription = nearbyService.dataReceivedSubscription( + callback: (data) { + try { + PeerToPeerMessageModel messageModel = + PeerToPeerMessageModelMapper.fromJson(data["message"]); + + if (messageModel.messageType == MessageTypes.confirmation.toValue()) { + if (confirmationType == ConfirmationTypes.chunk.toValue() && + messageModel.offset == offset) { + completer.complete(true); + } else if (confirmationType == + ConfirmationTypes.finalAcknowledgment.toValue() || + confirmationType == ConfirmationTypes.finalTransfer.toValue() || + confirmationType == ConfirmationTypes.handShake.toValue()) { + completer.complete(true); + } else if (confirmationType == ConfirmationTypes.failed.toValue()) { + completer.complete(false); + emit(PeerToPeerState.failedToTransfer( + error: i18.dataShare.failedToTransfer)); + } + } + } catch (e) { + debugPrint("Error processing confirmation: $e"); + completer.complete(false); + } + }, + ); + + bool result = await completer.future; + subscription.cancel(); + return result; + } +} + +@freezed +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( + {required String projectId, + required String selectedBoundaryCode, + 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, + required int offset, + required int totalCount}) = TransferInProgress; + + const factory PeerToPeerState.completedDataTransfer() = CompletedDataTransfer; + + const factory PeerToPeerState.failedToTransfer({required String error}) = + FailedToTransfer; + + const factory PeerToPeerState.receivingInProgress( + {required double progress, + required int offset, + required int totalCount}) = 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..6bc18c95ff --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/blocs/peer_to_peer/peer_to_peer.freezed.dart @@ -0,0 +1,2069 @@ +// 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; + String get selectedBoundaryCode => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult when({ + required TResult Function( + NearbyService nearbyService, + String selectedProject, + String selectedBoundaryCode, + List connectedDevice) + dataTransfer, + required TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data) + dataReceiver, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? + dataTransfer, + TResult? Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? + dataTransfer, + TResult Function(String projectId, String selectedBoundaryCode, + 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, String selectedBoundaryCode}); +} + +/// @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, + 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); + } +} + +/// @nodoc +abstract class _$$DataTransferEventImplCopyWith<$Res> + implements $PeerToPeerEventCopyWith<$Res> { + factory _$$DataTransferEventImplCopyWith(_$DataTransferEventImpl value, + $Res Function(_$DataTransferEventImpl) then) = + __$$DataTransferEventImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {NearbyService nearbyService, + String selectedProject, + String selectedBoundaryCode, + 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? selectedProject = null, + Object? selectedBoundaryCode = null, + Object? connectedDevice = null, + }) { + return _then(_$DataTransferEventImpl( + nearbyService: null == nearbyService + ? _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 + as List, + )); + } +} + +/// @nodoc + +class _$DataTransferEventImpl + with DiagnosticableTreeMixin + 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 { + 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, selectedProject: $selectedProject, selectedBoundaryCode: $selectedBoundaryCode, connectedDevice: $connectedDevice)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PeerToPeerEvent.dataTransfer')) + ..add(DiagnosticsProperty('nearbyService', nearbyService)) + ..add(DiagnosticsProperty('selectedProject', selectedProject)) + ..add(DiagnosticsProperty('selectedBoundaryCode', selectedBoundaryCode)) + ..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) && + (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, + selectedProject, + selectedBoundaryCode, + 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, + String selectedProject, + String selectedBoundaryCode, + List connectedDevice) + dataTransfer, + required TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data) + dataReceiver, + }) { + return dataTransfer( + nearbyService, selectedProject, selectedBoundaryCode, connectedDevice); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? + dataTransfer, + TResult? Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, + }) { + return dataTransfer?.call( + nearbyService, selectedProject, selectedBoundaryCode, connectedDevice); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? + dataTransfer, + TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, + required TResult orElse(), + }) { + if (dataTransfer != null) { + return dataTransfer(nearbyService, selectedProject, selectedBoundaryCode, + 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 String selectedProject, + required final String selectedBoundaryCode, + required final List connectedDevice}) = _$DataTransferEventImpl; + + @override + NearbyService get nearbyService; + String get selectedProject; + @override + String get selectedBoundaryCode; + 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( + {String projectId, + String selectedBoundaryCode, + 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? 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 + 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.projectId, + required this.selectedBoundaryCode, + required this.nearbyService, + required this.data}); + + @override + final String projectId; + @override + final String selectedBoundaryCode; + @override + final NearbyService nearbyService; + @override + final dynamic data; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerEvent.dataReceiver(projectId: $projectId, selectedBoundaryCode: $selectedBoundaryCode, nearbyService: $nearbyService, data: $data)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + 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)); + } + + @override + bool operator ==(Object other) { + 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, projectId, selectedBoundaryCode, + 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, + String selectedProject, + String selectedBoundaryCode, + List connectedDevice) + dataTransfer, + required TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data) + dataReceiver, + }) { + return dataReceiver(projectId, selectedBoundaryCode, nearbyService, data); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? + dataTransfer, + TResult? Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, + }) { + return dataReceiver?.call( + projectId, selectedBoundaryCode, nearbyService, data); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(NearbyService nearbyService, String selectedProject, + String selectedBoundaryCode, List connectedDevice)? + dataTransfer, + TResult Function(String projectId, String selectedBoundaryCode, + NearbyService nearbyService, dynamic data)? + dataReceiver, + required TResult orElse(), + }) { + if (dataReceiver != null) { + return dataReceiver(projectId, selectedBoundaryCode, 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 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; + @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, int offset, int totalCount) + transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress, int offset, int totalCount) + 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, int offset, int totalCount)? + transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount) + transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress, int offset, int totalCount) + 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, int offset, int totalCount)? + transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount)? + transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount) + transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress, int offset, int totalCount) + 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, int offset, int totalCount)? + transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount)? + transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount}); +} + +/// @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, + Object? offset = null, + Object? totalCount = null, + }) { + return _then(_$TransferInProgressImpl( + progress: null == progress + ? _value.progress + : progress // ignore: cast_nullable_to_non_nullable + as double, + 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, + )); + } +} + +/// @nodoc + +class _$TransferInProgressImpl + with DiagnosticableTreeMixin + implements TransferInProgress { + const _$TransferInProgressImpl( + {required this.progress, required this.offset, required this.totalCount}); + + @override + final double progress; + @override + final int offset; + @override + final int totalCount; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.transferInProgress(progress: $progress, offset: $offset, totalCount: $totalCount)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PeerToPeerState.transferInProgress')) + ..add(DiagnosticsProperty('progress', progress)) + ..add(DiagnosticsProperty('offset', offset)) + ..add(DiagnosticsProperty('totalCount', totalCount)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$TransferInProgressImpl && + (identical(other.progress, progress) || + other.progress == progress) && + (identical(other.offset, offset) || other.offset == offset) && + (identical(other.totalCount, totalCount) || + other.totalCount == totalCount)); + } + + @override + int get hashCode => Object.hash(runtimeType, progress, offset, totalCount); + + @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, int offset, int totalCount) + transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress, int offset, int totalCount) + receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return transferInProgress(progress, offset, totalCount); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return transferInProgress?.call(progress, offset, totalCount); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + 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, offset, totalCount); + } + 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, + required final int offset, + required final int totalCount}) = _$TransferInProgressImpl; + + double get progress; + int get offset; + int get totalCount; + @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, int offset, int totalCount) + transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress, int offset, int totalCount) + 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, int offset, int totalCount)? + transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount)? + transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount) + transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress, int offset, int totalCount) + 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, int offset, int totalCount)? + transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount)? + transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount}); +} + +/// @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, + Object? offset = null, + Object? totalCount = null, + }) { + return _then(_$ReceivingInProgressImpl( + progress: null == progress + ? _value.progress + : progress // ignore: cast_nullable_to_non_nullable + as double, + 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, + )); + } +} + +/// @nodoc + +class _$ReceivingInProgressImpl + with DiagnosticableTreeMixin + implements ReceivingInProgress { + const _$ReceivingInProgressImpl( + {required this.progress, required this.offset, required this.totalCount}); + + @override + final double progress; + @override + final int offset; + @override + final int totalCount; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PeerToPeerState.receivingInProgress(progress: $progress, offset: $offset, totalCount: $totalCount)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PeerToPeerState.receivingInProgress')) + ..add(DiagnosticsProperty('progress', progress)) + ..add(DiagnosticsProperty('offset', offset)) + ..add(DiagnosticsProperty('totalCount', totalCount)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ReceivingInProgressImpl && + (identical(other.progress, progress) || + other.progress == progress) && + (identical(other.offset, offset) || other.offset == offset) && + (identical(other.totalCount, totalCount) || + other.totalCount == totalCount)); + } + + @override + int get hashCode => Object.hash(runtimeType, progress, offset, totalCount); + + @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, int offset, int totalCount) + transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress, int offset, int totalCount) + receivingInProgress, + required TResult Function() dataReceived, + required TResult Function(String error) failedToReceive, + }) { + return receivingInProgress(progress, offset, totalCount); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(double progress, int offset, int totalCount)? + transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress, int offset, int totalCount)? + receivingInProgress, + TResult? Function()? dataReceived, + TResult? Function(String error)? failedToReceive, + }) { + return receivingInProgress?.call(progress, offset, totalCount); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? loading, + TResult Function(double progress, int offset, int totalCount)? + transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + 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, offset, totalCount); + } + 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, + required final int offset, + required final int totalCount}) = _$ReceivingInProgressImpl; + + double get progress; + int get offset; + int get totalCount; + @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, int offset, int totalCount) + transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress, int offset, int totalCount) + 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, int offset, int totalCount)? + transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount)? + transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount) + transferInProgress, + required TResult Function() completedDataTransfer, + required TResult Function(String error) failedToTransfer, + required TResult Function(double progress, int offset, int totalCount) + 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, int offset, int totalCount)? + transferInProgress, + TResult? Function()? completedDataTransfer, + TResult? Function(String error)? failedToTransfer, + TResult? Function(double progress, int offset, int totalCount)? + 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, int offset, int totalCount)? + transferInProgress, + TResult Function()? completedDataTransfer, + TResult Function(String error)? failedToTransfer, + TResult Function(double progress, int offset, int totalCount)? + 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/project/project.dart b/apps/health_campaign_field_worker_app/lib/blocs/project/project.dart index fbeffcd3cb..1d00d46f5d 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 @@ -578,7 +578,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/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 61c278aeb2..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 @@ -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_update/disk_space_update.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 'package:sync_service/sync_service_lib.dart'; @@ -29,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, @@ -201,6 +206,8 @@ class BeneficiaryDownSyncBloc ); // check if the API response is there or it failed if (downSyncResults.isNotEmpty) { + writeToFile(event.projectId, event.boundaryCode, + event.boundaryName, downSyncResults); await SyncServiceSingleton() .entityMapper ?.writeToEntityDB(downSyncResults, [ @@ -260,6 +267,67 @@ class BeneficiaryDownSyncBloc } } + void writeToFile( + String projectId, + String selectedBoundaryCode, + String selectedBoundaryName, + 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}/$projectId/$selectedBoundaryCode/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 + } + var downSyncModel = response["DownsyncCriteria"]; + // Create a unique key using just the offset + String uniqueKey = '${downSyncModel["offset"]}'; + + // Prepare data to insert + Map data = { + "totalCount": downSyncModel["totalCount"], + "response": response, + "boundaryCode": selectedBoundaryCode, + "boundaryName": selectedBoundaryName + }; + + // 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 updated data back to the file + await file.writeAsString(storedDataString); + + if (kDebugMode) { + print("Data successfully written to ${file.path}"); + } + } + FutureOr _handleDownSyncReport( DownSyncReportEvent event, BeneficiaryDownSyncEmitter emit, @@ -308,9 +376,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, @@ -318,21 +388,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/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/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/models/data_model.init.dart b/apps/health_campaign_field_worker_app/lib/models/data_model.init.dart index 6e78c3552c..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 @@ -7,9 +7,11 @@ 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/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; void initializeMappers() { p0.DownsyncSearchModelMapper.ensureInitialized(); @@ -18,7 +20,11 @@ void initializeMappers() { p1.AdditionalFieldsTypeMapper.ensureInitialized(); p2.MasterEnumsMapper.ensureInitialized(); p3.ModuleEnumsMapper.ensureInitialized(); - p4.RolesMapper.ensureInitialized(); - p5.RolesTypeMapper.ensureInitialized(); - p6.ScannerTypeMapper.ensureInitialized(); + p4.MessageTypesMapper.ensureInitialized(); + p4.ConfirmationTypesMapper.ensureInitialized(); + p4.MessageStatusMapper.ensureInitialized(); + p5.PeerToPeerMessageModelMapper.ensureInitialized(); + p6.RolesMapper.ensureInitialized(); + p7.RolesTypeMapper.ensureInitialized(); + p8.ScannerTypeMapper.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..e8b824dac6 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.dart @@ -0,0 +1,39 @@ +import 'package:dart_mappable/dart_mappable.dart'; + +part 'message_types.mapper.dart'; + +@MappableEnum(caseStyle: CaseStyle.upperCase) +enum MessageTypes { + @MappableValue("confirmation") + confirmation, + @MappableValue("chunk") + chunk, + @MappableValue("handshake") + handShake +} + +@MappableEnum(caseStyle: CaseStyle.upperCase) +enum ConfirmationTypes { + @MappableValue("finalTransfer") + finalTransfer, + @MappableValue("chunk") + chunk, + @MappableValue("failed") + failed, + @MappableValue("finalAcknowledgment") + finalAcknowledgment, + @MappableValue("handshake") + handShake +} + +@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..7be7d3045f --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/models/entities/peer_to_peer/message_types.mapper.dart @@ -0,0 +1,169 @@ +// 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; + case "handshake": + return MessageTypes.handShake; + default: + throw MapperException.unknownEnumValue(value); + } + } + + @override + dynamic encode(MessageTypes self) { + switch (self) { + case MessageTypes.confirmation: + return "confirmation"; + case MessageTypes.chunk: + return "chunk"; + case MessageTypes.handShake: + return "handshake"; + } + } +} + +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; + case "handshake": + return ConfirmationTypes.handShake; + 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"; + case ConfirmationTypes.handShake: + return "handshake"; + } + } +} + +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/pages/home.dart b/apps/health_campaign_field_worker_app/lib/pages/home.dart index 391ce163d0..0f45da4e5c 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/home.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/home.dart @@ -533,6 +533,15 @@ class _HomePageState extends LocalizedState { }, ), ), + i18.home.dataShare: homeShowcaseData.dataShare.buildWith( + child: HomeItemCard( + icon: Icons.send, + label: i18.home.dataShare, + onPressed: () async { + context.router.push(const DataShareHomeRoute()); + }, + ), + ), i18.home.dashboard: homeShowcaseData.dashBoard.buildWith( child: HomeItemCard( icon: Icons.bar_chart_sharp, @@ -605,11 +614,11 @@ 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 final List widgetList = filteredLabels.map((label) => homeItemsMap[label]!).toList(); 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/lib/pages/login.dart b/apps/health_campaign_field_worker_app/lib/pages/login.dart index ea7936c497..75d53ad1d4 100644 --- a/apps/health_campaign_field_worker_app/lib/pages/login.dart +++ b/apps/health_campaign_field_worker_app/lib/pages/login.dart @@ -231,12 +231,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/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..5097183a5f --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_receiver.dart @@ -0,0 +1,259 @@ +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/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 '../../utils/utils.dart'; +import '../../widgets/localized.dart'; +import '../../widgets/peer_to_peer/file_transfer_animation.dart'; + +@RoutePage() +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; + late PeerToPeerBloc peerToPeerBloc; + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + + @override + void initState() { + super.initState(); + nearbyService = widget.nearbyService; + peerToPeerBloc = context.read(); + nearbyService.dataReceivedSubscription(callback: (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) { + if (device.state == SessionState.notConnected) { + if (mounted) { + context.router.maybePop(); + Toast.showToast( + context, + message: localizations.translate( + '${device.deviceName} ${SessionState.notConnected.toString().toUpperCase()}'), + type: ToastType.error, + ); + } + } + } + }); + } + + @override + void dispose() { + nearbyService.stopAdvertisingPeer(); + nearbyService.stopBrowsingForPeers(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return PopScope( + onPopInvoked: (pop) {}, + child: BlocListener( + listener: (context, state) { + if (state is DataReceived) { + 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) { + return ScrollableContent( + header: const BackNavigationHelpHeaderWidget( + showHelp: true, + ), + footer: DigitCard( + margin: const EdgeInsets.only(top: spacer2), + padding: const EdgeInsets.all(spacer2), + children: [ + DigitButton( + type: DigitButtonType.secondary, + mainAxisSize: MainAxisSize.max, + onPressed: () { + context.router.maybePop(); + }, + label: localizations + .translate(i18.common.coreCommonCancel), + size: DigitButtonSize.large, + ), + ]), + slivers: [ + SliverToBoxAdapter( + child: Column(children: [ + Padding( + padding: const EdgeInsets.all(spacer2), + 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(spacer2), + child: state.maybeWhen( + orElse: () => Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: spacer4), + CircularPercentIndicator( + radius: MediaQuery.of(context).size.height * + 0.15, + lineWidth: spacer2 * 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: spacer4), + FileTransferAnimation(), + Wrap( + spacing: spacer2, + runSpacing: spacer1, + children: [ + // buildDeviceChip(), + Container( + padding: + const EdgeInsets.all(spacer2), + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme.instance.colors + .light.primary1Bg, + ), + borderRadius: + BorderRadius.circular(spacer2), + ), + child: Text( + widget.connectedDevice.deviceName, + style: TextStyle( + color: DigitTheme.instance.colors + .light.primary2, + ), + ), + ), + ]), + ], + ), + ), + receivingInProgress: + (progress, offset, totalCount) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(localizations.translate( + '${i18.dataShare.receiving} $offset / $totalCount')), + const SizedBox(height: spacer4), + CircularPercentIndicator( + radius: + MediaQuery.of(context).size.height * + 0.15, + lineWidth: spacer2 * 1.5, + animation: false, + percent: progress, + // Update this dynamically for progress + center: Text( + '${(progress * 100).toStringAsFixed(1)} %', + style: const TextStyle( + fontWeight: FontWeight.bold), + ), + progressBorderColor: DigitTheme + .instance.colors.light.primary1Bg, + progressColor: DigitTheme + .instance.colors.light.alertSuccess, + backgroundColor: DigitTheme + .instance.colors.light.primary1Bg, + ), + const SizedBox(height: spacer4), + FileTransferAnimation(), + Wrap( + spacing: spacer2, + runSpacing: spacer1, + children: [ + Container( + padding: + const EdgeInsets.all(spacer2), + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme.instance + .colors.light.primary1Bg, + ), + borderRadius: + BorderRadius.circular( + spacer2), + ), + 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 new file mode 100644 index 0000000000..56d8413212 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_share_home.dart @@ -0,0 +1,96 @@ +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/header/back_navigation_help_header.dart'; +import '../../widgets/localized.dart'; +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) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return ScrollableContent( + header: const BackNavigationHelpHeaderWidget( + showHelp: true, + ), + children: [ + Padding( + padding: const EdgeInsets.all(spacer2), + child: Align( + alignment: Alignment.topLeft, + child: Text( + localizations.translate(i18.dataShare.dataSharingLabel), + style: textTheme.headingM, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.2, + child: DigitCard( + padding: const EdgeInsets.only(top: spacer10), + margin: const EdgeInsets.all(spacer4), + inline: true, + 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: textTheme.label.copyWith( + color: DigitTheme.instance.colors.light.primary1), + ), + ) + ]), + ), + SizedBox( + 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(spacer4), + 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: 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 new file mode 100644 index 0000000000..d70c536c98 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/data_transfer.dart @@ -0,0 +1,277 @@ +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'; +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 '../../utils/utils.dart'; +import '../../widgets/localized.dart'; +import '../../widgets/peer_to_peer/file_transfer_animation.dart'; + +@RoutePage() +class DataTransferPage extends LocalizedStatefulWidget { + final List connectedDevices; + final NearbyService nearbyService; + + const DataTransferPage( + {super.key, required this.nearbyService, required this.connectedDevices}); + + @override + State createState() => _DataTransferScreenState(); +} + +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.connectedDevices, + nearbyService: nearbyService, + selectedBoundaryCode: context.boundary.code ?? '', + selectedProject: context.selectedProject.id)); + nearbyService.stateChangedSubscription(callback: (devices) { + for (var device in devices) { + if (device.state == SessionState.notConnected) { + if (mounted) { + context.router.maybePop(); + Toast.showToast( + context, + message: localizations.translate( + '${device.deviceName} ${SessionState.notConnected.name}'), + type: ToastType.error, + ); + } + } + } + }); + } + + @override + void dispose() { + widget.nearbyService.stopAdvertisingPeer(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return PopScope( + onPopInvoked: (pop) {}, + child: BlocListener( + listener: (context, state) { + if (state is CompletedDataTransfer) { + 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) { + return ScrollableContent( + header: const BackNavigationHelpHeaderWidget( + showHelp: true, + ), + footer: DigitCard( + margin: const EdgeInsets.only(top: spacer2), + padding: const EdgeInsets.all(spacer2), + children: [ + DigitButton( + type: DigitButtonType.secondary, + mainAxisSize: MainAxisSize.max, + onPressed: () { + context.router.maybePop(); + }, + label: localizations.translate(i18.common.coreCommonCancel), + size: DigitButtonSize.large, + ), + ]), + slivers: [ + SliverToBoxAdapter( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(spacer2), + child: Align( + alignment: Alignment.topLeft, + child: Text( + localizations.translate(i18.dataShare.sendAction), + style: textTheme.headingM, + ), + ), + ), + Container( + height: MediaQuery.of(context).size.height * 0.6, + color: DigitTheme.instance.colors.light.paperPrimary, + margin: const EdgeInsets.all(spacer2), + child: state.maybeWhen( + orElse: () => Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: spacer4), + CircularPercentIndicator( + radius: + MediaQuery.of(context).size.height * 0.15, + lineWidth: spacer2 * 1.5, + animation: false, + percent: 0, + // Update this dynamically for progress + center: const Text( + '0 %', + style: + TextStyle(fontWeight: FontWeight.bold), + ), + progressBorderColor: DigitTheme + .instance.colors.light.primary1Bg, + progressColor: DigitTheme + .instance.colors.light.alertSuccess, + backgroundColor: DigitTheme + .instance.colors.light.primary1Bg, + ), + ], + ), + ), + transferInProgress: (progress, offset, totalCount) => + Column( + mainAxisSize: MainAxisSize.max, + children: [ + 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: spacer2 * 1.5, + animation: false, + percent: progress, + // Update this dynamically for progress + center: Text( + '${(progress * 100).toStringAsFixed(1)} %', + style: const TextStyle( + fontWeight: FontWeight.bold), + ), + progressBorderColor: + DigitTheme.instance.colors.light.primary1Bg, + progressColor: DigitTheme + .instance.colors.light.alertSuccess, + backgroundColor: + DigitTheme.instance.colors.light.primary1Bg, + ), + 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, + ), + ), + ), + ]), + ], + ), + )), + ], + ), + ) + ], + ); + }), + ), + ); + } + + 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( + padding: const EdgeInsets.all(spacer2), + decoration: BoxDecoration( + border: Border.all( + color: DigitTheme.instance.colors.light.primary1Bg, + ), + borderRadius: BorderRadius.circular(spacer2), + ), + 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 new file mode 100644 index 0000000000..491a941828 --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/devices_list.dart @@ -0,0 +1,370 @@ +import 'dart:async'; +import 'dart:io'; +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_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_nearby_connections/flutter_nearby_connections.dart'; + +import '../../router/app_router.dart'; +import '../../utils/i18_key_constants.dart' as i18; +import '../../widgets/localized.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 { + final List devices = []; + final List connectedDevices = []; + late final String senderDeviceDetails; + late NearbyService nearbyService; + late StreamSubscription stateSubscription; + late AnimationController _controller; + late AnimationController _radarController; + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + + @override + void initState() { + super.initState(); + createAnimations(); + initializeNearbyService(); + fetchSenderDeviceDetails(); + } + + @override + void dispose() { + stateSubscription.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); + final screenWidth = MediaQuery.of(context).size.width; + final screenHeight = MediaQuery.of(context).size.height; + + return Scaffold( + body: ScrollableContent( + backgroundColor: DigitTheme.instance.colors.light.primary1Bg, + enableFixedDigitButton: true, + footer: DigitCard( + margin: const EdgeInsets.only(top: 16.0), + padding: const EdgeInsets.all(16.0), + children: [ + DigitButton( + onPressed: handleFooterButtonPress, + type: DigitButtonType.primary, + label: widget.deviceType == DeviceType.sender + ? localizations.translate(i18.dataShare.sendAction) + : localizations.translate(i18.dataShare.receiveAction), + size: DigitButtonSize.large, + mainAxisSize: MainAxisSize.max, + capitalizeLetters: false, + ), + ], + ), + slivers: [ + SliverToBoxAdapter( + child: Column( + children: [ + const BackNavigationHelpHeaderWidget(showHelp: true), + Padding( + padding: const EdgeInsets.all(16.0), + child: Align( + alignment: Alignment.topLeft, + child: Text( + widget.deviceType.name.toUpperCase(), + style: textTheme.headingM, + ), + ), + ), + buildRadarScreen(screenWidth, screenHeight), + ], + ), + ) + ], + ), + ); + } + + 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(); + final devicesToShow = + widget.deviceType == DeviceType.receiver ? connectedDevices : devices; + + 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(); + } + + Widget buildDeviceWidget(Device device) { + return device.state == SessionState.connected || + device.state == SessionState.notConnected + ? GestureDetector( + onTap: () { + handleDeviceTap(device); + }, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + decoration: BoxDecoration( + color: DigitTheme.instance.colors.light.primary1Bg + .withOpacity(0.5), + 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(spacer2), + 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(spacer2), + color: DigitTheme.instance.colors.light.primary1Bg, + child: Padding( + padding: const EdgeInsets.all(spacer1), + child: Text( + getStateName(device.state), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 8, color: getStateColor(device.state)), + ), + ), + ), + ], + ), + ) + : const CircularProgressIndicator(); + } + + void handleFooterButtonPress() { + if (connectedDevices.isEmpty) { + Toast.showToast( + context, + message: localizations.translate(i18.dataShare.noDevicesConnected), + type: ToastType.error, + ); + 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: senderDeviceDetails, + ); + } else if (device.state == SessionState.connected) { + nearbyService.disconnectPeer(deviceID: device.deviceId); + } + } + + 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.light.alertWarning; + case SessionState.connecting: + return DigitTheme.instance.colors.light.alertWarning; + case SessionState.connected: + return DigitTheme.instance.colors.light.alertSuccess; + default: + return Colors.grey; + } + } + + void createAnimations() { + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 10), + )..repeat(); + _radarController = AnimationController( + vsync: this, + duration: const Duration(seconds: 10), + )..repeat(); + } + + Future initializeNearbyService() async { + final deviceInfo = DeviceInfoPlugin(); + final deviceId = Platform.isAndroid + ? (await deviceInfo.androidInfo).model + : (await deviceInfo.iosInfo).localizedModel; + + nearbyService = NearbyService(); + await nearbyService.init( + serviceType: 'DigitShare', + deviceName: deviceId, + strategy: Strategy.Wi_Fi_P2P, + callback: (isRunning) async { + if (isRunning) { + if (widget.deviceType == DeviceType.sender) { + await nearbyService.startBrowsingForPeers(); + } else { + await nearbyService.startAdvertisingPeer(deviceName: deviceId); + } + } + }, + ); + + 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 + } + + // 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)); + }); + }, + ); + } + + Future getSenderDeviceName() async { + var deviceId = ''; + final deviceInfo = DeviceInfoPlugin(); + deviceId = Platform.isAndroid + ? (await deviceInfo.androidInfo).model + : (await deviceInfo.iosInfo).localizedModel; + return deviceId; + } + + void fetchSenderDeviceDetails() async { + senderDeviceDetails = await getSenderDeviceName(); + } +} 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..344e92898f --- /dev/null +++ b/apps/health_campaign_field_worker_app/lib/pages/peer_to_peer/peer_to_peer_wrapper.dart @@ -0,0 +1,44 @@ +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 '../../models/downsync/downsync.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>(), + downSyncLocalRepository: 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 f588a1f498..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 @@ -1,21 +1,17 @@ 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: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: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 +24,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 +202,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/lib/router/app_router.gr.dart b/apps/health_campaign_field_worker_app/lib/router/app_router.gr.dart index 2fcad75eef..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 @@ -55,6 +55,44 @@ 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, + child: const DataShareHomePage(), + ); + }, + DataTransferRoute.name: (routeData) { + final args = routeData.argsAs(); + return AutoRoutePage( + routeData: routeData, + child: DataTransferPage( + key: args.key, + nearbyService: args.nearbyService, + connectedDevices: args.connectedDevices, + ), + ); + }, + 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()); @@ -83,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()); @@ -284,6 +328,144 @@ 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 { + 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 List connectedDevices, + List? children, + }) : super( + DataTransferRoute.name, + args: DataTransferRouteArgs( + key: key, + nearbyService: nearbyService, + connectedDevices: connectedDevices, + ), + initialChildren: children, + ); + + static const String name = 'DataTransferRoute'; + + static const PageInfo page = + PageInfo(name); +} + +class DataTransferRouteArgs { + const DataTransferRouteArgs({ + this.key, + required this.nearbyService, + required this.connectedDevices, + }); + + final Key? key; + + final NearbyService nearbyService; + + final List connectedDevices; + + @override + String toString() { + return 'DataTransferRouteArgs{key: $key, nearbyService: $nearbyService, connectedDevices: $connectedDevices}'; + } +} + +/// 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 { @@ -372,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 b69bed1958..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 @@ -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(); @@ -102,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'; @@ -111,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'; @@ -118,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'; @@ -128,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'; } @@ -315,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'; } @@ -560,9 +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'; @@ -570,6 +584,32 @@ class Home { String get clfLabel => "HOME_COMMUNAL_LIVING_FACILITIES_LABEL"; } +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 { const AcknowledgementSuccess(); @@ -581,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'; } @@ -688,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'; @@ -732,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'; } @@ -918,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'; @@ -933,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'; @@ -982,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'; } @@ -1021,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/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/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 ca0f302f0f..8f053cd568 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/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, ), diff --git a/apps/health_campaign_field_worker_app/pubspec.lock b/apps/health_campaign_field_worker_app/pubspec.lock index d65cc86d58..08ff95acc7 100644 --- a/apps/health_campaign_field_worker_app/pubspec.lock +++ b/apps/health_campaign_field_worker_app/pubspec.lock @@ -929,6 +929,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: @@ -1637,6 +1646,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: @@ -1808,10 +1825,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 diff --git a/apps/health_campaign_field_worker_app/pubspec.yaml b/apps/health_campaign_field_worker_app/pubspec.yaml index 32889d9e39..b6b2d9f8e3 100644 --- a/apps/health_campaign_field_worker_app/pubspec.yaml +++ b/apps/health_campaign_field_worker_app/pubspec.yaml @@ -70,6 +70,11 @@ dependencies: permission_handler: ^11.3.1 survey_form: ^1.0.1 complaints: ^1.0.2 + flutter_nearby_connections: + git: + url: https://github.com/champeauxr/flutter_nearby_connections + ref: master + percent_indicator: ^4.2.4 dev_dependencies: flutter_test: 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"; } } } 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: