feat(api_service): Update try-catch funtion and handle exception
update(loading_animation): Update loading animation using Lottie
This commit is contained in:
anhtunz
2025-06-09 14:29:43 +07:00
parent 477646ab9d
commit 3a8fa3633c
44 changed files with 1659 additions and 1065 deletions

View File

@@ -12,7 +12,7 @@ import 'group_detail_model.dart';
addDeviceDialog(BuildContext context, DetailGroupBloc detailGroupBloc,
String groupID, List<DeviceOfGroup> devices) async {
List<Device> ownerDevices = await detailGroupBloc.getOwnerDevices();
List<Device> ownerDevices = await detailGroupBloc.getOwnerDevices(context);
List<String> selectedItems = [];
List<String> selectedDevices = [];
if (devices.isNotEmpty) {
@@ -131,7 +131,7 @@ addDeviceDialog(BuildContext context, DetailGroupBloc detailGroupBloc,
for (var device in selectedItems) {
await detailGroupBloc.addDeviceToGroup(
context, groupID, device);
await detailGroupBloc.getGroupDetail(groupID);
await detailGroupBloc.getGroupDetail(context,groupID);
}
Navigator.of(dialogContext).pop();

View File

@@ -4,6 +4,8 @@ import 'dart:async';
import 'package:flutter/material.dart';
import '../../../bloc/group_detail_bloc.dart';
import '../../../product/shared/shared_loading_animation.dart';
import '../../../product/shared/shared_snack_bar.dart';
import 'group_detail_model.dart';
import '../../../product/base/bloc/base_bloc.dart';
import '../../../product/constant/app/app_constants.dart';
@@ -35,15 +37,13 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
const duration = Duration(seconds: 10);
getGroupDetailTimer = Timer.periodic(
duration,
(Timer t) => detailGroupBloc.getGroupDetail(widget.group),
(Timer t) => detailGroupBloc.getGroupDetail(context, widget.group),
);
}
@override
void dispose() {
getGroupDetailTimer?.cancel();
// Thieeus hamf
super.dispose();
}
@@ -53,10 +53,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
stream: detailGroupBloc.streamDetailGroup,
builder: (context, detailGroupSnapshot) {
if (detailGroupSnapshot.data?.id == null) {
detailGroupBloc.getGroupDetail(widget.group);
return const Center(
child: CircularProgressIndicator(),
);
detailGroupBloc.getGroupDetail(context, widget.group);
return const SharedLoadingAnimation();
} else {
return Scaffold(
key: scaffoldKey,
@@ -142,8 +140,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
widget.group,
user.id!,
user.name!);
detailGroupBloc
.getGroupDetail(widget.group);
detailGroupBloc.getGroupDetail(
context, widget.group);
},
icon: const Icon(
Icons.check,
@@ -160,8 +158,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
widget.group,
user.id!,
user.name!);
await detailGroupBloc
.getGroupDetail(widget.group);
await detailGroupBloc.getGroupDetail(
context, widget.group);
},
icon: const Icon(
Icons.close,
@@ -207,8 +205,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
widget.group,
user.id!,
user.name!);
await detailGroupBloc
.getGroupDetail(widget.group);
await detailGroupBloc.getGroupDetail(
context, widget.group);
},
value: 2,
child: Text(appLocalization(context)
@@ -241,7 +239,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
? PopupMenuButton(
icon: IconConstants.instance
.getMaterialIcon(Icons.more_horiz),
itemBuilder: (contex) => [
itemBuilder: (context) => [
PopupMenuItem(
onTap: () {
Navigator.pop(context);
@@ -327,15 +325,21 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
Future.delayed(context.lowDuration).then(
(value) => Navigator.pop(context),
);
int statusCode = await apiServices
.deleteGroup(widget.group);
showSnackBarResponseByStatusCode(
context,
statusCode,
appLocalization(context)
.notification_delete_group_success,
appLocalization(context)
.notification_delete_group_failed);
try {
int statusCode = await apiServices
.deleteGroup(widget.group);
showSnackBarResponseByStatusCode(
context,
statusCode,
appLocalization(context)
.notification_delete_group_success,
appLocalization(context)
.notification_delete_group_failed);
} catch (e) {
if (!context.mounted) return;
showErrorTopSnackBarCustom(
context, e.toString());
}
},
child: Text(
appLocalization(context)
@@ -463,7 +467,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
DeviceUtils.instance.checkStateDevice(
context, devices[index].state!),
style: TextStyle(
color: DeviceUtils.instance.getTableRowColor(context,
color: DeviceUtils.instance.getTableRowColor(
context,
devices[index].state!,
),
),
@@ -525,7 +530,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
String alias = aliasController.text;
await detailGroupBloc.updateDeviceNameInGroup(
context, device.thingId!, alias);
await detailGroupBloc.getGroupDetail(widget.group);
await detailGroupBloc.getGroupDetail(context, widget.group);
},
child: Text(appLocalization(context).confirm_button_content)),
)

View File

@@ -6,6 +6,8 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../../../product/constant/enums/app_route_enums.dart';
import '../../../product/shared/shared_component_loading_animation.dart';
import '../../../product/shared/shared_loading_animation.dart';
import 'groups_model.dart';
import '../../../bloc/inter_family_bloc.dart';
import '../inter_family_widget.dart';
@@ -54,64 +56,76 @@ class _GroupsScreenState extends State<GroupsScreen> {
return StreamBuilder<List<Group>>(
stream: interFamilyBloc.streamCurrentGroups,
builder: (context, groupsSnapshot) {
if(groupsSnapshot.data == null){
if (groupsSnapshot.data == null) {
interFamilyBloc.getAllGroup(widget.role);
return const Center(child: CircularProgressIndicator(),);
}else if(groupsSnapshot.data!.isEmpty){
return Center(child: Text(appLocalization(context).dont_have_group),);
}else {
return const SharedLoadingAnimation();
} else if (groupsSnapshot.data!.isEmpty) {
return Center(
child: Text(appLocalization(context).dont_have_group),
);
} else {
return Scaffold(
body: groupsSnapshot.data?.isEmpty ?? true
? const Center(
child: CircularProgressIndicator(),
)
? const SharedComponentLoadingAnimation()
: ListView.builder(
itemCount: groupsSnapshot.data!.length,
itemBuilder: (context, index) {
return ListTile(
onTap: () {
context.pushNamed(AppRoutes.GROUP_DETAIL.name,
pathParameters: {"groupId": groupsSnapshot.data![index].id!},
extra: widget.role);
},
leading: IconConstants.instance.getMaterialIcon(Icons.diversity_2),
title: Text(
groupsSnapshot.data![index].name ?? '',
style: const TextStyle(fontWeight: FontWeight.bold),
itemCount: groupsSnapshot.data!.length,
itemBuilder: (context, index) {
return ListTile(
onTap: () {
context.pushNamed(AppRoutes.GROUP_DETAIL.name,
pathParameters: {
"groupId": groupsSnapshot.data![index].id!
},
extra: widget.role);
},
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(),
);
},
),
);
}
},
@@ -121,15 +135,16 @@ class _GroupsScreenState extends State<GroupsScreen> {
}
}
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,

View File

@@ -131,7 +131,7 @@ createOrJoinGroupDialog(
appLocalization(context)
.change_group_infomation_content) {
try {
await interFamilyBloc.changeGroupInfomation(
await interFamilyBloc.changeGroupInformation(
context, groupID, groupName, description);
interFamilyBloc.getAllGroup(role);
Navigator.of(dialogContext).pop();