import 'dart:async'; import 'dart:convert'; import 'dart:developer'; import 'package:flutter/material.dart'; import 'shared/alert_card.dart'; import 'shared/warning_card.dart'; 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/extension/context_extension.dart'; import '../../product/services/api_services.dart'; import '../../product/services/language_services.dart'; import '../../bloc/home_bloc.dart'; import '../../product/base/bloc/base_bloc.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { late HomeBloc homeBloc; APIServices apiServices = APIServices(); Map> allDevicesAliasMap = {}; Map> allDevicesAliasJoinedMap = {}; List devices = []; bool isFunctionCall = false; Timer? getAllDevicesTimer; int notificationCount = 0; Map> ownerDevicesStatus = {}; List ownerDevicesState = []; @override void initState() { super.initState(); homeBloc = BlocProvider.of(context); getOwnerAndJoinedDevices(); const duration = Duration(seconds: 10); getAllDevicesTimer = Timer.periodic(duration, (Timer t) => getOwnerAndJoinedDevices()); } @override void dispose() { getAllDevicesTimer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Padding( padding: context.paddingLow, child: SingleChildScrollView( child: Column( children: [ Row( children: [ Text( appLocalization(context).notification, style: context.titleMediumTextStyle, ), SizedBox(width: context.lowValue), StreamBuilder( stream: homeBloc.streamCountNotification, builder: (context, countSnapshot) { return Text( "(${countSnapshot.data ?? 0})", style: context.titleMediumTextStyle, ); }, ) ], ), SizedBox( child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: StreamBuilder>>( stream: homeBloc.streamOwnerDevicesStatus, builder: (context, snapshot) { if (snapshot.data?['state'] != null || snapshot.data?['battery'] != null) { return Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ if (snapshot.data?['state'] != null) ...snapshot.data!['state']! .map( (item) => FutureBuilder( future: warningCard(context, apiServices, item), builder: (context, warningCardSnapshot) { if (warningCardSnapshot.hasData) { return ConstrainedBox( constraints: const BoxConstraints( maxWidth: 400, maxHeight: 260, ), child: warningCardSnapshot.data!, ); } else { return const SizedBox.shrink(); } }, ), ) .toList(), if (snapshot.data?['battery'] != null) ...snapshot.data!['battery']! .map( (batteryItem) => FutureBuilder( future: notificationCard( context, "lowBattery", appLocalization(context).low_battery_message, batteryItem), builder: (context, warningCardSnapshot) { if (warningCardSnapshot.hasData) { return ConstrainedBox( constraints: const BoxConstraints( maxWidth: 400, maxHeight: 260, ), child: warningCardSnapshot.data!, ); } else { return const SizedBox.shrink(); } }, ), ) .toList(), ], ); } else { return Padding( padding: context.paddingMedium, child: Center( child: Row( children: [ const Icon( Icons.check_circle_outline_rounded, size: 40, color: Colors.green, ), SizedBox(width: context.lowValue), Text( appLocalization(context).notification_description, maxLines: 2, overflow: TextOverflow.ellipsis, softWrap: true, textAlign: TextAlign.start, ), ], ), ), ); } }, ), ), ), 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.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 OverviewCard( isOwner: false, total: total, active: active, inactive: inactive, warning: warning, unused: unused, ); }, ), ], ), ), ), ); } void getOwnerAndJoinedDevices() async { String response = await apiServices.getDashBoardDevices(); final data = jsonDecode(response); List result = data["items"]; devices = DeviceWithAlias.fromJsonDynamicList(result); getOwnerDeviceState(devices); checkSettingDevice(devices); getDeviceStatusAliasMap(devices); } void getOwnerDeviceState(List allDevices) async { List ownerDevices = []; for (var device in allDevices) { if (device.isOwner!) { ownerDevices.add(device); } } 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 ?? []); 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 (double.parse(sensorMap['sensorBattery']) <= 20) { ownerDevicesStatus['battery'] ??= []; ownerDevicesStatus['battery']!.add(device); homeBloc.sinkOwnerDevicesStatus.add(ownerDevicesStatus); count++; } } notificationCount = count; homeBloc.sinkCountNotification.add(notificationCount); } } } 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) { allDevicesAliasMap['all']!.add(device); if (device.state == 0 || device.state == 1) { allDevicesAliasMap['online']!.add(device); } if (device.state == -1) { allDevicesAliasMap['offline']!.add(device); } if (device.state == 1) { allDevicesAliasMap['warning']!.add(device); } if (device.state == -2) { allDevicesAliasMap['not-use']!.add(device); } } else { allDevicesAliasJoinedMap['all']!.add(device); if (device.state == 0 || device.state == 1) { allDevicesAliasJoinedMap['online']!.add(device); } if (device.state == -1) { allDevicesAliasJoinedMap['offline']!.add(device); } if (device.state == 1) { allDevicesAliasJoinedMap['warning']!.add(device); } if (device.state == -2) { allDevicesAliasJoinedMap['not-use']!.add(device); } } } homeBloc.sinkAllDevicesAliasMap.add(allDevicesAliasMap); homeBloc.sinkAllDevicesAliasJoinedMap.add(allDevicesAliasJoinedMap); } void checkSettingDevice(List devices) async { if (isFunctionCall) { log("Ham check setting da duoc goi"); } else { String? response = await apiServices.getAllSettingsNotificationOfDevices(); if (response != "") { final data = jsonDecode(response); final result = data['data']; // log("Data ${DeviceNotificationSettings.mapFromJson(jsonDecode(data)).values.toList()}"); List list = DeviceNotificationSettings.mapFromJson(result).values.toList(); // log("List: $list"); 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!); } else { log("All devices are in the notification settings list."); } } } else { log("apiServices: getAllSettingsNotificationofDevices error!"); } } isFunctionCall = true; } }