From d1bc973b38a76dbd7b5b8802c8604770b6d3c4aa Mon Sep 17 00:00:00 2001 From: Mohammad Salameh Date: Mon, 1 Apr 2024 12:09:01 +0300 Subject: [PATCH] Refactor HomeCubit class for better instance management Create a private static instance variable and refactor methods for better instance management in the HomeCubit class. --- lib/features/app_layout/bloc/home_cubit.dart | 28 ++++- lib/features/app_layout/bloc/home_state.dart | 2 +- lib/features/app_layout/view/app_layout.dart | 73 ++++++------ .../view/widgets/app_bar_home_dropdown.dart | 108 +++++++++--------- .../app_layout/view/widgets/app_body.dart | 7 +- .../view/widgets/default_app_bar.dart | 8 +- .../view/widgets/default_nav_bar.dart | 6 +- lib/features/devices/bloc/devices_cubit.dart | 4 +- .../view/widgets/devices_view_body.dart | 24 ++-- .../devices/view/widgets/rooms_slider.dart | 54 +++++---- 10 files changed, 169 insertions(+), 145 deletions(-) diff --git a/lib/features/app_layout/bloc/home_cubit.dart b/lib/features/app_layout/bloc/home_cubit.dart index b0e1932..8f7f572 100644 --- a/lib/features/app_layout/bloc/home_cubit.dart +++ b/lib/features/app_layout/bloc/home_cubit.dart @@ -17,8 +17,10 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; part 'home_state.dart'; class HomeCubit extends Cubit { - HomeCubit() : super(SpacesInitial()) { - if (HomeCubit.spaces != null) { + // Create a private static instance variable + static HomeCubit? _instance; + HomeCubit._() : super(HomeInitial()) { + if (spaces != null) { if (selectedSpace == null) { fetchSpaces().then((value) { if (selectedSpace != null) { @@ -31,12 +33,17 @@ class HomeCubit extends Cubit { fetchSpaces(); // this is for the first time } } + static HomeCubit getInstance() { + // If an instance already exists, return it + _instance ??= HomeCubit._(); + return _instance!; + } static HomeCubit get(context) => BlocProvider.of(context); - static List? spaces; + List? spaces; - static SpaceModel? selectedSpace; + SpaceModel? selectedSpace; RoomModel? selectedRoom; @@ -46,7 +53,12 @@ class HomeCubit extends Cubit { var duration = const Duration(milliseconds: 300); - selectSpace(SpaceModel space) { + // selectSpace(SpaceModel space) async { + // selectedSpace = space; + // emit(SpaceSelected(space)); + // } + + changeSelectedSpace(SpaceModel space) { selectedSpace = space; emit(SpaceSelected(space)); } @@ -102,7 +114,11 @@ class HomeCubit extends Cubit { emit(GetSpacesLoading()); try { spaces = await SpacesAPI.getSpaces(); - selectedSpace = spaces!.isNotEmpty ? selectSpace(spaces!.first) : null; + selectedSpace = spaces!.isNotEmpty + ? + // selectSpace(spaces!.first) + selectedSpace = spaces!.first + : null; emit(GetSpacesLoaded(spaces!)); } on DioException catch (e) { emit(GetSpacesError(ServerFailure.fromDioError(e).errMessage)); diff --git a/lib/features/app_layout/bloc/home_state.dart b/lib/features/app_layout/bloc/home_state.dart index e5880c7..d1f5b7d 100644 --- a/lib/features/app_layout/bloc/home_state.dart +++ b/lib/features/app_layout/bloc/home_state.dart @@ -2,7 +2,7 @@ part of 'home_cubit.dart'; abstract class HomeState {} -class SpacesInitial extends HomeState {} +class HomeInitial extends HomeState {} class GetSpacesLoading extends HomeState {} diff --git a/lib/features/app_layout/view/app_layout.dart b/lib/features/app_layout/view/app_layout.dart index 9c2c733..4aa4c4b 100644 --- a/lib/features/app_layout/view/app_layout.dart +++ b/lib/features/app_layout/view/app_layout.dart @@ -23,13 +23,13 @@ class AppLayout extends StatelessWidget { return MultiBlocProvider( providers: [ BlocProvider( - create: (context) => HomeCubit(), + create: (context) => HomeCubit.getInstance(), ), BlocProvider( create: (context) => DevicesCubit(), ), ], - child: BlocListener( + child: BlocConsumer( listener: (context, state) { if (state is GetSpacesError) { ScaffoldMessenger.of(context).showSnackBar( @@ -41,42 +41,41 @@ class AppLayout extends StatelessWidget { .popUntil((route) => route.settings.name == Routes.authLogin); } }, - child: BlocBuilder( - builder: (context, state) { - return AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarColor: ColorsManager.primaryColor.withOpacity(0.5), - statusBarIconBrightness: Brightness.light, + builder: (context, state) { + return AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarColor: ColorsManager.primaryColor.withOpacity(0.5), + statusBarIconBrightness: Brightness.light, + ), + child: SafeArea( + child: BlocBuilder( + builder: (context, state) { + return Scaffold( + backgroundColor: ColorsManager.backgroundColor, + extendBodyBehindAppBar: true, + extendBody: true, + appBar: + state is GetSpacesLoaded ? const DefaultAppBar() : null, + body: const AppBody(), + bottomNavigationBar: const DefaultNavBar(), + // floatingActionButton: FloatingActionButton( + // onPressed: () { + // Navigator.push( + // context, + // CustomPageRoute( + // builder: (context) => + // const ThreeGangSwitchesView(), + // ), + // ); + // }, + // child: const Icon(Icons.arrow_forward_ios_sharp), + // ), + ); + }, ), - child: SafeArea( - child: BlocBuilder( - builder: (context, state) { - return const Scaffold( - backgroundColor: ColorsManager.backgroundColor, - extendBodyBehindAppBar: true, - extendBody: true, - appBar: DefaultAppBar(), - body: AppBody(), - bottomNavigationBar: DefaultNavBar(), - // floatingActionButton: FloatingActionButton( - // onPressed: () { - // Navigator.push( - // context, - // CustomPageRoute( - // builder: (context) => - // const ThreeGangSwitchesView(), - // ), - // ); - // }, - // child: const Icon(Icons.arrow_forward_ios_sharp), - // ), - ); - }, - ), - ), - ); - }, - ), + ), + ); + }, ), ); } diff --git a/lib/features/app_layout/view/widgets/app_bar_home_dropdown.dart b/lib/features/app_layout/view/widgets/app_bar_home_dropdown.dart index 2b89da6..197893a 100644 --- a/lib/features/app_layout/view/widgets/app_bar_home_dropdown.dart +++ b/lib/features/app_layout/view/widgets/app_bar_home_dropdown.dart @@ -9,70 +9,68 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import '../../../../generated/assets.dart'; class AppBarHomeDropdown extends StatelessWidget { - const AppBarHomeDropdown({ - super.key, - }); + const AppBarHomeDropdown({super.key}); @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - return HomeCubit.selectedSpace == null - ? const Center(child: BodyMedium(text: 'No Home Selected')) - : Padding( - padding: const EdgeInsets.only(left: 10, right: 10), - child: DropdownButton( - icon: const Icon( - Icons.expand_more, - color: Colors.black, - size: 25, - ), - underline: const SizedBox.shrink(), - padding: const EdgeInsets.all(0), - borderRadius: BorderRadius.circular(20), - value: HomeCubit.selectedSpace!.id, - items: HomeCubit.spaces!.map((space) { - return DropdownMenuItem( - value: space.id, - child: SizedBox( - width: 100, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - SvgPicture.asset( - Assets.iconsHome, - width: 25, - height: 25, - colorFilter: const ColorFilter.mode( - ColorsManager.textPrimaryColor, - BlendMode.srcIn, - ), - ), - const SizedBox(width: 5), - Expanded( - child: BodyMedium( - text: space.name ?? "??", - style: context.bodyMedium.copyWith( - fontSize: 15, - color: ColorsManager.textPrimaryColor, - overflow: TextOverflow.ellipsis, - ), - ), - ), - ], + return Padding( + padding: const EdgeInsets.only(left: 10, right: 10), + child: DropdownButton( + icon: const Icon( + Icons.expand_more, + color: Colors.black, + size: 25, + ), + underline: const SizedBox.shrink(), + padding: const EdgeInsets.all(0), + borderRadius: BorderRadius.circular(20), + value: HomeCubit.getInstance().selectedSpace!.id, + items: HomeCubit.getInstance().spaces!.map((space) { + return DropdownMenuItem( + value: space.id, + child: SizedBox( + width: 100, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + Assets.iconsHome, + width: 25, + height: 25, + colorFilter: const ColorFilter.mode( + ColorsManager.textPrimaryColor, + BlendMode.srcIn, ), ), - ); - }).toList(), - onChanged: (value) { - if (value != null) { - HomeCubit.get(context).selectSpace(HomeCubit.spaces! - .firstWhere((element) => element.id == value)); - } - }, + const SizedBox(width: 5), + Expanded( + child: BodyMedium( + text: space.name ?? "??", + style: context.bodyMedium.copyWith( + fontSize: 15, + color: ColorsManager.textPrimaryColor, + overflow: TextOverflow.ellipsis, + ), + ), + ), + ], + ), ), ); + }).toList(), + onChanged: (value) { + if (value != null) { + HomeCubit.getInstance().changeSelectedSpace( + HomeCubit.getInstance() + .spaces! + .firstWhere((element) => element.id == value)); + } + }, + ), + ); }, ); } diff --git a/lib/features/app_layout/view/widgets/app_body.dart b/lib/features/app_layout/view/widgets/app_body.dart index ef2a47d..34343b3 100644 --- a/lib/features/app_layout/view/widgets/app_body.dart +++ b/lib/features/app_layout/view/widgets/app_body.dart @@ -37,9 +37,10 @@ class AppBody extends StatelessWidget { } }, builder: (context, state) { - return state is! GetSpacesLoading || - state is! GetSpaceRoomsLoading - ? HomeCubit.get(context).pages[HomeCubit.pageIndex] + return state is! GetSpacesLoading + ? state is! GetSpaceRoomsLoading + ? HomeCubit.getInstance().pages[HomeCubit.pageIndex] + : const Center(child: CircularProgressIndicator()) : const Center(child: CircularProgressIndicator()); }, ), diff --git a/lib/features/app_layout/view/widgets/default_app_bar.dart b/lib/features/app_layout/view/widgets/default_app_bar.dart index 0575441..6335873 100644 --- a/lib/features/app_layout/view/widgets/default_app_bar.dart +++ b/lib/features/app_layout/view/widgets/default_app_bar.dart @@ -20,11 +20,9 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { backgroundColor: Colors.transparent, leadingWidth: 150, toolbarHeight: Constants.appBarHeight, - leading: HomeCubit.spaces != null - ? HomeCubit.spaces!.isNotEmpty - ? HomeCubit.appBarLeading[ - HomeCubit.bottomNavItems[HomeCubit.pageIndex].label] - : const Center(child: BodySmall(text: 'Create Home')) + leading: HomeCubit.getInstance().spaces!.isNotEmpty + ? HomeCubit.appBarLeading[ + HomeCubit.bottomNavItems[HomeCubit.pageIndex].label] : null, actions: HomeCubit.appBarActions[ HomeCubit.bottomNavItems[HomeCubit.pageIndex].label], diff --git a/lib/features/app_layout/view/widgets/default_nav_bar.dart b/lib/features/app_layout/view/widgets/default_nav_bar.dart index 15aef6e..41aa2fd 100644 --- a/lib/features/app_layout/view/widgets/default_nav_bar.dart +++ b/lib/features/app_layout/view/widgets/default_nav_bar.dart @@ -15,7 +15,7 @@ class DefaultNavBar extends StatelessWidget { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - var cubit = HomeCubit.get(context); + var cubit = HomeCubit.getInstance(); return SizedBox( height: Constants.bottomNavBarHeight, child: BottomNavigationBar( @@ -25,8 +25,8 @@ class DefaultNavBar extends StatelessWidget { if (DevicesCubit.get(context).chosenCategoryView != null) { DevicesCubit().clearCategoriesSelection(context); } - if (HomeCubit.get(context).selectedRoom != null) { - HomeCubit.get(context).unselectRoom(); + if (HomeCubit.getInstance().selectedRoom != null) { + HomeCubit.getInstance().unselectRoom(); } }, currentIndex: HomeCubit.pageIndex, diff --git a/lib/features/devices/bloc/devices_cubit.dart b/lib/features/devices/bloc/devices_cubit.dart index fa44c92..2dd5ecf 100644 --- a/lib/features/devices/bloc/devices_cubit.dart +++ b/lib/features/devices/bloc/devices_cubit.dart @@ -22,8 +22,8 @@ part 'devices_state.dart'; class DevicesCubit extends Cubit { DevicesCubit() : super(DevicesInitial()) { - if (HomeCubit.selectedSpace != null) { - fetchGroups(HomeCubit.selectedSpace!.id!); + if (HomeCubit.getInstance().selectedSpace != null) { + fetchGroups(HomeCubit.getInstance().selectedSpace!.id!); } } bool _isClosed = false; diff --git a/lib/features/devices/view/widgets/devices_view_body.dart b/lib/features/devices/view/widgets/devices_view_body.dart index 7837d8b..949db78 100644 --- a/lib/features/devices/view/widgets/devices_view_body.dart +++ b/lib/features/devices/view/widgets/devices_view_body.dart @@ -42,15 +42,19 @@ class DevicesViewBody extends StatelessWidget { Expanded( child: PageView( controller: - HomeCubit.get(context).devicesPageController, + HomeCubit.getInstance().devicesPageController, onPageChanged: (index) { - HomeCubit.get(context).devicesPageChanged(index); + HomeCubit.getInstance().devicesPageChanged(index); }, children: [ const WizardPage(), - if (HomeCubit.selectedSpace != null) - if (HomeCubit.selectedSpace!.rooms != null) - ...HomeCubit.selectedSpace!.rooms!.map( + if (HomeCubit.getInstance().selectedSpace != null) + if (HomeCubit.getInstance().selectedSpace!.rooms != + null) + ...HomeCubit.getInstance() + .selectedSpace! + .rooms! + .map( (room) { return RoomPage( room: room, @@ -60,15 +64,19 @@ class DevicesViewBody extends StatelessWidget { ], ), ), - HomeCubit.selectedSpace != null + HomeCubit.getInstance().selectedSpace != null ? Padding( padding: const EdgeInsets.symmetric( vertical: 7, ), child: SmoothPageIndicator( controller: - HomeCubit.get(context).devicesPageController, - count: HomeCubit.selectedSpace!.rooms!.length + 1, + HomeCubit.getInstance().devicesPageController, + count: HomeCubit.getInstance() + .selectedSpace! + .rooms! + .length + + 1, effect: const WormEffect( paintStyle: PaintingStyle.stroke, dotHeight: 8, diff --git a/lib/features/devices/view/widgets/rooms_slider.dart b/lib/features/devices/view/widgets/rooms_slider.dart index 7d5795a..aeba2f4 100644 --- a/lib/features/devices/view/widgets/rooms_slider.dart +++ b/lib/features/devices/view/widgets/rooms_slider.dart @@ -18,51 +18,55 @@ class RoomsSlider extends StatelessWidget { return SizedBox( height: 40, child: PageView( - controller: HomeCubit.get(context).roomsPageController, + controller: HomeCubit.getInstance().roomsPageController, onPageChanged: (index) { - HomeCubit.get(context).roomSliderPageChanged(index); + HomeCubit.getInstance().roomSliderPageChanged(index); }, children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 15), child: InkWell( onTap: () { - HomeCubit.get(context).unselectRoom(); + HomeCubit.getInstance().unselectRoom(); }, child: TitleMedium( text: StringsManager.wizard, style: context.titleMedium.copyWith( fontSize: 25, - color: HomeCubit.get(context).selectedRoom == null + color: HomeCubit.getInstance().selectedRoom == null ? ColorsManager.textPrimaryColor : ColorsManager.textPrimaryColor.withOpacity(.2), ), ), ), ), - if (HomeCubit.selectedSpace != null) - if (HomeCubit.selectedSpace!.rooms != null) - ...HomeCubit.selectedSpace!.rooms!.map( - (room) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), - child: InkWell( - onTap: () { - HomeCubit.get(context).roomSliderPageChanged( - HomeCubit.selectedSpace!.rooms!.indexOf(room)); - }, - child: TitleMedium( - text: room.name!, - style: context.titleMedium.copyWith( - fontSize: 25, - color: HomeCubit.get(context).selectedRoom == room - ? ColorsManager.textPrimaryColor - : ColorsManager.textPrimaryColor - .withOpacity(.2), + if (HomeCubit.getInstance().selectedSpace != null) + if (HomeCubit.getInstance().selectedSpace!.rooms != null) + ...HomeCubit.getInstance().selectedSpace!.rooms!.map( + (room) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: InkWell( + onTap: () { + HomeCubit.getInstance().roomSliderPageChanged( + HomeCubit.getInstance() + .selectedSpace! + .rooms! + .indexOf(room)); + }, + child: TitleMedium( + text: room.name!, + style: context.titleMedium.copyWith( + fontSize: 25, + color: + HomeCubit.getInstance().selectedRoom == room + ? ColorsManager.textPrimaryColor + : ColorsManager.textPrimaryColor + .withOpacity(.2), + ), + ), ), ), - ), - ), - ) + ) ], ), );