diff --git a/lib/bloc/devices_manager_bloc.dart b/lib/bloc/devices_manager_bloc.dart index 95254d0..f450a17 100644 --- a/lib/bloc/devices_manager_bloc.dart +++ b/lib/bloc/devices_manager_bloc.dart @@ -89,7 +89,7 @@ class DevicesManagerBloc extends BlocBase { if (state != -2) { body = - await apiServices.getOwnerDevieByState({"state": state.toString()}); + await apiServices.getOwnerDeviceByState({"state": state.toString()}); } else { body = await apiServices.getOwnerDevices(); } diff --git a/lib/bloc/home_bloc.dart b/lib/bloc/home_bloc.dart index e0443bb..06a0a28 100644 --- a/lib/bloc/home_bloc.dart +++ b/lib/bloc/home_bloc.dart @@ -5,79 +5,22 @@ import '../feature/home/device_alias_model.dart'; import '../product/base/bloc/base_bloc.dart'; class HomeBloc extends BlocBase { - - final allDevicesAlias = StreamController>.broadcast(); - StreamSink> get sinkAllDevicesAlias => - allDevicesAlias.sink; - Stream> get streamAllDevicesAlias => - allDevicesAlias.stream; - final onlineDevicesAlias = - StreamController>.broadcast(); - StreamSink> get sinkOnlineDevicesAlias => - onlineDevicesAlias.sink; - Stream> get streamOnlineDevicesAlias => - onlineDevicesAlias.stream; + final allDevicesAliasMap = StreamController>>.broadcast(); + StreamSink>> get sinkAllDevicesAliasMap => + allDevicesAliasMap.sink; + Stream>> get streamAllDevicesAliasMap => + allDevicesAliasMap.stream; - final offlineDevicesAlias = - StreamController>.broadcast(); - StreamSink> get sinkOfflineDevicesAlias => - offlineDevicesAlias.sink; - Stream> get streamOfflineDevicesAlias => - offlineDevicesAlias.stream; + final allDevicesAliasJoinedMap = StreamController>>.broadcast(); + StreamSink>> get sinkAllDevicesAliasJoinedMap => + allDevicesAliasJoinedMap.sink; + Stream>> get streamAllDevicesAliasJoinedMap => + allDevicesAliasJoinedMap.stream; - final warningDevicesAlias = - StreamController>.broadcast(); - StreamSink> get sinkWarningDevicesAlias => - warningDevicesAlias.sink; - Stream> get streamWarningDevicesAlias => - warningDevicesAlias.stream; - - final notUseDevicesAlias = - StreamController>.broadcast(); - StreamSink> get sinkNotUseDevicesAlias => - notUseDevicesAlias.sink; - Stream> get streamNotUseDevicesAlias => - notUseDevicesAlias.stream; - - final allDevicesAliasJoined = - StreamController>.broadcast(); - StreamSink> get sinkAllDevicesAliasJoined => - allDevicesAliasJoined.sink; - Stream> get streamAllDevicesAliasJoined => - allDevicesAliasJoined.stream; - - final onlineDevicesAliasJoined = - StreamController>.broadcast(); - StreamSink> get sinkOnlineDevicesAliasJoined => - onlineDevicesAliasJoined.sink; - Stream> get streamOnlineDevicesAliasJoined => - onlineDevicesAliasJoined.stream; - - final offlineDevicesAliasJoined = - StreamController>.broadcast(); - StreamSink> get sinkOfflineDevicesAliasJoined => - offlineDevicesAliasJoined.sink; - Stream> get streamOfflineDevicesAliasJoined => - offlineDevicesAliasJoined.stream; - - final warningDevicesAliasJoined = - StreamController>.broadcast(); - StreamSink> get sinkWarningDevicesAliasJoined => - warningDevicesAliasJoined.sink; - Stream> get streamWarningDevicesAliasJoined => - warningDevicesAliasJoined.stream; - - final notUseDevicesAliasJoined = - StreamController>.broadcast(); - StreamSink> get sinkNotUseDevicesAliasJoined => - notUseDevicesAliasJoined.sink; - Stream> get streamNotUseDevicesAliasJoined => - notUseDevicesAliasJoined.stream; - - final countNotitication = StreamController.broadcast(); - StreamSink get sinkCountNotitication => countNotitication.sink; - Stream get streamCountNotitication => countNotitication.stream; + final countNotification = StreamController.broadcast(); + StreamSink get sinkCountNotification => countNotification.sink; + Stream get streamCountNotification => countNotification.stream; final ownerDevicesStatus = StreamController>>.broadcast(); @@ -86,7 +29,6 @@ class HomeBloc extends BlocBase { Stream>> get streamOwnerDevicesStatus => ownerDevicesStatus.stream; - @override void dispose() {} } diff --git a/lib/feature/auth/login/screen/login_screen.dart b/lib/feature/auth/login/screen/login_screen.dart index 3d2b137..9d541d2 100644 --- a/lib/feature/auth/login/screen/login_screen.dart +++ b/lib/feature/auth/login/screen/login_screen.dart @@ -13,7 +13,7 @@ import '../../../../product/constant/enums/local_keys_enums.dart'; import '../../../../product/services/api_services.dart'; import '../../../../product/shared/shared_snack_bar.dart'; import '../../../../product/constant/icon/icon_constants.dart'; -import '../../../../product/extention/context_extention.dart'; +import '../../../../product/extension/context_extension.dart'; import '../../../../product/constant/image/image_constants.dart'; import '../../../../product/services/language_services.dart'; import '../../../../bloc/login_bloc.dart'; diff --git a/lib/feature/bell/bell_screen.dart b/lib/feature/bell/bell_screen.dart index 5898ed3..d55bead 100644 --- a/lib/feature/bell/bell_screen.dart +++ b/lib/feature/bell/bell_screen.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import '../../product/extention/context_extention.dart'; +import '../../product/extension/context_extension.dart'; import '../../product/services/language_services.dart'; import '../../bloc/bell_bloc.dart'; import '../../product/base/bloc/base_bloc.dart'; diff --git a/lib/feature/device_log/device_logs_screen.dart b/lib/feature/device_log/device_logs_screen.dart index 6f01ee9..1e7bf60 100644 --- a/lib/feature/device_log/device_logs_screen.dart +++ b/lib/feature/device_log/device_logs_screen.dart @@ -7,7 +7,7 @@ import 'widgets/tag_widget.dart'; import '../devices/device_model.dart'; import '../../bloc/device_logs_bloc.dart'; import '../../product/constant/icon/icon_constants.dart'; -import '../../product/extention/context_extention.dart'; +import '../../product/extension/context_extension.dart'; import '../../product/services/language_services.dart'; import '../../product/shared/shared_snack_bar.dart'; import '../../product/utils/date_time_utils.dart'; diff --git a/lib/feature/devices/add_new_device_widget.dart b/lib/feature/devices/add_new_device_widget.dart index a5de72b..9cb9c62 100644 --- a/lib/feature/devices/add_new_device_widget.dart +++ b/lib/feature/devices/add_new_device_widget.dart @@ -7,7 +7,7 @@ import '../../product/constant/enums/role_enums.dart'; import '../../product/services/api_services.dart'; import '../../product/utils/qr_utils.dart'; import '../../product/constant/icon/icon_constants.dart'; -import '../../product/extention/context_extention.dart'; +import '../../product/extension/context_extension.dart'; import '../../product/services/language_services.dart'; addNewDevice(BuildContext context, String role) async { diff --git a/lib/feature/devices/device_detail/device_detail_screen.dart b/lib/feature/devices/device_detail/device_detail_screen.dart index c2b37d0..33e6c92 100644 --- a/lib/feature/devices/device_detail/device_detail_screen.dart +++ b/lib/feature/devices/device_detail/device_detail_screen.dart @@ -2,14 +2,14 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; -import 'package:sfm_app/feature/device_log/device_logs_model.dart'; -import 'package:sfm_app/product/constant/image/image_constants.dart'; -import 'package:sfm_app/product/shared/shared_line_chart.dart'; import 'package:simple_ripple_animation/simple_ripple_animation.dart'; +import 'package:sfm_app/feature/device_log/device_logs_model.dart'; +import '../../../product/constant/image/image_constants.dart'; +import '../../../product/shared/shared_line_chart.dart'; import '../../../product/shared/shared_curve.dart'; import '../device_model.dart'; import '../../../product/base/bloc/base_bloc.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/language_services.dart'; import '../../../product/utils/device_utils.dart'; @@ -18,7 +18,9 @@ import '../../../bloc/device_detail_bloc.dart'; class DetailDeviceScreen extends StatefulWidget { const DetailDeviceScreen({super.key, required this.thingID}); + final String thingID; + @override State createState() => _DetailDeviceScreenState(); } @@ -44,18 +46,29 @@ class _DetailDeviceScreenState extends State { late DetailDeviceBloc detailDeviceBloc; Completer controller = Completer(); - CameraPosition initialCamera = const CameraPosition( - target: LatLng(20.966048511844402, 105.74977710843086), zoom: 15); + CameraPosition initialCamera = + const CameraPosition(target: LatLng(20.966048511844402, 105.74977710843086), zoom: 15); + Timer? getDeviceDetailTimer; + @override void initState() { super.initState(); detailDeviceBloc = BlocProvider.of(context); + const duration = Duration(seconds: 10); + getDeviceDetailTimer = Timer.periodic( + duration, + (Timer t) => detailDeviceBloc.getDeviceDetail( + context, + widget.thingID, + controller, + ), + ); } - TextStyle textstyle = const TextStyle( - fontSize: 25, - fontWeight: FontWeight.w600, - ); + @override + void dispose() { + getDeviceDetailTimer?.cancel(); + } BoxDecoration boxDecoration = BoxDecoration( borderRadius: BorderRadius.circular(15), @@ -105,8 +118,7 @@ class _DetailDeviceScreenState extends State { children: [ Positioned.fill( child: Image.asset( - ImageConstants.instance - .getImage('smoke-detector'), + ImageConstants.instance.getImage('smoke-detector'), fit: BoxFit.fill, ), ), @@ -116,11 +128,9 @@ class _DetailDeviceScreenState extends State { width: 400, // color: Colors.blueAccent, alignment: Alignment.centerRight, - margin: const EdgeInsets.fromLTRB( - 0, 0, 0, 50), + margin: const EdgeInsets.fromLTRB(0, 0, 0, 50), child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const SizedBox(), Text( @@ -146,14 +156,13 @@ class _DetailDeviceScreenState extends State { height: context.dynamicHeight(0.08), width: context.dynamicWidth(0.5), decoration: BoxDecoration( - color: DeviceUtils.instance.getTableRowColor( - deviceSnapshot.data?.state ?? 3), + color: DeviceUtils.instance + .getTableRowColor(deviceSnapshot.data?.state ?? 3), borderRadius: BorderRadius.circular(50), ), alignment: Alignment.bottomCenter, child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, + mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ SizedBox( height: context.mediumValue, @@ -161,18 +170,17 @@ class _DetailDeviceScreenState extends State { child: deviceSnapshot.data?.state == 1 ? RippleAnimation( color: Colors.red, - delay: context - .dynamicMilliSecondDuration( + delay: context.dynamicMilliSecondDuration( 800, ), repeat: true, minRadius: 10, ripplesCount: 5, - duration: context - .dynamicMilliSecondDuration( + duration: context.dynamicMilliSecondDuration( 1800, ), child: CircleAvatar( + backgroundColor: Colors.transparent, minRadius: context.mediumValue, maxRadius: context.mediumValue, backgroundImage: AssetImage( @@ -183,9 +191,8 @@ class _DetailDeviceScreenState extends State { ), ) : CircleAvatar( - backgroundColor: DeviceUtils - .instance - .getTableRowColor( + backgroundColor: + DeviceUtils.instance.getTableRowColor( deviceSnapshot.data?.state ?? 3, ), minRadius: context.mediumValue, @@ -230,12 +237,10 @@ class _DetailDeviceScreenState extends State { child: Padding( padding: context.paddingLow, child: Column( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( appLocalization(context) @@ -254,8 +259,7 @@ class _DetailDeviceScreenState extends State { sensorSnapshot.data!['sensorCsq'], ), size: 30, - color: DeviceUtils.instance - .getSignalIconColor( + color: DeviceUtils.instance.getSignalIconColor( context, sensorSnapshot.data!['sensorCsq'], ), @@ -264,10 +268,8 @@ class _DetailDeviceScreenState extends State { ], ), Row( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( height: context.dynamicHeight(0.09), @@ -275,11 +277,9 @@ class _DetailDeviceScreenState extends State { child: Text( sensorSnapshot.data!['sensorCsq'], style: TextStyle( - color: DeviceUtils.instance - .getSignalIconColor( + color: DeviceUtils.instance.getSignalIconColor( context, - sensorSnapshot - .data!['sensorCsq'], + sensorSnapshot.data!['sensorCsq'], ), fontSize: 40, fontWeight: FontWeight.w900, @@ -299,12 +299,10 @@ class _DetailDeviceScreenState extends State { child: Padding( padding: context.paddingLow, child: Column( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( appLocalization(context) @@ -318,18 +316,14 @@ class _DetailDeviceScreenState extends State { height: context.dynamicWidth(0.12), width: context.dynamicWidth(0.12), child: Image.asset( - DeviceUtils.instance - .getDeviceBatteryImg( + DeviceUtils.instance.getDeviceBatteryImg( int.parse( - sensorSnapshot - .data!['sensorBattery'], + sensorSnapshot.data!['sensorBattery'], ), ), - color: DeviceUtils.instance - .getDeviceBatteryColor( + color: DeviceUtils.instance.getDeviceBatteryColor( int.parse( - sensorSnapshot - .data!['sensorBattery'], + sensorSnapshot.data!['sensorBattery'], ), ), ), @@ -337,23 +331,18 @@ class _DetailDeviceScreenState extends State { ], ), Row( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( height: context.dynamicHeight(0.09), alignment: Alignment.centerLeft, child: Text( - sensorSnapshot - .data!['sensorBattery'], + sensorSnapshot.data!['sensorBattery'], style: TextStyle( - color: DeviceUtils.instance - .getDeviceBatteryColor( + color: DeviceUtils.instance.getDeviceBatteryColor( int.parse( - sensorSnapshot - .data!['sensorBattery'], + sensorSnapshot.data!['sensorBattery'], ), ), fontSize: 50, @@ -371,11 +360,9 @@ class _DetailDeviceScreenState extends State { child: Text( '%', style: TextStyle( - color: DeviceUtils.instance - .getDeviceBatteryColor( + color: DeviceUtils.instance.getDeviceBatteryColor( int.parse( - sensorSnapshot - .data!['sensorBattery'], + sensorSnapshot.data!['sensorBattery'], ), ), fontSize: 30, @@ -403,8 +390,7 @@ class _DetailDeviceScreenState extends State { child: Column( children: [ Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( appLocalization(context) @@ -419,11 +405,9 @@ class _DetailDeviceScreenState extends State { width: context.dynamicWidth(0.12), child: Image.asset( 'assets/icons/temperature.png', - color: DeviceUtils.instance - .getDeviceTempColor( + color: DeviceUtils.instance.getDeviceTempColor( int.parse( - sensorSnapshot - .data!['sensorTemp'], + sensorSnapshot.data!['sensorTemp'], ), ), ), @@ -439,28 +423,20 @@ class _DetailDeviceScreenState extends State { width: double.infinity, height: 20, decoration: BoxDecoration( - color: Colors.grey - .withValues(alpha: 0.3), - borderRadius: - BorderRadius.circular(10), + color: Colors.grey.withValues(alpha: 0.3), + borderRadius: BorderRadius.circular(10), ), ), LayoutBuilder( - builder: (context, constraints) => - Container( + builder: (context, constraints) => Container( width: constraints.maxWidth * - (int.parse(sensorSnapshot - .data!['sensorTemp']) / - 75), + (int.parse(sensorSnapshot.data!['sensorTemp']) / 75), height: 20, decoration: BoxDecoration( - color: DeviceUtils.instance - .getDeviceTempColor( - int.parse(sensorSnapshot - .data!['sensorTemp']), + color: DeviceUtils.instance.getDeviceTempColor( + int.parse(sensorSnapshot.data!['sensorTemp']), ), - borderRadius: - BorderRadius.circular(10), + borderRadius: BorderRadius.circular(10), ), ), ) @@ -470,17 +446,14 @@ class _DetailDeviceScreenState extends State { height: 5, ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "${sensorSnapshot.data!['sensorTemp']} °C", style: TextStyle( - color: DeviceUtils.instance - .getDeviceTempColor( + color: DeviceUtils.instance.getDeviceTempColor( int.parse( - sensorSnapshot - .data!['sensorTemp'], + sensorSnapshot.data!['sensorTemp'], ), ), fontSize: 30, @@ -507,8 +480,7 @@ class _DetailDeviceScreenState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - appLocalization(context) - .paginated_data_table_column_devicePower, + appLocalization(context).paginated_data_table_column_devicePower, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, @@ -532,8 +504,7 @@ class _DetailDeviceScreenState extends State { stream: detailDeviceBloc.streamSensorTemps, builder: (context, sensorTempsSnapshot) { if (sensorTempsSnapshot.data == null) { - detailDeviceBloc - .getNearerSensorValue(widget.thingID); + detailDeviceBloc.getNearerSensorValue(widget.thingID); return const AspectRatio( aspectRatio: 3, child: Center( @@ -552,8 +523,7 @@ class _DetailDeviceScreenState extends State { child: Container( margin: context.paddingLow, child: sharedLineChart( - appLocalization(context) - .detail_device_volt_message, + appLocalization(context).detail_device_volt_message, sensorTempsSnapshot.data ?? [], ), ), @@ -580,48 +550,33 @@ class _DetailDeviceScreenState extends State { Radius.circular(15), ), ), - child: deviceSnapshot - .data!.settings!.latitude != - "" + child: deviceSnapshot.data!.settings!.latitude != "" ? StreamBuilder( - stream: detailDeviceBloc - .streamDeviceLocation, + stream: detailDeviceBloc.streamDeviceLocation, builder: (context, locationSnapshot) { if (locationSnapshot.data == null) { detailDeviceBloc.findLocation( - context, - deviceSnapshot - .data!.areaPath!); + context, deviceSnapshot.data!.areaPath!); } return GoogleMap( - initialCameraPosition: - initialCamera, + initialCameraPosition: initialCamera, mapType: MapType.normal, markers: { Marker( infoWindow: InfoWindow( - title: - locationSnapshot.data ?? - "", + title: locationSnapshot.data ?? "", ), - markerId: MarkerId( - deviceSnapshot - .data!.thingId!), + markerId: MarkerId(deviceSnapshot.data!.thingId!), position: LatLng( - double.parse(deviceSnapshot - .data! - .settings! - .latitude!), - double.parse(deviceSnapshot - .data! - .settings! - .longitude!), + double.parse( + deviceSnapshot.data!.settings!.latitude!), + double.parse( + deviceSnapshot.data!.settings!.longitude!), ), ), }, onMapCreated: (mapcontroller) { - controller - .complete(mapcontroller); + controller.complete(mapcontroller); }, mapToolbarEnabled: false, zoomControlsEnabled: false, @@ -636,8 +591,7 @@ class _DetailDeviceScreenState extends State { ), ), Text( - appLocalization(context) - .device_update_location, + appLocalization(context).device_update_location, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, diff --git a/lib/feature/devices/device_update/device_update_screen.dart b/lib/feature/devices/device_update/device_update_screen.dart index 3cb76dc..a0ea706 100644 --- a/lib/feature/devices/device_update/device_update_screen.dart +++ b/lib/feature/devices/device_update/device_update_screen.dart @@ -5,7 +5,7 @@ import '../device_model.dart'; import '../../../bloc/device_update_bloc.dart'; import 'map_dialog.dart'; import '../../../product/base/bloc/base_bloc.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/api_services.dart'; import '../../../product/services/language_services.dart'; diff --git a/lib/feature/devices/device_update/map_dialog.dart b/lib/feature/devices/device_update/map_dialog.dart index 4405e2d..5b4d740 100644 --- a/lib/feature/devices/device_update/map_dialog.dart +++ b/lib/feature/devices/device_update/map_dialog.dart @@ -7,7 +7,7 @@ import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart' ; import '../../../bloc/device_update_bloc.dart'; import '../../../product/constant/app/app_constants.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/language_services.dart'; import '../../../product/shared/find_location_maps/shared_map_search_location.dart'; diff --git a/lib/feature/devices/devices_manager_screen.dart b/lib/feature/devices/devices_manager_screen.dart index d71b3c5..6640698 100644 --- a/lib/feature/devices/devices_manager_screen.dart +++ b/lib/feature/devices/devices_manager_screen.dart @@ -13,7 +13,7 @@ import '../../product/base/bloc/base_bloc.dart'; import '../../product/constant/enums/app_route_enums.dart'; import '../../product/constant/enums/role_enums.dart'; import '../../product/constant/icon/icon_constants.dart'; -import '../../product/extention/context_extention.dart'; +import '../../product/extension/context_extension.dart'; import '../../product/services/api_services.dart'; import '../../product/services/language_services.dart'; import '../../product/utils/device_utils.dart'; diff --git a/lib/feature/home/home_screen.dart b/lib/feature/home/home_screen.dart index b47aba7..554820b 100644 --- a/lib/feature/home/home_screen.dart +++ b/lib/feature/home/home_screen.dart @@ -9,7 +9,7 @@ import '../../product/utils/device_utils.dart'; import 'device_alias_model.dart'; import 'shared/overview_card.dart'; import '../settings/device_notification_settings/device_notification_settings_model.dart'; -import '../../product/extention/context_extention.dart'; +import '../../product/extension/context_extension.dart'; import '../../product/services/api_services.dart'; import '../../product/services/language_services.dart'; import '../../bloc/home_bloc.dart'; @@ -25,18 +25,9 @@ class HomeScreen extends StatefulWidget { class _HomeScreenState extends State { late HomeBloc homeBloc; APIServices apiServices = APIServices(); + Map> allDevicesAliasMap = {}; + Map> allDevicesAliasJoinedMap = {}; List devices = []; - List allDevicesAlias = []; - List onlineDevicesAlias = []; - List offlineDevicesAlias = []; - List warningDevicesAlias = []; - List notUseDevicesAlias = []; - - List allDevicesAliasJoined = []; - List onlineDevicesAliasJoined = []; - List offlineDevicesAliasJoined = []; - List warningDevicesAliasJoined = []; - List notUseDevicesAliasJoined = []; bool isFunctionCall = false; Timer? getAllDevicesTimer; int notificationCount = 0; @@ -49,8 +40,7 @@ class _HomeScreenState extends State { homeBloc = BlocProvider.of(context); getOwnerAndJoinedDevices(); const duration = Duration(seconds: 10); - getAllDevicesTimer = - Timer.periodic(duration, (Timer t) => getOwnerAndJoinedDevices()); + getAllDevicesTimer = Timer.periodic(duration, (Timer t) => getOwnerAndJoinedDevices()); } @override @@ -75,7 +65,7 @@ class _HomeScreenState extends State { ), SizedBox(width: context.lowValue), StreamBuilder( - stream: homeBloc.streamCountNotitication, + stream: homeBloc.streamCountNotification, builder: (context, countSnapshot) { return Text( "(${countSnapshot.data ?? 0})", @@ -91,8 +81,7 @@ class _HomeScreenState extends State { child: StreamBuilder>>( stream: homeBloc.streamOwnerDevicesStatus, builder: (context, snapshot) { - if (snapshot.data?['state'] != null || - snapshot.data?['battery'] != null) { + if (snapshot.data?['state'] != null || snapshot.data?['battery'] != null) { return Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, @@ -101,8 +90,7 @@ class _HomeScreenState extends State { ...snapshot.data!['state']! .map( (item) => FutureBuilder( - future: warningCard( - context, apiServices, item), + future: warningCard(context, apiServices, item), builder: (context, warningCardSnapshot) { if (warningCardSnapshot.hasData) { return ConstrainedBox( @@ -124,11 +112,7 @@ class _HomeScreenState extends State { .map( (batteryItem) => FutureBuilder( future: notificationCard( - context, - "lowBattery", - "Cảnh báo pin yếu", - batteryItem - ), + context, "lowBattery", appLocalization(context).low_battery_message, batteryItem), builder: (context, warningCardSnapshot) { if (warningCardSnapshot.hasData) { return ConstrainedBox( @@ -160,8 +144,7 @@ class _HomeScreenState extends State { ), SizedBox(width: context.lowValue), Text( - appLocalization(context) - .notification_description, + appLocalization(context).notification_description, maxLines: 2, overflow: TextOverflow.ellipsis, softWrap: true, @@ -176,85 +159,47 @@ class _HomeScreenState extends State { ), ), ), - StreamBuilder>( - stream: homeBloc.streamAllDevicesAlias, - initialData: allDevicesAlias, - builder: (context, allDeviceSnapshot) { - return StreamBuilder>( - stream: homeBloc.streamOnlineDevicesAlias, - initialData: onlineDevicesAlias, - builder: (context, onlineDeviceSnapshot) { - return StreamBuilder>( - stream: homeBloc.streamOfflineDevicesAlias, - initialData: offlineDevicesAlias, - builder: (context, deviceDashboardSnapshot) { - return StreamBuilder>( - stream: homeBloc.streamWarningDevicesAlias, - initialData: warningDevicesAlias, - builder: (context, warningDeviceSnapshot) { - return StreamBuilder>( - stream: homeBloc.streamNotUseDevicesAlias, - initialData: notUseDevicesAlias, - builder: (context, notUseSnapshot) { - return OverviewCard( - isOwner: true, - total: allDeviceSnapshot.data!.length, - active: onlineDeviceSnapshot.data!.length, - inactive: - deviceDashboardSnapshot.data!.length, - warning: warningDeviceSnapshot.data!.length, - unused: notUseSnapshot.data!.length, - ); - }, - ); - }, - ); - }, - ); - }, - ); - }, - ), + StreamBuilder>>( + stream: homeBloc.streamAllDevicesAliasMap, + builder: (context, allDevicesAliasMapSnapshot) { + if (!allDevicesAliasMapSnapshot.hasData || + allDevicesAliasMapSnapshot.data == null) { + return const Center(child: CircularProgressIndicator()); + } + final data = allDevicesAliasMapSnapshot.data!; + return OverviewCard( + isOwner: true, + total: data['all']?.length ?? 0, + active: data['online']?.length ?? 0, + inactive: data['offline']?.length ?? 0, + warning: data['warn']?.length ?? 0, + unused: data['not-use']?.length ?? 0); + }), SizedBox(height: context.lowValue), - StreamBuilder>( - stream: homeBloc.streamAllDevicesAliasJoined, - initialData: allDevicesAliasJoined, - builder: (context, allDeviceSnapshot) { - if (allDeviceSnapshot.data?.isEmpty ?? true) { + StreamBuilder>>( + stream: homeBloc.streamAllDevicesAliasJoinedMap, + builder: (context, allDevicesAliasJoinedMapSnapshot) { + if (!allDevicesAliasJoinedMapSnapshot.hasData || + allDevicesAliasJoinedMapSnapshot.data == null) { + return const Center(child: CircularProgressIndicator()); + } + final data = allDevicesAliasJoinedMapSnapshot.data!; + final total = data['all']?.length ?? 0; + final active = data['online']?.length ?? 0; + final inactive = data['offline']?.length ?? 0; + final warning = data['warn']?.length ?? 0; + final unused = data['not-use']?.length ?? 0; + + if (total == 0 && active == 0 && inactive == 0 && warning == 0 && unused == 0) { return const SizedBox.shrink(); } - return StreamBuilder>( - stream: homeBloc.streamOnlineDevicesAliasJoined, - initialData: onlineDevicesAliasJoined, - builder: (context, onlineDeviceSnapshot) { - return StreamBuilder>( - stream: homeBloc.streamOfflineDevicesAliasJoined, - initialData: offlineDevicesAliasJoined, - builder: (context, deviceDashboardSnapshot) { - return StreamBuilder>( - stream: homeBloc.streamWarningDevicesAliasJoined, - initialData: warningDevicesAliasJoined, - builder: (context, warningDeviceSnapshot) { - return StreamBuilder>( - stream: homeBloc.streamNotUseDevicesAliasJoined, - initialData: notUseDevicesAliasJoined, - builder: (context, notUseSnapshot) { - return OverviewCard( - isOwner: false, - total: allDeviceSnapshot.data!.length, - active: onlineDeviceSnapshot.data!.length, - inactive: - deviceDashboardSnapshot.data!.length, - warning: warningDeviceSnapshot.data!.length, - unused: notUseSnapshot.data!.length, - ); - }, - ); - }, - ); - }, - ); - }, + return OverviewCard( + isOwner: false, + total: total, + active: active, + inactive: inactive, + warning: warning, + unused: unused, ); }, ), @@ -271,8 +216,8 @@ class _HomeScreenState extends State { List result = data["items"]; devices = DeviceWithAlias.fromJsonDynamicList(result); getOwnerDeviceState(devices); - getDevicesStatusAlias(devices); - checkSettingdevice(devices); + checkSettingDevice(devices); + getDeviceStatusAliasMap(devices); } void getOwnerDeviceState(List allDevices) async { @@ -282,23 +227,21 @@ class _HomeScreenState extends State { ownerDevices.add(device); } } - if (ownerDevicesState.isEmpty || - ownerDevicesState.length < devices.length) { + if (ownerDevicesState.isEmpty || ownerDevicesState.length < devices.length) { ownerDevicesState.clear(); ownerDevicesStatus.clear(); homeBloc.sinkOwnerDevicesStatus.add(ownerDevicesStatus); int count = 0; for (var device in ownerDevices) { - Map sensorMap = DeviceUtils.instance - .getDeviceSensors(context, device.status?.sensors ?? []); + Map sensorMap = + DeviceUtils.instance.getDeviceSensors(context, device.status?.sensors ?? []); if (device.state == 1 || device.state == 3) { ownerDevicesStatus["state"] ??= []; ownerDevicesStatus["state"]!.add(device); homeBloc.sinkOwnerDevicesStatus.add(ownerDevicesStatus); count++; } - if (sensorMap['sensorBattery'] != - appLocalization(context).no_data_message) { + if (sensorMap['sensorBattery'] != appLocalization(context).no_data_message) { if (double.parse(sensorMap['sensorBattery']) <= 20) { ownerDevicesStatus['battery'] ??= []; ownerDevicesStatus['battery']!.add(device); @@ -307,63 +250,61 @@ class _HomeScreenState extends State { } } notificationCount = count; - homeBloc.sinkCountNotitication.add(notificationCount); + homeBloc.sinkCountNotification.add(notificationCount); } } } - void getDevicesStatusAlias(List devices) async { - clearAllDeviceStatusAlias(); + void getDeviceStatusAliasMap(List devices) { + allDevicesAliasMap.clear(); + allDevicesAliasJoinedMap.clear(); + + for (var key in ['all', 'online', 'offline', 'warning', 'not-use']) { + allDevicesAliasMap[key] = []; + allDevicesAliasJoinedMap[key] = []; + } + for (DeviceWithAlias device in devices) { if (device.isOwner == true) { - allDevicesAlias.add(device); - if (device.state! == 0 || device.state! == 1) { - onlineDevicesAlias.add(device); - homeBloc.sinkOnlineDevicesAlias.add(onlineDevicesAlias); + allDevicesAliasMap['all']!.add(device); + if (device.state == 0 || device.state == 1) { + allDevicesAliasMap['online']!.add(device); } - if (device.state! == -1) { - offlineDevicesAlias.add(device); - homeBloc.sinkOfflineDevicesAlias.add(offlineDevicesAlias); + if (device.state == -1) { + allDevicesAliasMap['offline']!.add(device); } - if (device.state! == 1) { - warningDevicesAlias.add(device); - homeBloc.sinkWarningDevicesAlias.add(warningDevicesAlias); + if (device.state == 1) { + allDevicesAliasMap['warning']!.add(device); } - if (device.state! == -2) { - notUseDevicesAlias.add(device); - homeBloc.sinkNotUseDevicesAlias.add(notUseDevicesAlias); + if (device.state == -2) { + allDevicesAliasMap['not-use']!.add(device); } } else { - allDevicesAliasJoined.add(device); - if (device.state! == 0 || device.state! == 1) { - onlineDevicesAliasJoined.add(device); - homeBloc.sinkOnlineDevicesAliasJoined.add(onlineDevicesAliasJoined); + allDevicesAliasJoinedMap['all']!.add(device); + if (device.state == 0 || device.state == 1) { + allDevicesAliasJoinedMap['online']!.add(device); } - if (device.state! == -1) { - offlineDevicesAliasJoined.add(device); - homeBloc.sinkOfflineDevicesAliasJoined.add(offlineDevicesAliasJoined); + if (device.state == -1) { + allDevicesAliasJoinedMap['offline']!.add(device); } - if (device.state! == 1) { - warningDevicesAliasJoined.add(device); - homeBloc.sinkWarningDevicesAliasJoined.add(warningDevicesAliasJoined); + if (device.state == 1) { + allDevicesAliasJoinedMap['warning']!.add(device); } - if (device.state! == -2) { - notUseDevicesAliasJoined.add(device); - homeBloc.sinkNotUseDevicesAliasJoined.add(notUseDevicesAliasJoined); + if (device.state == -2) { + allDevicesAliasJoinedMap['not-use']!.add(device); } } } - // checkSettingdevice(allDevicesAliasJoined); - homeBloc.sinkAllDevicesAlias.add(allDevicesAlias); - homeBloc.sinkAllDevicesAliasJoined.add(allDevicesAliasJoined); + + homeBloc.sinkAllDevicesAliasMap.add(allDevicesAliasMap); + homeBloc.sinkAllDevicesAliasJoinedMap.add(allDevicesAliasJoinedMap); } - void checkSettingdevice(List devices) async { + void checkSettingDevice(List devices) async { if (isFunctionCall) { log("Ham check setting da duoc goi"); } else { - String? response = - await apiServices.getAllSettingsNotificationOfDevices(); + String? response = await apiServices.getAllSettingsNotificationOfDevices(); if (response != "") { final data = jsonDecode(response); final result = data['data']; @@ -371,13 +312,11 @@ class _HomeScreenState extends State { List list = DeviceNotificationSettings.mapFromJson(result).values.toList(); // log("List: $list"); - Set thingIdsInList = - list.map((device) => device.thingId!).toSet(); + Set thingIdsInList = list.map((device) => device.thingId!).toSet(); for (var device in devices) { if (!thingIdsInList.contains(device.thingId)) { log("Device with Thing ID ${device.thingId} is not in the notification settings list."); - await apiServices.setupDeviceNotification( - device.thingId!, device.name!); + await apiServices.setupDeviceNotification(device.thingId!, device.name!); } else { log("All devices are in the notification settings list."); } @@ -388,27 +327,4 @@ class _HomeScreenState extends State { } isFunctionCall = true; } - - void clearAllDeviceStatusAlias() { - allDevicesAlias.clear(); - homeBloc.sinkAllDevicesAlias.add(allDevicesAlias); - onlineDevicesAlias.clear(); - homeBloc.sinkOnlineDevicesAlias.add(onlineDevicesAlias); - offlineDevicesAlias.clear(); - homeBloc.sinkOfflineDevicesAlias.add(offlineDevicesAlias); - warningDevicesAlias.clear(); - homeBloc.sinkWarningDevicesAlias.add(warningDevicesAlias); - notUseDevicesAlias.clear(); - homeBloc.sinkNotUseDevicesAlias.add(notUseDevicesAlias); - allDevicesAliasJoined.clear(); - homeBloc.sinkAllDevicesAliasJoined.add(allDevicesAliasJoined); - onlineDevicesAliasJoined.clear(); - homeBloc.sinkOnlineDevicesAliasJoined.add(onlineDevicesAliasJoined); - offlineDevicesAliasJoined.clear(); - homeBloc.sinkOfflineDevicesAliasJoined.add(offlineDevicesAliasJoined); - warningDevicesAliasJoined.clear(); - homeBloc.sinkWarningDevicesAliasJoined.add(warningDevicesAliasJoined); - notUseDevicesAliasJoined.clear(); - homeBloc.sinkNotUseDevicesAliasJoined.add(notUseDevicesAliasJoined); - } } diff --git a/lib/feature/home/shared/alert_card.dart b/lib/feature/home/shared/alert_card.dart index 7615cf4..a35501f 100644 --- a/lib/feature/home/shared/alert_card.dart +++ b/lib/feature/home/shared/alert_card.dart @@ -6,7 +6,7 @@ import 'package:intl/intl.dart'; import 'package:sfm_app/feature/home/device_alias_model.dart'; import '../../../product/constant/enums/app_route_enums.dart'; import '../../../product/constant/image/image_constants.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/language_services.dart'; import '../../../product/utils/device_utils.dart'; diff --git a/lib/feature/home/shared/overview_card.dart b/lib/feature/home/shared/overview_card.dart index dfa68ad..8d00c70 100644 --- a/lib/feature/home/shared/overview_card.dart +++ b/lib/feature/home/shared/overview_card.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:sfm_app/feature/home/shared/status_card.dart'; -import 'package:sfm_app/product/extention/context_extention.dart'; -import 'package:sfm_app/product/services/language_services.dart'; +import 'status_card.dart'; +import '../../../product/extension/context_extension.dart'; +import '../../../product/services/language_services.dart'; class OverviewCard extends StatelessWidget { final bool isOwner; diff --git a/lib/feature/home/shared/warning_card.dart b/lib/feature/home/shared/warning_card.dart index 60cbda7..6b552b4 100644 --- a/lib/feature/home/shared/warning_card.dart +++ b/lib/feature/home/shared/warning_card.dart @@ -7,7 +7,7 @@ import 'package:badges/badges.dart' as badges; import '../device_alias_model.dart'; import '../../../product/constant/icon/icon_constants.dart'; import '../../../product/constant/image/image_constants.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/api_services.dart'; import '../../../product/services/language_services.dart'; import '../../../product/utils/device_utils.dart'; diff --git a/lib/feature/inter_family/group_detail/group_detail_screen.dart b/lib/feature/inter_family/group_detail/group_detail_screen.dart index 7e57068..80f788a 100644 --- a/lib/feature/inter_family/group_detail/group_detail_screen.dart +++ b/lib/feature/inter_family/group_detail/group_detail_screen.dart @@ -1,12 +1,14 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:async'; + import 'package:flutter/material.dart'; import '../../../bloc/group_detail_bloc.dart'; import 'group_detail_model.dart'; import '../../../product/base/bloc/base_bloc.dart'; import '../../../product/constant/app/app_constants.dart'; import '../../../product/constant/icon/icon_constants.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/api_services.dart'; import '../../../product/services/language_services.dart'; import '../../../product/utils/device_utils.dart'; @@ -25,10 +27,22 @@ class DetailGroupScreen extends StatefulWidget { class _DetailGroupScreenState extends State { late DetailGroupBloc detailGroupBloc; final scaffoldKey = GlobalKey(); + Timer? getGroupDetailTimer; @override void initState() { super.initState(); detailGroupBloc = BlocProvider.of(context); + const duration = Duration(seconds: 10); + getGroupDetailTimer = Timer.periodic( + duration, + (Timer t) => detailGroupBloc.getGroupDetail(widget.group), + ); + } + + + @override + void dispose() { + getGroupDetailTimer?.cancel(); } @override diff --git a/lib/feature/inter_family/groups/groups_screen.dart b/lib/feature/inter_family/groups/groups_screen.dart index 40e05ed..008d2e5 100644 --- a/lib/feature/inter_family/groups/groups_screen.dart +++ b/lib/feature/inter_family/groups/groups_screen.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -10,26 +12,38 @@ import '../inter_family_widget.dart'; import '../../../product/base/bloc/base_bloc.dart'; import '../../../product/constant/app/app_constants.dart'; import '../../../product/constant/icon/icon_constants.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/language_services.dart'; import 'groups_widget.dart'; class GroupsScreen extends StatefulWidget { const GroupsScreen({super.key, required this.role}); + final String role; + @override State createState() => _GroupsScreenState(); } class _GroupsScreenState extends State { late InterFamilyBloc interFamilyBloc; + Timer? getAllGroupsTimer; @override void initState() { super.initState(); interFamilyBloc = BlocProvider.of(context); - // interFamilyBloc.getAllGroup(widget.role); + const duration = Duration(seconds: 10); + getAllGroupsTimer = Timer.periodic( + duration, + (Timer t) => interFamilyBloc.getAllGroup(widget.role), + ); + } + + @override + void dispose() { + getAllGroupsTimer?.cancel(); } @override @@ -51,56 +65,44 @@ class _GroupsScreenState extends State { return ListTile( onTap: () { context.pushNamed(AppRoutes.GROUP_DETAIL.name, - pathParameters: { - "groupId": groupsSnapshot.data![index].id! - }, + pathParameters: {"groupId": groupsSnapshot.data![index].id!}, extra: widget.role); }, - leading: IconConstants.instance - .getMaterialIcon(Icons.diversity_2), + leading: IconConstants.instance.getMaterialIcon(Icons.diversity_2), title: Text( groupsSnapshot.data![index].name ?? '', style: const TextStyle(fontWeight: FontWeight.bold), ), - subtitle: - Text(groupsSnapshot.data![index].description ?? ""), - trailing: - widget.role == ApplicationConstants.OWNER_GROUP - ? PopupMenuButton( - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(8.0), - bottomRight: Radius.circular(8.0), - topLeft: Radius.circular(8.0), - topRight: Radius.circular(8.0), - ), - ), - itemBuilder: (ctx) => [ - _buildPopupMenuItem( - groupsSnapshot.data![index], - context, - appLocalization(context) - .share_group_title, - Icons.share, - 4), - _buildPopupMenuItem( - groupsSnapshot.data![index], - context, - appLocalization(context) - .change_group_infomation_title, - Icons.settings_backup_restore, - 2), - _buildPopupMenuItem( - groupsSnapshot.data![index], - context, - appLocalization(context) - .delete_group_title, - Icons.delete_forever_rounded, - 3), - ], - icon: const Icon(Icons.more_horiz), - ) - : const SizedBox.shrink(), + subtitle: Text(groupsSnapshot.data![index].description ?? ""), + trailing: widget.role == ApplicationConstants.OWNER_GROUP + ? PopupMenuButton( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(8.0), + bottomRight: Radius.circular(8.0), + topLeft: Radius.circular(8.0), + topRight: Radius.circular(8.0), + ), + ), + itemBuilder: (ctx) => [ + _buildPopupMenuItem(groupsSnapshot.data![index], context, + appLocalization(context).share_group_title, Icons.share, 4), + _buildPopupMenuItem( + groupsSnapshot.data![index], + context, + appLocalization(context).change_group_infomation_title, + Icons.settings_backup_restore, + 2), + _buildPopupMenuItem( + groupsSnapshot.data![index], + context, + appLocalization(context).delete_group_title, + Icons.delete_forever_rounded, + 3), + ], + icon: const Icon(Icons.more_horiz), + ) + : const SizedBox.shrink(), ); }, ), @@ -112,16 +114,15 @@ class _GroupsScreenState extends State { } } - PopupMenuItem _buildPopupMenuItem(Group group, BuildContext context, - String title, IconData iconData, int position) { + PopupMenuItem _buildPopupMenuItem( + Group group, BuildContext context, String title, IconData iconData, int position) { return PopupMenuItem( onTap: () { if (title == appLocalization(context).share_group_title) { Future.delayed(context.lowDuration, () { shareGroup(context, group); }); - } else if (title == - appLocalization(context).change_group_infomation_title) { + } else if (title == appLocalization(context).change_group_infomation_title) { Future.delayed(context.lowDuration, () { createOrJoinGroupDialog( context, diff --git a/lib/feature/inter_family/groups/groups_widget.dart b/lib/feature/inter_family/groups/groups_widget.dart index baa0a4f..a45c7df 100644 --- a/lib/feature/inter_family/groups/groups_widget.dart +++ b/lib/feature/inter_family/groups/groups_widget.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:qr_flutter/qr_flutter.dart'; import '../../../bloc/inter_family_bloc.dart'; import '../../../product/constant/icon/icon_constants.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/language_services.dart'; import 'groups_model.dart'; diff --git a/lib/feature/inter_family/inter_family_screen.dart b/lib/feature/inter_family/inter_family_screen.dart index eeb6751..646ef10 100644 --- a/lib/feature/inter_family/inter_family_screen.dart +++ b/lib/feature/inter_family/inter_family_screen.dart @@ -6,7 +6,7 @@ import 'inter_family_widget.dart'; import '../../product/base/bloc/base_bloc.dart'; import '../../product/constant/app/app_constants.dart'; import '../../product/constant/icon/icon_constants.dart'; -import '../../product/extention/context_extention.dart'; +import '../../product/extension/context_extension.dart'; import '../../product/services/language_services.dart'; class InterFamilyScreen extends StatefulWidget { diff --git a/lib/feature/main/main_screen.dart b/lib/feature/main/main_screen.dart index cd72e95..a4cbc12 100644 --- a/lib/feature/main/main_screen.dart +++ b/lib/feature/main/main_screen.dart @@ -5,13 +5,11 @@ import 'dart:developer'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -// import 'package:persistent_bottom_nav_bar_v2/persistent-tab-view.dart'; import 'package:badges/badges.dart' as badges; import 'package:persistent_bottom_nav_bar/persistent_bottom_nav_bar.dart'; -import 'package:sfm_app/feature/sound_notification_test/notification_screen.dart'; -import 'package:sfm_app/product/permission/notification_permission.dart'; +import '../../product/permission/notification_permission.dart'; import '../settings/profile/profile_model.dart'; -import '../../product/extention/context_extention.dart'; +import '../../product/extension/context_extension.dart'; import '../../bloc/home_bloc.dart'; import '../../product/constant/app/app_constants.dart'; import '../../product/constant/enums/app_route_enums.dart'; @@ -35,7 +33,6 @@ import '../../product/constant/icon/icon_constants.dart'; import '../../product/constant/lang/language_constants.dart'; import '../../product/services/language_services.dart'; import '../bell/bell_model.dart'; -import '../sound_notification_test/notification_bloc.dart'; class MainScreen extends StatefulWidget { const MainScreen({super.key}); @@ -192,6 +189,7 @@ class _MainScreenState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { + return StreamBuilder( stream: mainBloc.streamThemeMode, initialData: isLight, @@ -344,7 +342,7 @@ class _MainScreenState extends State with WidgetsBindingObserver { controller: controller, screens: _buildScreens(), items: _navBarsItems(), - handleAndroidBackButtonPress: false, + handleAndroidBackButtonPress: true, resizeToAvoidBottomInset: true, stateManagement: true, backgroundColor: diff --git a/lib/feature/map/widget/on_tap_marker_widget.dart b/lib/feature/map/widget/on_tap_marker_widget.dart index b5a8418..45c5a31 100644 --- a/lib/feature/map/widget/on_tap_marker_widget.dart +++ b/lib/feature/map/widget/on_tap_marker_widget.dart @@ -6,7 +6,7 @@ import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'show_direction_widget.dart'; import 'show_nearest_place.dart'; import '../../../product/constant/icon/icon_constants.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../bloc/map_bloc.dart'; import '../../../product/services/api_services.dart'; import '../../../product/services/language_services.dart'; diff --git a/lib/feature/map/widget/show_direction_widget.dart b/lib/feature/map/widget/show_direction_widget.dart index be120f1..e2bf828 100644 --- a/lib/feature/map/widget/show_direction_widget.dart +++ b/lib/feature/map/widget/show_direction_widget.dart @@ -3,9 +3,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:maps_launcher/maps_launcher.dart'; -import 'package:sfm_app/product/constant/icon/icon_constants.dart'; -import 'package:sfm_app/product/extention/context_extention.dart'; -import 'package:sfm_app/product/services/language_services.dart'; +import '../../../product/constant/icon/icon_constants.dart'; +import '../../../product/extension/context_extension.dart'; +import '../../../product/services/language_services.dart'; import '../../../bloc/map_bloc.dart'; diff --git a/lib/feature/map/widget/show_nearest_place.dart b/lib/feature/map/widget/show_nearest_place.dart index 2db0ec9..9038c81 100644 --- a/lib/feature/map/widget/show_nearest_place.dart +++ b/lib/feature/map/widget/show_nearest_place.dart @@ -7,7 +7,7 @@ import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../../../bloc/map_bloc.dart'; import 'show_direction_widget.dart'; import '../../../product/constant/icon/icon_constants.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/language_services.dart'; import '../../../product/services/map_services.dart'; import '../../../product/shared/model/near_by_search_model.dart'; diff --git a/lib/feature/settings/device_notification_settings/device_notification_settings_screen.dart b/lib/feature/settings/device_notification_settings/device_notification_settings_screen.dart index 742c0ec..a64e340 100644 --- a/lib/feature/settings/device_notification_settings/device_notification_settings_screen.dart +++ b/lib/feature/settings/device_notification_settings/device_notification_settings_screen.dart @@ -7,7 +7,7 @@ import '../../../product/shared/shared_snack_bar.dart'; import '../../../bloc/device_notification_settings_bloc.dart'; import 'device_notification_settings_model.dart'; import '../../../product/base/bloc/base_bloc.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/api_services.dart'; import '../../../product/services/language_services.dart'; diff --git a/lib/feature/settings/profile/profile_screen.dart b/lib/feature/settings/profile/profile_screen.dart index f46d305..12b95dd 100644 --- a/lib/feature/settings/profile/profile_screen.dart +++ b/lib/feature/settings/profile/profile_screen.dart @@ -6,7 +6,7 @@ import '../../../product/constant/icon/icon_constants.dart'; import '../../../product/services/api_services.dart'; import '../../../bloc/settings_bloc.dart'; import '../../../product/shared/shared_input_decoration.dart'; -import '../../../product/extention/context_extention.dart'; +import '../../../product/extension/context_extension.dart'; import '../../../product/services/language_services.dart'; import 'profile_model.dart'; diff --git a/lib/feature/settings/settings_screen.dart b/lib/feature/settings/settings_screen.dart index 853c40a..f5245d8 100644 --- a/lib/feature/settings/settings_screen.dart +++ b/lib/feature/settings/settings_screen.dart @@ -5,7 +5,7 @@ import 'package:go_router/go_router.dart'; import '../../product/constant/app/app_constants.dart'; import 'profile/profile_screen.dart'; import '../../product/constant/icon/icon_constants.dart'; -import '../../product/extention/context_extention.dart'; +import '../../product/extension/context_extension.dart'; import '../../product/services/api_services.dart'; import 'profile/profile_model.dart'; import '../../bloc/settings_bloc.dart'; diff --git a/lib/feature/sound_notification_test/notification_bloc.dart b/lib/feature/sound_notification_test/notification_bloc.dart deleted file mode 100644 index 8252afb..0000000 --- a/lib/feature/sound_notification_test/notification_bloc.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:sfm_app/product/base/bloc/base_bloc.dart'; - -class NotificationBloc extends BlocBase{ - - - @override - void dispose() { - // TODO: implement dispose - } - -} \ No newline at end of file diff --git a/lib/feature/sound_notification_test/notification_screen.dart b/lib/feature/sound_notification_test/notification_screen.dart deleted file mode 100644 index 7f26492..0000000 --- a/lib/feature/sound_notification_test/notification_screen.dart +++ /dev/null @@ -1,77 +0,0 @@ -// ignore_for_file: avoid_print - -import 'dart:math' as math; -import 'dart:developer' as dev; - -import 'package:flutter/material.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'notification_bloc.dart'; -import '../../product/base/bloc/base_bloc.dart'; -import '../../product/services/notification_services.dart'; - -class NotificationScreen extends StatefulWidget { - const NotificationScreen({super.key}); - - @override - State createState() => _NotificationScreenState(); -} - -class _NotificationScreenState extends State { - late NotificationBloc notificationBloc; - final notificationPlugin = FlutterLocalNotificationsPlugin(); - - @override - void initState() { - super.initState(); - initNotification(); - notificationBloc = BlocProvider.of(context); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - TextButton( - onPressed: () async { - showNewAlarmSoundNotification("warning_alarm"); - dev.log("Da vao day"); - }, - child: const Text("Show new Alarm Notification"), - ), - ], - )); - } - - Future initNotification() async{ - const isSettingAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); - const initSetting = InitializationSettings(android: isSettingAndroid); - await notificationPlugin.initialize(initSetting); - - } - - Future showNewAlarmSoundNotification(String sound) async { - AndroidNotificationChannel androidNotificationChannel = - AndroidNotificationChannel( - math.Random.secure().nextInt(1000000).toString(), - 'high Important Notification', - importance: Importance.max); - AndroidNotificationDetails androidNotificationDetails = - AndroidNotificationDetails( - "androidNotificationChannel.id.toString()", - androidNotificationChannel.name.toString(), - sound: RawResourceAndroidNotificationSound(sound), - channelDescription: "Channel description", - importance: androidNotificationChannel.importance, - priority: Priority.high, - ticker: 'ticker', - ); - - final NotificationDetails notificationDetails = - NotificationDetails(android: androidNotificationDetails); - await FlutterLocalNotificationsPlugin().show(0, 'New Notification', - 'Sound Notification Example', notificationDetails); - } -} diff --git a/lib/product/base/widget/dialog/request_permission_dialog.dart b/lib/product/base/widget/dialog/request_permission_dialog.dart index 0ea3395..6ffaca1 100644 --- a/lib/product/base/widget/dialog/request_permission_dialog.dart +++ b/lib/product/base/widget/dialog/request_permission_dialog.dart @@ -1,7 +1,7 @@ import 'package:app_settings/app_settings.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import '../../../extention/context_extention.dart'; +import '../../../extension/context_extension.dart'; import '../../../services/language_services.dart'; class RequestPermissionDialog { diff --git a/lib/product/constant/navigation/navigation_router.dart b/lib/product/constant/navigation/navigation_router.dart index e9154e7..0838db6 100644 --- a/lib/product/constant/navigation/navigation_router.dart +++ b/lib/product/constant/navigation/navigation_router.dart @@ -1,6 +1,4 @@ import 'package:go_router/go_router.dart'; -import '../../../feature/sound_notification_test/notification_bloc.dart'; -import '../../../feature/sound_notification_test/notification_screen.dart'; import '../../../bloc/device_detail_bloc.dart'; import '../../../feature/devices/device_detail/device_detail_screen.dart'; import '../../../bloc/device_notification_settings_bloc.dart'; @@ -153,14 +151,6 @@ GoRouter goRouter() { ), transitionsBuilder: transitionsRightToLeft), ), - GoRoute( - path: "/notification", - name: 'notification', - builder: (context, state) => BlocProvider( - child: const NotificationScreen(), - blocBuilder: () => NotificationBloc(), - ), - ), ], ); } diff --git a/lib/product/extention/context_extention.dart b/lib/product/extension/context_extension.dart similarity index 100% rename from lib/product/extention/context_extention.dart rename to lib/product/extension/context_extension.dart diff --git a/lib/product/lang/l10n/app_en.arb b/lib/product/lang/l10n/app_en.arb index b71f80d..733c864 100644 --- a/lib/product/lang/l10n/app_en.arb +++ b/lib/product/lang/l10n/app_en.arb @@ -11,6 +11,7 @@ "button_fake_fire_message": "False fire alarm", "in_progress_message": "In progress", "smoke_detecting_message": "Smoke detecting!", + "low_battery_message": "Low Battery!", "smoke_detecting_message_lowercase": "smoke detecting!", "disconnect_message_uppercase": "Disconnected", "disconnect_message_lowercase": "disconnected", diff --git a/lib/product/lang/l10n/app_vi.arb b/lib/product/lang/l10n/app_vi.arb index f081180..b45c522 100644 --- a/lib/product/lang/l10n/app_vi.arb +++ b/lib/product/lang/l10n/app_vi.arb @@ -11,6 +11,7 @@ "button_fake_fire_message": "Cháy giả?", "in_progress_message": "Đang xử lý", "smoke_detecting_message": "Phát hiện khói!", + "low_battery_message": "Cảnh báo pin yếu!", "smoke_detecting_message_lowercase": "Phát hiện khói!", "disconnect_message_uppercase": "Mất kết nối", "disconnect_message_lowercase": "mất kết nối", diff --git a/lib/product/services/api_services.dart b/lib/product/services/api_services.dart index 00c8405..ac89462 100644 --- a/lib/product/services/api_services.dart +++ b/lib/product/services/api_services.dart @@ -282,7 +282,7 @@ class APIServices { return data; } - Future getOwnerDevieByState(Map params) async { + Future getOwnerDeviceByState(Map params) async { String? data = await NetworkManager.instance! .getDataFromServerWithParams(APIPathConstants.DEVICE_PATH, params); return data; diff --git a/lib/product/services/notification_services.dart b/lib/product/services/notification_services.dart index 46ce265..a02915c 100644 --- a/lib/product/services/notification_services.dart +++ b/lib/product/services/notification_services.dart @@ -128,8 +128,6 @@ class NotificationServices { void handleMessage(String? payload) { dev.log("Handling notification tap with payload: $payload"); - // Thêm logic xử lý khi nhấn thông báo ở đây - // Ví dụ: Điều hướng màn hình hoặc xử lý dữ liệu } Future setupInteractMessage() async { diff --git a/lib/product/shared/shared_input_decoration.dart b/lib/product/shared/shared_input_decoration.dart index 857332d..7178d58 100644 --- a/lib/product/shared/shared_input_decoration.dart +++ b/lib/product/shared/shared_input_decoration.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import '../extention/context_extention.dart'; +import '../extension/context_extension.dart'; InputDecoration borderRadiusTopLeftAndBottomRight( BuildContext context, String hintText) => diff --git a/lib/product/shared/shared_pie_chart.dart b/lib/product/shared/shared_pie_chart.dart index 1235da7..d6eddab 100644 --- a/lib/product/shared/shared_pie_chart.dart +++ b/lib/product/shared/shared_pie_chart.dart @@ -2,10 +2,10 @@ import 'dart:developer'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; -import 'package:sfm_app/bloc/devices_manager_bloc.dart'; -import 'package:sfm_app/feature/devices/device_model.dart'; -import 'package:sfm_app/product/extention/context_extention.dart'; -import 'package:sfm_app/product/services/language_services.dart'; +import '../../bloc/devices_manager_bloc.dart'; +import '../../feature/devices/device_model.dart'; +import '../extension/context_extension.dart'; +import '../services/language_services.dart'; import '../constant/app/app_constants.dart'; @@ -54,18 +54,18 @@ class _SharedPieChartState extends State { aspectRatio: 1, child: PieChart( PieChartData( - pieTouchData: PieTouchData( - touchCallback: (FlTouchEvent event, pieTouchResponse) { - if (!event.isInterestedForInteractions || - pieTouchResponse == null || - pieTouchResponse.touchedSection == null) { - return; - } - int newTouchedIndex = - pieTouchResponse.touchedSection!.touchedSectionIndex; - updateDevicesOnTapPieChart(newTouchedIndex); - }, - ), + // pieTouchData: PieTouchData( + // touchCallback: (FlTouchEvent event, pieTouchResponse) { + // if (!event.isInterestedForInteractions || + // pieTouchResponse == null || + // pieTouchResponse.touchedSection == null) { + // return; + // } + // int newTouchedIndex = + // pieTouchResponse.touchedSection!.touchedSectionIndex; + // updateDevicesOnTapPieChart(newTouchedIndex); + // }, + // ), sections: [ PieChartSectionData( color: Colors.grey, @@ -96,7 +96,7 @@ class _SharedPieChartState extends State { titleStyle: titleStyle, ), PieChartSectionData( - color: Colors.black, // Có thể thêm màu cho trạng thái lỗi + color: Colors.black, value: errorCount.toDouble(), title: errorCount.toString(), radius: context.dynamicWidth(0.2), diff --git a/lib/product/shared/shared_snack_bar.dart b/lib/product/shared/shared_snack_bar.dart index 4a73520..33a42f0 100644 --- a/lib/product/shared/shared_snack_bar.dart +++ b/lib/product/shared/shared_snack_bar.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:sfm_app/product/extention/context_extention.dart'; +import 'package:sfm_app/product/extension/context_extension.dart'; import 'package:top_snackbar_flutter/custom_snack_bar.dart'; import 'package:top_snackbar_flutter/top_snack_bar.dart';