diff --git a/lib/features/devices/view/widgets/garage_door/garage_list.dart b/lib/features/devices/view/widgets/garage_door/garage_list.dart index 4ddef1b..8d5256d 100644 --- a/lib/features/devices/view/widgets/garage_door/garage_list.dart +++ b/lib/features/devices/view/widgets/garage_door/garage_list.dart @@ -8,8 +8,7 @@ import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart' import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; class GarageList extends StatelessWidget { - const GarageList( - {super.key, required this.garageList, required this.allSwitches}); + const GarageList({super.key, required this.garageList, required this.allSwitches}); final List garageList; final bool allSwitches; @@ -23,43 +22,42 @@ class GarageList extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 10), - const BodySmall(text: 'All Lights'), + const BodySmall(text: 'All Garages'), const SizedBox(height: 5), DevicesDefaultSwitch( - off: 'OFF', - on: 'ON', + off: 'Close', + on: 'Open', switchValue: allSwitches, - action: () { - BlocProvider.of(context) - .add(GroupAllOnEvent()); - }, - secondAction: () { - BlocProvider.of(context) - .add(GroupAllOffEvent()); - }, + action: () => BlocProvider.of(context).add( + GroupAllOnEvent(), + ), + secondAction: () => BlocProvider.of(context).add( + GroupAllOffEvent(), + ), ), ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - padding: const EdgeInsets.all(0), + padding: EdgeInsetsDirectional.zero, itemCount: garageList.length, itemBuilder: (context, index) { + final garageDoor = garageList[index]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 10), - BodySmall(text: garageList[index].deviceName), + BodySmall(text: garageDoor.deviceName), const SizedBox(height: 5), DevicesDefaultSwitch( - off: 'OFF', - on: 'ON', - switchValue: garageList[index].firstSwitch, - action: () { - BlocProvider.of(context).add( - ChangeFirstWizardSwitchStatusEvent( - value: garageList[index].firstSwitch, - deviceId: garageList[index].deviceId)); - }, + off: 'Close', + on: 'Open', + switchValue: garageDoor.firstSwitch, + action: () => BlocProvider.of(context).add( + ChangeFirstWizardSwitchStatusEvent( + value: garageDoor.firstSwitch, + deviceId: garageDoor.deviceId, + ), + ), ), ], ); diff --git a/lib/features/devices/view/widgets/water_heater/wh_list.dart b/lib/features/devices/view/widgets/water_heater/wh_list.dart index ebc2ddd..a3f672d 100644 --- a/lib/features/devices/view/widgets/water_heater/wh_list.dart +++ b/lib/features/devices/view/widgets/water_heater/wh_list.dart @@ -8,7 +8,11 @@ import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart' import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; class WHList extends StatelessWidget { - const WHList({super.key, required this.whList, required this.allSwitches}); + const WHList({ + required this.whList, + required this.allSwitches, + super.key, + }); final List whList; final bool allSwitches; @@ -22,43 +26,42 @@ class WHList extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 10), - const BodySmall(text: 'All Lights'), + const BodySmall(text: 'All Water Heaters'), const SizedBox(height: 5), DevicesDefaultSwitch( off: 'OFF', on: 'ON', switchValue: allSwitches, - action: () { - BlocProvider.of(context) - .add(GroupAllOnEvent()); - }, - secondAction: () { - BlocProvider.of(context) - .add(GroupAllOffEvent()); - }, + action: () => context.read().add( + GroupAllOnEvent(), + ), + secondAction: () => context.read().add( + GroupAllOffEvent(), + ), ), ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - padding: const EdgeInsets.all(0), + padding: EdgeInsetsDirectional.zero, itemCount: whList.length, itemBuilder: (context, index) { + final waterHeater = whList[index]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 10), - BodySmall(text: whList[index].deviceName), + BodySmall(text: waterHeater.deviceName), const SizedBox(height: 5), DevicesDefaultSwitch( off: 'OFF', on: 'ON', - switchValue: whList[index].firstSwitch, - action: () { - BlocProvider.of(context).add( + switchValue: waterHeater.firstSwitch, + action: () => context.read().add( ChangeFirstWizardSwitchStatusEvent( - value: whList[index].firstSwitch, - deviceId: whList[index].deviceId)); - }, + value: waterHeater.firstSwitch, + deviceId: waterHeater.deviceId, + ), + ), ), ], ); diff --git a/lib/features/scene/helper/scene_bloc_factory.dart b/lib/features/scene/helper/scene_bloc_factory.dart new file mode 100644 index 0000000..e47a7b6 --- /dev/null +++ b/lib/features/scene/helper/scene_bloc_factory.dart @@ -0,0 +1,48 @@ +import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; +import 'package:syncrow_app/features/app_layout/model/community_model.dart'; +import 'package:syncrow_app/features/app_layout/model/space_model.dart'; +import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart'; + +abstract final class SceneBlocFactory { + static SceneBloc create({ + required bool pageType, + required HomeCubit homeCubit, + }) { + final selectedSpace = homeCubit.selectedSpace; + final defaultSpace = SpaceModel( + id: '-1', + name: '', + community: Community( + uuid: '-1', + name: '', + ), + ); + + final spaceId = selectedSpace?.id ?? defaultSpace.id; + final space = selectedSpace ?? defaultSpace; + final communityUuid = + selectedSpace?.community.uuid ?? defaultSpace.community.uuid; + + final sceneBloc = SceneBloc(); + + sceneBloc.add( + LoadScenes( + spaceId, + space, + showInDevice: pageType, + ), + ); + + if (!pageType) { + sceneBloc.add( + LoadAutomation( + spaceId, + communityUuid, + ), + ); + } + + return sceneBloc; + } +} diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index 13fa92c..c6cadc9 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -1,92 +1,54 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; -import 'package:syncrow_app/features/app_layout/model/community_model.dart'; import 'package:syncrow_app/features/app_layout/model/space_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/scene_listview.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart'; import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart'; +import 'package:syncrow_app/features/scene/helper/scene_bloc_factory.dart'; import 'package:syncrow_app/features/scene/widgets/empty_devices_widget.dart'; import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_view.dart'; import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_header.dart'; +import 'package:syncrow_app/features/shared_widgets/app_loading_indicator.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class SceneView extends StatelessWidget { + const SceneView({ + this.pageType = false, + super.key, + }); + final bool pageType; - const SceneView({super.key, this.pageType = false}); @override Widget build(BuildContext context) { return BlocProvider( - create: (BuildContext context) { - if (pageType) { - return SceneBloc() - ..add(LoadScenes( - HomeCubit.getInstance().selectedSpace?.id ?? '', - HomeCubit.getInstance().selectedSpace ?? - SpaceModel( - id: '-1', - name: '', - community: Community( - uuid: '-1', - name: '', - )), - showInDevice: pageType)); - } else { - return SceneBloc() - ..add(LoadScenes( - HomeCubit.getInstance().selectedSpace?.id ?? '', - HomeCubit.getInstance().selectedSpace ?? - SpaceModel( - id: '-1', - name: '', - community: Community( - uuid: '-1', - name: '', - )), - showInDevice: pageType)) - ..add(LoadAutomation( - HomeCubit.getInstance().selectedSpace?.id ?? '', - HomeCubit.getInstance().selectedSpace?.community.uuid ?? '')); - } - }, + create: (context) => SceneBlocFactory.create( + pageType: pageType, + homeCubit: HomeCubit.getInstance(), + ), child: BlocBuilder( builder: (context, state) { + final selectedSpace = HomeCubit.getInstance().selectedSpace; if (state is DeleteSceneSuccess) { - if (state.success) { - BlocProvider.of(context).add(LoadScenes( - HomeCubit.getInstance().selectedSpace!.id, - HomeCubit.getInstance().selectedSpace!, - showInDevice: pageType)); - BlocProvider.of(context).add(LoadAutomation( - HomeCubit.getInstance().selectedSpace!.id, - HomeCubit.getInstance().selectedSpace!.community.uuid)); - } + if (state.success) _loadScenesAndAutomations(context, selectedSpace); } if (state is CreateSceneWithTasks) { - if (state.success == true) { - BlocProvider.of(context).add(LoadScenes( - HomeCubit.getInstance().selectedSpace!.id, - HomeCubit.getInstance().selectedSpace!, - showInDevice: pageType)); - BlocProvider.of(context).add(LoadAutomation( - HomeCubit.getInstance().selectedSpace!.id, - HomeCubit.getInstance().selectedSpace!.community.uuid)); - context - .read() - .add(const SmartSceneClearEvent()); + if (state.success) { + _loadScenesAndAutomations(context, selectedSpace); + context.read().add(const SmartSceneClearEvent()); } } return BlocListener( listener: (context, state) { if (state is SceneTriggerSuccess) { context.showCustomSnackbar( - message: - 'Scene ${state.sceneName} triggered successfully!'); + message: 'Scene ${state.sceneName} triggered successfully!', + ); } }, child: HomeCubit.getInstance().spaces.isEmpty @@ -95,13 +57,14 @@ class SceneView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - if (pageType == false) const SceneHeader(), - if (pageType == false) const SizedBox(height: 8), + if (!pageType) ...[ + const SceneHeader(), + const SizedBox(height: 8), + ], BlocBuilder( builder: (context, state) { if (state is SceneLoading) { - return const Center( - child: CircularProgressIndicator()); + return const AppLoadingIndicator(); } if (state is SceneError) { return Center( @@ -111,84 +74,81 @@ class SceneView extends StatelessWidget { if (state is SceneLoaded) { final scenes = state.scenes; final automationList = state.automationList; + if (scenes.isEmpty) return const EmptyDevicesWidget(); - return pageType - ? SizedBox( - height: context.height * 0.1, - child: SceneListview( - scenes: scenes, - loadingSceneId: state.loadingSceneId, - ), - ) - : Expanded( - child: ListView( + if (pageType) { + return SizedBox( + height: context.height * 0.1, + child: SceneListview( + scenes: scenes, + loadingSceneId: state.loadingSceneId, + ), + ); + } + + return Theme( + data: Theme.of(context).copyWith( + dividerColor: Colors.transparent, + ), + child: Expanded( + child: ListView( + children: [ + ExpansionTile( + tilePadding: const EdgeInsets.symmetric( + horizontal: 6, + ), + initiallyExpanded: true, + iconColor: ColorsManager.grayColor, + title: const BodyMedium( + text: 'Tap to run routines', + ), children: [ - Theme( - data: ThemeData().copyWith( - dividerColor: Colors.transparent), - child: ExpansionTile( - tilePadding: - const EdgeInsets.symmetric( - horizontal: 6), - initiallyExpanded: true, - iconColor: ColorsManager.grayColor, - title: const BodyMedium( - text: 'Tap to run routines'), - children: [ - scenes.isNotEmpty - ? SceneGrid( - scenes: scenes, - loadingSceneId: - state.loadingSceneId, - disablePlayButton: false, - loadingStates: state - .loadingStates, // Add this line - ) - : const Center( - child: BodyMedium( - text: - 'No scenes have been added yet', - ), - ), - const SizedBox(height: 10), - ], + if (scenes.isNotEmpty) + SceneGrid( + scenes: scenes, + loadingSceneId: state.loadingSceneId, + disablePlayButton: false, + loadingStates: state.loadingStates, + ) + else + const Center( + child: BodyMedium( + text: 'No scenes have been added yet', + ), ), - ), - Theme( - data: ThemeData().copyWith( - dividerColor: Colors.transparent), - child: ExpansionTile( - initiallyExpanded: true, - iconColor: ColorsManager.grayColor, - tilePadding: - const EdgeInsets.symmetric( - horizontal: 6), - title: const BodyMedium( - text: 'Automation'), - children: [ - automationList.isNotEmpty - ? SceneGrid( - scenes: automationList, - loadingSceneId: - state.loadingSceneId, - disablePlayButton: true, - loadingStates: state - .loadingStates, // Add this line - ) - : const Center( - child: BodyMedium( - text: - 'No automations have been added yet', - ), - ), - const SizedBox(height: 10), - ], - ), - ), - const SizedBox(height: 15), + const SizedBox(height: 10), ], ), - ); + ExpansionTile( + initiallyExpanded: true, + iconColor: ColorsManager.grayColor, + tilePadding: const EdgeInsets.symmetric( + horizontal: 6, + ), + title: const BodyMedium(text: 'Automation'), + children: [ + if (automationList.isNotEmpty) + SceneGrid( + scenes: automationList, + loadingSceneId: state.loadingSceneId, + disablePlayButton: true, + loadingStates: state.loadingStates, + ) + else + const Center( + child: BodyMedium( + text: + 'No automations have been added yet', + ), + ), + const SizedBox(height: 10), + ], + ), + const SizedBox(height: 15), + ], + ), + ), + ); } return const SizedBox.shrink(); }, @@ -200,4 +160,21 @@ class SceneView extends StatelessWidget { ), ); } + + void _loadScenesAndAutomations(BuildContext context, SpaceModel? selectedSpace) { + BlocProvider.of(context) + ..add( + LoadScenes( + selectedSpace!.id, + selectedSpace, + showInDevice: pageType, + ), + ) + ..add( + LoadAutomation( + selectedSpace.id, + selectedSpace.community.uuid, + ), + ); + } } diff --git a/lib/features/shared_widgets/app_loading_indicator.dart b/lib/features/shared_widgets/app_loading_indicator.dart new file mode 100644 index 0000000..0ca3fe3 --- /dev/null +++ b/lib/features/shared_widgets/app_loading_indicator.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class AppLoadingIndicator extends StatelessWidget { + const AppLoadingIndicator({super.key}); + + @override + Widget build(BuildContext context) { + return Center( + child: CircularProgressIndicator.adaptive(), + ); + } +}