// ignore_for_file: use_build_context_synchronously import 'dart:developer'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:go_router/go_router.dart'; import 'package:badges/badges.dart' as badges; import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart'; import 'package:sfm_app/product/shared/shared_snack_bar.dart'; import '../../product/services/notification_services.dart'; import '../../product/utils/permission_handler.dart'; import '../../product/permission/notification_permission.dart'; import '../settings/profile/profile_model.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'; import '../../product/services/theme_services.dart'; import '../../bloc/devices_manager_bloc.dart'; import '../devices/devices_manager_screen.dart'; import '../home/home_screen.dart'; import '../../bloc/inter_family_bloc.dart'; import '../inter_family/inter_family_screen.dart'; import '../../bloc/device_logs_bloc.dart'; import '../device_log/device_logs_screen.dart'; import '../../bloc/main_bloc.dart'; import '../../bloc/map_bloc.dart'; import '../map/map_screen.dart'; import '../../product/base/bloc/base_bloc.dart'; import '../../product/constant/enums/app_theme_enums.dart'; import '../../product/services/api_services.dart'; import '../../main.dart'; 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'; class MainScreen extends StatefulWidget { const MainScreen({super.key}); @override State createState() => _MainScreenState(); } class _MainScreenState extends State with WidgetsBindingObserver { APIServices apiServices = APIServices(); final NotificationServices notificationServices = NotificationServices(); late MainBloc mainBloc; bool isVN = true; bool isLight = true; String role = 'Unknown'; String titlePage = "Page Title"; int currentPageIndex = 0; final _badgeKey = GlobalKey(); Bell bell = Bell(); void initialCheck() async { String language = await apiServices.checkLanguage(); String theme = await apiServices.checkTheme(); if (language == LanguageConstants.VIETNAM) { isVN = true; } else { isVN = false; } if (theme == AppThemes.LIGHT.name) { isLight = true; } else if (theme == AppThemes.DARK.name) { isLight = false; } else { isLight = true; } mainBloc.sinkIsVNIcon.add(isVN); mainBloc.sinkThemeMode.add(isLight); checkAndRequestPermission(); NotificationServices.requestNotificationPermission(); NotificationPermission.instance.checkNotificationPermission(context); bool? notificationStatus = await NotificationPermission.instance.requestNotificationPermission(); if(!notificationStatus!){ showNoIconTopSnackBar(context, "Yêu cầu quyền thông báo không thành công", Colors.orange, Colors.white12); } } @override void initState() { super.initState(); mainBloc = BlocProvider.of(context); mainBloc.getFCMTokenAndPresentations(); WidgetsBinding.instance.addObserver(this); initialCheck(); getBellNotification(); mainBloc.getUserProfile(context); FirebaseMessaging.instance.onTokenRefresh.listen((newToken) { log("New FCM Token: $newToken"); // Gửi token mới lên server mainBloc.sendNotificationToken(newToken); }); // notificationServices.initLocalNotifications(controller); // notificationServices.firebaseInit(context); // NotificationServices().setupInteractMessage(controller); } @override void dispose() { super.dispose(); WidgetsBinding.instance.removeObserver(this); } @override Widget build(BuildContext context) { List tabs = [ PersistentTabConfig( screen: BlocProvider( child: const HomeScreen(), blocBuilder: () => HomeBloc(), ), item: ItemConfig( icon: IconConstants.instance.getMaterialIcon(Icons.home), title: appLocalization(context).home_page_destination, inactiveIcon: IconConstants.instance.getMaterialIcon(Icons.home_outlined), iconSize: 30, ), ), PersistentTabConfig( screen: BlocProvider( child: const DevicesManagerScreen(), blocBuilder: () => DevicesManagerBloc(), ), item: ItemConfig( icon: IconConstants.instance.getMaterialIcon(Icons.settings), title: appLocalization(context).manager_page_destination, inactiveIcon: IconConstants.instance.getMaterialIcon(Icons.settings_outlined), iconSize: 30, ), ), PersistentTabConfig( screen: BlocProvider( child: const MapScreen(), blocBuilder: () => MapBloc(), ), item: ItemConfig( icon: IconConstants.instance.getMaterialIcon(Icons.location_on), title: appLocalization(context).map_page_destination, inactiveIcon: IconConstants.instance .getMaterialIcon(Icons.location_on_outlined), iconSize: 30, ), ), PersistentTabConfig( screen: BlocProvider( child: const DeviceLogsScreen(), blocBuilder: () => DeviceLogsBloc(), ), item: ItemConfig( icon: IconConstants.instance.getMaterialIcon(Icons.history), title: appLocalization(context).history_page_destination, inactiveIcon: IconConstants.instance.getMaterialIcon(Icons.history_outlined), iconSize: 30, ), ), PersistentTabConfig( screen: BlocProvider( child: const InterFamilyScreen(), blocBuilder: () => InterFamilyBloc(), ), item: ItemConfig( icon: IconConstants.instance.getMaterialIcon(Icons.group), title: appLocalization(context).group_page_destination, inactiveIcon: IconConstants.instance.getMaterialIcon(Icons.group_outlined), iconSize: 30, ), ), ]; return StreamBuilder( stream: mainBloc.streamThemeMode, initialData: isLight, builder: (context, themeModeSnapshot) { return Scaffold( appBar: AppBar( title: StreamBuilder( stream: mainBloc.streamUserProfile, builder: (context, userSnapshot) { return Row( children: [ IconConstants.instance.getMaterialIcon(Icons.person), SizedBox( width: context.lowValue, ), Flexible(child: Text(userSnapshot.data?.name ?? "")) ], ); }), backgroundColor: Colors.transparent, actions: [ IconButton( onPressed: () async { ThemeData newTheme = await ThemeServices().changeTheme( isLight ? AppThemes.DARK.name : AppThemes.LIGHT.name); MyApp.setTheme(context, newTheme); isLight = !isLight; mainBloc.sinkThemeMode.add(isLight); }, icon: Icon( themeModeSnapshot.data ?? isLight ? Icons.light_mode_outlined : Icons.dark_mode_outlined, ), ), StreamBuilder( stream: mainBloc.streamIsVNIcon, initialData: isVN, builder: (context, isVnSnapshot) { return IconButton( onPressed: () async { log("Locale: ${LanguageServices().getLocale()}"); Locale locale = await LanguageServices().setLocale(isVN ? LanguageConstants.ENGLISH : LanguageConstants.VIETNAM); MyApp.setLocale(context, locale); isVN = !isVN; mainBloc.sinkIsVNIcon.add(isVN); }, icon: Image.asset( IconConstants.instance.getIcon( isVnSnapshot.data ?? isVN ? 'vi_icon' : 'en_icon'), height: 24, width: 24, ), ); }, ), StreamBuilder( stream: mainBloc.streamBellBloc, builder: (context, bellSnapshot) { return checkStatus(bellSnapshot.data?.items ?? []) ? IconButton( onPressed: () { context.pushNamed(AppRoutes.BELL.name); }, icon: const Icon( Icons.notifications, ), ) : GestureDetector( child: badges.Badge( badgeStyle: const badges.BadgeStyle( shape: badges.BadgeShape.twitter, ), key: _badgeKey, badgeContent: const Icon( CupertinoIcons.circle_filled, color: Colors.red, size: 5, ), badgeAnimation: const badges.BadgeAnimation.slide( animationDuration: Duration(milliseconds: 200), colorChangeAnimationDuration: Duration(seconds: 1), loopAnimation: false, curve: Curves.decelerate, colorChangeAnimationCurve: Curves.easeInCirc, ), showBadge: true, // ignorePointer: false, child: const Icon( Icons.notifications, size: 30, ), ), onTap: () { context.pushNamed(AppRoutes.BELL.name); }, ); }, ), PopupMenuButton( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), icon: const Icon(Icons.more_vert), itemBuilder: (context) { return [ PopupMenuItem( value: ApplicationConstants.SETTINGS_PATH, onTap: () { context.pushNamed(AppRoutes.SETTINGS.name); }, child: Row( children: [ const Icon(Icons.person), const SizedBox(width: 5), Text(appLocalization(context).profile_icon_title) ], ), ), PopupMenuItem( value: ApplicationConstants.LOGOUT_PATH, onTap: () { Future.delayed( const Duration(milliseconds: 200), () async { await apiServices.logOut(context); }, ); }, child: Row( children: [ const Icon(Icons.logout), const SizedBox(width: 5), Text( appLocalization(context).log_out, ), ], ), ), ]; }, ) ], ), body: PersistentTabView( stateManagement: false, controller: controller, tabs: tabs, navBarBuilder: (navBarConfig) => Style6BottomNavBar( navBarConfig: navBarConfig, navBarDecoration: NavBarDecoration( color: themeModeSnapshot.data! ? Colors.white : Colors.black, borderRadius: BorderRadius.circular(context.mediumValue), padding: const EdgeInsets.all(10)), ), backgroundColor: themeModeSnapshot.data! ? Colors.white : Colors.black, navBarOverlap: const NavBarOverlap.none(), // margin: EdgeInsets.only( // left: context.lowValue, // bottom: context.dynamicHeight(0.02), // right: context.lowValue), screenTransitionAnimation: const ScreenTransitionAnimation( curve: Curves.bounceInOut, duration: Duration(milliseconds: 200), ), ), ); }, ); } Future getBellNotification() async { await apiServices.execute(context, () async { bell = await apiServices.getBellNotifications("0", "20"); mainBloc.bellBloc.add(bell); }); } bool checkStatus(List bells) { if (bells.isEmpty) { return true; } return !bells.any((bell) => bell.status == 0); } }