From 2438dcf83d92d73154822963a7056bda1d35426a Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sat, 13 Jul 2024 20:30:10 +0300 Subject: [PATCH 01/30] adding asset images --- .../automation_functions/card_unlock.svg | 14 + .../automation_functions/doorbell.svg | 13 + .../doorlock_normal_open.svg | 12 + .../automation_functions/double_lock.svg | 12 + .../fingerprint_unlock.svg | 79 +++++ .../automation_functions/hijack_alarm.svg | 13 + .../automation_functions/lock_alarm.svg | 149 ++++++++++ .../automation_functions/password_unlock.svg | 16 + .../remote_unlock_req.svg | 15 + .../remote_unlock_via_app.svg | 40 +++ .../residual_electricity.svg | 4 + .../temp_password_unlock.svg | 16 + .../helper/scene_operations_data_helper.dart | 42 ++- .../scene/view/create_scene_view.dart | 12 +- .../scene/view/device_functions_view.dart | 7 +- .../scene_devices/scene_devices_body.dart | 19 +- lib/generated/assets.dart | 273 +++++++++++++----- pubspec.yaml | 1 + 18 files changed, 659 insertions(+), 78 deletions(-) create mode 100644 assets/icons/functions_icons/automation_functions/card_unlock.svg create mode 100644 assets/icons/functions_icons/automation_functions/doorbell.svg create mode 100644 assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg create mode 100644 assets/icons/functions_icons/automation_functions/double_lock.svg create mode 100644 assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg create mode 100644 assets/icons/functions_icons/automation_functions/hijack_alarm.svg create mode 100644 assets/icons/functions_icons/automation_functions/lock_alarm.svg create mode 100644 assets/icons/functions_icons/automation_functions/password_unlock.svg create mode 100644 assets/icons/functions_icons/automation_functions/remote_unlock_req.svg create mode 100644 assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg create mode 100644 assets/icons/functions_icons/automation_functions/residual_electricity.svg create mode 100644 assets/icons/functions_icons/automation_functions/temp_password_unlock.svg diff --git a/assets/icons/functions_icons/automation_functions/card_unlock.svg b/assets/icons/functions_icons/automation_functions/card_unlock.svg new file mode 100644 index 0000000..dd77680 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/card_unlock.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/doorbell.svg b/assets/icons/functions_icons/automation_functions/doorbell.svg new file mode 100644 index 0000000..1dc515a --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/doorbell.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg b/assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg new file mode 100644 index 0000000..8f4a590 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/double_lock.svg b/assets/icons/functions_icons/automation_functions/double_lock.svg new file mode 100644 index 0000000..d8ad971 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/double_lock.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg b/assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg new file mode 100644 index 0000000..f9f5b84 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/hijack_alarm.svg b/assets/icons/functions_icons/automation_functions/hijack_alarm.svg new file mode 100644 index 0000000..e32997f --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/hijack_alarm.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/lock_alarm.svg b/assets/icons/functions_icons/automation_functions/lock_alarm.svg new file mode 100644 index 0000000..8bd2dee --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/lock_alarm.svg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/password_unlock.svg b/assets/icons/functions_icons/automation_functions/password_unlock.svg new file mode 100644 index 0000000..1920b69 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/password_unlock.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/remote_unlock_req.svg b/assets/icons/functions_icons/automation_functions/remote_unlock_req.svg new file mode 100644 index 0000000..da128ff --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/remote_unlock_req.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg b/assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg new file mode 100644 index 0000000..39fc859 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/residual_electricity.svg b/assets/icons/functions_icons/automation_functions/residual_electricity.svg new file mode 100644 index 0000000..6a5b612 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/residual_electricity.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/functions_icons/automation_functions/temp_password_unlock.svg b/assets/icons/functions_icons/automation_functions/temp_password_unlock.svg new file mode 100644 index 0000000..98d7573 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/temp_password_unlock.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index 5c8cda0..6ed5115 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -11,6 +11,7 @@ mixin SceneOperationsDataHelper { required List functions, required String deviceId, required String deviceName, + required bool isAutomation, }) { switch (type) { case DeviceType.LightBulb: @@ -19,6 +20,7 @@ mixin SceneOperationsDataHelper { deviceId: deviceId, deviceName: deviceName, functionValue: null, + isAutomation: isAutomation, ); case DeviceType.CeilingSensor: return ceilingSensorFunctions( @@ -26,6 +28,7 @@ mixin SceneOperationsDataHelper { deviceId: deviceId, deviceName: deviceName, functionValue: null, + isAutomation: isAutomation, ); case DeviceType.WallSensor: return wallSensorFunctions( @@ -33,6 +36,7 @@ mixin SceneOperationsDataHelper { deviceId: deviceId, deviceName: deviceName, functionValue: null, + isAutomation: isAutomation, ); case DeviceType.AC: return acFunctions( @@ -40,6 +44,7 @@ mixin SceneOperationsDataHelper { deviceId: deviceId, deviceName: deviceName, functionValue: null, + isAutomation: isAutomation, ); case DeviceType.DoorLock: return doorLockFunctions( @@ -47,6 +52,7 @@ mixin SceneOperationsDataHelper { deviceId: deviceId, deviceName: deviceName, functionValue: null, + isAutomation: isAutomation, ); case DeviceType.Curtain: return curtainFunctions( @@ -54,6 +60,7 @@ mixin SceneOperationsDataHelper { deviceId: deviceId, deviceName: deviceName, functionValue: null, + isAutomation: isAutomation, ); case DeviceType.ThreeGang: return threeGangFunctions( @@ -61,6 +68,7 @@ mixin SceneOperationsDataHelper { deviceId: deviceId, deviceName: deviceName, functionValue: null, + isAutomation: isAutomation, ); case DeviceType.Gateway: return gatewayFunctions( @@ -68,6 +76,7 @@ mixin SceneOperationsDataHelper { deviceId: deviceId, deviceName: deviceName, functionValue: null, + isAutomation: isAutomation, ); default: return lightBulbFunctions( @@ -75,6 +84,7 @@ mixin SceneOperationsDataHelper { deviceId: deviceId, deviceName: deviceName, functionValue: null, + isAutomation: isAutomation, ); } } @@ -108,6 +118,7 @@ mixin SceneOperationsDataHelper { required String deviceId, required String deviceName, required dynamic functionValue, + required bool isAutomation, }) { return [ SceneStaticFunction( @@ -177,7 +188,8 @@ mixin SceneOperationsDataHelper { {required List functions, required String deviceId, required String deviceName, - required functionValue}) { + required functionValue, + required bool isAutomation}) { return []; } @@ -186,7 +198,28 @@ mixin SceneOperationsDataHelper { required String deviceId, required String deviceName, required functionValue, + required bool isAutomation, }) { + if (isAutomation) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIconsDoorLock, + operationName: 'Set Door lock Normal Open', + functionValue: functionValue, + code: 'normal_open_switch', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false), + ], + ), + ]; + } return [ SceneStaticFunction( deviceId: deviceId, @@ -210,6 +243,7 @@ mixin SceneOperationsDataHelper { required String deviceId, required String deviceName, required functionValue, + required bool isAutomation, }) { return [ SceneStaticFunction( @@ -377,7 +411,8 @@ mixin SceneOperationsDataHelper { {required List functions, required String deviceId, required String deviceName, - required functionValue}) { + required functionValue, + required bool isAutomation}) { return []; } @@ -386,6 +421,7 @@ mixin SceneOperationsDataHelper { required String deviceId, required String deviceName, required functionValue, + required bool isAutomation, }) { return [ SceneStaticFunction( @@ -444,6 +480,7 @@ mixin SceneOperationsDataHelper { required String deviceId, required String deviceName, required functionValue, + required bool isAutomation, }) { return [ SceneStaticFunction( @@ -530,6 +567,7 @@ mixin SceneOperationsDataHelper { required String deviceId, required String deviceName, required functionValue, + required bool isAutomation, }) { return [ SceneStaticFunction( diff --git a/lib/features/scene/view/create_scene_view.dart b/lib/features/scene/view/create_scene_view.dart index e19d3ea..11e2ff0 100644 --- a/lib/features/scene/view/create_scene_view.dart +++ b/lib/features/scene/view/create_scene_view.dart @@ -58,7 +58,17 @@ class CreateSceneView extends StatelessWidget { titleString: StringsManager.whenDeviceStatusChanges, subtitleString: StringsManager.whenUnusualActivityIsDetected, ), - onTap: () {}, + onTap: () { + Navigator.pushNamed( + context, + Routes.sceneControlDevicesRoute, + arguments: SceneSettingsRouteArguments( + sceneType: CreateSceneEnum.deviceStatusChanges.name, + sceneId: '', + sceneName: '', + ), + ); + }, ), ], ), diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index cd2b781..74aeb7a 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -27,7 +27,11 @@ class DeviceFunctionsView extends StatelessWidget /// this whole widget needs a refactor later /// /// static functions based on type - final device = ModalRoute.of(context)?.settings.arguments as DeviceModel; + final device = (ModalRoute.of(context)?.settings.arguments as Map)['device'] + as DeviceModel; + + final isAutomation = (ModalRoute.of(context)?.settings.arguments + as Map)['isAutomationDeviceStatus'] as bool; /// static custom functions based on type /// used for now until later backend fixes @@ -38,6 +42,7 @@ class DeviceFunctionsView extends StatelessWidget functions: device.functions, deviceId: device.uuid ?? '', deviceName: device.name ?? '', + isAutomation: isAutomation, ); } diff --git a/lib/features/scene/widgets/scene_devices/scene_devices_body.dart b/lib/features/scene/widgets/scene_devices/scene_devices_body.dart index 6ee9ab4..0c3b9ab 100644 --- a/lib/features/scene/widgets/scene_devices/scene_devices_body.dart +++ b/lib/features/scene/widgets/scene_devices/scene_devices_body.dart @@ -6,6 +6,8 @@ import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_man import 'package:syncrow_app/features/devices/model/room_model.dart'; import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart'; +import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; +import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; @@ -26,6 +28,10 @@ class SceneDevicesBody extends StatelessWidget { @override Widget build(BuildContext context) { + final isAutomationDeviceStatus = (ModalRoute.of(context)?.settings.arguments + as SceneSettingsRouteArguments) + .sceneType == + CreateSceneEnum.deviceStatusChanges.name; return BlocBuilder( builder: (context, tabState) { return Column( @@ -56,7 +62,10 @@ class SceneDevicesBody extends StatelessWidget { child: TabBarView( controller: _tabController, physics: const NeverScrollableScrollPhysics(), - children: rooms!.map((e) => _buildRoomTab(e, context)).toList(), + children: rooms! + .map((e) => + _buildRoomTab(e, context, isAutomationDeviceStatus)) + .toList(), ), ), ], @@ -65,7 +74,8 @@ class SceneDevicesBody extends StatelessWidget { ); } - Widget _buildRoomTab(RoomModel room, BuildContext context) { + Widget _buildRoomTab( + RoomModel room, BuildContext context, bool isAutomationDeviceStatus) { return BlocBuilder( builder: (context, state) { if (state.loading && state.devices == null) { @@ -96,7 +106,10 @@ class SceneDevicesBody extends StatelessWidget { Navigator.pushNamed( context, Routes.deviceFunctionsRoute, - arguments: device, + arguments: { + "device": device, + "isAutomationDeviceStatus": isAutomationDeviceStatus + }, ); }, ), diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index 3eb3827..d6599ef 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -3,7 +3,8 @@ class Assets { /// Assets for assetsFontsAftikaRegular /// assets/fonts/AftikaRegular.ttf - static const String assetsFontsAftikaRegular = "assets/fonts/AftikaRegular.ttf"; + static const String assetsFontsAftikaRegular = + "assets/fonts/AftikaRegular.ttf"; /// Assets for assetsIcons3GangSwitch /// assets/icons/3GangSwitch.svg @@ -19,82 +20,98 @@ class Assets { /// Assets for assetsIconsAutomatedClock /// assets/icons/automated_clock.svg - static const String assetsIconsAutomatedClock = "assets/icons/automated_clock.svg"; + static const String assetsIconsAutomatedClock = + "assets/icons/automated_clock.svg"; static const String acSwitchIcon = "assets/icons/ac_switch_ic.svg"; /// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff /// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg - static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff = + static const String + assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff = "assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff /// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg - static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff = + static const String + assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff = "assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff /// assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg - static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff = + static const String + assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff = "assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff /// assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg - static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff = + static const String + assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff = "assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff /// assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg - static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff = + static const String + assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff = "assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff /// assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg - static const String assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff = + static const String + assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff = "assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff /// assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg - static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff = + static const String + assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff = "assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff /// assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg - static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff = + static const String + assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff = "assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff /// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg - static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff = + static const String + assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff = "assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff /// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg - static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff = + static const String + assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff = "assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff /// assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg - static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff = + static const String + assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff = "assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff /// assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg - static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff = + static const String + assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff = "assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff /// assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg - static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff = + static const String + assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff = "assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff /// assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg - static const String assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff = + static const String + assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff = "assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff /// assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg - static const String assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff = + static const String + assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff = "assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg"; /// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOnstlowpmdmOff @@ -104,37 +121,44 @@ class Assets { /// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn /// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg - static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn = + static const String + assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn = "assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn /// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg - static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn = + static const String + assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn = "assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn /// assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg - static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn = + static const String + assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn = "assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn /// assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg - static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn = + static const String + assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn = "assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn /// assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg - static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn = + static const String + assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn = "assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn /// assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg - static const String assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn = + static const String + assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn = "assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn /// assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg - static const String assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn = + static const String + assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn = "assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOnstlowpmdmOn @@ -144,37 +168,44 @@ class Assets { /// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn /// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg - static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn = + static const String + assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn = "assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn /// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg - static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn = + static const String + assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn = "assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn /// assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg - static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn = + static const String + assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn = "assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn /// assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg - static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn = + static const String + assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn = "assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn /// assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg - static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn = + static const String + assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn = "assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn /// assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg - static const String assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn = + static const String + assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn = "assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn /// assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg - static const String assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn = + static const String + assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn = "assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg"; /// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOnstlowpmdmOn @@ -226,7 +257,8 @@ class Assets { /// Assets for assetsIconsDashboardFill /// assets/icons/dashboard-fill.svg - static const String assetsIconsDashboardFill = "assets/icons/dashboard-fill.svg"; + static const String assetsIconsDashboardFill = + "assets/icons/dashboard-fill.svg"; /// Assets for assetsIconsDevices /// assets/icons/Devices.svg @@ -242,7 +274,8 @@ class Assets { /// Assets for assetsIconsDoorLockLinkage /// assets/icons/DoorLockLinkage.svg - static const String assetsIconsDoorLockLinkage = "assets/icons/DoorLockLinkage.svg"; + static const String assetsIconsDoorLockLinkage = + "assets/icons/DoorLockLinkage.svg"; /// Assets for assetsIconsDoorLockLock /// assets/icons/DoorLockLock.svg @@ -250,15 +283,18 @@ class Assets { /// Assets for assetsIconsDoorLockMembers /// assets/icons/DoorLockMembers.svg - static const String assetsIconsDoorLockMembers = "assets/icons/DoorLockMembers.svg"; + static const String assetsIconsDoorLockMembers = + "assets/icons/DoorLockMembers.svg"; /// Assets for assetsIconsDoorLockPassword /// assets/icons/DoorLockPassword.svg - static const String assetsIconsDoorLockPassword = "assets/icons/DoorLockPassword.svg"; + static const String assetsIconsDoorLockPassword = + "assets/icons/DoorLockPassword.svg"; /// Assets for assetsIconsDoorLockRecords /// assets/icons/DoorLockRecords.svg - static const String assetsIconsDoorLockRecords = "assets/icons/DoorLockRecords.svg"; + static const String assetsIconsDoorLockRecords = + "assets/icons/DoorLockRecords.svg"; /// Assets for assetsIconsDoorlockAssetsBatteryIndicator /// assets/icons/doorlock-assets/BatteryIndicator.svg @@ -279,7 +315,8 @@ class Assets { /// assets/icons/doorlock-assets/lockIcon.svg static const String assetsIconsDoorlockAssetsLockIcon = "assets/icons/doorlock-assets/lockIcon.svg"; - static const String doorUnlockIcon = "assets/icons/doorlock-assets/door_un_look_ic.svg"; + static const String doorUnlockIcon = + "assets/icons/doorlock-assets/door_un_look_ic.svg"; /// Assets for assetsIconsDoorlockAssetsMembersManagement /// assets/icons/doorlock-assets/members-management.svg @@ -367,11 +404,13 @@ class Assets { /// Assets for assetsIconsLightSwitchOff /// assets/icons/lightSwitchOff.svg - static const String assetsIconsLightSwitchOff = "assets/icons/lightSwitchOff.svg"; + static const String assetsIconsLightSwitchOff = + "assets/icons/lightSwitchOff.svg"; /// Assets for assetsIconsLightSwitchOn /// assets/icons/lightSwitchOn.svg - static const String assetsIconsLightSwitchOn = "assets/icons/lightSwitchOn.svg"; + static const String assetsIconsLightSwitchOn = + "assets/icons/lightSwitchOn.svg"; /// Assets for assetsIconsLinkageIconsDoorLockAlarm /// assets/icons/linkageIcons/doorLockAlarm.svg @@ -380,7 +419,8 @@ class Assets { /// Assets for assetsIconsLinkTimeLimitedPasswordIcon /// assets/icons/timeLimitedPasswordIcon.svg - static const String timeLimitedPasswordIcon = "assets/icons/timeLimitedPasswordIcon.svg"; + static const String timeLimitedPasswordIcon = + "assets/icons/timeLimitedPasswordIcon.svg"; /// Assets for assetsIconsoneTimePassword /// assets/icons/oneTimePassword.svg @@ -388,7 +428,8 @@ class Assets { /// Assets for assetsIconsTimeLimitedPassword /// assets/icons/timeLimitedPassword.svg - static const String timeLimitedPassword = "assets/icons/timeLimitedPassword.svg"; + static const String timeLimitedPassword = + "assets/icons/timeLimitedPassword.svg"; /// Assets for assetsIconsNoValidPasswords /// assets/icons/noValidPasswords.svg @@ -557,11 +598,13 @@ class Assets { /// Assets for assetsIconsPresenceSensorAssetsParameterSettings /// assets/icons/presence-sensor-assets/space_type_icon.svg - static const String spaceTypeIcon = "assets/icons/presence-sensor-assets/space_type_icon.svg"; + static const String spaceTypeIcon = + "assets/icons/presence-sensor-assets/space_type_icon.svg"; /// Assets for assetsIconsPresenceSensorAssetsParameterSettings /// assets/icons/presence-sensor-assets/space_type_icon.svg - static const String sensitivityIcon = "assets/icons/presence-sensor-assets/Sensitivity.svg"; + static const String sensitivityIcon = + "assets/icons/presence-sensor-assets/Sensitivity.svg"; /// Assets for assetsIconsPresenceSensorAssetsParameterSettings /// assets/icons/presence-sensor-assets/maximum_distance.svg @@ -594,7 +637,8 @@ class Assets { /// Assets for assetsIconsRoutinesFill /// assets/icons/Routines-fill.svg - static const String assetsIconsRoutinesFill = "assets/icons/Routines-fill.svg"; + static const String assetsIconsRoutinesFill = + "assets/icons/Routines-fill.svg"; /// Assets for assetsIconsScan /// assets/icons/Scan.svg @@ -626,7 +670,8 @@ class Assets { /// Assets for assetsIconsSustainability /// assets/icons/sustainability.svg - static const String assetsIconsSustainability = "assets/icons/sustainability.svg"; + static const String assetsIconsSustainability = + "assets/icons/sustainability.svg"; /// Assets for assetsIconsUnlockingMethodsIconsFace /// assets/icons/unlockingMethodsIcons/face.svg @@ -718,7 +763,8 @@ class Assets { /// Assets for assetsImagesHorizintalBlade /// assets/images/HorizintalBlade.png - static const String assetsImagesHorizintalBlade = "assets/images/HorizintalBlade.png"; + static const String assetsImagesHorizintalBlade = + "assets/images/HorizintalBlade.png"; /// Assets for assetsImagesLogo /// assets/images/Logo.svg @@ -726,7 +772,8 @@ class Assets { /// Assets for assetsImagesLogoHorizontal /// assets/images/logo_horizontal.png - static const String assetsImagesLogoHorizontal = "assets/images/logo_horizontal.png"; + static const String assetsImagesLogoHorizontal = + "assets/images/logo_horizontal.png"; /// Assets for assetsImagesPause /// assets/images/Pause.png @@ -756,7 +803,8 @@ class Assets { /// assets/images/Window.png static const String assetsImagesWindow = "assets/images/Window.png"; - static const String assetsSensitivityFunction = "assets/icons/functions_icons/sensitivity.svg"; + static const String assetsSensitivityFunction = + "assets/icons/functions_icons/sensitivity.svg"; //assets/icons/functions_icons/sesitivity_operation_icon.svg static const String assetsSensitivityOperationIcon = @@ -764,59 +812,73 @@ class Assets { //assets/icons/functions_icons/ac_power.svg - static const String assetsAcPower = "assets/icons/functions_icons/ac_power.svg"; + static const String assetsAcPower = + "assets/icons/functions_icons/ac_power.svg"; //assets/icons/functions_icons/ac_power_off.svg - static const String assetsAcPowerOFF = "assets/icons/functions_icons/ac_power_off.svg"; + static const String assetsAcPowerOFF = + "assets/icons/functions_icons/ac_power_off.svg"; //assets/icons/functions_icons/child_lock.svg - static const String assetsChildLock = "assets/icons/functions_icons/child_lock.svg"; + static const String assetsChildLock = + "assets/icons/functions_icons/child_lock.svg"; //assets/icons/functions_icons/cooling.svg - static const String assetsFreezing = "assets/icons/functions_icons/freezing.svg"; + static const String assetsFreezing = + "assets/icons/functions_icons/freezing.svg"; //assets/icons/functions_icons/fan_speed.svg - static const String assetsFanSpeed = "assets/icons/functions_icons/fan_speed.svg"; + static const String assetsFanSpeed = + "assets/icons/functions_icons/fan_speed.svg"; //assets/icons/functions_icons/ac_cooling.svg - static const String assetsAcCooling = "assets/icons/functions_icons/ac_cooling.svg"; + static const String assetsAcCooling = + "assets/icons/functions_icons/ac_cooling.svg"; //assets/icons/functions_icons/ac_heating.svg - static const String assetsAcHeating = "assets/icons/functions_icons/ac_heating.svg"; + static const String assetsAcHeating = + "assets/icons/functions_icons/ac_heating.svg"; //assets/icons/functions_icons/celsius_degrees.svg - static const String assetsCelsiusDegrees = "assets/icons/functions_icons/celsius_degrees.svg"; + static const String assetsCelsiusDegrees = + "assets/icons/functions_icons/celsius_degrees.svg"; //assets/icons/functions_icons/tempreture.svg - static const String assetsTempreture = "assets/icons/functions_icons/tempreture.svg"; + static const String assetsTempreture = + "assets/icons/functions_icons/tempreture.svg"; //assets/icons/functions_icons/ac_fan_low.svg - static const String assetsAcFanLow = "assets/icons/functions_icons/ac_fan_low.svg"; + static const String assetsAcFanLow = + "assets/icons/functions_icons/ac_fan_low.svg"; //assets/icons/functions_icons/ac_fan_middle.svg - static const String assetsAcFanMiddle = "assets/icons/functions_icons/ac_fan_middle.svg"; + static const String assetsAcFanMiddle = + "assets/icons/functions_icons/ac_fan_middle.svg"; //assets/icons/functions_icons/ac_fan_high.svg - static const String assetsAcFanHigh = "assets/icons/functions_icons/ac_fan_high.svg"; + static const String assetsAcFanHigh = + "assets/icons/functions_icons/ac_fan_high.svg"; //assets/icons/functions_icons/ac_fan_auto.svg - static const String assetsAcFanAuto = "assets/icons/functions_icons/ac_fan_auto.svg"; + static const String assetsAcFanAuto = + "assets/icons/functions_icons/ac_fan_auto.svg"; //assets/icons/functions_icons/scene_child_lock.svg - static const String assetsSceneChildLock = "assets/icons/functions_icons/scene_child_lock.svg"; + static const String assetsSceneChildLock = + "assets/icons/functions_icons/scene_child_lock.svg"; //assets/icons/functions_icons/scene_child_unlock.svg @@ -825,15 +887,18 @@ class Assets { //assets/icons/functions_icons/scene_refresh.svg - static const String assetsSceneRefresh = "assets/icons/functions_icons/scene_refresh.svg"; + static const String assetsSceneRefresh = + "assets/icons/functions_icons/scene_refresh.svg"; //assets/icons/functions_icons/light_countdown.svg - static const String assetsLightCountdown = "assets/icons/functions_icons/light_countdown.svg"; + static const String assetsLightCountdown = + "assets/icons/functions_icons/light_countdown.svg"; //assets/icons/functions_icons/far_detection.svg - static const String assetsFarDetection = "assets/icons/functions_icons/far_detection.svg"; + static const String assetsFarDetection = + "assets/icons/functions_icons/far_detection.svg"; //assets/icons/functions_icons/far_detection_function.svg @@ -842,11 +907,13 @@ class Assets { //assets/icons/functions_icons/indicator.svg - static const String assetsIndicator = "assets/icons/functions_icons/indicator.svg"; + static const String assetsIndicator = + "assets/icons/functions_icons/indicator.svg"; //assets/icons/functions_icons/motion_detection.svg - static const String assetsMotionDetection = "assets/icons/functions_icons/motion_detection.svg"; + static const String assetsMotionDetection = + "assets/icons/functions_icons/motion_detection.svg"; //assets/icons/functions_icons/motionless_detection.svg @@ -855,15 +922,18 @@ class Assets { //assets/icons/functions_icons/nobody_time.svg - static const String assetsNobodyTime = "assets/icons/functions_icons/nobody_time.svg"; + static const String assetsNobodyTime = + "assets/icons/functions_icons/nobody_time.svg"; //assets/icons/functions_icons/factory_reset.svg - static const String assetsFactoryReset = "assets/icons/functions_icons/factory_reset.svg"; + static const String assetsFactoryReset = + "assets/icons/functions_icons/factory_reset.svg"; //assets/icons/functions_icons/master_state.svg - static const String assetsMasterState = "assets/icons/functions_icons/master_state.svg"; + static const String assetsMasterState = + "assets/icons/functions_icons/master_state.svg"; //assets/icons/functions_icons/switch_alarm_sound.svg @@ -872,5 +942,66 @@ class Assets { //assets/icons/functions_icons/reset_off.svg - static const String assetsResetOff = "assets/icons/functions_icons/reset_off.svg"; + static const String assetsResetOff = + "assets/icons/functions_icons/reset_off.svg"; + + //assets/icons/functions_icons/automation_functions/card_unlock.svg + + static const String assetsCardUnlock = + "assets/icons/functions_icons/automation_functions/card_unlock.svg"; + + //assets/icons/functions_icons/automation_functions/doorbell.svg + + static const String assetsDoorbell = + "assets/icons/functions_icons/automation_functions/doorbell.svg"; + + //assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg + + static const String assetsDoorlockNormalOpen = + "assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg"; + + //assets/icons/functions_icons/automation_functions/double_lock.svg + + static const String assetsDoubleLock = + "assets/icons/functions_icons/automation_functions/double_lock.svg"; + + //assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg + + static const String assetsFingerprintUnlock = + "assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg"; + + //assets/icons/functions_icons/automation_functions/hijack_alarm.svg + + static const String assetsHijackAlarm = + "assets/icons/functions_icons/automation_functions/hijack_alarm.svg"; + + //assets/icons/functions_icons/automation_functions/lock_alarm.svg + + static const String assetsLockAlarm = + "assets/icons/functions_icons/automation_functions/lock_alarm.svg"; + + //assets/icons/functions_icons/automation_functions/password_unlock.svg + + static const String assetsPasswordUnlock = + "assets/icons/functions_icons/automation_functions/password_unlock.svg"; + + //assets/icons/functions_icons/automation_functions/remote_unlock_req.svg + + static const String assetsRemoteUnlockReq = + "assets/icons/functions_icons/automation_functions/remote_unlock_req.svg"; + + //assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg + + static const String assetsRemoteUnlockViaApp = + "assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg"; + + //assets/icons/functions_icons/automation_functions/residual_electricity.svg + + static const String assetsResidualElectricity = + "assets/icons/functions_icons/automation_functions/residual_electricity.svg"; + + //assets/icons/functions_icons/automation_functions/temp_password_unlock.svg + + static const String assetsTempPasswordUnlock = + "assets/icons/functions_icons/automation_functions/temp_password_unlock.svg"; } diff --git a/pubspec.yaml b/pubspec.yaml index 0dbf15a..3708e95 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -74,6 +74,7 @@ flutter: - assets/icons/MenuIcons/SecurityAndPrivacyIcons/ - assets/icons/curtainsIcon/ - assets/icons/functions_icons/ + - assets/icons/functions_icons/automation_functions fonts: - family: Aftika fonts: From acbd4a9968b05f5d607ea6faca30c95103440c71 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sun, 14 Jul 2024 02:48:26 +0300 Subject: [PATCH 02/30] push door lock automation functions --- .../bloc/create_scene/create_scene_bloc.dart | 20 ++ .../scene/enum/operation_dialog_type.dart | 9 + .../scene/helper/scene_logic_helper.dart | 15 +- .../helper/scene_operations_data_helper.dart | 305 ++++++++++++++++-- .../scene/model/scene_static_function.dart | 16 +- .../scene/view/device_functions_view.dart | 250 +++++++------- .../scene/widgets/bottom_sheet_widget.dart | 2 + .../if_then_containers/then_added_tasks.dart | 2 +- pubspec.yaml | 2 +- 9 files changed, 460 insertions(+), 161 deletions(-) create mode 100644 lib/features/scene/enum/operation_dialog_type.dart diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index f314088..d6cf274 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart'; +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; @@ -68,11 +69,30 @@ class CreateSceneBloc extends Bloc } if (!updated) { // Add new function if not found + OperationDialogType getOperationDialogType(String? code, [value]) { + if (code == null) { + return OperationDialogType.none; + } + if (code.contains('delay')) { + return OperationDialogType.delay; + } else if (code.contains('countdown')) { + return OperationDialogType.countdown; + } else if (code.contains('set_temp')) { + return OperationDialogType.temperature; + } else if (value.toString().toLowerCase().trim() == 'on' || + value.toString().toLowerCase().trim() == 'off') { + return OperationDialogType.onOff; + } + return OperationDialogType.listOfOptions; + } + var newElement = SceneStaticFunction( operationName: event.operation, deviceName: event.deviceName, icon: event.icon, code: event.deviceControlModel.code ?? '', + operationDialogType: getOperationDialogType( + event.deviceControlModel.code, event.deviceControlModel.value), deviceId: event.deviceId, functionValue: event.deviceControlModel.value, operationalValues: [ diff --git a/lib/features/scene/enum/operation_dialog_type.dart b/lib/features/scene/enum/operation_dialog_type.dart new file mode 100644 index 0000000..b1829b1 --- /dev/null +++ b/lib/features/scene/enum/operation_dialog_type.dart @@ -0,0 +1,9 @@ +enum OperationDialogType { + countdown, + delay, + temperature, + onOff, + integerSteps, + listOfOptions, + none, +} diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 616e3fd..4372692 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -2,6 +2,7 @@ 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/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; @@ -80,24 +81,26 @@ mixin SceneLogicHelper { Widget getTheCorrectDialogBody( SceneStaticFunction taskItem, + dynamic functionValue, ) { - if (taskItem.code.contains('temp_set')) { + if (taskItem.operationDialogType == OperationDialogType.temperature) { return AlertDialogTemperatureBody( taskItem: taskItem, - functionValue: taskItem.functionValue, + functionValue: functionValue ?? taskItem.functionValue, ); - } else if (taskItem.code.contains('countdown') || - taskItem.deviceId.contains('delay')) { + } else if ((taskItem.operationDialogType == + OperationDialogType.countdown) || + (taskItem.operationDialogType == OperationDialogType.delay)) { return AlertDialogCountdown( durationValue: taskItem.functionValue, - functionValue: taskItem.functionValue, + functionValue: functionValue ?? taskItem.functionValue, function: taskItem, ); } return AlertDialogFunctionsOperationsBody( taskItem: taskItem, - functionValue: taskItem.functionValue, + functionValue: functionValue ?? taskItem.functionValue, ); } } diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index 6ed5115..a93bcfd 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -1,5 +1,6 @@ import 'package:syncrow_app/features/devices/model/function_model.dart'; import 'package:syncrow_app/features/scene/enum/ac_values.dart'; +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; import 'package:syncrow_app/features/scene/model/scene_details_model.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/generated/assets.dart'; @@ -128,6 +129,7 @@ mixin SceneOperationsDataHelper { operationName: 'Sensitivity', code: 'sensitivity', functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, @@ -205,17 +207,207 @@ mixin SceneOperationsDataHelper { SceneStaticFunction( deviceId: deviceId, deviceName: deviceName, - icon: Assets.assetsIconsDoorLock, - operationName: 'Set Door lock Normal Open', + icon: Assets.assetsFingerprintUnlock, + operationName: 'Fingerprint Unlock', functionValue: functionValue, - code: 'normal_open_switch', + code: 'unlock_fingerprint', + operationDialogType: OperationDialogType.integerSteps, operationalValues: [ SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsPasswordUnlock, + operationName: 'Password Unlock', + functionValue: functionValue, + code: 'unlock_password', + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false), + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsCardUnlock, + operationName: 'Card Unlock', + functionValue: functionValue, + code: 'unlock_card', + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsLockAlarm, + operationName: 'Lock Alarm', + functionValue: functionValue, + code: 'alarm_lock', + operationDialogType: OperationDialogType.none, + operationalValues: [], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsRemoteUnlockReq, + operationName: 'Remote Unlock Request', + functionValue: functionValue, + code: 'unlock_request', + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsResidualElectricity, + operationName: 'Residual Electricity', + functionValue: functionValue, + code: 'residual_electricity', + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsDoubleLock, + operationName: 'Double Lock', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + code: 'reverse_lock', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsRemoteUnlockViaApp, + operationName: 'Remote Unlock Via App', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + code: 'unlock_app', + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsHijackAlarm, + operationName: 'Hijack Alarm', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + code: 'hijack', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsDoorlockNormalOpen, + operationName: 'Set Door Lock Normal Open', + functionValue: functionValue, + code: 'normal_open_switch', + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsDoorlockNormalOpen, + operationName: 'Doorbell', + functionValue: functionValue, + code: 'doorbell', + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsTempPasswordUnlock, + operationName: 'Temporary Password Unlock', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + code: 'unlock_temporary', + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), ], ), ]; @@ -228,6 +420,7 @@ mixin SceneOperationsDataHelper { operationName: 'Set Door lock Normal Open', functionValue: functionValue, code: 'normal_open_switch', + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -253,6 +446,7 @@ mixin SceneOperationsDataHelper { operationName: 'Far Detection', code: 'far_detection', functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsFarDetectionFunction, @@ -311,6 +505,7 @@ mixin SceneOperationsDataHelper { operationName: 'Motion Detection Sensitivity', code: 'motion_sensitivity_value', functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, @@ -346,6 +541,7 @@ mixin SceneOperationsDataHelper { operationName: 'Motionless Detection Sensitivity', code: 'motionless_sensitivity', functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( iconValue: '1', @@ -386,6 +582,7 @@ mixin SceneOperationsDataHelper { operationName: 'Indicator', code: 'indicator', functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -400,6 +597,7 @@ mixin SceneOperationsDataHelper { operationName: 'Nobody Time', code: 'presence_time', functionValue: functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -431,6 +629,7 @@ mixin SceneOperationsDataHelper { operationName: 'Switch Alarm Sound', code: 'switch_alarm_sound', functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -445,6 +644,7 @@ mixin SceneOperationsDataHelper { operationName: 'Master State', code: 'master_state', functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -465,6 +665,7 @@ mixin SceneOperationsDataHelper { operationName: 'Factory Reset', code: 'factory_reset', functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSceneRefresh, description: "ON", value: true), @@ -490,6 +691,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 1 Switch', code: 'switch_1', functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -504,6 +706,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 2 Switch', code: 'switch_2', functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -518,6 +721,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 3 Switch', code: 'switch_3', functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -532,6 +736,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 1 CountDown', code: 'countdown_1', functionValue: functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -543,6 +748,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 2 CountDown', code: 'countdown_2', functionValue: functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -554,6 +760,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 3 CountDown', code: 'countdown_3', functionValue: functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -577,6 +784,7 @@ mixin SceneOperationsDataHelper { operationName: 'Power', code: 'switch', functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -597,6 +805,7 @@ mixin SceneOperationsDataHelper { operationName: 'Mode', code: 'mode', functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcCooling, @@ -622,6 +831,7 @@ mixin SceneOperationsDataHelper { operationName: 'Set Temperature', code: 'temp_set', functionValue: functionValue, + operationDialogType: OperationDialogType.temperature, operationalValues: [ SceneOperationalValue( icon: Assets.assetsCelsiusDegrees, @@ -637,6 +847,7 @@ mixin SceneOperationsDataHelper { operationName: 'Fan Speed', code: 'level', functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcFanLow, @@ -667,6 +878,7 @@ mixin SceneOperationsDataHelper { operationName: 'Child Lock', code: 'child_lock', functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSceneChildLock, @@ -700,6 +912,7 @@ mixin SceneOperationsDataHelper { deviceIcon: Assets.delay, icon: Assets.delay, operationName: 'delay', + operationDialogType: OperationDialogType.delay, functionValue: action.executorProperty.delaySeconds, code: '', operationalValues: [ @@ -725,6 +938,7 @@ mixin SceneOperationsDataHelper { operationName: 'Sensitivity', code: 'sensitivity', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, @@ -790,6 +1004,7 @@ mixin SceneOperationsDataHelper { operationName: 'Set Door lock Normal Open', functionValue: executorProperty.functionValue, code: 'normal_open_switch', + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -812,6 +1027,7 @@ mixin SceneOperationsDataHelper { operationName: 'Far Detection', functionValue: executorProperty.functionValue, code: 'far_detection', + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsFarDetectionFunction, @@ -875,6 +1091,7 @@ mixin SceneOperationsDataHelper { operationName: 'Motion Detection Sensitivity', functionValue: executorProperty.functionValue, code: 'motion_sensitivity_value', + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, @@ -915,6 +1132,7 @@ mixin SceneOperationsDataHelper { operationName: 'Motionless Detection Sensitivity', functionValue: executorProperty.functionValue, code: 'motion_sensitivity_value', + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( iconValue: '1', @@ -960,9 +1178,13 @@ mixin SceneOperationsDataHelper { operationName: 'Indicator', functionValue: executorProperty.functionValue, code: 'indicator', + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), SceneOperationalValue( icon: Assets.assetsAcPowerOFF, description: "OFF", @@ -982,6 +1204,7 @@ mixin SceneOperationsDataHelper { operationName: 'Nobody Time', functionValue: executorProperty.functionValue, code: 'presence_time', + operationDialogType: OperationDialogType.temperature, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -998,6 +1221,7 @@ mixin SceneOperationsDataHelper { operationName: 'Switch Alarm Sound', functionValue: executorProperty.functionValue, code: 'switch_alarm_sound', + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -1022,6 +1246,7 @@ mixin SceneOperationsDataHelper { operationName: 'Master State', functionValue: executorProperty.functionValue, code: 'master_state', + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -1047,6 +1272,7 @@ mixin SceneOperationsDataHelper { operationName: 'Reset Factory', functionValue: executorProperty.functionValue, code: 'factory_reset', + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSceneRefresh, @@ -1070,6 +1296,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 1 Switch', code: 'switch_1', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -1080,11 +1307,11 @@ mixin SceneOperationsDataHelper { icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - SceneOperationalValue( - icon: Assets.assetsSceneRefresh, - description: "Reverse Switch", - value: null, - ), + // SceneOperationalValue( + // icon: Assets.assetsSceneRefresh, + // description: "Reverse Switch", + // value: null, + // ), ], )); break; @@ -1097,6 +1324,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 2 Switch', code: 'switch_2', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -1104,11 +1332,11 @@ mixin SceneOperationsDataHelper { icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - SceneOperationalValue( - icon: Assets.assetsSceneRefresh, - description: "Reverse Switch", - value: null, - ), + // SceneOperationalValue( + // icon: Assets.assetsSceneRefresh, + // description: "Reverse Switch", + // value: null, + // ), ], )); break; @@ -1121,6 +1349,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 3 Switch', code: 'switch_3', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -1128,11 +1357,11 @@ mixin SceneOperationsDataHelper { icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - SceneOperationalValue( - icon: Assets.assetsSceneRefresh, - description: "Reverse Switch", - value: null, - ), + // SceneOperationalValue( + // icon: Assets.assetsSceneRefresh, + // description: "Reverse Switch", + // value: null, + // ), ], )); break; @@ -1145,6 +1374,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 1 CountDown', code: 'countdown_1', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -1159,6 +1389,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 2 CountDown', code: 'countdown_2', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -1173,6 +1404,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 3 CountDown', code: 'countdown_3', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -1187,6 +1419,7 @@ mixin SceneOperationsDataHelper { operationName: 'Power', code: 'switch', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -1210,6 +1443,7 @@ mixin SceneOperationsDataHelper { operationName: 'Set Temperature', code: 'temp_set', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.temperature, operationalValues: [ SceneOperationalValue( icon: Assets.assetsCelsiusDegrees, @@ -1228,6 +1462,7 @@ mixin SceneOperationsDataHelper { operationName: 'Mode', code: 'mode', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcCooling, @@ -1256,6 +1491,7 @@ mixin SceneOperationsDataHelper { operationName: 'Fan Speed', code: 'level', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcFanLow, @@ -1289,6 +1525,7 @@ mixin SceneOperationsDataHelper { operationName: 'Child Lock', code: 'child_lock', functionValue: executorProperty.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSceneChildLock, @@ -1330,6 +1567,7 @@ mixin SceneOperationsDataHelper { operationName: 'delay', functionValue: taskItem.functionValue, code: '', + operationDialogType: OperationDialogType.delay, operationalValues: [ SceneOperationalValue( icon: '', @@ -1352,6 +1590,7 @@ mixin SceneOperationsDataHelper { operationName: 'Sensitivity', code: 'sensitivity', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, @@ -1417,6 +1656,7 @@ mixin SceneOperationsDataHelper { operationName: 'Set Door lock Normal Open', functionValue: taskItem.functionValue, code: 'normal_open_switch', + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -1439,6 +1679,7 @@ mixin SceneOperationsDataHelper { operationName: 'Far Detection', functionValue: taskItem.functionValue, code: 'far_detection', + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsFarDetectionFunction, @@ -1502,6 +1743,7 @@ mixin SceneOperationsDataHelper { operationName: 'Motion Detection Sensitivity', functionValue: taskItem.functionValue, code: 'motion_sensitivity_value', + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, @@ -1542,6 +1784,7 @@ mixin SceneOperationsDataHelper { operationName: 'Motionless Detection Sensitivity', functionValue: taskItem.functionValue, code: 'motion_sensitivity_value', + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( iconValue: '1', @@ -1587,6 +1830,7 @@ mixin SceneOperationsDataHelper { operationName: 'Indicator', functionValue: taskItem.functionValue, code: 'indicator', + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -1609,6 +1853,7 @@ mixin SceneOperationsDataHelper { operationName: 'Nobody Time', functionValue: taskItem.functionValue, code: 'presence_time', + operationDialogType: OperationDialogType.temperature, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -1625,6 +1870,7 @@ mixin SceneOperationsDataHelper { operationName: 'Switch Alarm Sound', functionValue: taskItem.functionValue, code: 'switch_alarm_sound', + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -1649,6 +1895,7 @@ mixin SceneOperationsDataHelper { operationName: 'Master State', functionValue: taskItem.functionValue, code: 'master_state', + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -1674,6 +1921,7 @@ mixin SceneOperationsDataHelper { operationName: 'Reset Factory', functionValue: taskItem.functionValue, code: 'factory_reset', + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSceneRefresh, @@ -1697,6 +1945,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 1 Switch', code: 'switch_1', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -1719,6 +1968,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 2 Switch', code: 'switch_2', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -1738,6 +1988,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 3 Switch', code: 'switch_3', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, description: "ON", value: true), @@ -1757,6 +2008,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 1 CountDown', code: 'countdown_1', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -1771,6 +2023,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 2 CountDown', code: 'countdown_2', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -1785,6 +2038,7 @@ mixin SceneOperationsDataHelper { operationName: 'Light 3 CountDown', code: 'countdown_3', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.countdown, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], @@ -1799,6 +2053,7 @@ mixin SceneOperationsDataHelper { operationName: 'Power', code: 'switch', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcPower, @@ -1824,6 +2079,7 @@ mixin SceneOperationsDataHelper { functionValue: taskItem.functionValue != null ? ((taskItem.functionValue / 10) as double).toInt() : null, + operationDialogType: OperationDialogType.temperature, operationalValues: [ SceneOperationalValue( icon: Assets.assetsCelsiusDegrees, @@ -1842,6 +2098,7 @@ mixin SceneOperationsDataHelper { operationName: 'Mode', code: 'mode', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcCooling, @@ -1870,6 +2127,7 @@ mixin SceneOperationsDataHelper { operationName: 'Fan Speed', code: 'level', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.listOfOptions, operationalValues: [ SceneOperationalValue( icon: Assets.assetsAcFanLow, @@ -1903,6 +2161,7 @@ mixin SceneOperationsDataHelper { operationName: 'Child Lock', code: 'child_lock', functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, operationalValues: [ SceneOperationalValue( icon: Assets.assetsSceneChildLock, diff --git a/lib/features/scene/model/scene_static_function.dart b/lib/features/scene/model/scene_static_function.dart index 43f7f09..7b364f3 100644 --- a/lib/features/scene/model/scene_static_function.dart +++ b/lib/features/scene/model/scene_static_function.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; import 'package:uuid/uuid.dart'; class SceneStaticFunction { @@ -13,6 +14,7 @@ class SceneStaticFunction { final String uniqueCustomId; final dynamic functionValue; final String? deviceIcon; + final OperationDialogType operationDialogType; SceneStaticFunction({ required this.icon, @@ -23,6 +25,7 @@ class SceneStaticFunction { required this.operationName, required this.functionValue, this.deviceIcon, + required this.operationDialogType, }) : uniqueCustomId = const Uuid().v4(); SceneStaticFunction copyWith({ @@ -35,6 +38,7 @@ class SceneStaticFunction { dynamic functionValue, String? deviceIcon, String? deviceName, + OperationDialogType? operationDialogType, }) { return SceneStaticFunction( icon: icon ?? this.icon, @@ -45,6 +49,7 @@ class SceneStaticFunction { operationName: operationName ?? this.operationName, functionValue: functionValue ?? this.functionValue, deviceIcon: deviceIcon ?? this.deviceIcon, + operationDialogType: operationDialogType ?? this.operationDialogType, ); } @@ -57,8 +62,8 @@ class SceneStaticFunction { 'deviceId': deviceId, 'operationName': operationName, 'functionValue': functionValue, - 'deviceIcon': deviceIcon - + 'deviceIcon': deviceIcon, + 'operationDialogType': operationDialogType.name }; } @@ -74,6 +79,9 @@ class SceneStaticFunction { operationName: map['operationName'] ?? '', functionValue: map['functionValue'] ?? '', deviceIcon: map['deviceIcon'] ?? '', + operationDialogType: map['operationDialogType'] != null + ? OperationDialogType.values.byName(map['operationDialogType']) + : OperationDialogType.none, ); } @@ -84,7 +92,7 @@ class SceneStaticFunction { @override String toString() { - return 'SceneStaticFunction(icon: $icon, name: $deviceName, code: $code, operationalValues: $operationalValues, deviceId: $deviceId, operationName: $operationName, functionValue: $functionValue, deviceIcon: $deviceIcon)'; + return 'SceneStaticFunction(icon: $icon, name: $deviceName, code: $code, operationalValues: $operationalValues, deviceId: $deviceId, operationName: $operationName, functionValue: $functionValue, deviceIcon: $deviceIcon, operationDialogType: $operationDialogType)'; } @override @@ -98,6 +106,7 @@ class SceneStaticFunction { other.operationName == operationName && other.functionValue == functionValue && other.deviceIcon == deviceIcon && + other.operationDialogType == operationDialogType && listEquals(other.operationalValues, operationalValues) && other.deviceId == deviceId; } @@ -111,6 +120,7 @@ class SceneStaticFunction { operationName.hashCode ^ functionValue.hashCode ^ deviceIcon.hashCode ^ + operationDialogType.hashCode ^ operationalValues.hashCode; } } diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index 74aeb7a..45daa3c 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -3,6 +3,8 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; +import 'package:syncrow_app/features/scene/helper/scene_logic_helper.dart'; import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart'; @@ -19,7 +21,7 @@ import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class DeviceFunctionsView extends StatelessWidget - with SceneOperationsDataHelper { + with SceneOperationsDataHelper, SceneLogicHelper { const DeviceFunctionsView({super.key}); @override @@ -88,136 +90,130 @@ class DeviceFunctionsView extends StatelessWidget ), leadingWidth: 80, padding: EdgeInsets.zero, - child: Padding( + child: ListView.builder( + shrinkWrap: true, + itemCount: functions.length, padding: const EdgeInsets.only(top: 24.0), - child: ListView.builder( - shrinkWrap: true, - itemCount: functions.length, - padding: EdgeInsets.zero, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - return DefaultContainer( - padding: index == 0 - ? const EdgeInsets.only(top: 8) - : index == functions.length - 1 - ? const EdgeInsets.only(bottom: 8) - : EdgeInsets.zero, - margin: EdgeInsets.zero, - borderRadius: index == 0 - ? const BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20)) - : index == functions.length - 1 - ? const BorderRadius.only( - bottomLeft: Radius.circular(20), - bottomRight: Radius.circular(20)) - : BorderRadius.zero, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - BlocBuilder( - builder: (context, state) { - return SceneListTile( - iconsSize: 22, - minLeadingWidth: 20, - assetPath: functions[index].icon, - titleString: functions[index].operationName, - trailingWidget: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - /// selected value or the default value - // BodyMedium(text: ), - Icon( - Icons.arrow_forward_ios_rounded, - color: ColorsManager.greyColor, - size: 16, - ), - ], - ), - onPressed: () { - final functionValues = context - .read() - .selectedValues[functions[index].code]; + itemBuilder: (context, index) { + return DefaultContainer( + padding: index == 0 + ? const EdgeInsets.only(top: 8) + : index == functions.length - 1 + ? const EdgeInsets.only(bottom: 8) + : EdgeInsets.zero, + margin: EdgeInsets.zero, + borderRadius: index == 0 + ? const BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20)) + : index == functions.length - 1 + ? const BorderRadius.only( + bottomLeft: Radius.circular(20), + bottomRight: Radius.circular(20)) + : BorderRadius.zero, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + BlocBuilder( + builder: (context, state) { + return SceneListTile( + iconsSize: 22, + minLeadingWidth: 20, + assetPath: functions[index].icon, + titleString: functions[index].operationName, + trailingWidget: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + /// selected value or the default value + // BodyMedium(text: ), + Icon( + Icons.arrow_forward_ios_rounded, + color: ColorsManager.greyColor, + size: 16, + ), + ], + ), + onPressed: () { + final functionValues = context + .read() + .selectedValues[functions[index].code]; - context.customAlertDialog( - alertBody: functions[index].code == 'temp_set' - ? AlertDialogTemperatureBody( - taskItem: functions[index], - functionValue: functionValues, - ) - : (functions[index] - .code - .contains('countdown') || - functions[index] - .code - .contains('presence_time')) - ? AlertDialogCountdown( - durationValue: functions[index] - .operationalValues - .first - .value, - function: functions[index], - functionValue: functionValues, - ) - : AlertDialogFunctionsOperationsBody( - taskItem: functions[index], - functionValue: functionValues, - ), - title: functions[index].operationName, - onConfirm: () { - final selectedValue = context - .read() - .selectedValues[functions[index].code]; - if (selectedValue == null) { - return; - } - context - .read() - .add(TempHoldSceneTasksEvent( - deviceControlModel: DeviceControlModel( - deviceId: device.uuid, - code: functions[index].code, - value: selectedValue, + context.customAlertDialog( + alertBody: functions[index].operationDialogType == + OperationDialogType.temperature + ? AlertDialogTemperatureBody( + taskItem: functions[index], + functionValue: functionValues, + ) + : ((functions[index].operationDialogType == + OperationDialogType.countdown) || + (functions[index].operationDialogType == + OperationDialogType.countdown)) + ? AlertDialogCountdown( + durationValue: functions[index] + .operationalValues + .first + .value, + function: functions[index], + functionValue: functionValues, + ) + : AlertDialogFunctionsOperationsBody( + taskItem: functions[index], + functionValue: functionValues, ), - deviceId: device.uuid ?? '', - operation: functions[index].operationName, - icon: device.icon ?? '', - deviceName: device.name ?? '', - uniqueId: functions[index].uniqueCustomId, - )); - Navigator.pop(context); - }, - onDismiss: () { - final tempTaskList = context - .read() - .tempTasksList; - for (var element in tempTaskList) { - if (element.code == functions[index].code) { - context.read().add( - RemoveTempTaskByIdEvent( - code: functions[index].code)); - context.read().add( - RemoveFromSelectedValueById( - code: functions[index].code)); - } + title: functions[index].operationName, + onConfirm: () { + final selectedValue = context + .read() + .selectedValues[functions[index].code]; + if (selectedValue == null) { + return; + } + context + .read() + .add(TempHoldSceneTasksEvent( + deviceControlModel: DeviceControlModel( + deviceId: device.uuid, + code: functions[index].code, + value: selectedValue, + ), + deviceId: device.uuid ?? '', + operation: functions[index].operationName, + icon: device.icon ?? '', + deviceName: device.name ?? '', + uniqueId: functions[index].uniqueCustomId, + )); + Navigator.pop(context); + }, + onDismiss: () { + final tempTaskList = + context.read().tempTasksList; + for (var element in tempTaskList) { + if (element.code == functions[index].code) { + context.read().add( + RemoveTempTaskByIdEvent( + code: functions[index].code)); + context.read().add( + RemoveFromSelectedValueById( + code: functions[index].code)); } - Navigator.pop(context); - }, - ); - }, - ); - }, - ), - index != functions.length - 1 - ? SizedBox( - width: context.width * 0.8, - child: const LightDivider()) - : const SizedBox(), - ], - ), - ); - }, - ), + } + Navigator.pop(context); + }, + ); + }, + ); + }, + ), + index != functions.length - 1 + ? SizedBox( + width: context.width * 0.8, + child: const LightDivider()) + : const SizedBox(), + ], + ), + ); + }, )); } } diff --git a/lib/features/scene/widgets/bottom_sheet_widget.dart b/lib/features/scene/widgets/bottom_sheet_widget.dart index 1bbd631..6967cae 100644 --- a/lib/features/scene/widgets/bottom_sheet_widget.dart +++ b/lib/features/scene/widgets/bottom_sheet_widget.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; @@ -97,6 +98,7 @@ class CustomBottomSheetWidget extends StatelessWidget { operationName: 'Delay The Action', code: '', functionValue: 0, + operationDialogType: OperationDialogType.delay, operationalValues: [ SceneOperationalValue(icon: '', value: 0), ], diff --git a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart index a50b2a6..07c2d82 100644 --- a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart +++ b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart @@ -62,7 +62,7 @@ class ThenAddedTasksContainer extends StatelessWidget /// show alert dialog based on type context.customAlertDialog( - alertBody: getTheCorrectDialogBody(functionOperation.first), + alertBody: getTheCorrectDialogBody(functionOperation.first, null), title: functionOperation.first.operationName, onConfirm: () { final savedCode = functionOperation.first.deviceId.contains('delay') diff --git a/pubspec.yaml b/pubspec.yaml index 3708e95..aaead8f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -74,7 +74,7 @@ flutter: - assets/icons/MenuIcons/SecurityAndPrivacyIcons/ - assets/icons/curtainsIcon/ - assets/icons/functions_icons/ - - assets/icons/functions_icons/automation_functions + - assets/icons/functions_icons/automation_functions/ fonts: - family: Aftika fonts: From 5142fc57f92c1c9c03447e6b67868a1224955576 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sun, 14 Jul 2024 21:39:44 +0300 Subject: [PATCH 03/30] push devices automation functions --- .../automation_functions/current_temp.svg | 11 + .../automation_functions/motion.svg | 14 + .../automation_functions/presence.svg | 18 + .../automation_functions/self_test_result.svg | 23 + .../functions_per_device/ac_functions.dart | 265 +++ .../door_lock_functions.dart | 240 +++ .../gateway_functions.dart | 62 + .../human_presence_functions.dart | 174 ++ .../functions_per_device/presence_sensor.dart | 181 ++ .../three_gang_functions.dart | 92 + .../helper/scene_operations_data_helper.dart | 1919 ++++++----------- .../scene/view/create_scene_view.dart | 1 + .../scene/view/device_functions_view.dart | 30 +- .../if_then_containers/if_container.dart | 74 +- .../scene_devices/scene_devices_body.dart | 9 +- lib/generated/assets.dart | 20 + 16 files changed, 1855 insertions(+), 1278 deletions(-) create mode 100644 assets/icons/functions_icons/automation_functions/current_temp.svg create mode 100644 assets/icons/functions_icons/automation_functions/motion.svg create mode 100644 assets/icons/functions_icons/automation_functions/presence.svg create mode 100644 assets/icons/functions_icons/automation_functions/self_test_result.svg create mode 100644 lib/features/scene/helper/functions_per_device/ac_functions.dart create mode 100644 lib/features/scene/helper/functions_per_device/door_lock_functions.dart create mode 100644 lib/features/scene/helper/functions_per_device/gateway_functions.dart create mode 100644 lib/features/scene/helper/functions_per_device/human_presence_functions.dart create mode 100644 lib/features/scene/helper/functions_per_device/presence_sensor.dart create mode 100644 lib/features/scene/helper/functions_per_device/three_gang_functions.dart diff --git a/assets/icons/functions_icons/automation_functions/current_temp.svg b/assets/icons/functions_icons/automation_functions/current_temp.svg new file mode 100644 index 0000000..42cceb2 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/current_temp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/motion.svg b/assets/icons/functions_icons/automation_functions/motion.svg new file mode 100644 index 0000000..8d69463 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/motion.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/presence.svg b/assets/icons/functions_icons/automation_functions/presence.svg new file mode 100644 index 0000000..d71a474 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/presence.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/automation_functions/self_test_result.svg b/assets/icons/functions_icons/automation_functions/self_test_result.svg new file mode 100644 index 0000000..8739327 --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/self_test_result.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/features/scene/helper/functions_per_device/ac_functions.dart b/lib/features/scene/helper/functions_per_device/ac_functions.dart new file mode 100644 index 0000000..b295696 --- /dev/null +++ b/lib/features/scene/helper/functions_per_device/ac_functions.dart @@ -0,0 +1,265 @@ +import 'package:syncrow_app/features/scene/enum/ac_values.dart'; +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/utils/resource_manager/constants.dart'; + +class ACFunctionsHelper { + static List tabToRunAcFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsAcPower, + operationName: 'Power', + code: 'switch', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFreezing, + operationName: 'Mode', + code: 'mode', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcCooling, + description: AcValuesEnums.Cooling.name, + value: TempModes.cold.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcHeating, + description: AcValuesEnums.Heating.name, + value: TempModes.hot.name, + ), + SceneOperationalValue( + icon: Assets.assetsFanSpeed, + description: AcValuesEnums.Ventilation.name, + value: TempModes.wind.name, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsTempreture, + operationName: 'Set Temperature', + code: 'temp_set', + functionValue: functionValue, + operationDialogType: OperationDialogType.temperature, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsCelsiusDegrees, + value: 0, + description: 'COOL TO', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFanSpeed, + operationName: 'Fan Speed', + code: 'level', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcFanLow, + description: ValueACRange.LOW.name, + value: FanSpeeds.low.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanMiddle, + description: ValueACRange.MIDDLE.name, + value: FanSpeeds.middle.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanHigh, + description: ValueACRange.HIGH.name, + value: FanSpeeds.high.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanAuto, + description: ValueACRange.AUTO.name, + value: FanSpeeds.auto.name, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsChildLock, + operationName: 'Child Lock', + code: 'child_lock', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSceneChildLock, + description: 'Lock', + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsSceneChildUnlock, + description: 'Unlock', + value: false, + ), + ], + ), + ]; + } + + static List automationAcFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsAcPower, + operationName: 'Power', + code: 'switch', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFreezing, + operationName: 'Mode', + code: 'mode', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcCooling, + description: AcValuesEnums.Cooling.name, + value: TempModes.cold.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcHeating, + description: AcValuesEnums.Heating.name, + value: TempModes.hot.name, + ), + SceneOperationalValue( + icon: Assets.assetsFanSpeed, + description: AcValuesEnums.Ventilation.name, + value: TempModes.wind.name, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsTempreture, + operationName: 'Set Temperature', + code: 'temp_set', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsCelsiusDegrees, + value: 0, + description: 'COOL TO', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsCurrentTemp, + operationName: 'Current Temperature', + code: 'temp_current', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsCelsiusDegrees, + value: 0, + description: 'COOL TO', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFanSpeed, + operationName: 'Fan Speed', + code: 'level', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcFanLow, + description: ValueACRange.LOW.name, + value: FanSpeeds.low.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanMiddle, + description: ValueACRange.MIDDLE.name, + value: FanSpeeds.middle.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanHigh, + description: ValueACRange.HIGH.name, + value: FanSpeeds.high.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanAuto, + description: ValueACRange.AUTO.name, + value: FanSpeeds.auto.name, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsChildLock, + operationName: 'Child Lock', + code: 'child_lock', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSceneChildLock, + description: 'Lock', + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsSceneChildUnlock, + description: 'Unlock', + value: false, + ), + ], + ), + ]; + } +} diff --git a/lib/features/scene/helper/functions_per_device/door_lock_functions.dart b/lib/features/scene/helper/functions_per_device/door_lock_functions.dart new file mode 100644 index 0000000..ac504b4 --- /dev/null +++ b/lib/features/scene/helper/functions_per_device/door_lock_functions.dart @@ -0,0 +1,240 @@ +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/generated/assets.dart'; + +class DoorLockHelperFunctions { + /// tab to run functions + static List doorLockTapToRunFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIconsDoorLock, + operationName: 'Set Door lock Normal Open', + functionValue: functionValue, + code: 'normal_open_switch', + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + ]; + } + + //// automation functions + static List doorLockAutomationFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFingerprintUnlock, + operationName: 'Fingerprint Unlock', + functionValue: functionValue, + code: 'unlock_fingerprint', + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsPasswordUnlock, + operationName: 'Password Unlock', + functionValue: functionValue, + code: 'unlock_password', + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsCardUnlock, + operationName: 'Card Unlock', + functionValue: functionValue, + code: 'unlock_card', + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsLockAlarm, + operationName: 'Lock Alarm', + functionValue: functionValue, + code: 'alarm_lock', + operationDialogType: OperationDialogType.none, + operationalValues: [], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsRemoteUnlockReq, + operationName: 'Remote Unlock Request', + functionValue: functionValue, + code: 'unlock_request', + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsResidualElectricity, + operationName: 'Residual Electricity', + functionValue: functionValue, + code: 'residual_electricity', + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsDoubleLock, + operationName: 'Double Lock', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + code: 'reverse_lock', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsRemoteUnlockViaApp, + operationName: 'Remote Unlock Via App', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + code: 'unlock_app', + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsHijackAlarm, + operationName: 'Hijack Alarm', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + code: 'hijack', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsDoorlockNormalOpen, + operationName: 'Set Door Lock Normal Open', + functionValue: functionValue, + code: 'normal_open_switch', + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsDoorlockNormalOpen, + operationName: 'Doorbell', + functionValue: functionValue, + code: 'doorbell', + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsTempPasswordUnlock, + operationName: 'Temporary Password Unlock', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + code: 'unlock_temporary', + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), + ], + ), + ]; + } +} diff --git a/lib/features/scene/helper/functions_per_device/gateway_functions.dart b/lib/features/scene/helper/functions_per_device/gateway_functions.dart new file mode 100644 index 0000000..7a356a7 --- /dev/null +++ b/lib/features/scene/helper/functions_per_device/gateway_functions.dart @@ -0,0 +1,62 @@ +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/generated/assets.dart'; + +class GatewayHelperFunctions { + static List tabToRunGatewayFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsSwitchAlarmSound, + operationName: 'Switch Alarm Sound', + code: 'switch_alarm_sound', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsMasterState, + operationName: 'Master State', + code: 'master_state', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "Alarm", + value: 'alarm', + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "Normal", + value: 'normal', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFactoryReset, + operationName: 'Factory Reset', + code: 'factory_reset', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSceneRefresh, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsResetOff, description: "OFF", value: false), + ], + ), + ]; + } +} diff --git a/lib/features/scene/helper/functions_per_device/human_presence_functions.dart b/lib/features/scene/helper/functions_per_device/human_presence_functions.dart new file mode 100644 index 0000000..f29431a --- /dev/null +++ b/lib/features/scene/helper/functions_per_device/human_presence_functions.dart @@ -0,0 +1,174 @@ +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/generated/assets.dart'; + +class HumanPresenceHelperFunctions { + static List tabToRunHumanPresenceFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFarDetection, + operationName: 'Far Detection', + code: 'far_detection', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 75, + description: '75cm', + iconValue: '75', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 150, + description: '150cm', + iconValue: '150', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 225, + description: '225cm', + iconValue: '225', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 300, + description: '300cm', + iconValue: '300', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 375, + description: '375cm', + iconValue: '375', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 450, + description: '450cm', + iconValue: '450', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 525, + description: '525cm', + iconValue: '525', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 600, + description: '600cm', + iconValue: '600', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsMotionDetection, + operationName: 'Motion Detection Sensitivity', + code: 'motion_sensitivity_value', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 1, + description: 1.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 2, + description: 2.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 3, + description: 3.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 4, + description: 4.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 5, + description: 5.toString(), + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsMotionlessDetection, + operationName: 'Motionless Detection Sensitivity', + code: 'motionless_sensitivity', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + iconValue: '1', + icon: Assets.assetsFarDetectionFunction, + value: 1, + description: '1', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 2, + description: '2', + iconValue: '2', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 3, + description: '3', + iconValue: '3', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 4, + description: '4', + iconValue: '4', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 5, + description: '5', + iconValue: '5', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIndicator, + operationName: 'Indicator', + code: 'indicator', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsNobodyTime, + operationName: 'Nobody Time', + code: 'presence_time', + functionValue: functionValue, + operationDialogType: OperationDialogType.countdown, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ), + ]; + } +} diff --git a/lib/features/scene/helper/functions_per_device/presence_sensor.dart b/lib/features/scene/helper/functions_per_device/presence_sensor.dart new file mode 100644 index 0000000..fcd30b1 --- /dev/null +++ b/lib/features/scene/helper/functions_per_device/presence_sensor.dart @@ -0,0 +1,181 @@ +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/generated/assets.dart'; + +class PresenceSensorHelperFunctions { + static List tabToRunPresenceSensorFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsSensitivityFunction, + operationName: 'Sensitivity', + code: 'sensitivity', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 1, + description: 1.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 2, + description: 2.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 3, + description: 3.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 4, + description: 4.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 5, + description: 5.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 6, + description: 6.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 7, + description: 7.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 8, + description: 8.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 9, + description: 9.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 10, + description: 10.toString(), + ), + ], + ), + ]; + } + + static List automationPresenceSensorFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIconsSensors, + operationName: 'Presence Status', + code: 'presence_state', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsIconsPresenceSensorAssetsEmpty, + value: 'none', + description: 'None', + ), + SceneOperationalValue( + icon: Assets.assetsPresence, + value: 'presence', + description: 'Presence', + ), + SceneOperationalValue( + icon: Assets.assetsMotion, + value: 'motion', + description: 'Motion', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsSensitivityFunction, + operationName: 'Sensitivity', + code: 'sensitivity', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 1, + description: 1.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 2, + description: 2.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 3, + description: 3.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 4, + description: 4.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 5, + description: 5.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 6, + description: 6.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 7, + description: 7.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 8, + description: 8.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 9, + description: 9.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 10, + description: 10.toString(), + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsSelfTestResult, + operationName: 'Self-Test Result', + code: 'checking_result', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSelfTestResult, + value: 'check_success', + description: 'Self Testing Success', + ), + ], + ), + ]; + } +} diff --git a/lib/features/scene/helper/functions_per_device/three_gang_functions.dart b/lib/features/scene/helper/functions_per_device/three_gang_functions.dart new file mode 100644 index 0000000..6c0d9c9 --- /dev/null +++ b/lib/features/scene/helper/functions_per_device/three_gang_functions.dart @@ -0,0 +1,92 @@ +import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/generated/assets.dart'; + +class ThreeGangHelperFunctions { + static List threeGangHelperFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsAcPower, + operationName: 'Light 1 Switch', + code: 'switch_1', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsAcPower, + operationName: 'Light 2 Switch', + code: 'switch_2', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsAcPower, + operationName: 'Light 3 Switch', + code: 'switch_3', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsLightCountdown, + operationName: 'Light 1 CountDown', + code: 'countdown_1', + functionValue: functionValue, + operationDialogType: OperationDialogType.countdown, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsLightCountdown, + operationName: 'Light 2 CountDown', + code: 'countdown_2', + functionValue: functionValue, + operationDialogType: OperationDialogType.countdown, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsLightCountdown, + operationName: 'Light 3 CountDown', + code: 'countdown_3', + functionValue: functionValue, + operationDialogType: OperationDialogType.countdown, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ), + ]; + } +} diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index a93bcfd..037d2be 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -1,6 +1,12 @@ import 'package:syncrow_app/features/devices/model/function_model.dart'; import 'package:syncrow_app/features/scene/enum/ac_values.dart'; import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; +import 'package:syncrow_app/features/scene/helper/functions_per_device/ac_functions.dart'; +import 'package:syncrow_app/features/scene/helper/functions_per_device/door_lock_functions.dart'; +import 'package:syncrow_app/features/scene/helper/functions_per_device/gateway_functions.dart'; +import 'package:syncrow_app/features/scene/helper/functions_per_device/human_presence_functions.dart'; +import 'package:syncrow_app/features/scene/helper/functions_per_device/presence_sensor.dart'; +import 'package:syncrow_app/features/scene/helper/functions_per_device/three_gang_functions.dart'; import 'package:syncrow_app/features/scene/model/scene_details_model.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/generated/assets.dart'; @@ -121,69 +127,12 @@ mixin SceneOperationsDataHelper { required dynamic functionValue, required bool isAutomation, }) { - return [ - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsSensitivityFunction, - operationName: 'Sensitivity', - code: 'sensitivity', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 6, - description: 6.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 7, - description: 7.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 8, - description: 8.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 9, - description: 9.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 10, - description: 10.toString(), - ), - ], - ), - ]; + if (isAutomation) { + return PresenceSensorHelperFunctions.automationPresenceSensorFunctions( + deviceId, deviceName, functionValue); + } + return PresenceSensorHelperFunctions.tabToRunPresenceSensorFunctions( + deviceId, deviceName, functionValue); } List curtainFunctions( @@ -203,232 +152,11 @@ mixin SceneOperationsDataHelper { required bool isAutomation, }) { if (isAutomation) { - return [ - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsFingerprintUnlock, - operationName: 'Fingerprint Unlock', - functionValue: functionValue, - code: 'unlock_fingerprint', - operationDialogType: OperationDialogType.integerSteps, - operationalValues: [ - SceneOperationalValue( - icon: '', - description: "", - value: 0, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsPasswordUnlock, - operationName: 'Password Unlock', - functionValue: functionValue, - code: 'unlock_password', - operationDialogType: OperationDialogType.integerSteps, - operationalValues: [ - SceneOperationalValue( - icon: '', - description: "", - value: 0, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsCardUnlock, - operationName: 'Card Unlock', - functionValue: functionValue, - code: 'unlock_card', - operationDialogType: OperationDialogType.integerSteps, - operationalValues: [ - SceneOperationalValue( - icon: '', - description: "", - value: 0, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsLockAlarm, - operationName: 'Lock Alarm', - functionValue: functionValue, - code: 'alarm_lock', - operationDialogType: OperationDialogType.none, - operationalValues: [], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsRemoteUnlockReq, - operationName: 'Remote Unlock Request', - functionValue: functionValue, - code: 'unlock_request', - operationDialogType: OperationDialogType.integerSteps, - operationalValues: [ - SceneOperationalValue( - icon: '', - description: "", - value: 0, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsResidualElectricity, - operationName: 'Residual Electricity', - functionValue: functionValue, - code: 'residual_electricity', - operationDialogType: OperationDialogType.integerSteps, - operationalValues: [ - SceneOperationalValue( - icon: '', - description: "", - value: 0, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsDoubleLock, - operationName: 'Double Lock', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - code: 'reverse_lock', - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsRemoteUnlockViaApp, - operationName: 'Remote Unlock Via App', - functionValue: functionValue, - operationDialogType: OperationDialogType.integerSteps, - code: 'unlock_app', - operationalValues: [ - SceneOperationalValue( - icon: '', - description: "", - value: 0, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsHijackAlarm, - operationName: 'Hijack Alarm', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - code: 'hijack', - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsDoorlockNormalOpen, - operationName: 'Set Door Lock Normal Open', - functionValue: functionValue, - code: 'normal_open_switch', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsDoorlockNormalOpen, - operationName: 'Doorbell', - functionValue: functionValue, - code: 'doorbell', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsTempPasswordUnlock, - operationName: 'Temporary Password Unlock', - functionValue: functionValue, - operationDialogType: OperationDialogType.integerSteps, - code: 'unlock_temporary', - operationalValues: [ - SceneOperationalValue( - icon: '', - description: "", - value: 0, - ), - ], - ), - ]; + return DoorLockHelperFunctions.doorLockAutomationFunctions( + deviceId, deviceName, functionValue); } - return [ - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsIconsDoorLock, - operationName: 'Set Door lock Normal Open', - functionValue: functionValue, - code: 'normal_open_switch', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ), - ]; + return DoorLockHelperFunctions.doorLockTapToRunFunctions( + deviceId, deviceName, functionValue); } List wallSensorFunctions({ @@ -438,171 +166,8 @@ mixin SceneOperationsDataHelper { required functionValue, required bool isAutomation, }) { - return [ - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsFarDetection, - operationName: 'Far Detection', - code: 'far_detection', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 75, - description: '75cm', - iconValue: '75', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 150, - description: '150cm', - iconValue: '150', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 225, - description: '225cm', - iconValue: '225', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 300, - description: '300cm', - iconValue: '300', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 375, - description: '375cm', - iconValue: '375', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 450, - description: '450cm', - iconValue: '450', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 525, - description: '525cm', - iconValue: '525', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 600, - description: '600cm', - iconValue: '600', - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsMotionDetection, - operationName: 'Motion Detection Sensitivity', - code: 'motion_sensitivity_value', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsMotionlessDetection, - operationName: 'Motionless Detection Sensitivity', - code: 'motionless_sensitivity', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - iconValue: '1', - icon: Assets.assetsFarDetectionFunction, - value: 1, - description: '1', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 2, - description: '2', - iconValue: '2', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 3, - description: '3', - iconValue: '3', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 4, - description: '4', - iconValue: '4', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 5, - description: '5', - iconValue: '5', - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsIndicator, - operationName: 'Indicator', - code: 'indicator', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsNobodyTime, - operationName: 'Nobody Time', - code: 'presence_time', - functionValue: functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ), - ]; + return HumanPresenceHelperFunctions.tabToRunHumanPresenceFunctions( + deviceId, deviceName, functionValue); } List lightBulbFunctions( @@ -621,59 +186,8 @@ mixin SceneOperationsDataHelper { required functionValue, required bool isAutomation, }) { - return [ - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsSwitchAlarmSound, - operationName: 'Switch Alarm Sound', - code: 'switch_alarm_sound', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsMasterState, - operationName: 'Master State', - code: 'master_state', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "Alarm", - value: 'alarm', - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "Normal", - value: 'normal', - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsFactoryReset, - operationName: 'Factory Reset', - code: 'factory_reset', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSceneRefresh, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsResetOff, description: "OFF", value: false), - ], - ), - ]; + return GatewayHelperFunctions.tabToRunGatewayFunctions( + deviceId, deviceName, functionValue); } List threeGangFunctions({ @@ -683,89 +197,8 @@ mixin SceneOperationsDataHelper { required functionValue, required bool isAutomation, }) { - return [ - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsAcPower, - operationName: 'Light 1 Switch', - code: 'switch_1', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsAcPower, - operationName: 'Light 2 Switch', - code: 'switch_2', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsAcPower, - operationName: 'Light 3 Switch', - code: 'switch_3', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsLightCountdown, - operationName: 'Light 1 CountDown', - code: 'countdown_1', - functionValue: functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsLightCountdown, - operationName: 'Light 2 CountDown', - code: 'countdown_2', - functionValue: functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsLightCountdown, - operationName: 'Light 3 CountDown', - code: 'countdown_3', - functionValue: functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ), - ]; + return ThreeGangHelperFunctions.threeGangHelperFunctions( + deviceId, deviceName, functionValue); } /// smart ac thermostat @@ -776,123 +209,12 @@ mixin SceneOperationsDataHelper { required functionValue, required bool isAutomation, }) { - return [ - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsAcPower, - operationName: 'Power', - code: 'switch', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsFreezing, - operationName: 'Mode', - code: 'mode', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcCooling, - description: AcValuesEnums.Cooling.name, - value: TempModes.cold.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcHeating, - description: AcValuesEnums.Heating.name, - value: TempModes.hot.name, - ), - SceneOperationalValue( - icon: Assets.assetsFanSpeed, - description: AcValuesEnums.Ventilation.name, - value: TempModes.wind.name, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsTempreture, - operationName: 'Set Temperature', - code: 'temp_set', - functionValue: functionValue, - operationDialogType: OperationDialogType.temperature, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsCelsiusDegrees, - value: 0, - description: 'COOL TO', - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsFanSpeed, - operationName: 'Fan Speed', - code: 'level', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcFanLow, - description: ValueACRange.LOW.name, - value: FanSpeeds.low.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanMiddle, - description: ValueACRange.MIDDLE.name, - value: FanSpeeds.middle.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanHigh, - description: ValueACRange.HIGH.name, - value: FanSpeeds.high.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanAuto, - description: ValueACRange.AUTO.name, - value: FanSpeeds.auto.name, - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsChildLock, - operationName: 'Child Lock', - code: 'child_lock', - functionValue: functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSceneChildLock, - description: 'Lock', - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsSceneChildUnlock, - description: 'Unlock', - value: false, - ), - ], - ), - ]; + if (isAutomation) { + return ACFunctionsHelper.automationAcFunctions( + deviceId, deviceName, functionValue); + } + return ACFunctionsHelper.tabToRunAcFunctions( + deviceId, deviceName, functionValue); } ///////&************ END of get function with icons for device *************&&//////// @@ -1582,603 +904,720 @@ mixin SceneOperationsDataHelper { switch (taskItem.code) { case 'sensitivity': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsSensitivityFunction, - operationName: 'Sensitivity', - code: 'sensitivity', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 6, - description: 6.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 7, - description: 7.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 8, - description: 8.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 9, - description: 9.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 10, - description: 10.toString(), - ), - ], - ), + sensitivityFunctionsBasedOnCodeMatch(deviceId, taskItem), ); break; case 'normal_open_switch': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'WIFI LOCK PRO', - deviceIcon: Assets.assetsIconsDoorLock, - icon: Assets.assetsIconsDoorLock, - operationName: 'Set Door lock Normal Open', - functionValue: taskItem.functionValue, - code: 'normal_open_switch', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ), + normalOpenSwitchBasedOnCodeMatch(deviceId, taskItem), ); break; case 'far_detection': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsFarDetection, - operationName: 'Far Detection', - functionValue: taskItem.functionValue, - code: 'far_detection', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 75, - description: '75cm', - iconValue: '75', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 150, - description: '150cm', - iconValue: '150', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 225, - description: '225cm', - iconValue: '225', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 300, - description: '300cm', - iconValue: '300', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 375, - description: '375cm', - iconValue: '375', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 450, - description: '450cm', - iconValue: '450', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 525, - description: '525cm', - iconValue: '525', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 600, - description: '600cm', - iconValue: '600', - ), - ], - ), + farDetectionBasedOnCodeMatch(deviceId, taskItem), ); break; case 'motion_sensitivity_value': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsMotionDetection, - operationName: 'Motion Detection Sensitivity', - functionValue: taskItem.functionValue, - code: 'motion_sensitivity_value', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - ], - ), + motionSensitivityValueBasedOnCodeMatch(deviceId, taskItem), ); break; case 'motionless_sensitivity': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsMotionlessDetection, - operationName: 'Motionless Detection Sensitivity', - functionValue: taskItem.functionValue, - code: 'motion_sensitivity_value', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - iconValue: '1', - icon: Assets.assetsFarDetectionFunction, - value: 1, - description: '1', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 2, - description: '2', - iconValue: '2', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 3, - description: '3', - iconValue: '3', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 4, - description: '4', - iconValue: '4', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 5, - description: '5', - iconValue: '5', - ), - ], - ), + motionlessSensitivityBasedOnCodeMatch(deviceId, taskItem), ); break; case 'indicator': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsIndicator, - operationName: 'Indicator', - functionValue: taskItem.functionValue, - code: 'indicator', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ), + indicatorBasedOnCodeMatch(deviceId, taskItem), ); break; case 'presence_time': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsNobodyTime, - operationName: 'Nobody Time', - functionValue: taskItem.functionValue, - code: 'presence_time', - operationDialogType: OperationDialogType.temperature, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ), + presenceTimeBasedOnCodeMatch(deviceId, taskItem), ); break; case 'switch_alarm_sound': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Multi-Mode Gateway Z-W-B', - deviceIcon: Assets.assetsIconsGateway, - icon: Assets.assetsSwitchAlarmSound, - operationName: 'Switch Alarm Sound', - functionValue: taskItem.functionValue, - code: 'switch_alarm_sound', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false), - ], - ), + switchAlarmSoundBasedOnCodeMatch(deviceId, taskItem), ); break; case 'master_state': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Multi-Mode Gateway Z-W-B', - deviceIcon: Assets.assetsIconsGateway, - icon: Assets.assetsMasterState, - operationName: 'Master State', - functionValue: taskItem.functionValue, - code: 'master_state', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "Alarm", - value: 'alarm', - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "Normal", - value: 'normal', - ), - ], - ), + masterStateBasedOnCodeMatch(deviceId, taskItem), ); break; case 'factory_reset': functions.add( - SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Multi-Mode Gateway Z-W-B', - deviceIcon: Assets.assetsIconsGateway, - icon: Assets.assetsFactoryReset, - operationName: 'Reset Factory', - functionValue: taskItem.functionValue, - code: 'factory_reset', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSceneRefresh, - description: "ON", - value: true), - SceneOperationalValue( - icon: Assets.assetsResetOff, - description: "OFF", - value: false, - ), - ], - ), + factoryResetBasedOnCodeMatch(deviceId, taskItem), ); break; case 'switch_1': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsAcPower, - operationName: 'Light 1 Switch', - code: 'switch_1', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false), - ], - )); + functions.add( + switch1BasedOnCodeMatch(deviceId, taskItem), + ); break; case 'switch_2': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsAcPower, - operationName: 'Light 2 Switch', - code: 'switch_2', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false), - ], - )); + functions.add( + switch2BasedOnCodeMatch(deviceId, taskItem), + ); break; case 'switch_3': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsAcPower, - operationName: 'Light 3 Switch', - code: 'switch_3', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false), - ], - )); + functions.add( + switch3BasedOnCodeMatch(deviceId, taskItem), + ); break; case 'countdown_1': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsLightCountdown, - operationName: 'Light 1 CountDown', - code: 'countdown_1', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - )); + functions.add( + countdown1BasedOnCodeMatch(deviceId, taskItem), + ); break; case 'countdown_2': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsLightCountdown, - operationName: 'Light 2 CountDown', - code: 'countdown_2', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - )); + functions.add( + countdown2BasedOnCodeMatch(deviceId, taskItem), + ); break; case 'countdown_3': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsLightCountdown, - operationName: 'Light 3 CountDown', - code: 'countdown_3', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - )); + functions.add( + countdown3BasedOnCodeMatch(deviceId, taskItem), + ); break; case 'switch': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsAcPower, - operationName: 'Power', - code: 'switch', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - )); + functions.add( + switchBasedOnCodeMatch(deviceId, taskItem), + ); break; case 'temp_set': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsTempreture, - operationName: 'Set Temperature', - code: 'temp_set', - functionValue: taskItem.functionValue != null - ? ((taskItem.functionValue / 10) as double).toInt() - : null, - operationDialogType: OperationDialogType.temperature, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsCelsiusDegrees, - value: 0, - description: 'COOL TO', - ), - ], - )); + functions.add( + tempSetBasedOnCodeMatch(deviceId, taskItem), + ); break; case 'mode': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsFreezing, - operationName: 'Mode', - code: 'mode', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcCooling, - description: AcValuesEnums.Cooling.name, - value: TempModes.cold.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcHeating, - description: AcValuesEnums.Heating.name, - value: TempModes.hot.name, - ), - SceneOperationalValue( - icon: Assets.assetsFanSpeed, - description: AcValuesEnums.Ventilation.name, - value: TempModes.wind.name, - ), - ], - )); + functions.add( + modeBasedOnCodeMatch(deviceId, taskItem), + ); break; case 'level': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsFanSpeed, - operationName: 'Fan Speed', - code: 'level', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcFanLow, - description: ValueACRange.LOW.name, - value: FanSpeeds.low.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanMiddle, - description: ValueACRange.MIDDLE.name, - value: FanSpeeds.middle.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanHigh, - description: ValueACRange.HIGH.name, - value: FanSpeeds.high.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanAuto, - description: ValueACRange.AUTO.name, - value: FanSpeeds.auto.name, - ), - ], - )); + functions.add( + levelBasedOnCodeMatch(deviceId, taskItem), + ); break; case 'child_lock': - functions.add(SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsChildLock, - operationName: 'Child Lock', - code: 'child_lock', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSceneChildLock, - description: 'Lock', - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsSceneChildUnlock, - description: 'Unlock', - value: false, - ), - ], - )); + functions.add( + childLockBasedOnCodeMatch(deviceId, taskItem), + ); break; default: } return functions; } + + SceneStaticFunction childLockBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsChildLock, + operationName: 'Child Lock', + code: 'child_lock', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSceneChildLock, + description: 'Lock', + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsSceneChildUnlock, + description: 'Unlock', + value: false, + ), + ], + ); + } + + SceneStaticFunction levelBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsFanSpeed, + operationName: 'Fan Speed', + code: 'level', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcFanLow, + description: ValueACRange.LOW.name, + value: FanSpeeds.low.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanMiddle, + description: ValueACRange.MIDDLE.name, + value: FanSpeeds.middle.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanHigh, + description: ValueACRange.HIGH.name, + value: FanSpeeds.high.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcFanAuto, + description: ValueACRange.AUTO.name, + value: FanSpeeds.auto.name, + ), + ], + ); + } + + SceneStaticFunction modeBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsFreezing, + operationName: 'Mode', + code: 'mode', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcCooling, + description: AcValuesEnums.Cooling.name, + value: TempModes.cold.name, + ), + SceneOperationalValue( + icon: Assets.assetsAcHeating, + description: AcValuesEnums.Heating.name, + value: TempModes.hot.name, + ), + SceneOperationalValue( + icon: Assets.assetsFanSpeed, + description: AcValuesEnums.Ventilation.name, + value: TempModes.wind.name, + ), + ], + ); + } + + SceneStaticFunction tempSetBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsTempreture, + operationName: 'Set Temperature', + code: 'temp_set', + functionValue: taskItem.functionValue != null + ? ((taskItem.functionValue / 10) as double).toInt() + : null, + operationDialogType: OperationDialogType.temperature, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsCelsiusDegrees, + value: 0, + description: 'COOL TO', + ), + ], + ); + } + + SceneStaticFunction switchBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Smart AC Thermostat - Grey - Model A', + deviceIcon: Assets.assetsIconsAC, + icon: Assets.assetsAcPower, + operationName: 'Power', + code: 'switch', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ); + } + + SceneStaticFunction countdown3BasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsLightCountdown, + operationName: 'Light 3 CountDown', + code: 'countdown_3', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.countdown, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ); + } + + SceneStaticFunction countdown2BasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsLightCountdown, + operationName: 'Light 2 CountDown', + code: 'countdown_2', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.countdown, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ); + } + + SceneStaticFunction countdown1BasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsLightCountdown, + operationName: 'Light 1 CountDown', + code: 'countdown_1', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.countdown, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ); + } + + SceneStaticFunction switch3BasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsAcPower, + operationName: 'Light 3 Switch', + code: 'switch_3', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ); + } + + SceneStaticFunction switch2BasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsAcPower, + operationName: 'Light 2 Switch', + code: 'switch_2', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ); + } + + SceneStaticFunction switch1BasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: '3 Gang Button Switch L-L', + deviceIcon: Assets.assetsIcons3GangSwitch, + icon: Assets.assetsAcPower, + operationName: 'Light 1 Switch', + code: 'switch_1', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ); + } + + SceneStaticFunction factoryResetBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Multi-Mode Gateway Z-W-B', + deviceIcon: Assets.assetsIconsGateway, + icon: Assets.assetsFactoryReset, + operationName: 'Reset Factory', + functionValue: taskItem.functionValue, + code: 'factory_reset', + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSceneRefresh, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsResetOff, + description: "OFF", + value: false, + ), + ], + ); + } + + SceneStaticFunction masterStateBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Multi-Mode Gateway Z-W-B', + deviceIcon: Assets.assetsIconsGateway, + icon: Assets.assetsMasterState, + operationName: 'Master State', + functionValue: taskItem.functionValue, + code: 'master_state', + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "Alarm", + value: 'alarm', + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "Normal", + value: 'normal', + ), + ], + ); + } + + SceneStaticFunction switchAlarmSoundBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Multi-Mode Gateway Z-W-B', + deviceIcon: Assets.assetsIconsGateway, + icon: Assets.assetsSwitchAlarmSound, + operationName: 'Switch Alarm Sound', + functionValue: taskItem.functionValue, + code: 'switch_alarm_sound', + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ); + } + + SceneStaticFunction presenceTimeBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsNobodyTime, + operationName: 'Nobody Time', + functionValue: taskItem.functionValue, + code: 'presence_time', + operationDialogType: OperationDialogType.temperature, + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ); + } + + SceneStaticFunction indicatorBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsIndicator, + operationName: 'Indicator', + functionValue: taskItem.functionValue, + code: 'indicator', + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ); + } + + SceneStaticFunction motionlessSensitivityBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsMotionlessDetection, + operationName: 'Motionless Detection Sensitivity', + functionValue: taskItem.functionValue, + code: 'motion_sensitivity_value', + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + iconValue: '1', + icon: Assets.assetsFarDetectionFunction, + value: 1, + description: '1', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 2, + description: '2', + iconValue: '2', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 3, + description: '3', + iconValue: '3', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 4, + description: '4', + iconValue: '4', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 5, + description: '5', + iconValue: '5', + ), + ], + ); + } + + SceneStaticFunction motionSensitivityValueBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsMotionDetection, + operationName: 'Motion Detection Sensitivity', + functionValue: taskItem.functionValue, + code: 'motion_sensitivity_value', + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 1, + description: 1.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 2, + description: 2.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 3, + description: 3.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 4, + description: 4.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 5, + description: 5.toString(), + ), + ], + ); + } + + SceneStaticFunction farDetectionBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Human Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsFarDetection, + operationName: 'Far Detection', + functionValue: taskItem.functionValue, + code: 'far_detection', + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 75, + description: '75cm', + iconValue: '75', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 150, + description: '150cm', + iconValue: '150', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 225, + description: '225cm', + iconValue: '225', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 300, + description: '300cm', + iconValue: '300', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 375, + description: '375cm', + iconValue: '375', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 450, + description: '450cm', + iconValue: '450', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 525, + description: '525cm', + iconValue: '525', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 600, + description: '600cm', + iconValue: '600', + ), + ], + ); + } + + SceneStaticFunction normalOpenSwitchBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'WIFI LOCK PRO', + deviceIcon: Assets.assetsIconsDoorLock, + icon: Assets.assetsIconsDoorLock, + operationName: 'Set Door lock Normal Open', + functionValue: taskItem.functionValue, + code: 'normal_open_switch', + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ], + ); + } + + SceneStaticFunction sensitivityFunctionsBasedOnCodeMatch( + String deviceId, SceneStaticFunction taskItem) { + return SceneStaticFunction( + deviceId: deviceId, + deviceName: 'Presence Sensor', + deviceIcon: Assets.assetsIconsSensors, + icon: Assets.assetsSensitivityFunction, + operationName: 'Sensitivity', + code: 'sensitivity', + functionValue: taskItem.functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 1, + description: 1.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 2, + description: 2.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 3, + description: 3.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 4, + description: 4.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 5, + description: 5.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 6, + description: 6.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 7, + description: 7.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 8, + description: 8.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 9, + description: 9.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 10, + description: 10.toString(), + ), + ], + ); + } } diff --git a/lib/features/scene/view/create_scene_view.dart b/lib/features/scene/view/create_scene_view.dart index 11e2ff0..f89e512 100644 --- a/lib/features/scene/view/create_scene_view.dart +++ b/lib/features/scene/view/create_scene_view.dart @@ -68,6 +68,7 @@ class CreateSceneView extends StatelessWidget { sceneName: '', ), ); + context.read().add(const ClearTaskListEvent()); }, ), ], diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index 45daa3c..a6ef3b1 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -3,13 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; -import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; import 'package:syncrow_app/features/scene/helper/scene_logic_helper.dart'; import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; -import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart'; -import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart'; -import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; @@ -139,28 +135,10 @@ class DeviceFunctionsView extends StatelessWidget .selectedValues[functions[index].code]; context.customAlertDialog( - alertBody: functions[index].operationDialogType == - OperationDialogType.temperature - ? AlertDialogTemperatureBody( - taskItem: functions[index], - functionValue: functionValues, - ) - : ((functions[index].operationDialogType == - OperationDialogType.countdown) || - (functions[index].operationDialogType == - OperationDialogType.countdown)) - ? AlertDialogCountdown( - durationValue: functions[index] - .operationalValues - .first - .value, - function: functions[index], - functionValue: functionValues, - ) - : AlertDialogFunctionsOperationsBody( - taskItem: functions[index], - functionValue: functionValues, - ), + alertBody: getTheCorrectDialogBody( + functions[index], + functionValues, + ), title: functions[index].operationName, onConfirm: () { final selectedValue = context diff --git a/lib/features/scene/widgets/if_then_containers/if_container.dart b/lib/features/scene/widgets/if_then_containers/if_container.dart index 104b255..f2bceff 100644 --- a/lib/features/scene/widgets/if_then_containers/if_container.dart +++ b/lib/features/scene/widgets/if_then_containers/if_container.dart @@ -1,13 +1,17 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; +import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/light_divider.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; -import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; class IFDefaultContainer extends StatelessWidget { const IFDefaultContainer({ @@ -29,19 +33,73 @@ class IFDefaultContainer extends StatelessWidget { color: ColorsManager.primaryTextColor, ), ), - trailingWidget: SvgPicture.asset(Assets.addIcon), + trailingWidget: GestureDetector( + onTap: () => Navigator.pushNamed( + context, + Routes.sceneControlDevicesRoute, + arguments: SceneSettingsRouteArguments( + sceneType: CreateSceneEnum.deviceStatusChanges.name, + sceneId: '', + sceneName: '', + ), + ), + child: SvgPicture.asset( + Assets.addIcon, + colorFilter: const ColorFilter.mode( + ColorsManager.primaryColor, + BlendMode.srcIn, + ), + ), + ), padding: EdgeInsets.zero, ), const LightDivider(), - const SceneListTile( - assetPath: Assets.handClickIcon, - titleString: StringsManager.tapToRun, - padding: EdgeInsets.zero, + BlocBuilder( + builder: (context, state) { + if (state is CreateSceneLoading) { + return const Center(child: LinearProgressIndicator()); + } + + // if (state is AddSceneTask) { + // final taskLists = state.tasksList; + // if (taskLists.isNotEmpty) { + // return ListView.builder( + // shrinkWrap: true, + // physics: const NeverScrollableScrollPhysics(), + // itemCount: taskLists.length, + // reverse: true, + // itemBuilder: (context, index) { + // return ThenAddedTasksContainer( + // taskItem: taskLists[index], + // ); + // }, + // ); + // } + // return SceneListTile( + // titleString: '+ Add Task', + // textAlign: TextAlign.center, + // onPressed: () => context.customBottomSheet( + // child: const CustomBottomSheetWidget(), + // ), + // ); + // } + return SceneListTile( + titleString: '+ Add Condition', + textAlign: TextAlign.center, + onPressed: () => Navigator.pushNamed( + context, + Routes.sceneControlDevicesRoute, + arguments: SceneSettingsRouteArguments( + sceneType: CreateSceneEnum.deviceStatusChanges.name, + sceneId: '', + sceneName: '', + ), + ), + ); + }, ) ], ), ); } } - - diff --git a/lib/features/scene/widgets/scene_devices/scene_devices_body.dart b/lib/features/scene/widgets/scene_devices/scene_devices_body.dart index 0c3b9ab..60e97c8 100644 --- a/lib/features/scene/widgets/scene_devices/scene_devices_body.dart +++ b/lib/features/scene/widgets/scene_devices/scene_devices_body.dart @@ -28,10 +28,11 @@ class SceneDevicesBody extends StatelessWidget { @override Widget build(BuildContext context) { - final isAutomationDeviceStatus = (ModalRoute.of(context)?.settings.arguments - as SceneSettingsRouteArguments) - .sceneType == - CreateSceneEnum.deviceStatusChanges.name; + final isAutomationDeviceStatus = ((ModalRoute.of(context) + ?.settings + .arguments as SceneSettingsRouteArguments?) + ?.sceneType == + CreateSceneEnum.deviceStatusChanges.name); return BlocBuilder( builder: (context, tabState) { return Column( diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index d6599ef..0b31f0e 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -1004,4 +1004,24 @@ class Assets { static const String assetsTempPasswordUnlock = "assets/icons/functions_icons/automation_functions/temp_password_unlock.svg"; + + //assets/icons/functions_icons/automation_functions/self_test_result.svg + + static const String assetsSelfTestResult = + "assets/icons/functions_icons/automation_functions/self_test_result.svg"; + + ///assets/icons/functions_icons/automation_functions/presence.svg + + static const String assetsPresence = + "assets/icons/functions_icons/automation_functions/presence.svg"; + + //assets/icons/functions_icons/automation_functions/motion.svg + + static const String assetsMotion = + "assets/icons/functions_icons/automation_functions/motion.svg"; + + //assets/icons/functions_icons/automation_functions/current_temp.svg + + static const String assetsCurrentTemp = + "assets/icons/functions_icons/automation_functions/current_temp.svg"; } From 9ea499746766a3268d3a0bf95fac6533d10a5984 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Tue, 16 Jul 2024 01:13:45 +0300 Subject: [PATCH 04/30] push integer step dialog design --- .../automation_functions/presence_state.svg | 18 ++ ios/Podfile.lock | 16 +- .../functions_per_device/ac_functions.dart | 14 +- .../door_lock_functions.dart | 45 +++- .../human_presence_functions.dart | 235 ++++++++++++++++++ .../functions_per_device/presence_sensor.dart | 56 +---- .../scene/helper/scene_logic_helper.dart | 7 + .../helper/scene_operations_data_helper.dart | 4 + .../scene/model/scene_static_function.dart | 28 ++- .../alert_dialog_slider_steps.dart | 143 +++++++++++ lib/generated/assets.dart | 5 + 11 files changed, 499 insertions(+), 72 deletions(-) create mode 100644 assets/icons/functions_icons/automation_functions/presence_state.svg create mode 100644 lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart diff --git a/assets/icons/functions_icons/automation_functions/presence_state.svg b/assets/icons/functions_icons/automation_functions/presence_state.svg new file mode 100644 index 0000000..d5de48e --- /dev/null +++ b/assets/icons/functions_icons/automation_functions/presence_state.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 8c3f26a..0037d1d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -42,9 +42,9 @@ PODS: - FirebaseCoreInternal (~> 10.0) - GoogleUtilities/Environment (~> 7.12) - GoogleUtilities/Logger (~> 7.12) - - FirebaseCoreExtension (10.27.0): + - FirebaseCoreExtension (10.29.0): - FirebaseCore (~> 10.0) - - FirebaseCoreInternal (10.27.0): + - FirebaseCoreInternal (10.29.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" - FirebaseCrashlytics (10.20.0): - FirebaseCore (~> 10.5) @@ -54,12 +54,12 @@ PODS: - GoogleUtilities/Environment (~> 7.8) - nanopb (< 2.30910.0, >= 2.30908.0) - PromisesObjC (~> 2.1) - - FirebaseInstallations (10.27.0): + - FirebaseInstallations (10.29.0): - FirebaseCore (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) - PromisesObjC (~> 2.1) - - FirebaseSessions (10.27.0): + - FirebaseSessions (10.29.0): - FirebaseCore (~> 10.5) - FirebaseCoreExtension (~> 10.0) - FirebaseInstallations (~> 10.0) @@ -266,11 +266,11 @@ SPEC CHECKSUMS: firebase_crashlytics: 012078b4eec6fc9716f97ba3da0f0e44a04e95b1 FirebaseAnalytics: a2731bf3670747ce8f65368b118d18aa8e368246 FirebaseCore: 28045c1560a2600d284b9c45a904fe322dc890b6 - FirebaseCoreExtension: 4ec89dd0c6de93d6becde32122d68b7c35f6bf5d - FirebaseCoreInternal: 4b297a2d56063dbea2c1d0d04222d44a8d058862 + FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f + FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934 FirebaseCrashlytics: 81530595edb6d99f1918f723a6c33766a24a4c86 - FirebaseInstallations: 766dabca09fd94aef922538aaf144cc4a6fb6869 - FirebaseSessions: 2fdf949f9e58295a57703ae8f2efc44f9fa3aa16 + FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd + FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_localization: f43b18844a2b3d2c71fd64f04ffd6b1e64dd54d4 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be diff --git a/lib/features/scene/helper/functions_per_device/ac_functions.dart b/lib/features/scene/helper/functions_per_device/ac_functions.dart index b295696..35b47bd 100644 --- a/lib/features/scene/helper/functions_per_device/ac_functions.dart +++ b/lib/features/scene/helper/functions_per_device/ac_functions.dart @@ -187,8 +187,11 @@ class ACFunctionsHelper { operationalValues: [ SceneOperationalValue( icon: Assets.assetsCelsiusDegrees, - value: 0, - description: 'COOL TO', + value: 0.0, + description: '°C', + minValue: 20, + maxValue: 30, + stepValue: 0.5, ), ], ), @@ -203,8 +206,11 @@ class ACFunctionsHelper { operationalValues: [ SceneOperationalValue( icon: Assets.assetsCelsiusDegrees, - value: 0, - description: 'COOL TO', + value: 0.0, + description: '°C', + minValue: -9.9, + maxValue: 99.9, + stepValue: 0.1, ), ], ), diff --git a/lib/features/scene/helper/functions_per_device/door_lock_functions.dart b/lib/features/scene/helper/functions_per_device/door_lock_functions.dart index ac504b4..81f3589 100644 --- a/lib/features/scene/helper/functions_per_device/door_lock_functions.dart +++ b/lib/features/scene/helper/functions_per_device/door_lock_functions.dart @@ -41,7 +41,10 @@ class DoorLockHelperFunctions { SceneOperationalValue( icon: '', description: "", - value: 0, + value: 0.0, + minValue: 0.0, + maxValue: 999, + stepValue: 1.0, ), ], ), @@ -57,7 +60,10 @@ class DoorLockHelperFunctions { SceneOperationalValue( icon: '', description: "", - value: 0, + value: 0.0, + minValue: 0.0, + maxValue: 999, + stepValue: 1.0, ), ], ), @@ -73,7 +79,10 @@ class DoorLockHelperFunctions { SceneOperationalValue( icon: '', description: "", - value: 0, + value: 0.0, + minValue: 0.0, + maxValue: 999, + stepValue: 1.0, ), ], ), @@ -84,8 +93,14 @@ class DoorLockHelperFunctions { operationName: 'Lock Alarm', functionValue: functionValue, code: 'alarm_lock', - operationDialogType: OperationDialogType.none, - operationalValues: [], + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsFingerprintUnlock, + description: "Fingerprint Mismatch", + value: 0, + ), + ], ), SceneStaticFunction( deviceId: deviceId, @@ -99,7 +114,10 @@ class DoorLockHelperFunctions { SceneOperationalValue( icon: '', description: "", - value: 0, + value: 0.0, + minValue: 0, + maxValue: 90, + stepValue: 1, ), ], ), @@ -115,7 +133,10 @@ class DoorLockHelperFunctions { SceneOperationalValue( icon: '', description: "", - value: 0, + value: 0.0, + minValue: 0, + maxValue: 100, + stepValue: 1, ), ], ), @@ -152,7 +173,10 @@ class DoorLockHelperFunctions { SceneOperationalValue( icon: '', description: "", - value: 0, + value: 0.0, + minValue: 0, + maxValue: 999, + stepValue: 1, ), ], ), @@ -231,7 +255,10 @@ class DoorLockHelperFunctions { SceneOperationalValue( icon: '', description: "", - value: 0, + value: 0.0, + minValue: 0, + maxValue: 999, + stepValue: 1, ), ], ), diff --git a/lib/features/scene/helper/functions_per_device/human_presence_functions.dart b/lib/features/scene/helper/functions_per_device/human_presence_functions.dart index f29431a..bb3f49d 100644 --- a/lib/features/scene/helper/functions_per_device/human_presence_functions.dart +++ b/lib/features/scene/helper/functions_per_device/human_presence_functions.dart @@ -171,4 +171,239 @@ class HumanPresenceHelperFunctions { ), ]; } + + static List automationHumanPresenceFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsPresenceState, + operationName: 'Presence State', + code: 'presence_state', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsIconsPresenceSensorAssetsEmpty, + value: 'none', + description: 'None', + ), + SceneOperationalValue( + icon: Assets.assetsPresence, + value: 'presence', + description: 'Presence', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIconsPresenceSensorAssetsDistance, + operationName: 'Current Distance', + code: 'dis_current', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + value: 0.0, + description: "CM", + minValue: 1, + maxValue: 600, + stepValue: 1, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIconsPresenceSensorAssetsIlluminanceValue, + operationName: 'Illuminance Value', + code: 'illuminance_value', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + value: 0.0, + description: "Lux", + minValue: 0, + maxValue: 10000, + stepValue: 1, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFarDetection, + operationName: 'Far Detection', + code: 'far_detection', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 75, + description: '75cm', + iconValue: '75', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 150, + description: '150cm', + iconValue: '150', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 225, + description: '225cm', + iconValue: '225', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 300, + description: '300cm', + iconValue: '300', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 375, + description: '375cm', + iconValue: '375', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 450, + description: '450cm', + iconValue: '450', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 525, + description: '525cm', + iconValue: '525', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 600, + description: '600cm', + iconValue: '600', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsMotionDetection, + operationName: 'Motion Detection Sensitivity', + code: 'motion_sensitivity_value', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 1, + description: 1.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 2, + description: 2.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 3, + description: 3.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 4, + description: 4.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 5, + description: 5.toString(), + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsMotionlessDetection, + operationName: 'Motionless Detection Sensitivity', + code: 'motionless_sensitivity', + functionValue: functionValue, + operationDialogType: OperationDialogType.listOfOptions, + operationalValues: [ + SceneOperationalValue( + iconValue: '1', + icon: Assets.assetsFarDetectionFunction, + value: 1, + description: '1', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 2, + description: '2', + iconValue: '2', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 3, + description: '3', + iconValue: '3', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 4, + description: '4', + iconValue: '4', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 5, + description: '5', + iconValue: '5', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIndicator, + operationName: 'Indicator', + code: 'indicator', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIconsPresenceSensorAssetsTime, + operationName: 'Presence Time', + code: 'presence_time', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + value: 0.0, + minValue: 0.0, + maxValue: 65535, + stepValue: 1, + description: 'min' + ), + ], + ), + ]; + } } diff --git a/lib/features/scene/helper/functions_per_device/presence_sensor.dart b/lib/features/scene/helper/functions_per_device/presence_sensor.dart index fcd30b1..ee7aa54 100644 --- a/lib/features/scene/helper/functions_per_device/presence_sensor.dart +++ b/lib/features/scene/helper/functions_per_device/presence_sensor.dart @@ -106,57 +106,15 @@ class PresenceSensorHelperFunctions { operationName: 'Sensitivity', code: 'sensitivity', functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, + operationDialogType: OperationDialogType.integerSteps, operationalValues: [ SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 6, - description: 6.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 7, - description: 7.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 8, - description: 8.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 9, - description: 9.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 10, - description: 10.toString(), + icon: '', + description: "", + value: 0.0, + minValue: 0, + maxValue: 10, + stepValue: 1, ), ], ), diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 4372692..95d302d 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -10,6 +10,7 @@ import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart'; +import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart'; import 'package:syncrow_app/utils/context_extension.dart'; @@ -96,6 +97,12 @@ mixin SceneLogicHelper { functionValue: functionValue ?? taskItem.functionValue, function: taskItem, ); + } else if (taskItem.operationDialogType == + OperationDialogType.integerSteps) { + return AlertDialogSliderSteps( + taskItem: taskItem, + functionValue: functionValue ?? taskItem.functionValue, + ); } return AlertDialogFunctionsOperationsBody( diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index 037d2be..bb4e672 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -166,6 +166,10 @@ mixin SceneOperationsDataHelper { required functionValue, required bool isAutomation, }) { + if (isAutomation) { + return HumanPresenceHelperFunctions.automationHumanPresenceFunctions( + deviceId, deviceName, functionValue); + } return HumanPresenceHelperFunctions.tabToRunHumanPresenceFunctions( deviceId, deviceName, functionValue); } diff --git a/lib/features/scene/model/scene_static_function.dart b/lib/features/scene/model/scene_static_function.dart index 7b364f3..cd1a3d3 100644 --- a/lib/features/scene/model/scene_static_function.dart +++ b/lib/features/scene/model/scene_static_function.dart @@ -130,12 +130,18 @@ class SceneOperationalValue { final dynamic value; final String? description; final String? iconValue; + final double? minValue; + final double? maxValue; + final double? stepValue; SceneOperationalValue({ required this.icon, required this.value, this.description, this.iconValue, + this.minValue, + this.maxValue, + this.stepValue, }); SceneOperationalValue copyWith({ @@ -143,12 +149,18 @@ class SceneOperationalValue { dynamic value, String? description, String? iconValue, + double? minValue, + double? maxValue, + double? stepValue, }) { return SceneOperationalValue( icon: icon ?? this.icon, value: value ?? this.value, description: description ?? this.description, iconValue: iconValue ?? this.iconValue, + minValue: minValue ?? this.minValue, + maxValue: maxValue ?? this.maxValue, + stepValue: stepValue ?? this.stepValue, ); } @@ -157,7 +169,10 @@ class SceneOperationalValue { 'icon': icon, 'value': value, 'description': description, - 'iconValue': iconValue + 'iconValue': iconValue, + 'minValue': minValue, + 'maxValue': maxValue, + 'stepValue': stepValue }; } @@ -167,6 +182,9 @@ class SceneOperationalValue { value: map['value'], description: map['description'], iconValue: map['iconValue'] ?? '', + minValue: map['minValue'], + maxValue: map['maxValue'], + stepValue: map['stepValue'], ); } @@ -177,7 +195,7 @@ class SceneOperationalValue { @override String toString() => - 'StaticFunctionOperationHelper(icon: $icon, value: $value, description: $description, iconValue: $iconValue)'; + 'StaticFunctionOperationHelper(icon: $icon, value: $value, description: $description, iconValue: $iconValue, minValue: $minValue, maxValue: $maxValue, stepValue: $stepValue)'; @override bool operator ==(Object other) { @@ -187,6 +205,9 @@ class SceneOperationalValue { other.icon == icon && other.description == description && other.iconValue == iconValue && + other.minValue == minValue && + other.maxValue == maxValue && + other.stepValue == stepValue && other.value == value; } @@ -196,5 +217,8 @@ class SceneOperationalValue { value.hashCode ^ description.hashCode ^ iconValue.hashCode ^ + minValue.hashCode ^ + maxValue.hashCode ^ + stepValue.hashCode ^ description.hashCode; } diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart new file mode 100644 index 0000000..2b6b594 --- /dev/null +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/title_small.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class AlertDialogSliderSteps extends StatefulWidget { + const AlertDialogSliderSteps({ + super.key, + this.functionValue, + required this.taskItem, + }); + + final dynamic functionValue; + final SceneStaticFunction taskItem; + + @override + State createState() => _AlertDialogSliderStepsState(); +} + +class _AlertDialogSliderStepsState extends State { + double? groupValue; + int selectedToggleIndex = 0; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + final tempTaskList = context.read().tempTasksList; + if (tempTaskList.isNotEmpty) { + for (var element in tempTaskList) { + if (element.code == widget.taskItem.code) { + groupValue = element.functionValue; + } else { + context + .read() + .add(RemoveFromSelectedValueById(code: widget.taskItem.code)); + } + } + } + if (widget.functionValue != null) { + setState(() { + groupValue = widget.functionValue; + }); + } else { + groupValue = widget.taskItem.operationalValues[0].minValue; + } + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + ToggleButtons( + isSelected: [ + selectedToggleIndex == 0, + selectedToggleIndex == 1, + selectedToggleIndex == 2 + ], + onPressed: (index) { + setState(() { + selectedToggleIndex = index; + }); + }, + borderRadius: BorderRadius.circular(30), + selectedColor: Colors.white, + color: ColorsManager.blackColor, + fillColor: ColorsManager.primaryColorWithOpacity, + constraints: const BoxConstraints(minHeight: 30, minWidth: 30), + children: const [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 30.0), + child: Text("<"), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 30.0), + child: Text("="), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 30.0), + child: Text(">"), + ), + ], + ), + const SizedBox(height: 12), + ...widget.taskItem.operationalValues.map( + (operation) => BlocBuilder( + builder: (context, state) { + return Column( + children: [ + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TitleMedium( + text: groupValue?.toStringAsFixed(1) ?? "0", + style: context.titleMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontSize: 30, + ), + ), + const SizedBox(width: 8), + TitleMedium( + text: operation.description.toString(), + style: context.titleMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontSize: 30, + ), + ), + ], + ), + const SizedBox(height: 8), + Slider( + value: groupValue ?? 0, + min: operation.minValue?.toDouble() ?? 0, + max: operation.maxValue?.toDouble() ?? 0, + inactiveColor: ColorsManager.primaryColorWithOpacity, + divisions: operation.stepValue != null + ? ((operation.maxValue!.toDouble() - + operation.minValue!.toDouble()) / + operation.stepValue!.toDouble()) + .round() + : null, + onChanged: (value) { + setState(() { + groupValue = value; + }); + }, + ), + const SizedBox(height: 12), + ], + ); + }, + ), + ), + ], + ); + } +} diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index 0b31f0e..caae2da 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -1024,4 +1024,9 @@ class Assets { static const String assetsCurrentTemp = "assets/icons/functions_icons/automation_functions/current_temp.svg"; + + //assets/icons/functions_icons/automation_functions/presence_state.svg + + static const String assetsPresenceState = + "assets/icons/functions_icons/automation_functions/presence_state.svg"; } From 8f1db7615fea8e2e543b2330d7fb7311183dda1c Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Tue, 16 Jul 2024 01:45:44 +0300 Subject: [PATCH 05/30] push toggle buttons color --- .../alert_dialog_slider_steps.dart | 86 +++++++++++++------ 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart index 2b6b594..989df8c 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart @@ -70,19 +70,41 @@ class _AlertDialogSliderStepsState extends State { selectedColor: Colors.white, color: ColorsManager.blackColor, fillColor: ColorsManager.primaryColorWithOpacity, - constraints: const BoxConstraints(minHeight: 30, minWidth: 30), - children: const [ - Padding( - padding: EdgeInsets.symmetric(horizontal: 30.0), - child: Text("<"), + borderColor: ColorsManager.greyColor, + constraints: BoxConstraints.tight(const Size(70, 30)), + children: [ + SizedBox( + width: 70, + height: 30, + child: Container( + color: selectedToggleIndex == 0 + ? ColorsManager.primaryColorWithOpacity + : ColorsManager.greyColor, + alignment: Alignment.center, + child: const Text("<"), + ), ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 30.0), - child: Text("="), + SizedBox( + width: 70, + height: 30, + child: Container( + color: selectedToggleIndex == 1 + ? ColorsManager.primaryColorWithOpacity + : ColorsManager.greyColor, + alignment: Alignment.center, + child: const Text("="), + ), ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 30.0), - child: Text(">"), + SizedBox( + width: 70, + height: 30, + child: Container( + color: selectedToggleIndex == 2 + ? ColorsManager.primaryColorWithOpacity + : ColorsManager.greyColor, + alignment: Alignment.center, + child: const Text(">"), + ), ), ], ), @@ -97,7 +119,11 @@ class _AlertDialogSliderStepsState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ TitleMedium( - text: groupValue?.toStringAsFixed(1) ?? "0", + text: groupValue != null + ? (groupValue! % 1 == 0 + ? groupValue!.toStringAsFixed(0) + : groupValue!.toStringAsFixed(1)) + : "0", style: context.titleMedium.copyWith( color: ColorsManager.primaryColorWithOpacity, fontSize: 30, @@ -114,22 +140,26 @@ class _AlertDialogSliderStepsState extends State { ], ), const SizedBox(height: 8), - Slider( - value: groupValue ?? 0, - min: operation.minValue?.toDouble() ?? 0, - max: operation.maxValue?.toDouble() ?? 0, - inactiveColor: ColorsManager.primaryColorWithOpacity, - divisions: operation.stepValue != null - ? ((operation.maxValue!.toDouble() - - operation.minValue!.toDouble()) / - operation.stepValue!.toDouble()) - .round() - : null, - onChanged: (value) { - setState(() { - groupValue = value; - }); - }, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Slider( + value: groupValue ?? 0, + min: operation.minValue?.toDouble() ?? 0, + max: operation.maxValue?.toDouble() ?? 0, + inactiveColor: ColorsManager.primaryColorWithOpacity + .withOpacity(0.2), + divisions: operation.stepValue != null + ? ((operation.maxValue!.toDouble() - + operation.minValue!.toDouble()) / + operation.stepValue!.toDouble()) + .round() + : null, + onChanged: (value) { + setState(() { + groupValue = value; + }); + }, + ), ), const SizedBox(height: 12), ], From 201931659dcb502a901dde961a2e91ba5634b7f0 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Tue, 16 Jul 2024 22:30:12 +0300 Subject: [PATCH 06/30] added automation flag in the the bloc and event --- .../bloc/create_scene/create_scene_bloc.dart | 232 ++++++++++++++---- .../bloc/create_scene/create_scene_event.dart | 45 +++- .../bloc/create_scene/create_scene_state.dart | 7 +- .../three_gang_functions.dart | 108 ++++++++ .../helper/scene_operations_data_helper.dart | 4 + .../scene/view/create_scene_view.dart | 4 +- .../scene/view/device_functions_view.dart | 200 ++++++++++----- .../alert_dialogs/alert_dialog_countdown.dart | 1 + .../alert_dialog_functions_body.dart | 1 + .../alert_dialog_slider_steps.dart | 2 - .../scene/widgets/bottom_sheet_widget.dart | 3 +- .../if_then_containers/if_container.dart | 41 ++-- .../if_then_containers/then_added_tasks.dart | 53 +++- 13 files changed, 536 insertions(+), 165 deletions(-) diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index d6cf274..4e95171 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -28,21 +28,45 @@ class CreateSceneBloc extends Bloc on(_updateTaskValue); } + /// tab to run values and list List tasksList = []; List tempTasksList = []; final Map selectedValues = {}; + /// automation values and list + List automationTasksList = []; + List automationTempTasksList = []; + final Map automationSelectedValues = {}; + FutureOr _onAddSceneTask( AddTaskEvent event, Emitter emit) { - final copyList = List.from(tempTasksList); - tasksList.addAll(copyList); - tempTasksList.clear(); - selectedValues.clear(); - emit(AddSceneTask(tasksList: tasksList)); + if (event.isAutomation == true) { + final copyList = List.from(automationTempTasksList); + automationTasksList.addAll(copyList); + automationTempTasksList.clear(); + automationSelectedValues.clear(); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } else { + final copyList = List.from(tempTasksList); + tasksList.addAll(copyList); + tempTasksList.clear(); + selectedValues.clear(); + emit(AddSceneTask(tasksList: tasksList)); + } } FutureOr _onTempHoldSceneTask( TempHoldSceneTasksEvent event, Emitter emit) { + if (event.isAutomation == true) { + addToTempAutomationTaskList(event, emit); + } else { + addToTempTaskList(event, emit); + } + } + + void addToTempTaskList( + TempHoldSceneTasksEvent event, Emitter emit) { bool updated = false; for (var element in tempTasksList) { if (element.code == event.deviceControlModel.code) { @@ -54,6 +78,7 @@ class CreateSceneBloc extends Bloc code: event.deviceControlModel.code ?? '', deviceId: event.deviceId, functionValue: event.deviceControlModel.value, + operationDialogType: event.operationType, operationalValues: [ SceneOperationalValue( value: event.deviceControlModel.value, @@ -68,31 +93,12 @@ class CreateSceneBloc extends Bloc } } if (!updated) { - // Add new function if not found - OperationDialogType getOperationDialogType(String? code, [value]) { - if (code == null) { - return OperationDialogType.none; - } - if (code.contains('delay')) { - return OperationDialogType.delay; - } else if (code.contains('countdown')) { - return OperationDialogType.countdown; - } else if (code.contains('set_temp')) { - return OperationDialogType.temperature; - } else if (value.toString().toLowerCase().trim() == 'on' || - value.toString().toLowerCase().trim() == 'off') { - return OperationDialogType.onOff; - } - return OperationDialogType.listOfOptions; - } - var newElement = SceneStaticFunction( operationName: event.operation, deviceName: event.deviceName, icon: event.icon, code: event.deviceControlModel.code ?? '', - operationDialogType: getOperationDialogType( - event.deviceControlModel.code, event.deviceControlModel.value), + operationDialogType: event.operationType, deviceId: event.deviceId, functionValue: event.deviceControlModel.value, operationalValues: [ @@ -105,41 +111,68 @@ class CreateSceneBloc extends Bloc tempTasksList.add(newElement); selectedValues[newElement.code] = event.deviceControlModel.value; } - emit(TempHoldSceneTask(tempTasksList: tempTasksList)); emit(AddSceneTask(tasksList: tasksList)); } FutureOr _selectedValue( SelectedValueEvent event, Emitter emit) { - selectedValues[event.code] = event.value; - emit(SelectedTaskValueState(value: event.value)); - emit(AddSceneTask(tasksList: tasksList)); + if (event.isAutomation == true) { + automationSelectedValues[event.code] = event.value; + emit(SelectedTaskValueState(value: event.value)); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } else { + selectedValues[event.code] = event.value; + emit(SelectedTaskValueState(value: event.value)); + emit(AddSceneTask(tasksList: tasksList)); + } } FutureOr _removeTaskById( RemoveTaskByIdEvent event, Emitter emit) { emit(CreateSceneLoading()); + if (event.isAutomation == true) { + for (var element in automationTasksList) { + if (element.uniqueCustomId == event.taskId) { + automationTasksList.remove(element); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + break; + } + } + } else { + for (var element in tasksList) { + if (element.uniqueCustomId == event.taskId) { + tasksList.remove(element); - for (var element in tasksList) { - if (element.uniqueCustomId == event.taskId) { - tasksList.remove(element); - - emit(AddSceneTask(tasksList: tasksList)); - break; + emit(AddSceneTask(tasksList: tasksList)); + break; + } } } } FutureOr _removeTempTaskById( RemoveTempTaskByIdEvent event, Emitter emit) { - for (var element in tempTasksList) { - if (element.code == event.code) { - tempTasksList.remove(element); + if (event.isAutomation == true) { + for (var element in automationTempTasksList) { + if (element.uniqueCustomId == event.code) { + automationTempTasksList.remove(element); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + break; + } + } + } else { + for (var element in tempTasksList) { + if (element.code == event.code) { + tempTasksList.remove(element); - emit(AddSceneTask(tasksList: tasksList)); + emit(AddSceneTask(tasksList: tasksList)); - break; + break; + } } } } @@ -167,8 +200,14 @@ class CreateSceneBloc extends Bloc FutureOr _clearTaskList( ClearTaskListEvent event, Emitter emit) { - tasksList.clear(); - emit(AddSceneTask(tasksList: tasksList)); + if (event.isAutomation == true) { + automationTasksList.clear(); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } else { + tasksList.clear(); + emit(AddSceneTask(tasksList: tasksList)); + } } FutureOr _fetchSceneTasks( @@ -193,17 +232,33 @@ class CreateSceneBloc extends Bloc FutureOr _clearTempTaskList( ClearTempTaskListEvent event, Emitter emit) { - tempTasksList.clear(); - selectedValues.clear(); - emit(AddSceneTask(tasksList: tempTasksList)); + if (event.isAutomation == true) { + automationTempTasksList.clear(); + automationSelectedValues.clear(); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } else { + tempTasksList.clear(); + selectedValues.clear(); + emit(AddSceneTask(tasksList: tempTasksList)); + } } FutureOr _removeFromSelectedValueById( RemoveFromSelectedValueById event, Emitter emit) { - if (selectedValues.containsKey(event.code)) { - selectedValues.remove(event.code); - emit(const SelectedTaskValueState(value: null)); - emit(AddSceneTask(tasksList: tasksList)); + if (event.isAutomation == true) { + if (automationSelectedValues.containsKey(event.code)) { + automationSelectedValues.remove(event.code); + emit(const SelectedTaskValueState(value: null)); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } + } else { + if (selectedValues.containsKey(event.code)) { + selectedValues.remove(event.code); + emit(const SelectedTaskValueState(value: null)); + emit(AddSceneTask(tasksList: tasksList)); + } } } @@ -226,14 +281,83 @@ class CreateSceneBloc extends Bloc FutureOr _updateTaskValue( UpdateTaskEvent event, Emitter emit) { - for (var i = 0; i < tasksList.length; i++) { - if (tasksList[i].uniqueCustomId == event.taskId) { - tasksList[i] = tasksList[i].copyWith( - functionValue: event.newValue, + if (event.isAutomation == true) { + for (var i = 0; i < automationTasksList.length; i++) { + if (automationTasksList[i].uniqueCustomId == event.taskId) { + automationTasksList[i] = automationTasksList[i].copyWith( + functionValue: event.newValue, + ); + break; + } + } + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } else { + for (var i = 0; i < tasksList.length; i++) { + if (tasksList[i].uniqueCustomId == event.taskId) { + tasksList[i] = tasksList[i].copyWith( + functionValue: event.newValue, + ); + break; + } + } + emit(AddSceneTask(tasksList: tasksList)); + } + } + + void addToTempAutomationTaskList( + TempHoldSceneTasksEvent event, Emitter emit) { + bool updated = false; + for (var element in automationTempTasksList) { + if (element.code == event.deviceControlModel.code) { + // Update the existing function with new values + var updatedElement = element.copyWith( + operationName: event.operation, + deviceName: event.deviceName, + icon: event.icon, + code: event.deviceControlModel.code ?? '', + deviceId: event.deviceId, + functionValue: event.deviceControlModel.value, + operationDialogType: event.operationType, + operationalValues: [ + SceneOperationalValue( + value: event.deviceControlModel.value, + icon: '', + ), + ], ); + automationTempTasksList[automationTempTasksList.indexOf(element)] = + updatedElement; + automationSelectedValues[updatedElement.code] = + event.deviceControlModel.value; + updated = true; break; } } - emit(AddSceneTask(tasksList: tasksList)); + if (!updated) { + var newElement = SceneStaticFunction( + operationName: event.operation, + deviceName: event.deviceName, + icon: event.icon, + code: event.deviceControlModel.code ?? '', + operationDialogType: event.operationType, + deviceId: event.deviceId, + functionValue: event.deviceControlModel.value, + operationalValues: [ + SceneOperationalValue( + value: event.deviceControlModel.value, + icon: '', + ), + ], + ); + automationTempTasksList.add(newElement); + automationSelectedValues[newElement.code] = + event.deviceControlModel.value; + } + emit(TempHoldSceneTask( + tempTasksList: tempTasksList, + automationTempTasksList: automationTempTasksList)); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); } } diff --git a/lib/features/scene/bloc/create_scene/create_scene_event.dart b/lib/features/scene/bloc/create_scene/create_scene_event.dart index 60fd098..b97154b 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_event.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_event.dart @@ -8,6 +8,9 @@ sealed class CreateSceneEvent extends Equatable { } class AddTaskEvent extends CreateSceneEvent { + const AddTaskEvent({this.isAutomation}); + final bool? isAutomation; + @override List get props => []; } @@ -19,6 +22,8 @@ class TempHoldSceneTasksEvent extends CreateSceneEvent { final String operation; final String deviceName; final String uniqueId; + final bool? isAutomation; + final OperationDialogType operationType; const TempHoldSceneTasksEvent({ required this.deviceControlModel, @@ -27,6 +32,8 @@ class TempHoldSceneTasksEvent extends CreateSceneEvent { required this.operation, required this.deviceName, required this.uniqueId, + this.isAutomation, + required this.operationType, }); @override @@ -38,23 +45,35 @@ class TempHoldSceneTasksEvent extends CreateSceneEvent { operation, uniqueId, deviceName, - icon + icon, ]; } class UpdateTaskEvent extends CreateSceneEvent { final String taskId; final dynamic newValue; - const UpdateTaskEvent({required this.taskId, required this.newValue}); + final bool? isAutomation; + const UpdateTaskEvent({ + required this.taskId, + required this.newValue, + this.isAutomation, + }); @override List get props => [taskId, newValue]; } class SelectedValueEvent extends CreateSceneEvent { final dynamic value; + final dynamic automationValue; final String code; + final bool? isAutomation; - const SelectedValueEvent({this.value, required this.code}); + const SelectedValueEvent({ + this.value, + required this.code, + this.isAutomation, + this.automationValue, + }); @override List get props => [value!, code]; @@ -62,8 +81,11 @@ class SelectedValueEvent extends CreateSceneEvent { class RemoveTaskByIdEvent extends CreateSceneEvent { final String taskId; - - const RemoveTaskByIdEvent({required this.taskId}); + final bool? isAutomation; + const RemoveTaskByIdEvent({ + required this.taskId, + this.isAutomation, + }); @override List get props => [taskId]; @@ -71,7 +93,8 @@ class RemoveTaskByIdEvent extends CreateSceneEvent { class RemoveTempTaskByIdEvent extends CreateSceneEvent { final String code; - const RemoveTempTaskByIdEvent({required this.code}); + final bool? isAutomation; + const RemoveTempTaskByIdEvent({required this.code, this.isAutomation}); @override List get props => [code]; @@ -79,8 +102,8 @@ class RemoveTempTaskByIdEvent extends CreateSceneEvent { class RemoveFromSelectedValueById extends CreateSceneEvent { final String code; - - const RemoveFromSelectedValueById({required this.code}); + final bool? isAutomation; + const RemoveFromSelectedValueById({required this.code, this.isAutomation}); @override List get props => [code]; @@ -101,14 +124,16 @@ class CreateSceneWithTasksEvent extends CreateSceneEvent { } class ClearTaskListEvent extends CreateSceneEvent { - const ClearTaskListEvent(); + const ClearTaskListEvent({this.isAutomation}); + final bool? isAutomation; @override List get props => []; } class ClearTempTaskListEvent extends CreateSceneEvent { - const ClearTempTaskListEvent(); + const ClearTempTaskListEvent({this.isAutomation}); + final bool? isAutomation; @override List get props => []; diff --git a/lib/features/scene/bloc/create_scene/create_scene_state.dart b/lib/features/scene/bloc/create_scene/create_scene_state.dart index 3cc9da1..f0bcfd5 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_state.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_state.dart @@ -21,7 +21,8 @@ class CreateSceneError extends CreateSceneState { class AddSceneTask extends CreateSceneState { final List tasksList; - const AddSceneTask({required this.tasksList}); + final List? automationTasksList; + const AddSceneTask({required this.tasksList, this.automationTasksList}); @override List get props => [tasksList]; @@ -29,7 +30,9 @@ class AddSceneTask extends CreateSceneState { class TempHoldSceneTask extends CreateSceneState { final List tempTasksList; - const TempHoldSceneTask({required this.tempTasksList}); + final List? automationTempTasksList; + const TempHoldSceneTask( + {required this.tempTasksList, this.automationTempTasksList}); @override List get props => [tempTasksList]; diff --git a/lib/features/scene/helper/functions_per_device/three_gang_functions.dart b/lib/features/scene/helper/functions_per_device/three_gang_functions.dart index 6c0d9c9..88eaef3 100644 --- a/lib/features/scene/helper/functions_per_device/three_gang_functions.dart +++ b/lib/features/scene/helper/functions_per_device/three_gang_functions.dart @@ -89,4 +89,112 @@ class ThreeGangHelperFunctions { ), ]; } + + static List threeGangAutomationFunctions( + String deviceId, String deviceName, functionValue) { + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsAcPower, + operationName: 'Light 1 Switch', + code: 'switch_1', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsAcPower, + operationName: 'Light 2 Switch', + code: 'switch_2', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsAcPower, + operationName: 'Light 3 Switch', + code: 'switch_3', + functionValue: functionValue, + operationDialogType: OperationDialogType.onOff, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsLightCountdown, + operationName: 'Light 1 CountDown', + code: 'countdown_1', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "sec", + value: 0.0, + minValue: 0, + maxValue: 43200, + stepValue: 1, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsLightCountdown, + operationName: 'Light 2 CountDown', + code: 'countdown_2', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "sec", + value: 0.0, + minValue: 0, + maxValue: 43200, + stepValue: 1, + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsLightCountdown, + operationName: 'Light 3 CountDown', + code: 'countdown_3', + functionValue: functionValue, + operationDialogType: OperationDialogType.integerSteps, + operationalValues: [ + SceneOperationalValue( + icon: '', + description: "sec", + value: 0.0, + minValue: 0, + maxValue: 43200, + stepValue: 1, + ), + ], + ), + ]; + } } diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index bb4e672..f53708a 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -201,6 +201,10 @@ mixin SceneOperationsDataHelper { required functionValue, required bool isAutomation, }) { + if (isAutomation) { + return ThreeGangHelperFunctions.threeGangAutomationFunctions( + deviceId, deviceName, functionValue); + } return ThreeGangHelperFunctions.threeGangHelperFunctions( deviceId, deviceName, functionValue); } diff --git a/lib/features/scene/view/create_scene_view.dart b/lib/features/scene/view/create_scene_view.dart index f89e512..a1e8562 100644 --- a/lib/features/scene/view/create_scene_view.dart +++ b/lib/features/scene/view/create_scene_view.dart @@ -68,7 +68,9 @@ class CreateSceneView extends StatelessWidget { sceneName: '', ), ); - context.read().add(const ClearTaskListEvent()); + context + .read() + .add(const ClearTaskListEvent(isAutomation: true)); }, ), ], diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index a6ef3b1..a98fe4d 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; @@ -49,7 +50,9 @@ class DeviceFunctionsView extends StatelessWidget actions: [ TextButton( onPressed: () { - context.read().add(AddTaskEvent()); + context + .read() + .add(AddTaskEvent(isAutomation: isAutomation)); Navigator.popUntil(context, (route) { return route.settings.name == Routes.sceneTasksRoute; }); @@ -63,16 +66,30 @@ class DeviceFunctionsView extends StatelessWidget ], leading: TextButton( onPressed: () { - final selectedValue = - context.read().selectedValues; - for (var element in device.functions) { - if (selectedValue.containsKey(element.code)) { - context - .read() - .add(RemoveTempTaskByIdEvent(code: element.code!)); - context - .read() - .add(RemoveFromSelectedValueById(code: element.code!)); + if (isAutomation) { + final automationSelectedValue = + context.read().automationSelectedValues; + for (var element in device.functions) { + if (automationSelectedValue.containsKey(element.code)) { + context.read().add(RemoveTempTaskByIdEvent( + code: element.code!, isAutomation: true)); + context.read().add( + RemoveFromSelectedValueById( + code: element.code!, isAutomation: true)); + } + } + } else { + final selectedValue = + context.read().selectedValues; + for (var element in device.functions) { + if (selectedValue.containsKey(element.code)) { + context + .read() + .add(RemoveTempTaskByIdEvent(code: element.code!)); + context + .read() + .add(RemoveFromSelectedValueById(code: element.code!)); + } } } @@ -130,55 +147,19 @@ class DeviceFunctionsView extends StatelessWidget ], ), onPressed: () { - final functionValues = context - .read() - .selectedValues[functions[index].code]; - - context.customAlertDialog( - alertBody: getTheCorrectDialogBody( + if (isAutomation) { + _showAutomationDialog( + context, functions[index], - functionValues, - ), - title: functions[index].operationName, - onConfirm: () { - final selectedValue = context - .read() - .selectedValues[functions[index].code]; - if (selectedValue == null) { - return; - } - context - .read() - .add(TempHoldSceneTasksEvent( - deviceControlModel: DeviceControlModel( - deviceId: device.uuid, - code: functions[index].code, - value: selectedValue, - ), - deviceId: device.uuid ?? '', - operation: functions[index].operationName, - icon: device.icon ?? '', - deviceName: device.name ?? '', - uniqueId: functions[index].uniqueCustomId, - )); - Navigator.pop(context); - }, - onDismiss: () { - final tempTaskList = - context.read().tempTasksList; - for (var element in tempTaskList) { - if (element.code == functions[index].code) { - context.read().add( - RemoveTempTaskByIdEvent( - code: functions[index].code)); - context.read().add( - RemoveFromSelectedValueById( - code: functions[index].code)); - } - } - Navigator.pop(context); - }, - ); + device, + ); + } else { + _showTabToRunDialog( + context, + functions[index], + device, + ); + } }, ); }, @@ -194,4 +175,105 @@ class DeviceFunctionsView extends StatelessWidget }, )); } + + void _showTabToRunDialog( + BuildContext context, + SceneStaticFunction function, + DeviceModel device, + ) { + final functionValues = + context.read().selectedValues[function.code]; + + context.customAlertDialog( + alertBody: getTheCorrectDialogBody( + function, + functionValues, + ), + title: function.operationName, + onConfirm: () { + final selectedValue = + context.read().selectedValues[function.code]; + if (selectedValue == null) { + return; + } + context.read().add(TempHoldSceneTasksEvent( + deviceControlModel: DeviceControlModel( + deviceId: device.uuid, + code: function.code, + value: selectedValue, + ), + deviceId: device.uuid ?? '', + operation: function.operationName, + icon: device.icon ?? '', + deviceName: device.name ?? '', + uniqueId: function.uniqueCustomId, + operationType: function.operationDialogType, + )); + Navigator.pop(context); + }, + onDismiss: () { + final tempTaskList = context.read().tempTasksList; + for (var element in tempTaskList) { + if (element.code == function.code) { + context + .read() + .add(RemoveTempTaskByIdEvent(code: function.code)); + context + .read() + .add(RemoveFromSelectedValueById(code: function.code)); + } + } + Navigator.pop(context); + }, + ); + } + + void _showAutomationDialog( + BuildContext context, SceneStaticFunction function, DeviceModel device) { + final functionValues = + context.read().selectedValues[function.code]; + + context.customAlertDialog( + alertBody: getTheCorrectDialogBody( + function, + functionValues, + ), + title: function.operationName, + onConfirm: () { + final selectedValue = + context.read().selectedValues[function.code]; + if (selectedValue == null) { + return; + } + context.read().add(TempHoldSceneTasksEvent( + deviceControlModel: DeviceControlModel( + deviceId: device.uuid, + code: function.code, + value: selectedValue, + ), + deviceId: device.uuid ?? '', + operation: function.operationName, + icon: device.icon ?? '', + deviceName: device.name ?? '', + uniqueId: function.uniqueCustomId, + operationType: function.operationDialogType, + )); + Navigator.pop(context); + }, + onDismiss: () { + final tempTaskList = context.read().tempTasksList; + for (var element in tempTaskList) { + if (element.code == function.code) { + context + .read() + .add(RemoveTempTaskByIdEvent(code: function.code)); + context + .read() + .add(RemoveFromSelectedValueById(code: function.code)); + } + } + Navigator.pop(context); + }, + ); + } } diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart index 73371a0..35f1d37 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart @@ -26,6 +26,7 @@ class _AlertDialogCountdownState extends State { @override didChangeDependencies() { super.didChangeDependencies(); + final tempTaskList = context.read().tempTasksList; for (var element in tempTaskList) { diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart index bf0246c..b93abcf 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart @@ -26,6 +26,7 @@ class _AlertDialogFunctionsOperationsBodyState @override didChangeDependencies() { super.didChangeDependencies(); + final tempTaskList = context.read().tempTasksList; if (tempTaskList.isNotEmpty) { diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart index 989df8c..ebfff07 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart @@ -2,9 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/title_small.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; diff --git a/lib/features/scene/widgets/bottom_sheet_widget.dart b/lib/features/scene/widgets/bottom_sheet_widget.dart index 6967cae..0efea4d 100644 --- a/lib/features/scene/widgets/bottom_sheet_widget.dart +++ b/lib/features/scene/widgets/bottom_sheet_widget.dart @@ -125,8 +125,9 @@ class CustomBottomSheetWidget extends StatelessWidget { icon: Assets.delay, deviceName: 'Delay The Action', uniqueId: functions[0].uniqueCustomId, + operationType: functions[0].operationDialogType, )); - context.read().add(AddTaskEvent()); + context.read().add(const AddTaskEvent()); Navigator.pop(context); Navigator.pop(context); }, diff --git a/lib/features/scene/widgets/if_then_containers/if_container.dart b/lib/features/scene/widgets/if_then_containers/if_container.dart index f2bceff..d923b94 100644 --- a/lib/features/scene/widgets/if_then_containers/if_container.dart +++ b/lib/features/scene/widgets/if_then_containers/if_container.dart @@ -4,6 +4,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; +import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_added_tasks.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/light_divider.dart'; @@ -60,29 +61,23 @@ class IFDefaultContainer extends StatelessWidget { return const Center(child: LinearProgressIndicator()); } - // if (state is AddSceneTask) { - // final taskLists = state.tasksList; - // if (taskLists.isNotEmpty) { - // return ListView.builder( - // shrinkWrap: true, - // physics: const NeverScrollableScrollPhysics(), - // itemCount: taskLists.length, - // reverse: true, - // itemBuilder: (context, index) { - // return ThenAddedTasksContainer( - // taskItem: taskLists[index], - // ); - // }, - // ); - // } - // return SceneListTile( - // titleString: '+ Add Task', - // textAlign: TextAlign.center, - // onPressed: () => context.customBottomSheet( - // child: const CustomBottomSheetWidget(), - // ), - // ); - // } + if (state is AddSceneTask) { + final automationTasksList = state.automationTasksList; + if (automationTasksList?.isNotEmpty == true) { + return ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: automationTasksList?.length, + reverse: true, + itemBuilder: (context, index) { + return ThenAddedTasksContainer( + taskItem: automationTasksList![index], + isAutomation: true, + ); + }, + ); + } + } return SceneListTile( titleString: '+ Add Condition', textAlign: TextAlign.center, diff --git a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart index 07c2d82..85612f6 100644 --- a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart +++ b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart @@ -22,11 +22,13 @@ class ThenAddedTasksContainer extends StatelessWidget required this.taskItem, this.sceneId, this.index, + this.isAutomation, }); final SceneStaticFunction taskItem; String? sceneId; int? index; + bool? isAutomation; @override Widget build(BuildContext context) { @@ -68,18 +70,36 @@ class ThenAddedTasksContainer extends StatelessWidget final savedCode = functionOperation.first.deviceId.contains('delay') ? 'delay' : functionOperation.first.code; - final selectedValue = createSceneBloc.selectedValues[savedCode]; + if (isAutomation == true) { + final automationSelectedValue = + createSceneBloc.automationSelectedValues[savedCode]; - try { - createSceneBloc.add( - UpdateTaskEvent( - newValue: selectedValue, - taskId: taskItem.uniqueCustomId, - ), - ); - } catch (e) { - debugPrint('Error adding UpdateTaskEvent: $e'); + try { + createSceneBloc.add( + UpdateTaskEvent( + newValue: automationSelectedValue, + taskId: taskItem.uniqueCustomId, + isAutomation: true, + ), + ); + } catch (e) { + debugPrint('Error adding UpdateTaskEvent: $e'); + } + } else { + final selectedValue = createSceneBloc.selectedValues[savedCode]; + + try { + createSceneBloc.add( + UpdateTaskEvent( + newValue: selectedValue, + taskId: taskItem.uniqueCustomId, + ), + ); + } catch (e) { + debugPrint('Error adding UpdateTaskEvent: $e'); + } } + Navigator.pop(context); }, ); @@ -109,9 +129,16 @@ class ThenAddedTasksContainer extends StatelessWidget onDismissed: (direction) { String removeFunctionById = taskItem.uniqueCustomId; - context - .read() - .add(RemoveTaskByIdEvent(taskId: removeFunctionById)); + if (isAutomation == true) { + context.read().add(RemoveTaskByIdEvent( + taskId: removeFunctionById, + isAutomation: true, + )); + } else { + context.read().add(RemoveTaskByIdEvent( + taskId: removeFunctionById, + )); + } String removeFunction = "${taskItem.operationName} with value ${taskItem.operationalValues.first.value}"; From 007e1707550fbc94dc36d005aba286eb817abf5c Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Tue, 16 Jul 2024 22:47:06 +0300 Subject: [PATCH 07/30] push add temp task flag --- .../scene/helper/scene_logic_helper.dart | 2 +- .../scene/view/device_functions_view.dart | 31 ++++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 95d302d..3c115b4 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -93,7 +93,7 @@ mixin SceneLogicHelper { OperationDialogType.countdown) || (taskItem.operationDialogType == OperationDialogType.delay)) { return AlertDialogCountdown( - durationValue: taskItem.functionValue, + durationValue: taskItem.functionValue ?? 0, functionValue: functionValue ?? taskItem.functionValue, function: taskItem, ); diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index a98fe4d..0990a32 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -230,26 +230,27 @@ class DeviceFunctionsView extends StatelessWidget void _showAutomationDialog( BuildContext context, SceneStaticFunction function, DeviceModel device) { - final functionValues = - context.read().selectedValues[function.code]; + final automationFunctionValues = + context.read().automationSelectedValues[function.code]; context.customAlertDialog( alertBody: getTheCorrectDialogBody( function, - functionValues, + automationFunctionValues, ), title: function.operationName, onConfirm: () { - final selectedValue = - context.read().selectedValues[function.code]; - if (selectedValue == null) { + final automationFunctionValues = context + .read() + .automationSelectedValues[function.code]; + if (automationFunctionValues == null) { return; } context.read().add(TempHoldSceneTasksEvent( deviceControlModel: DeviceControlModel( deviceId: device.uuid, code: function.code, - value: selectedValue, + value: automationFunctionValues, ), deviceId: device.uuid ?? '', operation: function.operationName, @@ -257,19 +258,19 @@ class DeviceFunctionsView extends StatelessWidget deviceName: device.name ?? '', uniqueId: function.uniqueCustomId, operationType: function.operationDialogType, + isAutomation: true, )); Navigator.pop(context); }, onDismiss: () { - final tempTaskList = context.read().tempTasksList; - for (var element in tempTaskList) { + final automationTempTaskList = + context.read().automationTempTasksList; + for (var element in automationTempTaskList) { if (element.code == function.code) { - context - .read() - .add(RemoveTempTaskByIdEvent(code: function.code)); - context - .read() - .add(RemoveFromSelectedValueById(code: function.code)); + context.read().add(RemoveTempTaskByIdEvent( + code: function.code, isAutomation: true)); + context.read().add(RemoveFromSelectedValueById( + code: function.code, isAutomation: true)); } } Navigator.pop(context); From 033f33683cff314759bbcd73e107fc6e8176a56e Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Mon, 22 Jul 2024 10:46:22 +0300 Subject: [PATCH 08/30] new api paths --- lib/services/api/api_links_endpoints.dart | 48 ++++++++++++++++------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/lib/services/api/api_links_endpoints.dart b/lib/services/api/api_links_endpoints.dart index d32bdba..457f96b 100644 --- a/lib/services/api/api_links_endpoints.dart +++ b/lib/services/api/api_links_endpoints.dart @@ -1,5 +1,9 @@ +import 'package:flutter/foundation.dart'; + abstract class ApiEndpoints { - static const String baseUrl = 'https://syncrow.azurewebsites.net'; + static const String baseUrl = kReleaseMode + ? 'https://syncrow-staging.azurewebsites.net/api' + : 'https://syncrow-dev.azurewebsites.net/api'; // static const String baseUrl = 'http://100.107.182.63:4001'; //Localhost ////////////////////////////////////// Authentication /////////////////////////////// @@ -9,7 +13,8 @@ abstract class ApiEndpoints { static const String deleteUser = '$baseUrl/authentication/user/delete/{id}'; static const String sendOtp = '$baseUrl/authentication/user/send-otp'; static const String verifyOtp = '$baseUrl/authentication/user/verify-otp'; - static const String forgetPassword = '$baseUrl/authentication/user/forget-password'; + static const String forgetPassword = + '$baseUrl/authentication/user/forget-password'; ////////////////////////////////////// Spaces /////////////////////////////////////// @@ -19,10 +24,12 @@ abstract class ApiEndpoints { static const String addCommunityToUser = '$baseUrl/community/user'; //GET static const String communityByUuid = '$baseUrl/community/{communityUuid}'; - static const String communityChild = '$baseUrl/community/child/{communityUuid}'; + static const String communityChild = + '$baseUrl/community/child/{communityUuid}'; static const String communityUser = '$baseUrl/community/user/{userUuid}'; //PUT - static const String renameCommunity = '$baseUrl/community/rename/{communityUuid}'; + static const String renameCommunity = + '$baseUrl/community/rename/{communityUuid}'; ///Building Module //POST @@ -31,10 +38,12 @@ abstract class ApiEndpoints { //GET static const String buildingByUuid = '$baseUrl/building/{buildingUuid}'; static const String buildingChild = '$baseUrl/building/child/{buildingUuid}'; - static const String buildingParent = '$baseUrl/building/parent/{buildingUuid}'; + static const String buildingParent = + '$baseUrl/building/parent/{buildingUuid}'; static const String buildingUser = '$baseUrl/building/user/{userUuid}'; //PUT - static const String renameBuilding = '$baseUrl/building/rename/{buildingUuid}'; + static const String renameBuilding = + '$baseUrl/building/rename/{buildingUuid}'; ///Floor Module //POST @@ -57,7 +66,8 @@ abstract class ApiEndpoints { static const String unitChild = '$baseUrl/unit/child/'; static const String unitParent = '$baseUrl/unit/parent/{unitUuid}'; static const String unitUser = '$baseUrl/unit/user/'; - static const String invitationCode = '$baseUrl/unit/{unitUuid}/invitation-code'; + static const String invitationCode = + '$baseUrl/unit/{unitUuid}/invitation-code'; static const String verifyInvitationCode = '$baseUrl/unit/user/verify-code'; //PUT @@ -80,7 +90,8 @@ abstract class ApiEndpoints { static const String controlGroup = '$baseUrl/group/control'; //GET static const String groupBySpace = '$baseUrl/group/{unitUuid}'; - static const String devicesByGroupName = '$baseUrl/group/{unitUuid}/devices/{groupName}'; + static const String devicesByGroupName = + '$baseUrl/group/{unitUuid}/devices/{groupName}'; static const String groupByUuid = '$baseUrl/group/{groupUuid}'; //DELETE @@ -92,16 +103,20 @@ abstract class ApiEndpoints { static const String addDeviceToRoom = '$baseUrl/device/room'; static const String addDeviceToGroup = '$baseUrl/device/group'; static const String controlDevice = '$baseUrl/device/{deviceUuid}/control'; - static const String firmwareDevice = '$baseUrl/device/{deviceUuid}/firmware/{firmwareVersion}'; + static const String firmwareDevice = + '$baseUrl/device/{deviceUuid}/firmware/{firmwareVersion}'; static const String getDevicesByUserId = '$baseUrl/device/user/{userId}'; static const String getDevicesByUnitId = '$baseUrl/device/unit/{unitUuid}'; //GET static const String deviceByRoom = '$baseUrl/device/room'; static const String deviceByUuid = '$baseUrl/device/{deviceUuid}'; - static const String deviceFunctions = '$baseUrl/device/{deviceUuid}/functions'; - static const String gatewayApi = '$baseUrl/device/gateway/{gatewayUuid}/devices'; - static const String deviceFunctionsStatus = '$baseUrl/device/{deviceUuid}/functions/status'; + static const String deviceFunctions = + '$baseUrl/device/{deviceUuid}/functions'; + static const String gatewayApi = + '$baseUrl/device/gateway/{gatewayUuid}/devices'; + static const String deviceFunctionsStatus = + '$baseUrl/device/{deviceUuid}/functions/status'; ///Device Permission Module //POST @@ -109,14 +124,16 @@ abstract class ApiEndpoints { //GET static const String devicePermissionList = '$baseUrl/device-permission/list'; //PUT - static const String editDevicePermission = '$baseUrl/device-permission/edit/{userId}'; + static const String editDevicePermission = + '$baseUrl/device-permission/edit/{userId}'; static const String assignDeviceToRoom = '$baseUrl/device/room'; /// Scene API //////////////////// /// POST static const String createScene = '$baseUrl/scene/tap-to-run'; - static const String triggerScene = '$baseUrl/scene/tap-to-run/trigger/{sceneId}'; + static const String triggerScene = + '$baseUrl/scene/tap-to-run/trigger/{sceneId}'; /// GET static const String getUnitScenes = '$baseUrl/scene/tap-to-run/{unitUuid}'; @@ -127,7 +144,8 @@ abstract class ApiEndpoints { static const String updateScene = '$baseUrl/scene/tap-to-run/{sceneId}'; /// DELETE - static const String deleteScene = '$baseUrl/scene/tap-to-run/{unitUuid}/{sceneId}'; + static const String deleteScene = + '$baseUrl/scene/tap-to-run/{unitUuid}/{sceneId}'; //////////////////////Door Lock ////////////////////// //online From 9f68e4695f3d4a5b5a13368a80631869b25b734e Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Mon, 22 Jul 2024 23:56:33 +0300 Subject: [PATCH 09/30] add autoamtion tasks --- lib/features/devices/model/device_model.dart | 6 +- .../bloc/create_scene/create_scene_bloc.dart | 399 ++-- .../bloc/create_scene/create_scene_event.dart | 2 + .../human_presence_functions.dart | 161 +- .../scene/helper/scene_logic_helper.dart | 7 +- .../helper/scene_operations_data_helper.dart | 1892 ++++------------- .../scene/model/create_scene_model.dart | 40 +- .../scene/view/device_functions_view.dart | 2 + .../alert_dialog_functions_body.dart | 61 +- .../alert_dialog_slider_steps.dart | 43 +- .../alert_dialog_temperature_body.dart | 26 +- .../if_then_containers/then_added_tasks.dart | 5 +- lib/services/api/api_links_endpoints.dart | 4 +- lib/services/api/scene_api.dart | 2 +- 14 files changed, 745 insertions(+), 1905 deletions(-) diff --git a/lib/features/devices/model/device_model.dart b/lib/features/devices/model/device_model.dart index 24cd95e..4109397 100644 --- a/lib/features/devices/model/device_model.dart +++ b/lib/features/devices/model/device_model.dart @@ -44,7 +44,8 @@ class DeviceModel { if (type == DeviceType.LightBulb) { tempIcon = Assets.assetsIconsLight; - } else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) { + } else if (type == DeviceType.CeilingSensor || + type == DeviceType.WallSensor) { tempIcon = Assets.assetsIconsSensors; } else if (type == DeviceType.AC) { tempIcon = Assets.assetsIconsAC; @@ -93,5 +94,6 @@ class DeviceModel { }; } - List getFunctions(DeviceType type) => devicesFunctionsMap[productType] ?? []; + List getFunctions(DeviceType type) => + devicesFunctionsMap[productType] ?? []; } diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index 4e95171..9033d6d 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -40,19 +40,25 @@ class CreateSceneBloc extends Bloc FutureOr _onAddSceneTask( AddTaskEvent event, Emitter emit) { + emit(CreateSceneLoading()); if (event.isAutomation == true) { final copyList = List.from(automationTempTasksList); automationTasksList.addAll(copyList); automationTempTasksList.clear(); automationSelectedValues.clear(); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + automationTasksList: automationTasksList, + tasksList: tasksList, + )); } else { final copyList = List.from(tempTasksList); tasksList.addAll(copyList); tempTasksList.clear(); selectedValues.clear(); - emit(AddSceneTask(tasksList: tasksList)); + emit(AddSceneTask( + tasksList: tasksList, + automationTasksList: automationTasksList, + )); } } @@ -111,198 +117,9 @@ class CreateSceneBloc extends Bloc tempTasksList.add(newElement); selectedValues[newElement.code] = event.deviceControlModel.value; } - emit(TempHoldSceneTask(tempTasksList: tempTasksList)); - emit(AddSceneTask(tasksList: tasksList)); - } - FutureOr _selectedValue( - SelectedValueEvent event, Emitter emit) { - if (event.isAutomation == true) { - automationSelectedValues[event.code] = event.value; - emit(SelectedTaskValueState(value: event.value)); - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); - } else { - selectedValues[event.code] = event.value; - emit(SelectedTaskValueState(value: event.value)); - emit(AddSceneTask(tasksList: tasksList)); - } - } - - FutureOr _removeTaskById( - RemoveTaskByIdEvent event, Emitter emit) { - emit(CreateSceneLoading()); - if (event.isAutomation == true) { - for (var element in automationTasksList) { - if (element.uniqueCustomId == event.taskId) { - automationTasksList.remove(element); - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); - break; - } - } - } else { - for (var element in tasksList) { - if (element.uniqueCustomId == event.taskId) { - tasksList.remove(element); - - emit(AddSceneTask(tasksList: tasksList)); - break; - } - } - } - } - - FutureOr _removeTempTaskById( - RemoveTempTaskByIdEvent event, Emitter emit) { - if (event.isAutomation == true) { - for (var element in automationTempTasksList) { - if (element.uniqueCustomId == event.code) { - automationTempTasksList.remove(element); - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); - break; - } - } - } else { - for (var element in tempTasksList) { - if (element.code == event.code) { - tempTasksList.remove(element); - - emit(AddSceneTask(tasksList: tasksList)); - - break; - } - } - } - } - - FutureOr _createSceneWithTasks( - CreateSceneWithTasksEvent event, Emitter emit) async { - emit(CreateSceneLoading()); - try { - final response = event.updateScene - ? await SceneApi.updateScene(event.createSceneModel, event.sceneId) - : await SceneApi.createScene(event.createSceneModel); - if (response['success'] == true) { - tasksList.clear(); - tempTasksList.clear(); - selectedValues.clear(); - emit(const CreateSceneWithTasks(success: true)); - } else { - emit(const CreateSceneError(message: 'Something went wrong')); - } - } catch (e) { - emit(const CreateSceneError(message: 'Something went wrong')); - emit(AddSceneTask(tasksList: tasksList)); - } - } - - FutureOr _clearTaskList( - ClearTaskListEvent event, Emitter emit) { - if (event.isAutomation == true) { - automationTasksList.clear(); - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); - } else { - tasksList.clear(); - emit(AddSceneTask(tasksList: tasksList)); - } - } - - FutureOr _fetchSceneTasks( - FetchSceneTasksEvent event, Emitter emit) async { - emit(CreateSceneLoading()); - - try { - final response = await SceneApi.getSceneDetails(event.sceneId); - if (response.id.isNotEmpty) { - tasksList = List.from( - getTaskListFunctionsFromApi(actions: response.actions)); - emit(AddSceneTask( - tasksList: tasksList, - )); - } else { - emit(const CreateSceneError(message: 'Something went wrong')); - } - } catch (e) { - emit(const CreateSceneError(message: 'Something went wrong')); - } - } - - FutureOr _clearTempTaskList( - ClearTempTaskListEvent event, Emitter emit) { - if (event.isAutomation == true) { - automationTempTasksList.clear(); - automationSelectedValues.clear(); - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); - } else { - tempTasksList.clear(); - selectedValues.clear(); - emit(AddSceneTask(tasksList: tempTasksList)); - } - } - - FutureOr _removeFromSelectedValueById( - RemoveFromSelectedValueById event, Emitter emit) { - if (event.isAutomation == true) { - if (automationSelectedValues.containsKey(event.code)) { - automationSelectedValues.remove(event.code); - emit(const SelectedTaskValueState(value: null)); - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); - } - } else { - if (selectedValues.containsKey(event.code)) { - selectedValues.remove(event.code); - emit(const SelectedTaskValueState(value: null)); - emit(AddSceneTask(tasksList: tasksList)); - } - } - } - - FutureOr _deleteScene( - DeleteSceneEvent event, Emitter emit) async { - emit(DeleteSceneLoading()); - - try { - final response = await SceneApi.deleteScene( - sceneId: event.sceneId, unitUuid: event.unitUuid); - if (response == true) { - emit(const DeleteSceneSuccess(true)); - } else { - emit(const DeleteSceneError(message: 'Something went wrong')); - } - } catch (e) { - emit(const DeleteSceneError(message: 'Something went wrong')); - } - } - - FutureOr _updateTaskValue( - UpdateTaskEvent event, Emitter emit) { - if (event.isAutomation == true) { - for (var i = 0; i < automationTasksList.length; i++) { - if (automationTasksList[i].uniqueCustomId == event.taskId) { - automationTasksList[i] = automationTasksList[i].copyWith( - functionValue: event.newValue, - ); - break; - } - } - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); - } else { - for (var i = 0; i < tasksList.length; i++) { - if (tasksList[i].uniqueCustomId == event.taskId) { - tasksList[i] = tasksList[i].copyWith( - functionValue: event.newValue, - ); - break; - } - } - emit(AddSceneTask(tasksList: tasksList)); - } + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); } void addToTempAutomationTaskList( @@ -354,10 +171,200 @@ class CreateSceneBloc extends Bloc automationSelectedValues[newElement.code] = event.deviceControlModel.value; } - emit(TempHoldSceneTask( - tempTasksList: tempTasksList, - automationTempTasksList: automationTempTasksList)); emit(AddSceneTask( tasksList: tasksList, automationTasksList: automationTasksList)); } + + FutureOr _selectedValue( + SelectedValueEvent event, Emitter emit) { + if (event.isAutomation == true) { + automationSelectedValues[event.code] = event.value; + emit(SelectedTaskValueState(value: event.value)); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } else { + selectedValues[event.code] = event.value; + emit(SelectedTaskValueState(value: event.value)); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } + } + + FutureOr _removeTaskById( + RemoveTaskByIdEvent event, Emitter emit) { + emit(CreateSceneLoading()); + if (event.isAutomation == true) { + for (var element in automationTasksList) { + if (element.uniqueCustomId == event.taskId) { + automationTasksList.remove(element); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + break; + } + } + } else { + for (var element in tasksList) { + if (element.uniqueCustomId == event.taskId) { + tasksList.remove(element); + + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + break; + } + } + } + } + + FutureOr _removeTempTaskById( + RemoveTempTaskByIdEvent event, Emitter emit) { + if (event.isAutomation == true) { + for (var element in automationTempTasksList) { + if (element.uniqueCustomId == event.code) { + automationTempTasksList.remove(element); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + break; + } + } + } else { + for (var element in tempTasksList) { + if (element.code == event.code) { + tempTasksList.remove(element); + + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + + break; + } + } + } + } + + FutureOr _createSceneWithTasks( + CreateSceneWithTasksEvent event, Emitter emit) async { + emit(CreateSceneLoading()); + try { + final response = event.updateScene + ? await SceneApi.updateScene(event.createSceneModel, event.sceneId) + : await SceneApi.createScene(event.createSceneModel); + if (response['success'] == true) { + tasksList.clear(); + tempTasksList.clear(); + selectedValues.clear(); + emit(const CreateSceneWithTasks(success: true)); + } else { + emit(const CreateSceneError(message: 'Something went wrong')); + } + } catch (e) { + emit(const CreateSceneError(message: 'Something went wrong')); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } + } + + FutureOr _clearTaskList( + ClearTaskListEvent event, Emitter emit) { + automationTasksList.clear(); + tasksList.clear(); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } + + FutureOr _fetchSceneTasks( + FetchSceneTasksEvent event, Emitter emit) async { + emit(CreateSceneLoading()); + + try { + final response = await SceneApi.getSceneDetails(event.sceneId); + if (response.id.isNotEmpty) { + tasksList = List.from(getTaskListFunctionsFromApi( + actions: response.actions, isAutomation: false)); + emit(AddSceneTask( + tasksList: tasksList, + )); + } else { + emit(const CreateSceneError(message: 'Something went wrong')); + } + } catch (e) { + emit(const CreateSceneError(message: 'Something went wrong')); + } + } + + FutureOr _clearTempTaskList( + ClearTempTaskListEvent event, Emitter emit) { + if (event.isAutomation == true) { + automationTempTasksList.clear(); + automationSelectedValues.clear(); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } else { + tempTasksList.clear(); + selectedValues.clear(); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } + } + + FutureOr _removeFromSelectedValueById( + RemoveFromSelectedValueById event, Emitter emit) { + if (event.isAutomation == true) { + if (automationSelectedValues.containsKey(event.code)) { + automationSelectedValues.remove(event.code); + emit(const SelectedTaskValueState(value: null)); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } + } else { + if (selectedValues.containsKey(event.code)) { + selectedValues.remove(event.code); + emit(const SelectedTaskValueState(value: null)); + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } + } + } + + FutureOr _deleteScene( + DeleteSceneEvent event, Emitter emit) async { + emit(DeleteSceneLoading()); + + try { + final response = await SceneApi.deleteScene( + sceneId: event.sceneId, unitUuid: event.unitUuid); + if (response == true) { + emit(const DeleteSceneSuccess(true)); + } else { + emit(const DeleteSceneError(message: 'Something went wrong')); + } + } catch (e) { + emit(const DeleteSceneError(message: 'Something went wrong')); + } + } + + FutureOr _updateTaskValue( + UpdateTaskEvent event, Emitter emit) { + if (event.isAutomation == true) { + for (var i = 0; i < automationTasksList.length; i++) { + if (automationTasksList[i].uniqueCustomId == event.taskId) { + automationTasksList[i] = automationTasksList[i].copyWith( + functionValue: event.newValue, + ); + break; + } + } + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } else { + for (var i = 0; i < tasksList.length; i++) { + if (tasksList[i].uniqueCustomId == event.taskId) { + tasksList[i] = tasksList[i].copyWith( + functionValue: event.newValue, + ); + break; + } + } + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); + } + } } diff --git a/lib/features/scene/bloc/create_scene/create_scene_event.dart b/lib/features/scene/bloc/create_scene/create_scene_event.dart index b97154b..16f0fb4 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_event.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_event.dart @@ -113,10 +113,12 @@ class CreateSceneWithTasksEvent extends CreateSceneEvent { final CreateSceneModel createSceneModel; final bool updateScene; final String sceneId; + //final bool isAutomation; const CreateSceneWithTasksEvent({ required this.createSceneModel, required this.updateScene, required this.sceneId, + // required this.isAutomation, }); @override diff --git a/lib/features/scene/helper/functions_per_device/human_presence_functions.dart b/lib/features/scene/helper/functions_per_device/human_presence_functions.dart index bb3f49d..d6f6070 100644 --- a/lib/features/scene/helper/functions_per_device/human_presence_functions.dart +++ b/lib/features/scene/helper/functions_per_device/human_presence_functions.dart @@ -157,18 +157,6 @@ class HumanPresenceHelperFunctions { icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), ], ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsNobodyTime, - operationName: 'Nobody Time', - code: 'presence_time', - functionValue: functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ), ]; } @@ -234,142 +222,6 @@ class HumanPresenceHelperFunctions { ), ], ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsFarDetection, - operationName: 'Far Detection', - code: 'far_detection', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 75, - description: '75cm', - iconValue: '75', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 150, - description: '150cm', - iconValue: '150', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 225, - description: '225cm', - iconValue: '225', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 300, - description: '300cm', - iconValue: '300', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 375, - description: '375cm', - iconValue: '375', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 450, - description: '450cm', - iconValue: '450', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 525, - description: '525cm', - iconValue: '525', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 600, - description: '600cm', - iconValue: '600', - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsMotionDetection, - operationName: 'Motion Detection Sensitivity', - code: 'motion_sensitivity_value', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - ], - ), - SceneStaticFunction( - deviceId: deviceId, - deviceName: deviceName, - icon: Assets.assetsMotionlessDetection, - operationName: 'Motionless Detection Sensitivity', - code: 'motionless_sensitivity', - functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - iconValue: '1', - icon: Assets.assetsFarDetectionFunction, - value: 1, - description: '1', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 2, - description: '2', - iconValue: '2', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 3, - description: '3', - iconValue: '3', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 4, - description: '4', - iconValue: '4', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 5, - description: '5', - iconValue: '5', - ), - ], - ), SceneStaticFunction( deviceId: deviceId, deviceName: deviceName, @@ -395,13 +247,12 @@ class HumanPresenceHelperFunctions { operationDialogType: OperationDialogType.integerSteps, operationalValues: [ SceneOperationalValue( - icon: '', - value: 0.0, - minValue: 0.0, - maxValue: 65535, - stepValue: 1, - description: 'min' - ), + icon: '', + value: 0.0, + minValue: 0.0, + maxValue: 65535, + stepValue: 1, + description: 'min'), ], ), ]; diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 3c115b4..a6f6ad8 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -81,9 +81,8 @@ mixin SceneLogicHelper { } Widget getTheCorrectDialogBody( - SceneStaticFunction taskItem, - dynamic functionValue, - ) { + SceneStaticFunction taskItem, dynamic functionValue, + {required bool isAutomation}) { if (taskItem.operationDialogType == OperationDialogType.temperature) { return AlertDialogTemperatureBody( taskItem: taskItem, @@ -102,12 +101,14 @@ mixin SceneLogicHelper { return AlertDialogSliderSteps( taskItem: taskItem, functionValue: functionValue ?? taskItem.functionValue, + isAutomation: isAutomation, ); } return AlertDialogFunctionsOperationsBody( taskItem: taskItem, functionValue: functionValue ?? taskItem.functionValue, + isAutomation: isAutomation, ); } } diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index f53708a..dff462b 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -20,79 +20,36 @@ mixin SceneOperationsDataHelper { required String deviceName, required bool isAutomation, }) { + const functionValue = null; + switch (type) { case DeviceType.LightBulb: return lightBulbFunctions( - functions: functions, - deviceId: deviceId, - deviceName: deviceName, - functionValue: null, - isAutomation: isAutomation, - ); + functions, deviceId, deviceName, functionValue, isAutomation); case DeviceType.CeilingSensor: return ceilingSensorFunctions( - functions: functions, - deviceId: deviceId, - deviceName: deviceName, - functionValue: null, - isAutomation: isAutomation, - ); + functions, deviceId, deviceName, functionValue, isAutomation); case DeviceType.WallSensor: return wallSensorFunctions( - functions: functions, - deviceId: deviceId, - deviceName: deviceName, - functionValue: null, - isAutomation: isAutomation, - ); + functions, deviceId, deviceName, functionValue, isAutomation); case DeviceType.AC: return acFunctions( - functions: functions, - deviceId: deviceId, - deviceName: deviceName, - functionValue: null, - isAutomation: isAutomation, - ); + functions, deviceId, deviceName, functionValue, isAutomation); case DeviceType.DoorLock: return doorLockFunctions( - functions: functions, - deviceId: deviceId, - deviceName: deviceName, - functionValue: null, - isAutomation: isAutomation, - ); + functions, deviceId, deviceName, functionValue, isAutomation); case DeviceType.Curtain: return curtainFunctions( - functions: functions, - deviceId: deviceId, - deviceName: deviceName, - functionValue: null, - isAutomation: isAutomation, - ); + functions, deviceId, deviceName, functionValue, isAutomation); case DeviceType.ThreeGang: return threeGangFunctions( - functions: functions, - deviceId: deviceId, - deviceName: deviceName, - functionValue: null, - isAutomation: isAutomation, - ); + functions, deviceId, deviceName, functionValue, isAutomation); case DeviceType.Gateway: return gatewayFunctions( - functions: functions, - deviceId: deviceId, - deviceName: deviceName, - functionValue: null, - isAutomation: isAutomation, - ); + functions, deviceId, deviceName, functionValue, isAutomation); default: return lightBulbFunctions( - functions: functions, - deviceId: deviceId, - deviceName: deviceName, - functionValue: null, - isAutomation: isAutomation, - ); + functions, deviceId, deviceName, functionValue, isAutomation); } } @@ -119,14 +76,12 @@ mixin SceneOperationsDataHelper { } } - /// presence sensor - List ceilingSensorFunctions({ - required List functions, - required String deviceId, - required String deviceName, - required dynamic functionValue, - required bool isAutomation, - }) { + List ceilingSensorFunctions( + List functions, + String deviceId, + String deviceName, + dynamic functionValue, + bool isAutomation) { if (isAutomation) { return PresenceSensorHelperFunctions.automationPresenceSensorFunctions( deviceId, deviceName, functionValue); @@ -136,21 +91,20 @@ mixin SceneOperationsDataHelper { } List curtainFunctions( - {required List functions, - required String deviceId, - required String deviceName, - required functionValue, - required bool isAutomation}) { + List functions, + String deviceId, + String deviceName, + dynamic functionValue, + bool isAutomation) { return []; } - List doorLockFunctions({ - required List functions, - required String deviceId, - required String deviceName, - required functionValue, - required bool isAutomation, - }) { + List doorLockFunctions( + List functions, + String deviceId, + String deviceName, + dynamic functionValue, + bool isAutomation) { if (isAutomation) { return DoorLockHelperFunctions.doorLockAutomationFunctions( deviceId, deviceName, functionValue); @@ -159,13 +113,12 @@ mixin SceneOperationsDataHelper { deviceId, deviceName, functionValue); } - List wallSensorFunctions({ - required List functions, - required String deviceId, - required String deviceName, - required functionValue, - required bool isAutomation, - }) { + List wallSensorFunctions( + List functions, + String deviceId, + String deviceName, + dynamic functionValue, + bool isAutomation) { if (isAutomation) { return HumanPresenceHelperFunctions.automationHumanPresenceFunctions( deviceId, deviceName, functionValue); @@ -175,32 +128,30 @@ mixin SceneOperationsDataHelper { } List lightBulbFunctions( - {required List functions, - required String deviceId, - required String deviceName, - required functionValue, - required bool isAutomation}) { + List functions, + String deviceId, + String deviceName, + dynamic functionValue, + bool isAutomation) { return []; } - List gatewayFunctions({ - required List functions, - required String deviceId, - required String deviceName, - required functionValue, - required bool isAutomation, - }) { + List gatewayFunctions( + List functions, + String deviceId, + String deviceName, + dynamic functionValue, + bool isAutomation) { return GatewayHelperFunctions.tabToRunGatewayFunctions( deviceId, deviceName, functionValue); } - List threeGangFunctions({ - required List functions, - required String deviceId, - required String deviceName, - required functionValue, - required bool isAutomation, - }) { + List threeGangFunctions( + List functions, + String deviceId, + String deviceName, + dynamic functionValue, + bool isAutomation) { if (isAutomation) { return ThreeGangHelperFunctions.threeGangAutomationFunctions( deviceId, deviceName, functionValue); @@ -209,14 +160,12 @@ mixin SceneOperationsDataHelper { deviceId, deviceName, functionValue); } - /// smart ac thermostat - List acFunctions({ - required List functions, - required String deviceId, - required String deviceName, - required functionValue, - required bool isAutomation, - }) { + List acFunctions( + List functions, + String deviceId, + String deviceName, + dynamic functionValue, + bool isAutomation) { if (isAutomation) { return ACFunctionsHelper.automationAcFunctions( deviceId, deviceName, functionValue); @@ -225,14 +174,9 @@ mixin SceneOperationsDataHelper { deviceId, deviceName, functionValue); } -///////&************ END of get function with icons for device *************&&//////// - /// - /// - List getTaskListFunctionsFromApi({ - required List actions, - }) { + List getTaskListFunctionsFromApi( + {required List actions, required bool isAutomation}) { List functions = []; - for (var action in actions) { if (action.entityId == 'delay') { functions.add( @@ -247,648 +191,366 @@ mixin SceneOperationsDataHelper { code: '', operationalValues: [ SceneOperationalValue( - icon: '', - description: "", - value: action.executorProperty.delaySeconds, - ), + icon: '', + description: "", + value: action.executorProperty.delaySeconds), ], ), ); - } - ExecutorProperty executorProperty = action.executorProperty; - - switch (executorProperty.functionCode) { - case 'sensitivity': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsSensitivityFunction, - operationName: 'Sensitivity', - code: 'sensitivity', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 6, - description: 6.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 7, - description: 7.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 8, - description: 8.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 9, - description: 9.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 10, - description: 10.toString(), - ), - ], - ), - ); - break; - case 'normal_open_switch': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'WIFI LOCK PRO', - deviceIcon: Assets.assetsIconsDoorLock, - icon: Assets.assetsIconsDoorLock, - operationName: 'Set Door lock Normal Open', - functionValue: executorProperty.functionValue, - code: 'normal_open_switch', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ), - ); - break; - case 'far_detection': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsFarDetection, - operationName: 'Far Detection', - functionValue: executorProperty.functionValue, - code: 'far_detection', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 75, - description: '75cm', - iconValue: '75', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 150, - description: '150cm', - iconValue: '150', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 225, - description: '225cm', - iconValue: '225', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 300, - description: '300cm', - iconValue: '300', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 375, - description: '375cm', - iconValue: '375', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 450, - description: '450cm', - iconValue: '450', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 525, - description: '525cm', - iconValue: '525', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 600, - description: '600cm', - iconValue: '600', - ), - ], - ), - ); - break; - case 'motion_sensitivity_value': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsMotionDetection, - operationName: 'Motion Detection Sensitivity', - functionValue: executorProperty.functionValue, - code: 'motion_sensitivity_value', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - ], - ), - ); - break; - case 'motionless_sensitivity': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsMotionlessDetection, - operationName: 'Motionless Detection Sensitivity', - functionValue: executorProperty.functionValue, - code: 'motion_sensitivity_value', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - iconValue: '1', - icon: Assets.assetsFarDetectionFunction, - value: 1, - description: '1', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 2, - description: '2', - iconValue: '2', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 3, - description: '3', - iconValue: '3', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 4, - description: '4', - iconValue: '4', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 5, - description: '5', - iconValue: '5', - ), - ], - ), - ); - break; - case 'indicator': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsIndicator, - operationName: 'Indicator', - functionValue: executorProperty.functionValue, - code: 'indicator', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ), - ); - break; - case 'presence_time': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsNobodyTime, - operationName: 'Nobody Time', - functionValue: executorProperty.functionValue, - code: 'presence_time', - operationDialogType: OperationDialogType.temperature, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ), - ); - break; - case 'switch_alarm_sound': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Multi-Mode Gateway Z-W-B', - deviceIcon: Assets.assetsIconsGateway, - icon: Assets.assetsSwitchAlarmSound, - operationName: 'Switch Alarm Sound', - functionValue: executorProperty.functionValue, - code: 'switch_alarm_sound', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false), - ], - ), - ); - break; - case 'master_state': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Multi-Mode Gateway Z-W-B', - deviceIcon: Assets.assetsIconsGateway, - icon: Assets.assetsMasterState, - operationName: 'Master State', - functionValue: executorProperty.functionValue, - code: 'master_state', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "Alarm", - value: 'alarm', - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "Normal", - value: 'normal', - ), - ], - ), - ); - break; - case 'factory_reset': - functions.add( - SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Multi-Mode Gateway Z-W-B', - deviceIcon: Assets.assetsIconsGateway, - icon: Assets.assetsFactoryReset, - operationName: 'Reset Factory', - functionValue: executorProperty.functionValue, - code: 'factory_reset', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSceneRefresh, - description: "ON", - value: true), - SceneOperationalValue( - icon: Assets.assetsResetOff, - description: "OFF", - value: false, - ), - ], - ), - ); - break; - case 'switch_1': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsAcPower, - operationName: 'Light 1 Switch', - code: 'switch_1', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false), - // SceneOperationalValue( - // icon: Assets.assetsSceneRefresh, - // description: "Reverse Switch", - // value: null, - // ), - ], - )); - break; - case 'switch_2': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsAcPower, - operationName: 'Light 2 Switch', - code: 'switch_2', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false), - // SceneOperationalValue( - // icon: Assets.assetsSceneRefresh, - // description: "Reverse Switch", - // value: null, - // ), - ], - )); - break; - case 'switch_3': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsAcPower, - operationName: 'Light 3 Switch', - code: 'switch_3', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false), - // SceneOperationalValue( - // icon: Assets.assetsSceneRefresh, - // description: "Reverse Switch", - // value: null, - // ), - ], - )); - break; - case 'countdown_1': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsLightCountdown, - operationName: 'Light 1 CountDown', - code: 'countdown_1', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - )); - break; - case 'countdown_2': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsLightCountdown, - operationName: 'Light 2 CountDown', - code: 'countdown_2', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - )); - break; - case 'countdown_3': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsLightCountdown, - operationName: 'Light 3 CountDown', - code: 'countdown_3', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - )); - break; - case 'switch': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsAcPower, - operationName: 'Power', - code: 'switch', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - )); - break; - case 'temp_set': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsTempreture, - operationName: 'Set Temperature', - code: 'temp_set', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.temperature, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsCelsiusDegrees, - value: 0, - description: 'COOL TO', - ), - ], - )); - break; - case 'mode': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsFreezing, - operationName: 'Mode', - code: 'mode', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcCooling, - description: AcValuesEnums.Cooling.name, - value: TempModes.cold.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcHeating, - description: AcValuesEnums.Heating.name, - value: TempModes.hot.name, - ), - SceneOperationalValue( - icon: Assets.assetsFanSpeed, - description: AcValuesEnums.Ventilation.name, - value: TempModes.wind.name, - ), - ], - )); - break; - case 'level': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsFanSpeed, - operationName: 'Fan Speed', - code: 'level', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcFanLow, - description: ValueACRange.LOW.name, - value: FanSpeeds.low.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanMiddle, - description: ValueACRange.MIDDLE.name, - value: FanSpeeds.middle.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanHigh, - description: ValueACRange.HIGH.name, - value: FanSpeeds.high.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanAuto, - description: ValueACRange.AUTO.name, - value: FanSpeeds.auto.name, - ), - ], - )); - break; - case 'child_lock': - functions.add(SceneStaticFunction( - deviceId: action.entityId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsChildLock, - operationName: 'Child Lock', - code: 'child_lock', - functionValue: executorProperty.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSceneChildLock, - description: 'Lock', - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsSceneChildUnlock, - description: 'Unlock', - value: false, - ), - ], - )); - break; - default: + } else { + functions + .add(_mapExecutorPropertyToSceneFunction(action, isAutomation)); } } - return functions; } - ///// END of get fucntion for once device based on the CODE ***** /////// - /// - /// - /// + SceneStaticFunction _mapExecutorPropertyToSceneFunction( + Action action, bool isAutomation) { + ExecutorProperty executorProperty = action.executorProperty; + switch (executorProperty.functionCode) { + case 'sensitivity': + return _createSceneFunction( + action, + 'Presence Sensor', + Assets.assetsSensitivityFunction, + 'Sensitivity', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.listOfOptions, + isAutomation + ? _createIntegerStepsOptions() + : _createSensitivityOptions(), + isAutomation); + case 'normal_open_switch': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Set Door lock Normal Open', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'far_detection': + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsFarDetection, + 'Far Detection', + OperationDialogType.listOfOptions, + _createFarDetectionOptions(), + isAutomation); + case 'motion_sensitivity_value': + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsMotionDetection, + 'Motion Detection Sensitivity', + OperationDialogType.listOfOptions, + _createSensitivityOptions(), + isAutomation); + case 'motionless_sensitivity': + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsMotionlessDetection, + 'Motionless Detection Sensitivity', + OperationDialogType.listOfOptions, + _createSensitivityOptions(), + isAutomation); + case 'indicator': + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIndicator, + 'Indicator', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'presence_time': + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsNobodyTime, + 'Nobody Time', + OperationDialogType.countdown, + _createCountdownOptions(), + isAutomation); + case 'switch_alarm_sound': + return _createSceneFunction( + action, + 'Multi-Mode Gateway Z-W-B', + Assets.assetsSwitchAlarmSound, + 'Switch Alarm Sound', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'master_state': + return _createSceneFunction( + action, + 'Multi-Mode Gateway Z-W-B', + Assets.assetsMasterState, + 'Master State', + OperationDialogType.listOfOptions, + _createMasterStateOptions(), + isAutomation); + case 'factory_reset': + return _createSceneFunction( + action, + 'Multi-Mode Gateway Z-W-B', + Assets.assetsFactoryReset, + 'Reset Factory', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'switch_1': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsAcPower, + 'Light 1 Switch', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'switch_2': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsAcPower, + 'Light 2 Switch', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'switch_3': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsAcPower, + 'Light 3 Switch', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'countdown_1': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsLightCountdown, + 'Light 1 CountDown', + OperationDialogType.countdown, + _createCountdownOptions(), + isAutomation); + case 'countdown_2': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsLightCountdown, + 'Light 2 CountDown', + OperationDialogType.countdown, + _createCountdownOptions(), + isAutomation); + case 'countdown_3': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsLightCountdown, + 'Light 3 CountDown', + OperationDialogType.countdown, + _createCountdownOptions(), + isAutomation); + case 'switch': + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsAcPower, + 'Power', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'temp_set': + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsTempreture, + 'Set Temperature', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.temperature, + isAutomation + ? _createAutomationTemperatureOptions() + : _createTemperatureOptions(), + isAutomation); + case 'mode': + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsFreezing, + 'Mode', + OperationDialogType.listOfOptions, + _createAcModeOptions(), + isAutomation); + case 'level': + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsFanSpeed, + 'Fan Speed', + OperationDialogType.listOfOptions, + _createFanSpeedOptions(), + isAutomation); + case 'child_lock': + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsChildLock, + 'Child Lock', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + default: + throw ArgumentError( + 'Unsupported function code: ${executorProperty.functionCode}'); + } + } - List getOperationsForOneFunction({ - required String deviceId, - required SceneStaticFunction taskItem, - }) { - List functions = []; + List _createAutomationTemperatureOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsCelsiusDegrees, + value: 0.0, + description: '°C', + minValue: 20, + maxValue: 30, + stepValue: 0.5) + ]; + } + + List _createIntegerStepsOptions() { + return [ + SceneOperationalValue( + icon: '', + value: 0.0, + description: "CM", + minValue: 1, + maxValue: 600, + stepValue: 1) + ]; + } + + SceneStaticFunction _createSceneFunction( + Action action, + String deviceName, + String icon, + String operationName, + OperationDialogType operationDialogType, + List operationalValues, + bool isAutomation) { + final functionValue = action.executorProperty.functionValue; + return SceneStaticFunction( + deviceId: action.entityId, + deviceName: deviceName, + deviceIcon: icon, + icon: icon, + operationName: operationName, + functionValue: functionValue, + code: action.executorProperty.functionCode ?? '', + operationDialogType: operationDialogType, + operationalValues: operationalValues, + ); + } + + List _createOnOffOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ]; + } + + List _createSensitivityOptions() { + return List.generate( + 10, + (index) => SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: index + 1, + description: (index + 1).toString())); + } + + List _createFarDetectionOptions() { + final distances = [75, 150, 225, 300, 375, 450, 525, 600]; + return distances + .map((distance) => SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: distance, + description: '${distance}cm', + iconValue: distance.toString())) + .toList(); + } + + List _createTemperatureOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsCelsiusDegrees, value: 0, description: 'COOL TO') + ]; + } + + List _createMasterStateOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "Alarm", value: 'alarm'), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "Normal", + value: 'normal'), + ]; + } + + List _createAcModeOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsAcCooling, + description: AcValuesEnums.Cooling.name, + value: TempModes.cold.name), + SceneOperationalValue( + icon: Assets.assetsAcHeating, + description: AcValuesEnums.Heating.name, + value: TempModes.hot.name), + SceneOperationalValue( + icon: Assets.assetsFanSpeed, + description: AcValuesEnums.Ventilation.name, + value: TempModes.wind.name), + ]; + } + + List _createFanSpeedOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsAcFanLow, + description: ValueACRange.LOW.name, + value: FanSpeeds.low.name), + SceneOperationalValue( + icon: Assets.assetsAcFanMiddle, + description: ValueACRange.MIDDLE.name, + value: FanSpeeds.middle.name), + SceneOperationalValue( + icon: Assets.assetsAcFanHigh, + description: ValueACRange.HIGH.name, + value: FanSpeeds.high.name), + SceneOperationalValue( + icon: Assets.assetsAcFanAuto, + description: ValueACRange.AUTO.name, + value: FanSpeeds.auto.name), + ]; + } + + List _createCountdownOptions() { + return [SceneOperationalValue(icon: '', value: 0)]; + } + + List getOperationsForOneFunction( + {required String deviceId, required SceneStaticFunction taskItem}) { if (deviceId.contains('delay')) { - functions.add( + return [ SceneStaticFunction( deviceId: taskItem.deviceId, deviceName: 'delay', @@ -899,733 +561,21 @@ mixin SceneOperationsDataHelper { code: '', operationDialogType: OperationDialogType.delay, operationalValues: [ - SceneOperationalValue( - icon: '', - description: "", - value: 0, - ), + SceneOperationalValue(icon: '', description: "", value: 0) ], ), - ); - return functions; - } - switch (taskItem.code) { - case 'sensitivity': - functions.add( - sensitivityFunctionsBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'normal_open_switch': - functions.add( - normalOpenSwitchBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'far_detection': - functions.add( - farDetectionBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'motion_sensitivity_value': - functions.add( - motionSensitivityValueBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'motionless_sensitivity': - functions.add( - motionlessSensitivityBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'indicator': - functions.add( - indicatorBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'presence_time': - functions.add( - presenceTimeBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'switch_alarm_sound': - functions.add( - switchAlarmSoundBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'master_state': - functions.add( - masterStateBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'factory_reset': - functions.add( - factoryResetBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'switch_1': - functions.add( - switch1BasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'switch_2': - functions.add( - switch2BasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'switch_3': - functions.add( - switch3BasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'countdown_1': - functions.add( - countdown1BasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'countdown_2': - functions.add( - countdown2BasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'countdown_3': - functions.add( - countdown3BasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'switch': - functions.add( - switchBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'temp_set': - functions.add( - tempSetBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'mode': - functions.add( - modeBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'level': - functions.add( - levelBasedOnCodeMatch(deviceId, taskItem), - ); - break; - case 'child_lock': - functions.add( - childLockBasedOnCodeMatch(deviceId, taskItem), - ); - break; - default: + ]; } - return functions; - } - - SceneStaticFunction childLockBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsChildLock, - operationName: 'Child Lock', - code: 'child_lock', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSceneChildLock, - description: 'Lock', - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsSceneChildUnlock, - description: 'Unlock', - value: false, - ), - ], - ); - } - - SceneStaticFunction levelBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsFanSpeed, - operationName: 'Fan Speed', - code: 'level', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcFanLow, - description: ValueACRange.LOW.name, - value: FanSpeeds.low.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanMiddle, - description: ValueACRange.MIDDLE.name, - value: FanSpeeds.middle.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanHigh, - description: ValueACRange.HIGH.name, - value: FanSpeeds.high.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcFanAuto, - description: ValueACRange.AUTO.name, - value: FanSpeeds.auto.name, - ), - ], - ); - } - - SceneStaticFunction modeBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsFreezing, - operationName: 'Mode', - code: 'mode', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcCooling, - description: AcValuesEnums.Cooling.name, - value: TempModes.cold.name, - ), - SceneOperationalValue( - icon: Assets.assetsAcHeating, - description: AcValuesEnums.Heating.name, - value: TempModes.hot.name, - ), - SceneOperationalValue( - icon: Assets.assetsFanSpeed, - description: AcValuesEnums.Ventilation.name, - value: TempModes.wind.name, - ), - ], - ); - } - - SceneStaticFunction tempSetBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsTempreture, - operationName: 'Set Temperature', - code: 'temp_set', - functionValue: taskItem.functionValue != null - ? ((taskItem.functionValue / 10) as double).toInt() - : null, - operationDialogType: OperationDialogType.temperature, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsCelsiusDegrees, - value: 0, - description: 'COOL TO', - ), - ], - ); - } - - SceneStaticFunction switchBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Smart AC Thermostat - Grey - Model A', - deviceIcon: Assets.assetsIconsAC, - icon: Assets.assetsAcPower, - operationName: 'Power', - code: 'switch', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ); - } - - SceneStaticFunction countdown3BasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsLightCountdown, - operationName: 'Light 3 CountDown', - code: 'countdown_3', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ); - } - - SceneStaticFunction countdown2BasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsLightCountdown, - operationName: 'Light 2 CountDown', - code: 'countdown_2', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ); - } - - SceneStaticFunction countdown1BasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsLightCountdown, - operationName: 'Light 1 CountDown', - code: 'countdown_1', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.countdown, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ); - } - - SceneStaticFunction switch3BasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsAcPower, - operationName: 'Light 3 Switch', - code: 'switch_3', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ); - } - - SceneStaticFunction switch2BasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsAcPower, - operationName: 'Light 2 Switch', - code: 'switch_2', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ); - } - - SceneStaticFunction switch1BasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: '3 Gang Button Switch L-L', - deviceIcon: Assets.assetsIcons3GangSwitch, - icon: Assets.assetsAcPower, - operationName: 'Light 1 Switch', - code: 'switch_1', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ); - } - - SceneStaticFunction factoryResetBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Multi-Mode Gateway Z-W-B', - deviceIcon: Assets.assetsIconsGateway, - icon: Assets.assetsFactoryReset, - operationName: 'Reset Factory', - functionValue: taskItem.functionValue, - code: 'factory_reset', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSceneRefresh, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsResetOff, - description: "OFF", - value: false, - ), - ], - ); - } - - SceneStaticFunction masterStateBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Multi-Mode Gateway Z-W-B', - deviceIcon: Assets.assetsIconsGateway, - icon: Assets.assetsMasterState, - operationName: 'Master State', - functionValue: taskItem.functionValue, - code: 'master_state', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "Alarm", - value: 'alarm', - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "Normal", - value: 'normal', - ), - ], - ); - } - - SceneStaticFunction switchAlarmSoundBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Multi-Mode Gateway Z-W-B', - deviceIcon: Assets.assetsIconsGateway, - icon: Assets.assetsSwitchAlarmSound, - operationName: 'Switch Alarm Sound', - functionValue: taskItem.functionValue, - code: 'switch_alarm_sound', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, - description: "ON", - value: true, - ), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ], - ); - } - - SceneStaticFunction presenceTimeBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsNobodyTime, - operationName: 'Nobody Time', - functionValue: taskItem.functionValue, - code: 'presence_time', - operationDialogType: OperationDialogType.temperature, - operationalValues: [ - SceneOperationalValue(icon: '', value: 0), - ], - ); - } - - SceneStaticFunction indicatorBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsIndicator, - operationName: 'Indicator', - functionValue: taskItem.functionValue, - code: 'indicator', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ); - } - - SceneStaticFunction motionlessSensitivityBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsMotionlessDetection, - operationName: 'Motionless Detection Sensitivity', - functionValue: taskItem.functionValue, - code: 'motion_sensitivity_value', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - iconValue: '1', - icon: Assets.assetsFarDetectionFunction, - value: 1, - description: '1', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 2, - description: '2', - iconValue: '2', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 3, - description: '3', - iconValue: '3', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 4, - description: '4', - iconValue: '4', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 5, - description: '5', - iconValue: '5', - ), - ], - ); - } - - SceneStaticFunction motionSensitivityValueBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsMotionDetection, - operationName: 'Motion Detection Sensitivity', - functionValue: taskItem.functionValue, - code: 'motion_sensitivity_value', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - ], - ); - } - - SceneStaticFunction farDetectionBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Human Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsFarDetection, - operationName: 'Far Detection', - functionValue: taskItem.functionValue, - code: 'far_detection', - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 75, - description: '75cm', - iconValue: '75', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 150, - description: '150cm', - iconValue: '150', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 225, - description: '225cm', - iconValue: '225', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 300, - description: '300cm', - iconValue: '300', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 375, - description: '375cm', - iconValue: '375', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 450, - description: '450cm', - iconValue: '450', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 525, - description: '525cm', - iconValue: '525', - ), - SceneOperationalValue( - icon: Assets.assetsFarDetectionFunction, - value: 600, - description: '600cm', - iconValue: '600', - ), - ], - ); - } - - SceneStaticFunction normalOpenSwitchBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'WIFI LOCK PRO', - deviceIcon: Assets.assetsIconsDoorLock, - icon: Assets.assetsIconsDoorLock, - operationName: 'Set Door lock Normal Open', - functionValue: taskItem.functionValue, - code: 'normal_open_switch', - operationDialogType: OperationDialogType.onOff, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "OFF", - value: false, - ), - ], - ); - } - - SceneStaticFunction sensitivityFunctionsBasedOnCodeMatch( - String deviceId, SceneStaticFunction taskItem) { - return SceneStaticFunction( - deviceId: deviceId, - deviceName: 'Presence Sensor', - deviceIcon: Assets.assetsIconsSensors, - icon: Assets.assetsSensitivityFunction, - operationName: 'Sensitivity', - code: 'sensitivity', - functionValue: taskItem.functionValue, - operationDialogType: OperationDialogType.listOfOptions, - operationalValues: [ - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 4, - description: 4.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 5, - description: 5.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 6, - description: 6.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 7, - description: 7.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 8, - description: 8.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 9, - description: 9.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 10, - description: 10.toString(), - ), - ], - ); + return [ + _mapExecutorPropertyToSceneFunction( + Action( + entityId: deviceId, + executorProperty: ExecutorProperty( + functionCode: taskItem.code, + functionValue: taskItem.functionValue), + actionExecutor: ''), + false) + ]; } } diff --git a/lib/features/scene/model/create_scene_model.dart b/lib/features/scene/model/create_scene_model.dart index 53dc344..ca7919a 100644 --- a/lib/features/scene/model/create_scene_model.dart +++ b/lib/features/scene/model/create_scene_model.dart @@ -3,29 +3,11 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; class CreateSceneModel { - /* -{ - "unitUuid": "string", - "sceneName": "string", - "decisionExpr": "string", - "actions": [ - { - "entityId": "string", - "actionExecutor": "string", - "executorProperty": { - "functionCode": "string", - "functionValue": {}, - "delaySeconds": 0 - } - } - ] -} - */ - String unitUuid; String sceneName; String decisionExpr; List actions; + CreateSceneModel({ required this.unitUuid, required this.sceneName, @@ -100,6 +82,7 @@ class CreateSceneAction { String entityId; String actionExecutor; CreateSceneExecutorProperty executorProperty; + CreateSceneAction({ required this.entityId, required this.actionExecutor, @@ -122,7 +105,7 @@ class CreateSceneAction { return { 'entityId': entityId, 'actionExecutor': actionExecutor, - 'executorProperty': executorProperty.toMap(), + 'executorProperty': executorProperty.toMap(actionExecutor), }; } @@ -163,6 +146,7 @@ class CreateSceneExecutorProperty { String functionCode; dynamic functionValue; int delaySeconds; + CreateSceneExecutorProperty({ required this.functionCode, required this.functionValue, @@ -181,12 +165,14 @@ class CreateSceneExecutorProperty { ); } - Map toMap() { - return { - if (functionCode.isNotEmpty == true) 'functionCode': functionCode, - if (functionValue != '') 'functionValue': functionValue, - if (delaySeconds > 0) 'delaySeconds': delaySeconds, - }; + Map toMap(String actionExecutor) { + final map = {}; + if (functionCode.isNotEmpty) map['functionCode'] = functionCode; + if (functionValue != null) map['functionValue'] = functionValue; + if (actionExecutor == 'delay' && delaySeconds > 0) { + map['delaySeconds'] = delaySeconds; + } + return map; } factory CreateSceneExecutorProperty.fromMap(Map map) { @@ -197,7 +183,7 @@ class CreateSceneExecutorProperty { ); } - String toJson() => json.encode(toMap()); + String toJson(String actionExecutor) => json.encode(toMap(actionExecutor)); factory CreateSceneExecutorProperty.fromJson(String source) => CreateSceneExecutorProperty.fromMap(json.decode(source)); diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index 0990a32..e707889 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -188,6 +188,7 @@ class DeviceFunctionsView extends StatelessWidget alertBody: getTheCorrectDialogBody( function, functionValues, + isAutomation: false, ), title: function.operationName, onConfirm: () { @@ -237,6 +238,7 @@ class DeviceFunctionsView extends StatelessWidget alertBody: getTheCorrectDialogBody( function, automationFunctionValues, + isAutomation: true, ), title: function.operationName, onConfirm: () { diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart index b93abcf..58ef349 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart @@ -11,10 +11,12 @@ class AlertDialogFunctionsOperationsBody extends StatefulWidget { super.key, this.functionValue, required this.taskItem, + required this.isAutomation, }); dynamic functionValue; final SceneStaticFunction taskItem; + final bool isAutomation; @override State createState() => @@ -26,25 +28,46 @@ class _AlertDialogFunctionsOperationsBodyState @override didChangeDependencies() { super.didChangeDependencies(); - - final tempTaskList = context.read().tempTasksList; + if (widget.isAutomation) { + final automationTempTasksList = + context.read().automationTempTasksList; - if (tempTaskList.isNotEmpty) { - for (var element in tempTaskList) { - if (element.code == widget.taskItem.code) { - groupValue = element.functionValue; - } else { - context - .read() - .add(RemoveFromSelectedValueById(code: widget.taskItem.code)); + if (automationTempTasksList.isNotEmpty) { + for (var element in automationTempTasksList) { + if (element.code == widget.taskItem.code) { + groupValue = element.functionValue; + } else { + context.read().add(RemoveFromSelectedValueById( + code: widget.taskItem.code, isAutomation: widget.isAutomation)); + } } } - } - if (widget.functionValue != null) { - setState(() { - groupValue = widget.functionValue; - }); + if (widget.functionValue != null) { + setState(() { + groupValue = widget.functionValue; + }); + } + } else { + final tempTaskList = context.read().tempTasksList; + + if (tempTaskList.isNotEmpty) { + for (var element in tempTaskList) { + if (element.code == widget.taskItem.code) { + groupValue = element.functionValue; + } else { + context + .read() + .add(RemoveFromSelectedValueById(code: widget.taskItem.code)); + } + } + } + + if (widget.functionValue != null) { + setState(() { + groupValue = widget.functionValue; + }); + } } } @@ -77,7 +100,9 @@ class _AlertDialogFunctionsOperationsBodyState groupValue = value; }); context.read().add(SelectedValueEvent( - value: value!, code: widget.taskItem.code)); + value: value!, + code: widget.taskItem.code, + isAutomation: widget.isAutomation)); }, ), onPressed: () { @@ -85,7 +110,9 @@ class _AlertDialogFunctionsOperationsBodyState groupValue = operation.value; }); context.read().add(SelectedValueEvent( - value: groupValue, code: widget.taskItem.code)); + value: groupValue, + code: widget.taskItem.code, + isAutomation: widget.isAutomation)); }, ); }, diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart index ebfff07..c732142 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart @@ -11,10 +11,12 @@ class AlertDialogSliderSteps extends StatefulWidget { super.key, this.functionValue, required this.taskItem, + required this.isAutomation, }); final dynamic functionValue; final SceneStaticFunction taskItem; + final bool isAutomation; @override State createState() => _AlertDialogSliderStepsState(); @@ -27,24 +29,27 @@ class _AlertDialogSliderStepsState extends State { @override void didChangeDependencies() { super.didChangeDependencies(); - final tempTaskList = context.read().tempTasksList; - if (tempTaskList.isNotEmpty) { - for (var element in tempTaskList) { - if (element.code == widget.taskItem.code) { - groupValue = element.functionValue; - } else { - context - .read() - .add(RemoveFromSelectedValueById(code: widget.taskItem.code)); + + if (widget.isAutomation) { + final automationTempTaskList = + context.read().automationTempTasksList; + if (automationTempTaskList.isNotEmpty) { + for (var element in automationTempTaskList) { + if (element.code == widget.taskItem.code) { + groupValue = element.functionValue; + } else { + context.read().add(RemoveFromSelectedValueById( + code: widget.taskItem.code, isAutomation: widget.isAutomation)); + } } } - } - if (widget.functionValue != null) { - setState(() { - groupValue = widget.functionValue; - }); - } else { - groupValue = widget.taskItem.operationalValues[0].minValue; + if (widget.functionValue != null) { + setState(() { + groupValue = widget.functionValue; + }); + } else { + groupValue = widget.taskItem.operationalValues[0].minValue; + } } } @@ -154,8 +159,12 @@ class _AlertDialogSliderStepsState extends State { : null, onChanged: (value) { setState(() { - groupValue = value; + groupValue = value.round().toDouble(); }); + context.read().add(SelectedValueEvent( + value: groupValue, + code: widget.taskItem.code, + isAutomation: widget.isAutomation)); }, ), ), diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart index fb662ad..783d8c1 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart @@ -14,14 +14,10 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class AlertDialogTemperatureBody extends StatefulWidget { AlertDialogTemperatureBody({ super.key, - //required this.index, - // required this.functions, this.functionValue, required this.taskItem, }); - //final List functions; - // final int index; final SceneStaticFunction taskItem; dynamic functionValue; @@ -32,14 +28,16 @@ class AlertDialogTemperatureBody extends StatefulWidget { class _AlertDialogTemperatureBodyState extends State { + int temperature = 24; + @override - didChangeDependencies() { + void didChangeDependencies() { super.didChangeDependencies(); final tempTaskList = context.read().tempTasksList; for (var element in tempTaskList) { if (element.code == widget.taskItem.code) { - temperature = element.functionValue; + temperature = _normalizeTemperature(element.functionValue); } else { context .read() @@ -48,12 +46,18 @@ class _AlertDialogTemperatureBodyState } if (widget.functionValue != null) { setState(() { - temperature = widget.functionValue; + temperature = _normalizeTemperature(widget.functionValue); }); } } - int temperature = 24; + int _normalizeTemperature(dynamic value) { + if (value is int && value >= 100) { + return value ~/ 10; + } + return value as int? ?? 24; + } + @override Widget build(BuildContext context) { return ListTile( @@ -98,8 +102,7 @@ class _AlertDialogTemperatureBodyState ], ), subtitle: BodyLarge( - text: widget.taskItem.operationalValues[0].description - .toString(), + text: widget.taskItem.operationalValues[0].description.toString(), textAlign: TextAlign.center, ), trailing: IconButton( @@ -110,8 +113,7 @@ class _AlertDialogTemperatureBodyState } }); context.read().add(SelectedValueEvent( - value: temperature * 10, - code: widget.taskItem.code)); + value: temperature * 10, code: widget.taskItem.code)); }, icon: const Icon( Icons.add, diff --git a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart index 85612f6..61510a5 100644 --- a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart +++ b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart @@ -34,7 +34,7 @@ class ThenAddedTasksContainer extends StatelessWidget Widget build(BuildContext context) { final createSceneBloc = context.read(); String operationValue = ''; - if (taskItem.code.contains('countdown') || + if ((taskItem.code.contains('countdown') && isAutomation != true) || taskItem.deviceId.contains('delay')) { final functionValue = taskItem.functionValue ?? taskItem.operationalValues.first.value; @@ -64,7 +64,8 @@ class ThenAddedTasksContainer extends StatelessWidget /// show alert dialog based on type context.customAlertDialog( - alertBody: getTheCorrectDialogBody(functionOperation.first, null), + alertBody: getTheCorrectDialogBody(functionOperation.first, null, + isAutomation: isAutomation ?? false), title: functionOperation.first.operationName, onConfirm: () { final savedCode = functionOperation.first.deviceId.contains('delay') diff --git a/lib/services/api/api_links_endpoints.dart b/lib/services/api/api_links_endpoints.dart index 457f96b..f252a09 100644 --- a/lib/services/api/api_links_endpoints.dart +++ b/lib/services/api/api_links_endpoints.dart @@ -2,8 +2,8 @@ import 'package:flutter/foundation.dart'; abstract class ApiEndpoints { static const String baseUrl = kReleaseMode - ? 'https://syncrow-staging.azurewebsites.net/api' - : 'https://syncrow-dev.azurewebsites.net/api'; + ? 'https://syncrow-staging.azurewebsites.net' + : 'https://syncrow-dev.azurewebsites.net'; // static const String baseUrl = 'http://100.107.182.63:4001'; //Localhost ////////////////////////////////////// Authentication /////////////////////////////// diff --git a/lib/services/api/scene_api.dart b/lib/services/api/scene_api.dart index d28c03d..4d377f1 100644 --- a/lib/services/api/scene_api.dart +++ b/lib/services/api/scene_api.dart @@ -12,7 +12,7 @@ class SceneApi { try { final response = await _httpService.post( path: ApiEndpoints.createScene, - body: createSceneModel.toJson(), + body: createSceneModel.toMap(), showServerMessage: false, expectedResponseModel: (json) { return json; From 079f7a7b129d4515314405f5ae78dfb39b036c9d Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Tue, 23 Jul 2024 02:18:28 +0300 Subject: [PATCH 10/30] push automation function add conditions --- .../bloc/create_scene/create_scene_bloc.dart | 14 +- .../helper/scene_operations_data_helper.dart | 458 +++++++++++++++--- .../if_then_containers/then_added_tasks.dart | 4 +- 3 files changed, 400 insertions(+), 76 deletions(-) diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index 9033d6d..1baac0c 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -73,6 +73,7 @@ class CreateSceneBloc extends Bloc void addToTempTaskList( TempHoldSceneTasksEvent event, Emitter emit) { + emit(CreateSceneLoading()); bool updated = false; for (var element in tempTasksList) { if (element.code == event.deviceControlModel.code) { @@ -124,6 +125,7 @@ class CreateSceneBloc extends Bloc void addToTempAutomationTaskList( TempHoldSceneTasksEvent event, Emitter emit) { + emit(CreateSceneLoading()); bool updated = false; for (var element in automationTempTasksList) { if (element.code == event.deviceControlModel.code) { @@ -177,6 +179,7 @@ class CreateSceneBloc extends Bloc FutureOr _selectedValue( SelectedValueEvent event, Emitter emit) { + emit(CreateSceneLoading()); if (event.isAutomation == true) { automationSelectedValues[event.code] = event.value; emit(SelectedTaskValueState(value: event.value)); @@ -217,6 +220,7 @@ class CreateSceneBloc extends Bloc FutureOr _removeTempTaskById( RemoveTempTaskByIdEvent event, Emitter emit) { + emit(CreateSceneLoading()); if (event.isAutomation == true) { for (var element in automationTempTasksList) { if (element.uniqueCustomId == event.code) { @@ -264,6 +268,7 @@ class CreateSceneBloc extends Bloc FutureOr _clearTaskList( ClearTaskListEvent event, Emitter emit) { + emit(CreateSceneLoading()); automationTasksList.clear(); tasksList.clear(); emit(AddSceneTask( @@ -292,6 +297,7 @@ class CreateSceneBloc extends Bloc FutureOr _clearTempTaskList( ClearTempTaskListEvent event, Emitter emit) { + emit(CreateSceneLoading()); if (event.isAutomation == true) { automationTempTasksList.clear(); automationSelectedValues.clear(); @@ -307,6 +313,7 @@ class CreateSceneBloc extends Bloc FutureOr _removeFromSelectedValueById( RemoveFromSelectedValueById event, Emitter emit) { + emit(CreateSceneLoading()); if (event.isAutomation == true) { if (automationSelectedValues.containsKey(event.code)) { automationSelectedValues.remove(event.code); @@ -343,6 +350,7 @@ class CreateSceneBloc extends Bloc FutureOr _updateTaskValue( UpdateTaskEvent event, Emitter emit) { + emit(CreateSceneLoading()); if (event.isAutomation == true) { for (var i = 0; i < automationTasksList.length; i++) { if (automationTasksList[i].uniqueCustomId == event.taskId) { @@ -352,8 +360,6 @@ class CreateSceneBloc extends Bloc break; } } - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); } else { for (var i = 0; i < tasksList.length; i++) { if (tasksList[i].uniqueCustomId == event.taskId) { @@ -363,8 +369,8 @@ class CreateSceneBloc extends Bloc break; } } - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); } + emit(AddSceneTask( + tasksList: tasksList, automationTasksList: automationTasksList)); } } diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index dff462b..747f2e5 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -231,6 +231,105 @@ mixin SceneOperationsDataHelper { OperationDialogType.onOff, _createOnOffOptions(), isAutomation); + case 'unlock_fingerprint': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsFingerprintUnlock, + 'Fingerprint Unlock', + OperationDialogType.integerSteps, + _createFingerprintUnlockOptions(), + isAutomation); + case 'unlock_password': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsPasswordUnlock, + 'Password Unlock', + OperationDialogType.integerSteps, + _createPasswordUnlockOptions(), + isAutomation); + case 'unlock_card': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsCardUnlock, + 'Card Unlock', + OperationDialogType.integerSteps, + _createCardUnlockOptions(), + isAutomation); + case 'alarm_lock': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsLockAlarm, + 'Lock Alarm', + OperationDialogType.listOfOptions, + _createLockAlarmOptions(), + isAutomation); + case 'unlock_request': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsRemoteUnlockReq, + 'Remote Unlock Request', + OperationDialogType.integerSteps, + _createUnlockRequestOptions(), + isAutomation); + case 'residual_electricity': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsResidualElectricity, + 'Residual Electricity', + OperationDialogType.integerSteps, + _createResidualElectricityOptions(), + isAutomation); + case 'reverse_lock': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsDoubleLock, + 'Double Lock', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'unlock_app': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsRemoteUnlockViaApp, + 'Remote Unlock Via App', + OperationDialogType.integerSteps, + _createUnlockAppOptions(), + isAutomation); + case 'hijack': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsHijackAlarm, + 'Hijack Alarm', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'doorbell': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsDoorlockNormalOpen, + 'Doorbell', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'unlock_temporary': + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsTempPasswordUnlock, + 'Temporary Password Unlock', + OperationDialogType.integerSteps, + _createTemporaryPasswordUnlockOptions(), + isAutomation); case 'far_detection': return _createSceneFunction( action, @@ -276,86 +375,41 @@ mixin SceneOperationsDataHelper { OperationDialogType.countdown, _createCountdownOptions(), isAutomation); - case 'switch_alarm_sound': + case 'presence_state': return _createSceneFunction( action, - 'Multi-Mode Gateway Z-W-B', - Assets.assetsSwitchAlarmSound, - 'Switch Alarm Sound', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation); - case 'master_state': - return _createSceneFunction( - action, - 'Multi-Mode Gateway Z-W-B', - Assets.assetsMasterState, - 'Master State', + 'Human Presence Sensor', + Assets.assetsPresenceState, + 'Presence State', OperationDialogType.listOfOptions, - _createMasterStateOptions(), + _createPresenceStateOptions(), isAutomation); - case 'factory_reset': + case 'dis_current': return _createSceneFunction( action, - 'Multi-Mode Gateway Z-W-B', - Assets.assetsFactoryReset, - 'Reset Factory', - OperationDialogType.onOff, - _createOnOffOptions(), + 'Human Presence Sensor', + Assets.assetsIconsPresenceSensorAssetsDistance, + 'Current Distance', + OperationDialogType.integerSteps, + _createCurrentDistanceOptions(), isAutomation); - case 'switch_1': + case 'illuminance_value': return _createSceneFunction( action, - '3 Gang Button Switch L-L', - Assets.assetsAcPower, - 'Light 1 Switch', - OperationDialogType.onOff, - _createOnOffOptions(), + 'Human Presence Sensor', + Assets.assetsIconsPresenceSensorAssetsIlluminanceValue, + 'Illuminance Value', + OperationDialogType.integerSteps, + _createIlluminanceValueOptions(), isAutomation); - case 'switch_2': + case 'checking_result': return _createSceneFunction( action, - '3 Gang Button Switch L-L', - Assets.assetsAcPower, - 'Light 2 Switch', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation); - case 'switch_3': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsAcPower, - 'Light 3 Switch', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation); - case 'countdown_1': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsLightCountdown, - 'Light 1 CountDown', - OperationDialogType.countdown, - _createCountdownOptions(), - isAutomation); - case 'countdown_2': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsLightCountdown, - 'Light 2 CountDown', - OperationDialogType.countdown, - _createCountdownOptions(), - isAutomation); - case 'countdown_3': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsLightCountdown, - 'Light 3 CountDown', - OperationDialogType.countdown, - _createCountdownOptions(), + 'Human Presence Sensor', + Assets.assetsSelfTestResult, + 'Self-Test Result', + OperationDialogType.listOfOptions, + _createSelfTestResultOptions(), isAutomation); case 'switch': return _createSceneFunction( @@ -406,12 +460,258 @@ mixin SceneOperationsDataHelper { OperationDialogType.onOff, _createOnOffOptions(), isAutomation); + case 'switch_1': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsIconsLightSwitchOn, + 'Light 1 Switch', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'switch_2': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsIconsLightSwitchOn, + 'Light 2 Switch', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'switch_3': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsIconsLightSwitchOn, + 'Light 3 Switch', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + + case 'countdown_1': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsLightCountdown, + 'Light 1 CountDown', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.countdown, + isAutomation + ? _createAutomationCountDownOptions() + : _createCountdownOptions(), + isAutomation); + case 'countdown_2': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsLightCountdown, + 'Light 2 CountDown', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.countdown, + isAutomation + ? _createAutomationCountDownOptions() + : _createCountdownOptions(), + isAutomation); + case 'countdown_3': + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsLightCountdown, + 'Light 3 CountDown', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.countdown, + isAutomation + ? _createAutomationCountDownOptions() + : _createCountdownOptions(), + isAutomation); + case 'switch_alarm_sound': + return _createSceneFunction( + action, + 'Gateway', + Assets.assetsSwitchAlarmSound, + 'Switch Alarm Sound', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); + case 'master_state': + return _createSceneFunction( + action, + 'Gateway', + Assets.assetsMasterState, + 'Master State', + OperationDialogType.listOfOptions, + _createMasterStateOptions(), + isAutomation); + case 'factory_reset': + return _createSceneFunction( + action, + 'Gateway', + Assets.assetsFactoryReset, + 'Factory Reset', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation); default: throw ArgumentError( 'Unsupported function code: ${executorProperty.functionCode}'); } } + List _createFingerprintUnlockOptions() { + return [ + SceneOperationalValue( + icon: '', + description: "", + value: 0.0, + minValue: 0.0, + maxValue: 999, + stepValue: 1.0, + ), + ]; + } + + List _createPasswordUnlockOptions() { + return [ + SceneOperationalValue( + icon: '', + description: "", + value: 0.0, + minValue: 0.0, + maxValue: 999, + stepValue: 1.0, + ), + ]; + } + + List _createCardUnlockOptions() { + return [ + SceneOperationalValue( + icon: '', + description: "", + value: 0.0, + minValue: 0.0, + maxValue: 999, + stepValue: 1.0, + ), + ]; + } + + List _createLockAlarmOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsFingerprintUnlock, + description: "Fingerprint Mismatch", + value: 0, + ), + ]; + } + + List _createUnlockRequestOptions() { + return [ + SceneOperationalValue( + icon: '', + description: "", + value: 0.0, + minValue: 0, + maxValue: 90, + stepValue: 1, + ), + ]; + } + + List _createResidualElectricityOptions() { + return [ + SceneOperationalValue( + icon: '', + description: "", + value: 0.0, + minValue: 0, + maxValue: 100, + stepValue: 1, + ), + ]; + } + + List _createUnlockAppOptions() { + return [ + SceneOperationalValue( + icon: '', + description: "", + value: 0.0, + minValue: 0, + maxValue: 999, + stepValue: 1, + ), + ]; + } + + List _createTemporaryPasswordUnlockOptions() { + return [ + SceneOperationalValue( + icon: '', + description: "", + value: 0.0, + minValue: 0, + maxValue: 999, + stepValue: 1, + ), + ]; + } + + List _createPresenceStateOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsIconsPresenceSensorAssetsEmpty, + value: 'none', + description: 'None', + ), + SceneOperationalValue( + icon: Assets.assetsPresence, + value: 'presence', + description: 'Presence', + ), + ]; + } + + List _createCurrentDistanceOptions() { + return [ + SceneOperationalValue( + icon: '', + value: 0.0, + description: "CM", + minValue: 1, + maxValue: 600, + stepValue: 1, + ), + ]; + } + + List _createIlluminanceValueOptions() { + return [ + SceneOperationalValue( + icon: '', + value: 0.0, + description: "Lux", + minValue: 0, + maxValue: 10000, + stepValue: 1, + ), + ]; + } + + List _createSelfTestResultOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsSelfTestResult, + value: 'check_success', + description: 'Self Testing Success', + ), + ]; + } + List _createAutomationTemperatureOptions() { return [ SceneOperationalValue( @@ -436,6 +736,19 @@ mixin SceneOperationsDataHelper { ]; } + _createAutomationCountDownOptions() { + return [ + SceneOperationalValue( + icon: '', + description: "sec", + value: 0.0, + minValue: 0, + maxValue: 43200, + stepValue: 1, + ) + ]; + } + SceneStaticFunction _createSceneFunction( Action action, String deviceName, @@ -547,8 +860,11 @@ mixin SceneOperationsDataHelper { return [SceneOperationalValue(icon: '', value: 0)]; } - List getOperationsForOneFunction( - {required String deviceId, required SceneStaticFunction taskItem}) { + List getOperationsForOneFunction({ + required String deviceId, + required SceneStaticFunction taskItem, + required bool isAutomation, + }) { if (deviceId.contains('delay')) { return [ SceneStaticFunction( @@ -575,7 +891,7 @@ mixin SceneOperationsDataHelper { functionCode: taskItem.code, functionValue: taskItem.functionValue), actionExecutor: ''), - false) + isAutomation) ]; } } diff --git a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart index 61510a5..4c3f531 100644 --- a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart +++ b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart @@ -60,7 +60,9 @@ class ThenAddedTasksContainer extends StatelessWidget /// get the task functions functionOperation = List.from(getOperationsForOneFunction( - taskItem: taskItem, deviceId: taskItem.deviceId)); + taskItem: taskItem, + deviceId: taskItem.deviceId, + isAutomation: isAutomation ?? false)); /// show alert dialog based on type context.customAlertDialog( From 9a088353e05d1cc127b483192b41013e380f04d3 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Tue, 23 Jul 2024 02:40:07 +0300 Subject: [PATCH 11/30] fix devices icons --- .../helper/scene_operations_data_helper.dart | 92 ++++++++++++------- .../if_then_containers/if_container.dart | 4 - 2 files changed, 57 insertions(+), 39 deletions(-) diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index 747f2e5..20d87d9 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -208,12 +208,34 @@ mixin SceneOperationsDataHelper { SceneStaticFunction _mapExecutorPropertyToSceneFunction( Action action, bool isAutomation) { ExecutorProperty executorProperty = action.executorProperty; + /* + + if (type == DeviceType.LightBulb) { + tempIcon = Assets.assetsIconsLight; + } else if (type == DeviceType.CeilingSensor || + type == DeviceType.WallSensor) { + tempIcon = Assets.assetsIconsSensors; + } else if (type == DeviceType.AC) { + tempIcon = Assets.assetsIconsAC; + } else if (type == DeviceType.DoorLock) { + tempIcon = Assets.assetsIconsDoorLock; + } else if (type == DeviceType.Curtain) { + tempIcon = Assets.assetsIconsCurtain; + } else if (type == DeviceType.ThreeGang) { + tempIcon = Assets.assetsIcons3GangSwitch; + } else if (type == DeviceType.Gateway) { + tempIcon = Assets.assetsIconsGateway; + } else { + tempIcon = Assets.assetsIconsLogo; + } + */ + switch (executorProperty.functionCode) { case 'sensitivity': return _createSceneFunction( action, 'Presence Sensor', - Assets.assetsSensitivityFunction, + Assets.assetsIconsSensors, 'Sensitivity', isAutomation ? OperationDialogType.integerSteps @@ -235,7 +257,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsFingerprintUnlock, + Assets.assetsIconsDoorLock, 'Fingerprint Unlock', OperationDialogType.integerSteps, _createFingerprintUnlockOptions(), @@ -244,7 +266,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsPasswordUnlock, + Assets.assetsIconsDoorLock, 'Password Unlock', OperationDialogType.integerSteps, _createPasswordUnlockOptions(), @@ -253,7 +275,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsCardUnlock, + Assets.assetsIconsDoorLock, 'Card Unlock', OperationDialogType.integerSteps, _createCardUnlockOptions(), @@ -262,7 +284,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsLockAlarm, + Assets.assetsIconsDoorLock, 'Lock Alarm', OperationDialogType.listOfOptions, _createLockAlarmOptions(), @@ -271,7 +293,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsRemoteUnlockReq, + Assets.assetsIconsDoorLock, 'Remote Unlock Request', OperationDialogType.integerSteps, _createUnlockRequestOptions(), @@ -280,7 +302,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsResidualElectricity, + Assets.assetsIconsDoorLock, 'Residual Electricity', OperationDialogType.integerSteps, _createResidualElectricityOptions(), @@ -289,7 +311,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsDoubleLock, + Assets.assetsIconsDoorLock, 'Double Lock', OperationDialogType.onOff, _createOnOffOptions(), @@ -298,7 +320,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsRemoteUnlockViaApp, + Assets.assetsIconsDoorLock, 'Remote Unlock Via App', OperationDialogType.integerSteps, _createUnlockAppOptions(), @@ -307,7 +329,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsHijackAlarm, + Assets.assetsIconsDoorLock, 'Hijack Alarm', OperationDialogType.onOff, _createOnOffOptions(), @@ -316,7 +338,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsDoorlockNormalOpen, + Assets.assetsIconsDoorLock, 'Doorbell', OperationDialogType.onOff, _createOnOffOptions(), @@ -325,7 +347,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'WIFI LOCK PRO', - Assets.assetsTempPasswordUnlock, + Assets.assetsIconsDoorLock, 'Temporary Password Unlock', OperationDialogType.integerSteps, _createTemporaryPasswordUnlockOptions(), @@ -334,7 +356,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Human Presence Sensor', - Assets.assetsFarDetection, + Assets.assetsIconsSensors, 'Far Detection', OperationDialogType.listOfOptions, _createFarDetectionOptions(), @@ -343,7 +365,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Human Presence Sensor', - Assets.assetsMotionDetection, + Assets.assetsIconsSensors, 'Motion Detection Sensitivity', OperationDialogType.listOfOptions, _createSensitivityOptions(), @@ -352,7 +374,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Human Presence Sensor', - Assets.assetsMotionlessDetection, + Assets.assetsIconsSensors, 'Motionless Detection Sensitivity', OperationDialogType.listOfOptions, _createSensitivityOptions(), @@ -361,7 +383,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Human Presence Sensor', - Assets.assetsIndicator, + Assets.assetsIconsSensors, 'Indicator', OperationDialogType.onOff, _createOnOffOptions(), @@ -370,7 +392,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Human Presence Sensor', - Assets.assetsNobodyTime, + Assets.assetsIconsSensors, 'Nobody Time', OperationDialogType.countdown, _createCountdownOptions(), @@ -379,7 +401,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Human Presence Sensor', - Assets.assetsPresenceState, + Assets.assetsIconsSensors, 'Presence State', OperationDialogType.listOfOptions, _createPresenceStateOptions(), @@ -388,7 +410,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Human Presence Sensor', - Assets.assetsIconsPresenceSensorAssetsDistance, + Assets.assetsIconsSensors, 'Current Distance', OperationDialogType.integerSteps, _createCurrentDistanceOptions(), @@ -397,7 +419,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Human Presence Sensor', - Assets.assetsIconsPresenceSensorAssetsIlluminanceValue, + Assets.assetsIconsSensors, 'Illuminance Value', OperationDialogType.integerSteps, _createIlluminanceValueOptions(), @@ -406,7 +428,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Human Presence Sensor', - Assets.assetsSelfTestResult, + Assets.assetsIconsSensors, 'Self-Test Result', OperationDialogType.listOfOptions, _createSelfTestResultOptions(), @@ -415,7 +437,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Smart AC Thermostat - Grey - Model A', - Assets.assetsAcPower, + Assets.assetsIconsAC, 'Power', OperationDialogType.onOff, _createOnOffOptions(), @@ -424,7 +446,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Smart AC Thermostat - Grey - Model A', - Assets.assetsTempreture, + Assets.assetsIconsAC, 'Set Temperature', isAutomation ? OperationDialogType.integerSteps @@ -437,7 +459,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Smart AC Thermostat - Grey - Model A', - Assets.assetsFreezing, + Assets.assetsIconsAC, 'Mode', OperationDialogType.listOfOptions, _createAcModeOptions(), @@ -446,7 +468,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Smart AC Thermostat - Grey - Model A', - Assets.assetsFanSpeed, + Assets.assetsIconsAC, 'Fan Speed', OperationDialogType.listOfOptions, _createFanSpeedOptions(), @@ -455,7 +477,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Smart AC Thermostat - Grey - Model A', - Assets.assetsChildLock, + Assets.assetsIconsAC, 'Child Lock', OperationDialogType.onOff, _createOnOffOptions(), @@ -464,7 +486,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, '3 Gang Button Switch L-L', - Assets.assetsIconsLightSwitchOn, + Assets.assetsIcons3GangSwitch, 'Light 1 Switch', OperationDialogType.onOff, _createOnOffOptions(), @@ -473,7 +495,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, '3 Gang Button Switch L-L', - Assets.assetsIconsLightSwitchOn, + Assets.assetsIcons3GangSwitch, 'Light 2 Switch', OperationDialogType.onOff, _createOnOffOptions(), @@ -482,7 +504,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, '3 Gang Button Switch L-L', - Assets.assetsIconsLightSwitchOn, + Assets.assetsIcons3GangSwitch, 'Light 3 Switch', OperationDialogType.onOff, _createOnOffOptions(), @@ -492,7 +514,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, '3 Gang Button Switch L-L', - Assets.assetsLightCountdown, + Assets.assetsIcons3GangSwitch, 'Light 1 CountDown', isAutomation ? OperationDialogType.integerSteps @@ -505,7 +527,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, '3 Gang Button Switch L-L', - Assets.assetsLightCountdown, + Assets.assetsIcons3GangSwitch, 'Light 2 CountDown', isAutomation ? OperationDialogType.integerSteps @@ -518,7 +540,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, '3 Gang Button Switch L-L', - Assets.assetsLightCountdown, + Assets.assetsIcons3GangSwitch, 'Light 3 CountDown', isAutomation ? OperationDialogType.integerSteps @@ -531,7 +553,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Gateway', - Assets.assetsSwitchAlarmSound, + Assets.assetsIconsGateway, 'Switch Alarm Sound', OperationDialogType.onOff, _createOnOffOptions(), @@ -540,7 +562,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Gateway', - Assets.assetsMasterState, + Assets.assetsIconsGateway, 'Master State', OperationDialogType.listOfOptions, _createMasterStateOptions(), @@ -549,7 +571,7 @@ mixin SceneOperationsDataHelper { return _createSceneFunction( action, 'Gateway', - Assets.assetsFactoryReset, + Assets.assetsIconsGateway, 'Factory Reset', OperationDialogType.onOff, _createOnOffOptions(), diff --git a/lib/features/scene/widgets/if_then_containers/if_container.dart b/lib/features/scene/widgets/if_then_containers/if_container.dart index d923b94..b862eb0 100644 --- a/lib/features/scene/widgets/if_then_containers/if_container.dart +++ b/lib/features/scene/widgets/if_then_containers/if_container.dart @@ -57,10 +57,6 @@ class IFDefaultContainer extends StatelessWidget { const LightDivider(), BlocBuilder( builder: (context, state) { - if (state is CreateSceneLoading) { - return const Center(child: LinearProgressIndicator()); - } - if (state is AddSceneTask) { final automationTasksList = state.automationTasksList; if (automationTasksList?.isNotEmpty == true) { From 7a773f165380add754bcfaad76b41de7878c5beb Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Wed, 24 Jul 2024 01:41:10 +0300 Subject: [PATCH 12/30] push autoamtion api connect --- lib/features/app_layout/bloc/home_cubit.dart | 61 ++++-- .../bloc/create_scene/create_scene_bloc.dart | 61 +++++- .../bloc/create_scene/create_scene_event.dart | 21 ++- .../bloc/create_scene/create_scene_state.dart | 11 ++ .../scene/enum/create_scene_enum.dart | 1 + .../scene/helper/scene_logic_helper.dart | 103 +++++++--- .../helper/scene_operations_data_helper.dart | 176 +++++++++++------- .../scene/model/create_automation_model.dart | 172 +++++++++++++++++ .../scene/model/scene_static_function.dart | 12 +- .../scene/view/create_scene_view.dart | 10 +- .../scene/view/device_functions_view.dart | 5 +- .../scene/view/scene_rooms_tabbar.dart | 19 +- .../alert_dialog_slider_steps.dart | 52 +++++- .../widgets/create_scene_save_button.dart | 102 +++++----- .../if_then_containers/if_container.dart | 162 ++++++++++++---- .../if_then_containers/then_container.dart | 60 +++--- lib/navigation/navigate_to_route.dart | 17 ++ lib/services/api/api_links_endpoints.dart | 2 + lib/services/api/scene_api.dart | 18 ++ lib/utils/context_extension.dart | 81 +++++--- 20 files changed, 874 insertions(+), 272 deletions(-) create mode 100644 lib/features/scene/model/create_automation_model.dart create mode 100644 lib/navigation/navigate_to_route.dart diff --git a/lib/features/app_layout/bloc/home_cubit.dart b/lib/features/app_layout/bloc/home_cubit.dart index eee72a1..faa4f7b 100644 --- a/lib/features/app_layout/bloc/home_cubit.dart +++ b/lib/features/app_layout/bloc/home_cubit.dart @@ -17,10 +17,15 @@ import 'package:syncrow_app/features/devices/model/status_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart'; import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart'; import 'package:syncrow_app/features/menu/view/menu_view.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; +import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; import 'package:syncrow_app/features/scene/view/create_scene_view.dart'; +import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart'; import 'package:syncrow_app/features/scene/view/scene_view.dart'; import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/navigation/navigation_service.dart'; +import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/services/api/devices_api.dart'; import 'package:syncrow_app/services/api/spaces_api.dart'; import 'package:syncrow_app/utils/helpers/custom_page_route.dart'; @@ -63,9 +68,12 @@ class HomeCubit extends Cubit { selectedSpace = null; selectedRoom = null; pageIndex = 0; - OneSignal.User.pushSubscription.removeObserver((stateChanges) => oneSignalSubscriptionObserver); - OneSignal.Notifications.removePermissionObserver((permission) => oneSignalPermissionObserver); - OneSignal.Notifications.removeClickListener((event) => oneSignalClickListenerObserver); + OneSignal.User.pushSubscription + .removeObserver((stateChanges) => oneSignalSubscriptionObserver); + OneSignal.Notifications.removePermissionObserver( + (permission) => oneSignalPermissionObserver); + OneSignal.Notifications.removeClickListener( + (event) => oneSignalClickListenerObserver); return super.close(); } @@ -107,7 +115,9 @@ class HomeCubit extends Cubit { return; } - var userUuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? ''; + var userUuid = + await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? + ''; if (userUuid.isNotEmpty) { await OneSignal.login(userUuid); } @@ -115,21 +125,24 @@ class HomeCubit extends Cubit { await OneSignal.User.pushSubscription.optIn(); //this function will be called once a user is subscribed - oneSignalSubscriptionObserver = OneSignal.User.pushSubscription.addObserver((state) async { + oneSignalSubscriptionObserver = + OneSignal.User.pushSubscription.addObserver((state) async { if (state.current.optedIn) { await _sendSubscriptionId(); } }); // Send the player id when a user allows notifications - oneSignalPermissionObserver = OneSignal.Notifications.addPermissionObserver((state) async { + oneSignalPermissionObserver = + OneSignal.Notifications.addPermissionObserver((state) async { await _sendSubscriptionId(); }); //check if the player id is sent, if not send it again await _sendSubscriptionId(); - oneSignalClickListenerObserver = OneSignal.Notifications.addClickListener((event) async { + oneSignalClickListenerObserver = + OneSignal.Notifications.addClickListener((event) async { //Once the user clicks on the notification }); } catch (err) { @@ -216,7 +229,9 @@ class HomeCubit extends Cubit { Future joinAUnit(String code) async { try { - var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? ''; + var uuid = + await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? + ''; Map body = {'userUuid': uuid, 'inviteCode': code}; final success = await SpacesAPI.joinUnit(body); @@ -334,15 +349,25 @@ class HomeCubit extends Cubit { size: 32, ), style: ButtonStyle( - foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor), + foregroundColor: + WidgetStateProperty.all(ColorsManager.textPrimaryColor), ), onPressed: () { - Navigator.push( + Navigator.pushNamed( NavigationService.navigatorKey.currentContext!, - CustomPageRoute( - builder: (context) => const CreateSceneView(), + Routes.sceneTasksRoute, + arguments: SceneSettingsRouteArguments( + sceneType: '', + sceneId: '', + sceneName: '', ), ); + NavigationService.navigatorKey.currentContext! + .read() + .add(const ClearTaskListEvent()); + NavigationService.navigatorKey.currentContext! + .read() + .add(const SceneTypeEvent(CreateSceneEnum.none)); }, ), IconButton( @@ -351,7 +376,8 @@ class HomeCubit extends Cubit { size: 28, ), style: ButtonStyle( - foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor), + foregroundColor: + WidgetStateProperty.all(ColorsManager.textPrimaryColor), ), onPressed: () {}, ), @@ -384,7 +410,8 @@ class HomeCubit extends Cubit { }; static var bottomNavItems = [ - defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'), + defaultBottomNavBarItem( + icon: Assets.assetsIconsDashboard, label: 'Dashboard'), // defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'), defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'), defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'), @@ -410,7 +437,8 @@ class HomeCubit extends Cubit { void updateDevice(String deviceId) async { try { - final response = await DevicesAPI.firmwareDevice(deviceId: deviceId, firmwareVersion: '0'); + final response = await DevicesAPI.firmwareDevice( + deviceId: deviceId, firmwareVersion: '0'); if (response['success'] ?? false) { CustomSnackBar.displaySnackBar('No updates available'); } @@ -418,7 +446,8 @@ class HomeCubit extends Cubit { } } -BottomNavigationBarItem defaultBottomNavBarItem({required String icon, required String label}) { +BottomNavigationBarItem defaultBottomNavBarItem( + {required String icon, required String label}) { return BottomNavigationBarItem( icon: SvgPicture.asset(icon), activeIcon: SvgPicture.asset( diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index 1baac0c..5ac0c32 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -2,8 +2,10 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart'; +import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart'; +import 'package:syncrow_app/features/scene/model/create_automation_model.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/services/api/scene_api.dart'; @@ -26,8 +28,12 @@ class CreateSceneBloc extends Bloc on(_removeFromSelectedValueById); on(_deleteScene); on(_updateTaskValue); + on(_selectConditionRule); + on(_sceneTypeEvent); } + CreateSceneEnum sceneType = CreateSceneEnum.none; + /// tab to run values and list List tasksList = []; List tempTasksList = []; @@ -37,6 +43,8 @@ class CreateSceneBloc extends Bloc List automationTasksList = []; List automationTempTasksList = []; final Map automationSelectedValues = {}; + final Map automationComparatorValues = {}; + String conditionRule = 'or'; FutureOr _onAddSceneTask( AddTaskEvent event, Emitter emit) { @@ -46,6 +54,7 @@ class CreateSceneBloc extends Bloc automationTasksList.addAll(copyList); automationTempTasksList.clear(); automationSelectedValues.clear(); + automationComparatorValues.clear(); emit(AddSceneTask( automationTasksList: automationTasksList, tasksList: tasksList, @@ -144,6 +153,7 @@ class CreateSceneBloc extends Bloc icon: '', ), ], + comparator: automationComparatorValues[element.code], ); automationTempTasksList[automationTempTasksList.indexOf(element)] = updatedElement; @@ -168,6 +178,8 @@ class CreateSceneBloc extends Bloc icon: '', ), ], + comparator: + automationComparatorValues[event.deviceControlModel.code] ?? '==', ); automationTempTasksList.add(newElement); automationSelectedValues[newElement.code] = @@ -182,6 +194,7 @@ class CreateSceneBloc extends Bloc emit(CreateSceneLoading()); if (event.isAutomation == true) { automationSelectedValues[event.code] = event.value; + automationComparatorValues[event.code] = event.comparator ?? '=='; emit(SelectedTaskValueState(value: event.value)); emit(AddSceneTask( tasksList: tasksList, automationTasksList: automationTasksList)); @@ -248,13 +261,26 @@ class CreateSceneBloc extends Bloc CreateSceneWithTasksEvent event, Emitter emit) async { emit(CreateSceneLoading()); try { - final response = event.updateScene - ? await SceneApi.updateScene(event.createSceneModel, event.sceneId) - : await SceneApi.createScene(event.createSceneModel); + dynamic response; + if (event.createSceneModel != null) { + response = event.updateScene + ? await SceneApi.updateScene(event.createSceneModel!, event.sceneId) + : await SceneApi.createScene(event.createSceneModel!); + } else if (event.createAutomationModel != null) { + response = + await SceneApi.createAutomation(event.createAutomationModel!); + } + if (response['success'] == true) { tasksList.clear(); tempTasksList.clear(); selectedValues.clear(); + automationTasksList.clear(); + automationTempTasksList.clear(); + automationSelectedValues.clear(); + automationComparatorValues.clear(); + sceneType = CreateSceneEnum.none; + conditionRule = 'or'; emit(const CreateSceneWithTasks(success: true)); } else { emit(const CreateSceneError(message: 'Something went wrong')); @@ -301,6 +327,7 @@ class CreateSceneBloc extends Bloc if (event.isAutomation == true) { automationTempTasksList.clear(); automationSelectedValues.clear(); + automationComparatorValues.clear(); emit(AddSceneTask( tasksList: tasksList, automationTasksList: automationTasksList)); } else { @@ -317,6 +344,7 @@ class CreateSceneBloc extends Bloc if (event.isAutomation == true) { if (automationSelectedValues.containsKey(event.code)) { automationSelectedValues.remove(event.code); + automationComparatorValues.remove(event.code); emit(const SelectedTaskValueState(value: null)); emit(AddSceneTask( tasksList: tasksList, automationTasksList: automationTasksList)); @@ -373,4 +401,31 @@ class CreateSceneBloc extends Bloc emit(AddSceneTask( tasksList: tasksList, automationTasksList: automationTasksList)); } + + FutureOr _selectConditionRule( + SelectConditionEvent event, Emitter emit) { + emit(CreateSceneInitial()); + if (event.condition.contains('any')) { + conditionRule = 'or'; + } else { + conditionRule = 'and'; + } + + emit(ConditionSelectedState(event.condition)); + } + + FutureOr _sceneTypeEvent( + SceneTypeEvent event, Emitter emit) { + emit(CreateSceneInitial()); + + if (event.type == CreateSceneEnum.tabToRun) { + sceneType = CreateSceneEnum.tabToRun; + } else if (event.type == CreateSceneEnum.deviceStatusChanges) { + sceneType = CreateSceneEnum.deviceStatusChanges; + } else { + sceneType = CreateSceneEnum.none; + } + + emit(SceneTypeState(event.type)); + } } diff --git a/lib/features/scene/bloc/create_scene/create_scene_event.dart b/lib/features/scene/bloc/create_scene/create_scene_event.dart index 16f0fb4..0994a43 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_event.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_event.dart @@ -67,12 +67,14 @@ class SelectedValueEvent extends CreateSceneEvent { final dynamic automationValue; final String code; final bool? isAutomation; + final String? comparator; const SelectedValueEvent({ this.value, required this.code, this.isAutomation, this.automationValue, + this.comparator, }); @override @@ -110,19 +112,21 @@ class RemoveFromSelectedValueById extends CreateSceneEvent { } class CreateSceneWithTasksEvent extends CreateSceneEvent { - final CreateSceneModel createSceneModel; + final CreateSceneModel? createSceneModel; final bool updateScene; final String sceneId; + final CreateAutomationModel? createAutomationModel; //final bool isAutomation; const CreateSceneWithTasksEvent({ required this.createSceneModel, required this.updateScene, required this.sceneId, - // required this.isAutomation, + required this.createAutomationModel, + // required this.isAutomation, }); @override - List get props => [createSceneModel]; + List get props => []; } class ClearTaskListEvent extends CreateSceneEvent { @@ -160,3 +164,14 @@ class DeleteSceneEvent extends CreateSceneEvent { @override List get props => [sceneId, unitUuid]; } + +class SelectConditionEvent extends CreateSceneEvent { + final String condition; + + const SelectConditionEvent(this.condition); +} + +class SceneTypeEvent extends CreateSceneEvent { + final CreateSceneEnum type; + const SceneTypeEvent(this.type); +} diff --git a/lib/features/scene/bloc/create_scene/create_scene_state.dart b/lib/features/scene/bloc/create_scene/create_scene_state.dart index f0bcfd5..3e9e7e5 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_state.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_state.dart @@ -71,3 +71,14 @@ class DeleteSceneError extends CreateSceneState { } class DeleteSceneLoading extends CreateSceneState {} + +class ConditionSelectedState extends CreateSceneState { + final String condition; + + const ConditionSelectedState(this.condition); +} + +class SceneTypeState extends CreateSceneState { + final CreateSceneEnum type; + const SceneTypeState(this.type); +} diff --git a/lib/features/scene/enum/create_scene_enum.dart b/lib/features/scene/enum/create_scene_enum.dart index 6a65abc..5eaf0fb 100644 --- a/lib/features/scene/enum/create_scene_enum.dart +++ b/lib/features/scene/enum/create_scene_enum.dart @@ -1,4 +1,5 @@ enum CreateSceneEnum { tabToRun, deviceStatusChanges, + none, } diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index a6f6ad8..005162d 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -3,11 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; - +import 'package:syncrow_app/features/scene/model/create_automation_model.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; - import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; - import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart'; @@ -22,34 +20,87 @@ mixin SceneLogicHelper { } void handleSaveButtonPress( - BuildContext context, - TextEditingController sceneNameController, - List tasks, { + BuildContext context, { required bool updateScene, required String sceneId, + required bool isAutomation, + required TextEditingController sceneName, + required List actions, + required List conditions, }) { - if (isOnlyDelayOrDelayLast(tasks)) { - // Show snackbar indicating restriction - Navigator.pop(context); - context.showCustomSnackbar( - message: 'A single delay or delay-last operations are NOT allowed.', - icon: const Icon( - Icons.error, - color: Colors.red, - ), - ); + final sceneBloc = context.read(); + + if (isAutomation) { + // Handle Automation Creation + if (isOnlyDelayOrDelayLast(actions)) { + Navigator.pop(context); + context.showCustomSnackbar( + message: 'A single delay or delay-last operations are NOT allowed.', + icon: const Icon( + Icons.error, + color: Colors.red, + ), + ); + } else { + final createAutomationModel = CreateAutomationModel( + unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '', + automationName: sceneName.text, + decisionExpr: sceneBloc.conditionRule, + effectiveTime: + EffectiveTime(start: '00:00', end: '23:59', loops: '1111111'), + conditions: List.generate( + conditions.length, + (index) { + final task = conditions[index]; + return CreateCondition( + code: index + 1, + entityId: task.deviceId, + entityType: 'device_report', + expr: ConditionExpr( + statusCode: task.code, + comparator: task.comparator ?? '==', + statusValue: task.functionValue, + ), + ); + }, + ), + actions: List.generate( + actions.length, + (index) { + final task = actions[index]; + return CreateSceneAction( + entityId: task.deviceId, + actionExecutor: 'device_issue', + executorProperty: CreateSceneExecutorProperty( + functionCode: task.code, + functionValue: task.functionValue, + delaySeconds: 0, + ), + ); + }, + ), + ); + sceneBloc.add(CreateSceneWithTasksEvent( + createSceneModel: null, + updateScene: updateScene, + sceneId: sceneId, + createAutomationModel: createAutomationModel, + )); + Navigator.pop(context); + } } else { + // Handle Scene Creation final createSceneModel = CreateSceneModel( unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '', - sceneName: sceneNameController.text, + sceneName: sceneName.text, decisionExpr: 'and', actions: List.generate( - tasks.length, + actions.length, (index) { - final task = tasks[index]; + final task = actions[index]; if (task.deviceId == 'delay') { return CreateSceneAction( - entityId: tasks[index].deviceId, + entityId: actions[index].deviceId, actionExecutor: 'delay', executorProperty: CreateSceneExecutorProperty( functionCode: '', @@ -70,12 +121,12 @@ mixin SceneLogicHelper { }, ), ); - context.read().add(CreateSceneWithTasksEvent( - createSceneModel: createSceneModel, - updateScene: updateScene, - sceneId: sceneId, - )); - + sceneBloc.add(CreateSceneWithTasksEvent( + createSceneModel: createSceneModel, + createAutomationModel: null, + updateScene: updateScene, + sceneId: sceneId, + )); Navigator.pop(context); } } diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index 20d87d9..a00d6ce 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -206,29 +206,9 @@ mixin SceneOperationsDataHelper { } SceneStaticFunction _mapExecutorPropertyToSceneFunction( - Action action, bool isAutomation) { + Action action, bool isAutomation, + {String? comparator}) { ExecutorProperty executorProperty = action.executorProperty; - /* - - if (type == DeviceType.LightBulb) { - tempIcon = Assets.assetsIconsLight; - } else if (type == DeviceType.CeilingSensor || - type == DeviceType.WallSensor) { - tempIcon = Assets.assetsIconsSensors; - } else if (type == DeviceType.AC) { - tempIcon = Assets.assetsIconsAC; - } else if (type == DeviceType.DoorLock) { - tempIcon = Assets.assetsIconsDoorLock; - } else if (type == DeviceType.Curtain) { - tempIcon = Assets.assetsIconsCurtain; - } else if (type == DeviceType.ThreeGang) { - tempIcon = Assets.assetsIcons3GangSwitch; - } else if (type == DeviceType.Gateway) { - tempIcon = Assets.assetsIconsGateway; - } else { - tempIcon = Assets.assetsIconsLogo; - } - */ switch (executorProperty.functionCode) { case 'sensitivity': @@ -243,7 +223,8 @@ mixin SceneOperationsDataHelper { isAutomation ? _createIntegerStepsOptions() : _createSensitivityOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'normal_open_switch': return _createSceneFunction( action, @@ -252,7 +233,8 @@ mixin SceneOperationsDataHelper { 'Set Door lock Normal Open', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'unlock_fingerprint': return _createSceneFunction( action, @@ -261,7 +243,8 @@ mixin SceneOperationsDataHelper { 'Fingerprint Unlock', OperationDialogType.integerSteps, _createFingerprintUnlockOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'unlock_password': return _createSceneFunction( action, @@ -270,7 +253,8 @@ mixin SceneOperationsDataHelper { 'Password Unlock', OperationDialogType.integerSteps, _createPasswordUnlockOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'unlock_card': return _createSceneFunction( action, @@ -279,7 +263,8 @@ mixin SceneOperationsDataHelper { 'Card Unlock', OperationDialogType.integerSteps, _createCardUnlockOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'alarm_lock': return _createSceneFunction( action, @@ -288,7 +273,8 @@ mixin SceneOperationsDataHelper { 'Lock Alarm', OperationDialogType.listOfOptions, _createLockAlarmOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'unlock_request': return _createSceneFunction( action, @@ -297,7 +283,8 @@ mixin SceneOperationsDataHelper { 'Remote Unlock Request', OperationDialogType.integerSteps, _createUnlockRequestOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'residual_electricity': return _createSceneFunction( action, @@ -306,7 +293,8 @@ mixin SceneOperationsDataHelper { 'Residual Electricity', OperationDialogType.integerSteps, _createResidualElectricityOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'reverse_lock': return _createSceneFunction( action, @@ -315,7 +303,8 @@ mixin SceneOperationsDataHelper { 'Double Lock', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'unlock_app': return _createSceneFunction( action, @@ -324,7 +313,8 @@ mixin SceneOperationsDataHelper { 'Remote Unlock Via App', OperationDialogType.integerSteps, _createUnlockAppOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'hijack': return _createSceneFunction( action, @@ -333,7 +323,8 @@ mixin SceneOperationsDataHelper { 'Hijack Alarm', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'doorbell': return _createSceneFunction( action, @@ -342,7 +333,8 @@ mixin SceneOperationsDataHelper { 'Doorbell', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'unlock_temporary': return _createSceneFunction( action, @@ -351,7 +343,8 @@ mixin SceneOperationsDataHelper { 'Temporary Password Unlock', OperationDialogType.integerSteps, _createTemporaryPasswordUnlockOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'far_detection': return _createSceneFunction( action, @@ -360,7 +353,8 @@ mixin SceneOperationsDataHelper { 'Far Detection', OperationDialogType.listOfOptions, _createFarDetectionOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'motion_sensitivity_value': return _createSceneFunction( action, @@ -369,7 +363,8 @@ mixin SceneOperationsDataHelper { 'Motion Detection Sensitivity', OperationDialogType.listOfOptions, _createSensitivityOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'motionless_sensitivity': return _createSceneFunction( action, @@ -378,7 +373,8 @@ mixin SceneOperationsDataHelper { 'Motionless Detection Sensitivity', OperationDialogType.listOfOptions, _createSensitivityOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'indicator': return _createSceneFunction( action, @@ -387,7 +383,8 @@ mixin SceneOperationsDataHelper { 'Indicator', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'presence_time': return _createSceneFunction( action, @@ -396,7 +393,8 @@ mixin SceneOperationsDataHelper { 'Nobody Time', OperationDialogType.countdown, _createCountdownOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'presence_state': return _createSceneFunction( action, @@ -405,7 +403,8 @@ mixin SceneOperationsDataHelper { 'Presence State', OperationDialogType.listOfOptions, _createPresenceStateOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'dis_current': return _createSceneFunction( action, @@ -414,7 +413,8 @@ mixin SceneOperationsDataHelper { 'Current Distance', OperationDialogType.integerSteps, _createCurrentDistanceOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'illuminance_value': return _createSceneFunction( action, @@ -423,7 +423,8 @@ mixin SceneOperationsDataHelper { 'Illuminance Value', OperationDialogType.integerSteps, _createIlluminanceValueOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'checking_result': return _createSceneFunction( action, @@ -432,7 +433,8 @@ mixin SceneOperationsDataHelper { 'Self-Test Result', OperationDialogType.listOfOptions, _createSelfTestResultOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'switch': return _createSceneFunction( action, @@ -441,7 +443,8 @@ mixin SceneOperationsDataHelper { 'Power', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'temp_set': return _createSceneFunction( action, @@ -454,7 +457,19 @@ mixin SceneOperationsDataHelper { isAutomation ? _createAutomationTemperatureOptions() : _createTemperatureOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); + case 'temp_current': + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsIconsAC, + 'Current Temperature', + OperationDialogType.integerSteps, + _createCurrentTemperatureOptions(), + isAutomation, + comparator ?? '=='); + case 'mode': return _createSceneFunction( action, @@ -463,7 +478,8 @@ mixin SceneOperationsDataHelper { 'Mode', OperationDialogType.listOfOptions, _createAcModeOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'level': return _createSceneFunction( action, @@ -472,7 +488,8 @@ mixin SceneOperationsDataHelper { 'Fan Speed', OperationDialogType.listOfOptions, _createFanSpeedOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'child_lock': return _createSceneFunction( action, @@ -481,7 +498,8 @@ mixin SceneOperationsDataHelper { 'Child Lock', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'switch_1': return _createSceneFunction( action, @@ -490,7 +508,8 @@ mixin SceneOperationsDataHelper { 'Light 1 Switch', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'switch_2': return _createSceneFunction( action, @@ -499,7 +518,8 @@ mixin SceneOperationsDataHelper { 'Light 2 Switch', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'switch_3': return _createSceneFunction( action, @@ -508,7 +528,8 @@ mixin SceneOperationsDataHelper { 'Light 3 Switch', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'countdown_1': return _createSceneFunction( @@ -522,7 +543,8 @@ mixin SceneOperationsDataHelper { isAutomation ? _createAutomationCountDownOptions() : _createCountdownOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'countdown_2': return _createSceneFunction( action, @@ -535,7 +557,8 @@ mixin SceneOperationsDataHelper { isAutomation ? _createAutomationCountDownOptions() : _createCountdownOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'countdown_3': return _createSceneFunction( action, @@ -548,7 +571,8 @@ mixin SceneOperationsDataHelper { isAutomation ? _createAutomationCountDownOptions() : _createCountdownOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'switch_alarm_sound': return _createSceneFunction( action, @@ -557,7 +581,8 @@ mixin SceneOperationsDataHelper { 'Switch Alarm Sound', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'master_state': return _createSceneFunction( action, @@ -566,7 +591,8 @@ mixin SceneOperationsDataHelper { 'Master State', OperationDialogType.listOfOptions, _createMasterStateOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); case 'factory_reset': return _createSceneFunction( action, @@ -575,7 +601,8 @@ mixin SceneOperationsDataHelper { 'Factory Reset', OperationDialogType.onOff, _createOnOffOptions(), - isAutomation); + isAutomation, + comparator ?? '=='); default: throw ArgumentError( 'Unsupported function code: ${executorProperty.functionCode}'); @@ -778,7 +805,8 @@ mixin SceneOperationsDataHelper { String operationName, OperationDialogType operationDialogType, List operationalValues, - bool isAutomation) { + bool isAutomation, + String comparator) { final functionValue = action.executorProperty.functionValue; return SceneStaticFunction( deviceId: action.entityId, @@ -790,6 +818,7 @@ mixin SceneOperationsDataHelper { code: action.executorProperty.functionCode ?? '', operationDialogType: operationDialogType, operationalValues: operationalValues, + comparator: comparator, ); } @@ -907,13 +936,28 @@ mixin SceneOperationsDataHelper { return [ _mapExecutorPropertyToSceneFunction( - Action( - entityId: deviceId, - executorProperty: ExecutorProperty( - functionCode: taskItem.code, - functionValue: taskItem.functionValue), - actionExecutor: ''), - isAutomation) + Action( + entityId: deviceId, + executorProperty: ExecutorProperty( + functionCode: taskItem.code, + functionValue: taskItem.functionValue), + actionExecutor: ''), + isAutomation, + comparator: taskItem.comparator, + ) + ]; + } + + List _createCurrentTemperatureOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsCelsiusDegrees, + value: 0.0, + description: '°C', + minValue: -9.9, + maxValue: 99.9, + stepValue: 0.1, + ), ]; } } diff --git a/lib/features/scene/model/create_automation_model.dart b/lib/features/scene/model/create_automation_model.dart new file mode 100644 index 0000000..61fa472 --- /dev/null +++ b/lib/features/scene/model/create_automation_model.dart @@ -0,0 +1,172 @@ +import 'dart:convert'; + +import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; + +class CreateAutomationModel { + String unitUuid; + String automationName; + String decisionExpr; + EffectiveTime effectiveTime; + List conditions; + List actions; + + CreateAutomationModel({ + required this.unitUuid, + required this.automationName, + required this.decisionExpr, + required this.effectiveTime, + required this.conditions, + required this.actions, + }); + + CreateAutomationModel copyWith({ + String? unitUuid, + String? automationName, + String? decisionExpr, + EffectiveTime? effectiveTime, + List? conditions, + List? actions, + }) { + return CreateAutomationModel( + unitUuid: unitUuid ?? this.unitUuid, + automationName: automationName ?? this.automationName, + decisionExpr: decisionExpr ?? this.decisionExpr, + effectiveTime: effectiveTime ?? this.effectiveTime, + conditions: conditions ?? this.conditions, + actions: actions ?? this.actions, + ); + } + + Map toMap() { + return { + 'unitUuid': unitUuid, + 'automationName': automationName, + 'decisionExpr': decisionExpr, + 'effectiveTime': effectiveTime.toMap(), + 'conditions': conditions.map((x) => x.toMap()).toList(), + 'actions': actions.map((x) => x.toMap()).toList(), + }; + } + + factory CreateAutomationModel.fromMap(Map map) { + return CreateAutomationModel( + unitUuid: map['unitUuid'] ?? '', + automationName: map['automationName'] ?? '', + decisionExpr: map['decisionExpr'] ?? '', + effectiveTime: EffectiveTime.fromMap(map['effectiveTime']), + conditions: List.from( + map['conditions']?.map((x) => CreateCondition.fromMap(x))), + actions: List.from( + map['actions']?.map((x) => CreateSceneAction.fromMap(x))), + ); + } + + String toJson() => json.encode(toMap()); + + factory CreateAutomationModel.fromJson(String source) => + CreateAutomationModel.fromMap(json.decode(source)); + + @override + String toString() { + return 'CreateAutomationModel(unitUuid: $unitUuid, automationName: $automationName, decisionExpr: $decisionExpr, effectiveTime: $effectiveTime, conditions: $conditions, actions: $actions)'; + } +} + +class EffectiveTime { + String start; + String end; + String loops; + + EffectiveTime({ + required this.start, + required this.end, + required this.loops, + }); + + Map toMap() { + return { + 'start': start, + 'end': end, + 'loops': loops, + }; + } + + factory EffectiveTime.fromMap(Map map) { + return EffectiveTime( + start: map['start'] ?? '', + end: map['end'] ?? '', + loops: map['loops'] ?? '', + ); + } + + @override + String toString() => 'EffectiveTime(start: $start, end: $end, loops: $loops)'; +} + +class CreateCondition { + int code; + String entityId; + String entityType; + ConditionExpr expr; + + CreateCondition({ + required this.code, + required this.entityId, + required this.entityType, + required this.expr, + }); + + Map toMap() { + return { + 'code': code, + 'entityId': entityId, + 'entityType': entityType, + 'expr': expr.toMap(), + }; + } + + factory CreateCondition.fromMap(Map map) { + return CreateCondition( + code: map['code'] ?? 0, + entityId: map['entityId'] ?? '', + entityType: map['entityType'] ?? '', + expr: ConditionExpr.fromMap(map['expr']), + ); + } + + @override + String toString() => + 'CreateCondition(code: $code, entityId: $entityId, entityType: $entityType, expr: $expr)'; +} + +class ConditionExpr { + String statusCode; + String comparator; + dynamic statusValue; + + ConditionExpr({ + required this.statusCode, + required this.comparator, + required this.statusValue, + }); + + Map toMap() { + return { + 'statusCode': statusCode, + 'comparator': comparator, + 'statusValue': statusValue, + }; + } + + factory ConditionExpr.fromMap(Map map) { + return ConditionExpr( + statusCode: map['statusCode'] ?? '', + comparator: map['comparator'] ?? '', + statusValue: map['statusValue'], + ); + } + + @override + String toString() => + 'ConditionExpr(statusCode: $statusCode, comparator: $comparator, statusValue: $statusValue)'; +} diff --git a/lib/features/scene/model/scene_static_function.dart b/lib/features/scene/model/scene_static_function.dart index cd1a3d3..f73e130 100644 --- a/lib/features/scene/model/scene_static_function.dart +++ b/lib/features/scene/model/scene_static_function.dart @@ -15,6 +15,7 @@ class SceneStaticFunction { final dynamic functionValue; final String? deviceIcon; final OperationDialogType operationDialogType; + final String? comparator; SceneStaticFunction({ required this.icon, @@ -26,6 +27,7 @@ class SceneStaticFunction { required this.functionValue, this.deviceIcon, required this.operationDialogType, + this.comparator, }) : uniqueCustomId = const Uuid().v4(); SceneStaticFunction copyWith({ @@ -39,6 +41,7 @@ class SceneStaticFunction { String? deviceIcon, String? deviceName, OperationDialogType? operationDialogType, + String? comparator, }) { return SceneStaticFunction( icon: icon ?? this.icon, @@ -50,6 +53,7 @@ class SceneStaticFunction { functionValue: functionValue ?? this.functionValue, deviceIcon: deviceIcon ?? this.deviceIcon, operationDialogType: operationDialogType ?? this.operationDialogType, + comparator: comparator ?? this.comparator, ); } @@ -63,7 +67,8 @@ class SceneStaticFunction { 'operationName': operationName, 'functionValue': functionValue, 'deviceIcon': deviceIcon, - 'operationDialogType': operationDialogType.name + 'operationDialogType': operationDialogType.name, + 'comparator': comparator }; } @@ -82,6 +87,7 @@ class SceneStaticFunction { operationDialogType: map['operationDialogType'] != null ? OperationDialogType.values.byName(map['operationDialogType']) : OperationDialogType.none, + comparator: map['comparator'], ); } @@ -92,7 +98,7 @@ class SceneStaticFunction { @override String toString() { - return 'SceneStaticFunction(icon: $icon, name: $deviceName, code: $code, operationalValues: $operationalValues, deviceId: $deviceId, operationName: $operationName, functionValue: $functionValue, deviceIcon: $deviceIcon, operationDialogType: $operationDialogType)'; + return 'SceneStaticFunction(icon: $icon, name: $deviceName, code: $code, operationalValues: $operationalValues, deviceId: $deviceId, operationName: $operationName, functionValue: $functionValue, deviceIcon: $deviceIcon, operationDialogType: $operationDialogType, comparator: $comparator)'; } @override @@ -106,6 +112,7 @@ class SceneStaticFunction { other.operationName == operationName && other.functionValue == functionValue && other.deviceIcon == deviceIcon && + other.comparator == comparator && other.operationDialogType == operationDialogType && listEquals(other.operationalValues, operationalValues) && other.deviceId == deviceId; @@ -120,6 +127,7 @@ class SceneStaticFunction { operationName.hashCode ^ functionValue.hashCode ^ deviceIcon.hashCode ^ + comparator.hashCode ^ operationDialogType.hashCode ^ operationalValues.hashCode; } diff --git a/lib/features/scene/view/create_scene_view.dart b/lib/features/scene/view/create_scene_view.dart index a1e8562..283f87f 100644 --- a/lib/features/scene/view/create_scene_view.dart +++ b/lib/features/scene/view/create_scene_view.dart @@ -6,10 +6,9 @@ import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments. import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; - import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/navigation/navigate_to_route.dart'; import 'package:syncrow_app/navigation/routing_constants.dart'; - import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; class CreateSceneView extends StatelessWidget { @@ -22,7 +21,7 @@ class CreateSceneView extends StatelessWidget { padding: const EdgeInsets.only(top: 24), leading: IconButton( onPressed: () { - Navigator.pop(context); + navigateToRoute(context, Routes.sceneTasksRoute); }, icon: const Icon( Icons.arrow_back_ios, @@ -48,6 +47,9 @@ class CreateSceneView extends StatelessWidget { ), ); context.read().add(const ClearTaskListEvent()); + context + .read() + .add(const SceneTypeEvent(CreateSceneEnum.tabToRun)); }, ), DefaultContainer( @@ -71,6 +73,8 @@ class CreateSceneView extends StatelessWidget { context .read() .add(const ClearTaskListEvent(isAutomation: true)); + context.read().add( + const SceneTypeEvent(CreateSceneEnum.deviceStatusChanges)); }, ), ], diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index e707889..0d5736b 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -12,6 +12,7 @@ import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; import 'package:syncrow_app/features/shared_widgets/light_divider.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/navigation/navigate_to_route.dart'; import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/utils/context_extension.dart'; @@ -53,9 +54,7 @@ class DeviceFunctionsView extends StatelessWidget context .read() .add(AddTaskEvent(isAutomation: isAutomation)); - Navigator.popUntil(context, (route) { - return route.settings.name == Routes.sceneTasksRoute; - }); + navigateToRoute(context, Routes.sceneTasksRoute); }, child: BodyMedium( text: 'Save', diff --git a/lib/features/scene/view/scene_rooms_tabbar.dart b/lib/features/scene/view/scene_rooms_tabbar.dart index 64143b1..a97d668 100644 --- a/lib/features/scene/view/scene_rooms_tabbar.dart +++ b/lib/features/scene/view/scene_rooms_tabbar.dart @@ -8,6 +8,8 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_body.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; +import 'package:syncrow_app/navigation/navigate_to_route.dart'; +import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; @@ -16,10 +18,12 @@ class SceneRoomsTabBarDevicesView extends StatefulWidget { const SceneRoomsTabBarDevicesView({super.key}); @override - State createState() => _SceneRoomsTabBarDevicesViewState(); + State createState() => + _SceneRoomsTabBarDevicesViewState(); } -class _SceneRoomsTabBarDevicesViewState extends State +class _SceneRoomsTabBarDevicesViewState + extends State with SingleTickerProviderStateMixin { late final TabController _tabController; List? rooms = []; @@ -41,7 +45,8 @@ class _SceneRoomsTabBarDevicesViewState extends State() - .add(TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? '')); + context.read().add( + TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? '')); return; } } @@ -72,8 +76,7 @@ class _SceneRoomsTabBarDevicesViewState extends State { double? groupValue; - int selectedToggleIndex = 0; + int selectedToggleIndex = 1; @override void didChangeDependencies() { @@ -33,23 +33,53 @@ class _AlertDialogSliderStepsState extends State { if (widget.isAutomation) { final automationTempTaskList = context.read().automationTempTasksList; + final automationComparatorValues = + context.read().automationComparatorValues; + if (automationTempTaskList.isNotEmpty) { for (var element in automationTempTaskList) { if (element.code == widget.taskItem.code) { groupValue = element.functionValue; - } else { - context.read().add(RemoveFromSelectedValueById( - code: widget.taskItem.code, isAutomation: widget.isAutomation)); + selectedToggleIndex = + _comparatorToIndex(automationComparatorValues[element.code]); } } } if (widget.functionValue != null) { - setState(() { - groupValue = widget.functionValue; - }); + groupValue = widget.functionValue; } else { groupValue = widget.taskItem.operationalValues[0].minValue; } + if (widget.taskItem.comparator != null) { + selectedToggleIndex = _comparatorToIndex(widget.taskItem.comparator); + } + setState(() {}); + } + } + + int _comparatorToIndex(String? comparator) { + switch (comparator) { + case "<=": + return 0; + case "==": + return 1; + case ">=": + return 2; + default: + return 1; + } + } + + String _indexToComparator(int index) { + switch (index) { + case 0: + return "<="; + case 1: + return "=="; + case 2: + return ">="; + default: + return "=="; } } @@ -68,6 +98,10 @@ class _AlertDialogSliderStepsState extends State { setState(() { selectedToggleIndex = index; }); + context.read().add(SelectedValueEvent( + code: widget.taskItem.code, + isAutomation: widget.isAutomation, + comparator: _indexToComparator(selectedToggleIndex))); }, borderRadius: BorderRadius.circular(30), selectedColor: Colors.white, @@ -164,7 +198,9 @@ class _AlertDialogSliderStepsState extends State { context.read().add(SelectedValueEvent( value: groupValue, code: widget.taskItem.code, - isAutomation: widget.isAutomation)); + isAutomation: widget.isAutomation, + comparator: + _indexToComparator(selectedToggleIndex))); }, ), ), diff --git a/lib/features/scene/widgets/create_scene_save_button.dart b/lib/features/scene/widgets/create_scene_save_button.dart index 5a31914..59e375b 100644 --- a/lib/features/scene/widgets/create_scene_save_button.dart +++ b/lib/features/scene/widgets/create_scene_save_button.dart @@ -1,9 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/helper/scene_logic_helper.dart'; import 'package:syncrow_app/features/shared_widgets/default_button.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/navigation/navigate_to_route.dart'; +import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; @@ -43,8 +46,7 @@ class _CreateSceneSaveButtonState extends State listener: (context, state) { if (state is CreateSceneWithTasks) { if (state.success == true) { - Navigator.pop(context); - Navigator.pop(context); + navigateToRoute(context, Routes.homeRoute); context.showCustomSnackbar( message: 'Scene created successfully', icon: const Icon( @@ -66,55 +68,59 @@ class _CreateSceneSaveButtonState extends State }, builder: (context, state) { return DefaultButton( - onPressed: widget.sceneName.isNotEmpty - ? () { - final tasks = context.read().tasksList; - handleSaveButtonPress( - context, - sceneNameController, - tasks, - updateScene: true, - sceneId: widget.sceneId, - ); - } - : () { - context.customAlertDialog( - alertBody: Padding( - padding: - const EdgeInsets.only(left: 8, right: 8, bottom: 8), - child: SizedBox( - height: 40, - child: SearchBar( - controller: sceneNameController, - elevation: WidgetStateProperty.all(0), - textStyle: - WidgetStateProperty.all(context.bodyMedium), - hintStyle: WidgetStateProperty.all( - context.bodyMedium.copyWith( - fontSize: 14, - color: ColorsManager.secondaryTextColor), - ), - hintText: 'Enter scene name', - backgroundColor: WidgetStateProperty.all( - ColorsManager.backgroundColor), - ), + onPressed: () { + final sceneBloc = context.read(); + final isAutomation = + sceneBloc.sceneType == CreateSceneEnum.deviceStatusChanges; + + if (widget.sceneName.isNotEmpty) { + handleSaveButtonPress( + context, + sceneName: sceneNameController, + actions: sceneBloc.tasksList, + updateScene: true, + sceneId: widget.sceneId, + isAutomation: isAutomation, + conditions: sceneBloc.automationTasksList, + ); + } else { + context.customAlertDialog( + alertBody: Padding( + padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), + child: SizedBox( + height: 40, + child: SearchBar( + controller: sceneNameController, + elevation: WidgetStateProperty.all(0), + textStyle: WidgetStateProperty.all(context.bodyMedium), + hintStyle: WidgetStateProperty.all( + context.bodyMedium.copyWith( + fontSize: 14, + color: ColorsManager.secondaryTextColor), ), + hintText: 'Enter scene name', + backgroundColor: WidgetStateProperty.all( + ColorsManager.backgroundColor), ), - title: 'Scene Name', - onConfirm: () { - if (sceneNameController.text.isNotEmpty) { - final tasks = context.read().tasksList; - handleSaveButtonPress( - context, - sceneNameController, - tasks, - updateScene: false, - sceneId: widget.sceneId, - ); - } - }, - ); + ), + ), + title: 'Scene Name', + onConfirm: () { + if (sceneNameController.text.isNotEmpty) { + handleSaveButtonPress( + context, + sceneName: sceneNameController, + actions: sceneBloc.tasksList, + updateScene: false, + sceneId: widget.sceneId, + isAutomation: isAutomation, + conditions: sceneBloc.automationTasksList, + ); + } }, + ); + } + }, customButtonStyle: ButtonStyle( backgroundColor: WidgetStateProperty.all( ColorsManager.primaryColor, diff --git a/lib/features/scene/widgets/if_then_containers/if_container.dart b/lib/features/scene/widgets/if_then_containers/if_container.dart index b862eb0..4639abf 100644 --- a/lib/features/scene/widgets/if_then_containers/if_container.dart +++ b/lib/features/scene/widgets/if_then_containers/if_container.dart @@ -1,18 +1,24 @@ import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; +import 'package:syncrow_app/features/scene/view/create_scene_view.dart'; import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_added_tasks.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/light_divider.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/helpers/custom_page_route.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; +import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; class IFDefaultContainer extends StatelessWidget { const IFDefaultContainer({ @@ -27,30 +33,101 @@ class IFDefaultContainer extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ SceneListTile( - leadingWidget: BodyLarge( - text: 'IF', - style: context.bodyLarge.copyWith( - fontWeight: FontWeight.bold, - color: ColorsManager.primaryTextColor, + leadingWidget: InkWell( + onTap: () { + final sceneType = context.read().sceneType; + if (sceneType.name == + CreateSceneEnum.deviceStatusChanges.name) { + context.customAlertDialog( + hideConfirmButton: true, + alertBody: Column( + children: [ + ListTile( + title: const BodyMedium( + text: "When all conditions are met"), + onTap: () { + context.read().add( + const SelectConditionEvent( + "When all conditions are met")); + Navigator.pop(context); + }, + ), + ListTile( + title: const BodyMedium( + text: "When any condition is met"), + onTap: () { + context.read().add( + const SelectConditionEvent( + "When any condition is met")); + Navigator.pop(context); + }, + ), + ], + ), + title: 'Conditions Rule', + onConfirm: () {}, + ); + } + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + BodyLarge( + text: 'IF', + style: context.bodyLarge.copyWith( + fontWeight: FontWeight.bold, + color: ColorsManager.primaryTextColor, + ), + ), + BlocBuilder( + builder: (context, state) { + String conditionText = "When any condition is met"; + if (state is ConditionSelectedState) { + conditionText = state.condition; + } + return SizedBox( + width: context.width * 0.6, + child: Row(children: [ + BodySmall(text: conditionText), + const Icon(Icons.keyboard_arrow_down) + ]), + ); + }, + ), + ], ), ), - trailingWidget: GestureDetector( - onTap: () => Navigator.pushNamed( - context, - Routes.sceneControlDevicesRoute, - arguments: SceneSettingsRouteArguments( - sceneType: CreateSceneEnum.deviceStatusChanges.name, - sceneId: '', - sceneName: '', - ), - ), - child: SvgPicture.asset( - Assets.addIcon, - colorFilter: const ColorFilter.mode( - ColorsManager.primaryColor, - BlendMode.srcIn, - ), - ), + trailingWidget: BlocBuilder( + builder: (context, state) { + bool isClickable = false; + if (state is AddSceneTask) { + isClickable = state.automationTasksList?.isNotEmpty ?? false; + } + return GestureDetector( + onTap: isClickable + ? () => Navigator.pushNamed( + context, + Routes.sceneControlDevicesRoute, + arguments: SceneSettingsRouteArguments( + sceneType: + CreateSceneEnum.deviceStatusChanges.name, + sceneId: '', + sceneName: '', + ), + ) + : null, + child: SvgPicture.asset( + Assets.addIcon, + colorFilter: ColorFilter.mode( + isClickable + ? ColorsManager.primaryColor + : ColorsManager.greyColor, + BlendMode.srcIn, + ), + ), + ); + }, ), padding: EdgeInsets.zero, ), @@ -74,19 +151,36 @@ class IFDefaultContainer extends StatelessWidget { ); } } + final sceneType = context.read().sceneType; + if (sceneType.name == CreateSceneEnum.tabToRun.name) { + return const SceneListTile( + assetPath: Assets.handClickIcon, + titleString: StringsManager.tapToRun, + subtitleString: '', + ); + } return SceneListTile( - titleString: '+ Add Condition', - textAlign: TextAlign.center, - onPressed: () => Navigator.pushNamed( - context, - Routes.sceneControlDevicesRoute, - arguments: SceneSettingsRouteArguments( - sceneType: CreateSceneEnum.deviceStatusChanges.name, - sceneId: '', - sceneName: '', - ), - ), - ); + titleString: '+ Add Condition', + textAlign: TextAlign.center, + onPressed: () { + final sceneType = context.read().sceneType; + if (sceneType.name == CreateSceneEnum.none.name) { + Navigator.push( + context, + CustomPageRoute( + builder: (context) => const CreateSceneView())); + } else { + Navigator.pushNamed( + context, + Routes.sceneControlDevicesRoute, + arguments: SceneSettingsRouteArguments( + sceneType: CreateSceneEnum.deviceStatusChanges.name, + sceneId: '', + sceneName: '', + ), + ); + } + }); }, ) ], diff --git a/lib/features/scene/widgets/if_then_containers/then_container.dart b/lib/features/scene/widgets/if_then_containers/then_container.dart index 3c36709..3b322e4 100644 --- a/lib/features/scene/widgets/if_then_containers/then_container.dart +++ b/lib/features/scene/widgets/if_then_containers/then_container.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; +import 'package:syncrow_app/features/scene/view/create_scene_view.dart'; import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_added_tasks.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/scene/widgets/bottom_sheet_widget.dart'; @@ -10,6 +12,7 @@ import 'package:syncrow_app/features/shared_widgets/light_divider.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/helpers/custom_page_route.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class ThenDefaultContainer extends StatelessWidget { @@ -35,17 +38,29 @@ class ThenDefaultContainer extends StatelessWidget { color: ColorsManager.primaryTextColor, ), ), - trailingWidget: GestureDetector( - onTap: () => context.customBottomSheet( - child: const CustomBottomSheetWidget(), - ), - child: SvgPicture.asset( - Assets.addIcon, - colorFilter: const ColorFilter.mode( - ColorsManager.primaryColor, - BlendMode.srcIn, - ), - ), + trailingWidget: BlocBuilder( + builder: (context, state) { + bool isClickable = false; + if (state is AddSceneTask) { + isClickable = state.tasksList.isNotEmpty; + } + return GestureDetector( + onTap: isClickable + ? () => context.customBottomSheet( + child: const CustomBottomSheetWidget(), + ) + : null, + child: SvgPicture.asset( + Assets.addIcon, + colorFilter: ColorFilter.mode( + isClickable + ? ColorsManager.primaryColor + : ColorsManager.greyColor, + BlendMode.srcIn, + ), + ), + ); + }, ), padding: EdgeInsets.zero, ), @@ -71,20 +86,23 @@ class ThenDefaultContainer extends StatelessWidget { }, ); } - return SceneListTile( - titleString: '+ Add Task', - textAlign: TextAlign.center, - onPressed: () => context.customBottomSheet( - child: const CustomBottomSheetWidget(), - ), - ); } return SceneListTile( titleString: '+ Add Task', textAlign: TextAlign.center, - onPressed: () => context.customBottomSheet( - child: const CustomBottomSheetWidget(), - ), + onPressed: () { + final sceneType = context.read().sceneType; + if (sceneType.name == CreateSceneEnum.none.name) { + Navigator.push( + context, + CustomPageRoute( + builder: (context) => const CreateSceneView())); + } else { + context.customBottomSheet( + child: const CustomBottomSheetWidget(), + ); + } + }, ); }, ) diff --git a/lib/navigation/navigate_to_route.dart b/lib/navigation/navigate_to_route.dart new file mode 100644 index 0000000..e7c2715 --- /dev/null +++ b/lib/navigation/navigate_to_route.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +void navigateToRoute(BuildContext context, String targetRoute) { + bool routeFound = false; + + Navigator.popUntil(context, (route) { + if (route.settings.name == targetRoute) { + routeFound = true; + return true; + } + return route.isFirst; + }); + + if (!routeFound) { + Navigator.pushNamed(context, targetRoute); + } +} diff --git a/lib/services/api/api_links_endpoints.dart b/lib/services/api/api_links_endpoints.dart index f252a09..351d2d0 100644 --- a/lib/services/api/api_links_endpoints.dart +++ b/lib/services/api/api_links_endpoints.dart @@ -135,6 +135,8 @@ abstract class ApiEndpoints { static const String triggerScene = '$baseUrl/scene/tap-to-run/trigger/{sceneId}'; + static const String createAutomation = '$baseUrl/automation'; + /// GET static const String getUnitScenes = '$baseUrl/scene/tap-to-run/{unitUuid}'; diff --git a/lib/services/api/scene_api.dart b/lib/services/api/scene_api.dart index 4d377f1..e8630c6 100644 --- a/lib/services/api/scene_api.dart +++ b/lib/services/api/scene_api.dart @@ -1,3 +1,4 @@ +import 'package:syncrow_app/features/scene/model/create_automation_model.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; import 'package:syncrow_app/features/scene/model/scene_details_model.dart'; import 'package:syncrow_app/features/scene/model/scenes_model.dart'; @@ -24,6 +25,23 @@ class SceneApi { } } + static Future> createAutomation( + CreateAutomationModel createAutomationModel) async { + try { + final response = await _httpService.post( + path: ApiEndpoints.createAutomation, + body: createAutomationModel.toMap(), + showServerMessage: false, + expectedResponseModel: (json) { + return json; + }, + ); + return response; + } catch (e) { + rethrow; + } + } + static Future> getScenesByUnitId(String unitId) async { try { final response = await _httpService.get( diff --git a/lib/utils/context_extension.dart b/lib/utils/context_extension.dart index 1dc20e9..c9db183 100644 --- a/lib/utils/context_extension.dart +++ b/lib/utils/context_extension.dart @@ -65,6 +65,7 @@ extension ContextExtension on BuildContext { required String title, required VoidCallback onConfirm, VoidCallback? onDismiss, + bool? hideConfirmButton, }) { showDialog( context: this, @@ -110,39 +111,57 @@ extension ContextExtension on BuildContext { width: double.infinity, color: ColorsManager.greyColor, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - GestureDetector( - onTap: onDismiss ?? - () { - Navigator.pop(context); - }, - child: Center( - child: BodyMedium( - text: 'Cancel', - style: context.bodyMedium - .copyWith(color: ColorsManager.greyColor), + hideConfirmButton != true + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + GestureDetector( + onTap: onDismiss ?? + () { + Navigator.pop(context); + }, + child: Center( + child: BodyMedium( + text: 'Cancel', + style: context.bodyMedium + .copyWith(color: ColorsManager.greyColor), + ), + ), + ), + Container( + height: 50, + width: 1, + color: ColorsManager.greyColor, + ), + GestureDetector( + onTap: onConfirm, + child: Center( + child: BodyMedium( + text: 'Confirm', + style: context.bodyMedium.copyWith( + color: + ColorsManager.primaryColorWithOpacity), + ), + ), + ), + ], + ) + : Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: GestureDetector( + onTap: onDismiss ?? + () { + Navigator.pop(context); + }, + child: Center( + child: BodyMedium( + text: 'Cancel', + style: context.bodyMedium + .copyWith(color: ColorsManager.greyColor), + ), + ), ), ), - ), - Container( - height: 50, - width: 1, - color: ColorsManager.greyColor, - ), - GestureDetector( - onTap: onConfirm, - child: Center( - child: BodyMedium( - text: 'Confirm', - style: context.bodyMedium.copyWith( - color: ColorsManager.primaryColorWithOpacity), - ), - ), - ), - ], - ) ], ), ), From 56024ba3a323c03237b07fbca5dbf6d50ff159d8 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Wed, 24 Jul 2024 20:22:44 +0300 Subject: [PATCH 13/30] fixed automation bugs --- .../bloc/create_scene/create_scene_bloc.dart | 23 +++-- .../scene/helper/scene_logic_helper.dart | 11 +++ .../alert_dialog_slider_steps.dart | 84 ++++++++++++------- 3 files changed, 80 insertions(+), 38 deletions(-) diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index 5ac0c32..4182ed2 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -191,19 +191,28 @@ class CreateSceneBloc extends Bloc FutureOr _selectedValue( SelectedValueEvent event, Emitter emit) { - emit(CreateSceneLoading()); if (event.isAutomation == true) { automationSelectedValues[event.code] = event.value; automationComparatorValues[event.code] = event.comparator ?? '=='; - emit(SelectedTaskValueState(value: event.value)); - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + + // Update the comparator value for the specific task in automationTasksList + for (int i = 0; i < automationTasksList.length; i++) { + if (automationTasksList[i].code == event.code) { + automationTasksList[i] = automationTasksList[i].copyWith( + comparator: event.comparator ?? '==', + functionValue: event.value, + ); + break; + } + } } else { selectedValues[event.code] = event.value; - emit(SelectedTaskValueState(value: event.value)); - emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); } + emit(SelectedTaskValueState(value: event.value)); + emit(AddSceneTask( + tasksList: List.from(tasksList), + automationTasksList: List.from(automationTasksList), + )); } FutureOr _removeTaskById( diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 005162d..f77da60 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -68,6 +68,17 @@ mixin SceneLogicHelper { actions.length, (index) { final task = actions[index]; + if (task.deviceId == 'delay') { + return CreateSceneAction( + entityId: actions[index].deviceId, + actionExecutor: 'delay', + executorProperty: CreateSceneExecutorProperty( + functionCode: '', + functionValue: '', + delaySeconds: task.functionValue, + ), + ); + } return CreateSceneAction( entityId: task.deviceId, actionExecutor: 'device_issue', diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart index 66e4647..2563b28 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart @@ -29,41 +29,51 @@ class _AlertDialogSliderStepsState extends State { @override void didChangeDependencies() { super.didChangeDependencies(); + final createSceneBloc = context.read(); if (widget.isAutomation) { - final automationTempTaskList = - context.read().automationTempTasksList; + final automationTempTaskList = createSceneBloc.automationTempTasksList; final automationComparatorValues = - context.read().automationComparatorValues; + createSceneBloc.automationComparatorValues; - if (automationTempTaskList.isNotEmpty) { - for (var element in automationTempTaskList) { - if (element.code == widget.taskItem.code) { - groupValue = element.functionValue; - selectedToggleIndex = - _comparatorToIndex(automationComparatorValues[element.code]); - } + for (var element in automationTempTaskList) { + if (element.code == widget.taskItem.code) { + groupValue = element.functionValue; + selectedToggleIndex = + _comparatorToIndex(automationComparatorValues[element.code]); } } - if (widget.functionValue != null) { - groupValue = widget.functionValue; - } else { - groupValue = widget.taskItem.operationalValues[0].minValue; - } - if (widget.taskItem.comparator != null) { - selectedToggleIndex = _comparatorToIndex(widget.taskItem.comparator); - } - setState(() {}); } + + if (widget.functionValue != null) { + groupValue = _normalizeValue(widget.functionValue); + } else { + groupValue = + _normalizeValue(widget.taskItem.operationalValues[0].minValue); + } + + if (widget.taskItem.comparator != null) { + selectedToggleIndex = _comparatorToIndex(widget.taskItem.comparator); + } + + setState(() {}); + } + + double _normalizeValue(dynamic value) { + if (widget.taskItem.code == "temp_set" || + widget.taskItem.code == "temp_current") { + return (value as double) / 10; + } + return value.toDouble(); } int _comparatorToIndex(String? comparator) { switch (comparator) { - case "<=": + case "<": return 0; case "==": return 1; - case ">=": + case ">": return 2; default: return 1; @@ -73,11 +83,11 @@ class _AlertDialogSliderStepsState extends State { String _indexToComparator(int index) { switch (index) { case 0: - return "<="; + return "<"; case 1: return "=="; case 2: - return ">="; + return ">"; default: return "=="; } @@ -98,10 +108,14 @@ class _AlertDialogSliderStepsState extends State { setState(() { selectedToggleIndex = index; }); - context.read().add(SelectedValueEvent( - code: widget.taskItem.code, - isAutomation: widget.isAutomation, - comparator: _indexToComparator(selectedToggleIndex))); + context.read().add( + SelectedValueEvent( + value: _deNormalizeValue(groupValue), + code: widget.taskItem.code, + isAutomation: widget.isAutomation, + comparator: _indexToComparator(selectedToggleIndex), + ), + ); }, borderRadius: BorderRadius.circular(30), selectedColor: Colors.white, @@ -181,8 +195,8 @@ class _AlertDialogSliderStepsState extends State { padding: const EdgeInsets.symmetric(horizontal: 8), child: Slider( value: groupValue ?? 0, - min: operation.minValue?.toDouble() ?? 0, - max: operation.maxValue?.toDouble() ?? 0, + min: operation.minValue ?? 0, + max: operation.maxValue ?? 0, inactiveColor: ColorsManager.primaryColorWithOpacity .withOpacity(0.2), divisions: operation.stepValue != null @@ -193,10 +207,10 @@ class _AlertDialogSliderStepsState extends State { : null, onChanged: (value) { setState(() { - groupValue = value.round().toDouble(); + groupValue = value; }); context.read().add(SelectedValueEvent( - value: groupValue, + value: _deNormalizeValue(groupValue), code: widget.taskItem.code, isAutomation: widget.isAutomation, comparator: @@ -213,4 +227,12 @@ class _AlertDialogSliderStepsState extends State { ], ); } + + double _deNormalizeValue(double? value) { + if (widget.taskItem.code == "temp_set" || + widget.taskItem.code == "temp_current") { + return (value ?? 0) * 10; + } + return value ?? 0; + } } From 8a4c5af2e7dc7080ade67229b20dd69d969b44ab Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Thu, 25 Jul 2024 00:25:48 +0300 Subject: [PATCH 14/30] push automation details and update automation --- .../devices/view/widgets/scene_listview.dart | 19 +- .../bloc/create_scene/create_scene_bloc.dart | 42 +- .../bloc/create_scene/create_scene_event.dart | 7 +- .../bloc/create_scene/create_scene_state.dart | 4 +- .../scene/bloc/scene_bloc/scene_bloc.dart | 32 +- .../scene/bloc/scene_bloc/scene_event.dart | 9 + .../scene/bloc/scene_bloc/scene_state.dart | 5 +- .../scene/helper/scene_logic_helper.dart | 81 +- .../helper/scene_operations_data_helper.dart | 1353 ++++++++++------- .../scene/model/create_automation_model.dart | 6 +- .../scene/model/scene_details_model.dart | 109 ++ lib/features/scene/model/scenes_model.dart | 5 +- .../scene/view/device_functions_view.dart | 4 +- lib/features/scene/view/scene_tasks_view.dart | 6 +- lib/features/scene/view/scene_view.dart | 90 +- .../alert_dialog_slider_steps.dart | 2 +- .../if_then_containers/if_container.dart | 8 +- .../scene_view_widget/scene_grid_view.dart | 14 +- .../scene_view_widget/scene_header.dart | 9 +- .../widgets/scene_view_widget/scene_item.dart | 55 +- lib/navigation/router.dart | 47 +- lib/services/api/api_links_endpoints.dart | 9 +- lib/services/api/scene_api.dart | 64 +- 23 files changed, 1271 insertions(+), 709 deletions(-) diff --git a/lib/features/devices/view/widgets/scene_listview.dart b/lib/features/devices/view/widgets/scene_listview.dart index b44fdbe..cbea49d 100644 --- a/lib/features/devices/view/widgets/scene_listview.dart +++ b/lib/features/devices/view/widgets/scene_listview.dart @@ -1,6 +1,3 @@ - - - import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; @@ -12,7 +9,6 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dar import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/navigation/routing_constants.dart'; - class SceneListview extends StatelessWidget { final List scenes; final String? loadingSceneId; @@ -24,8 +20,7 @@ class SceneListview extends StatelessWidget { @override Widget build(BuildContext context) { - return - ListView.builder( + return ListView.builder( shrinkWrap: true, scrollDirection: Axis.horizontal, itemCount: scenes.length, @@ -34,7 +29,7 @@ class SceneListview extends StatelessWidget { final isLoading = loadingSceneId == scene.id; return Container( padding: const EdgeInsets.only(right: 10), - child:DefaultContainer( + child: DefaultContainer( onTap: () { Navigator.pushNamed( context, @@ -45,10 +40,11 @@ class SceneListview extends StatelessWidget { sceneName: scene.name, ), ); - BlocProvider.of(context).add(FetchSceneTasksEvent(sceneId: scene.id)); + BlocProvider.of(context) + .add(FetchSceneTasksEvent(sceneId: scene.id)); }, - child:SizedBox( - width: MediaQuery.of(context).size.width*0.4, + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.4, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -73,8 +69,7 @@ class SceneListview extends StatelessWidget { ], ), ), - ) - ); + )); }, ); } diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index 4182ed2..cf6de85 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -276,8 +276,10 @@ class CreateSceneBloc extends Bloc ? await SceneApi.updateScene(event.createSceneModel!, event.sceneId) : await SceneApi.createScene(event.createSceneModel!); } else if (event.createAutomationModel != null) { - response = - await SceneApi.createAutomation(event.createAutomationModel!); + response = event.updateScene + ? await SceneApi.updateAutomation( + event.createAutomationModel!, event.sceneId) + : await SceneApi.createAutomation(event.createAutomationModel!); } if (response['success'] == true) { @@ -315,13 +317,31 @@ class CreateSceneBloc extends Bloc emit(CreateSceneLoading()); try { - final response = await SceneApi.getSceneDetails(event.sceneId); + final response = event.isAutomation + ? await SceneApi.getAutomationDetails(event.sceneId) + : await SceneApi.getSceneDetails(event.sceneId); if (response.id.isNotEmpty) { - tasksList = List.from(getTaskListFunctionsFromApi( - actions: response.actions, isAutomation: false)); - emit(AddSceneTask( - tasksList: tasksList, - )); + if (event.isAutomation) { + automationTasksList = List.from( + getTaskListFunctionsFromApi( + actions: [], + isAutomation: true, + conditions: response.conditions)); + tasksList = List.from( + getTaskListFunctionsFromApi( + actions: response.actions, isAutomation: false)); + emit(AddSceneTask( + automationTasksList: automationTasksList, + tasksList: tasksList, + )); + } else { + tasksList = List.from( + getTaskListFunctionsFromApi( + actions: response.actions, isAutomation: false)); + emit(AddSceneTask( + tasksList: tasksList, + )); + } } else { emit(const CreateSceneError(message: 'Something went wrong')); } @@ -420,7 +440,11 @@ class CreateSceneBloc extends Bloc conditionRule = 'and'; } - emit(ConditionSelectedState(event.condition)); + emit(AddSceneTask( + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } FutureOr _sceneTypeEvent( diff --git a/lib/features/scene/bloc/create_scene/create_scene_event.dart b/lib/features/scene/bloc/create_scene/create_scene_event.dart index 0994a43..28953fe 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_event.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_event.dart @@ -147,10 +147,13 @@ class ClearTempTaskListEvent extends CreateSceneEvent { class FetchSceneTasksEvent extends CreateSceneEvent { final String sceneId; - const FetchSceneTasksEvent({required this.sceneId}); + final bool isAutomation; + + const FetchSceneTasksEvent( + {this.isAutomation = false, required this.sceneId}); @override - List get props => []; + List get props => [sceneId, isAutomation]; } class DeleteSceneEvent extends CreateSceneEvent { diff --git a/lib/features/scene/bloc/create_scene/create_scene_state.dart b/lib/features/scene/bloc/create_scene/create_scene_state.dart index 3e9e7e5..4108738 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_state.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_state.dart @@ -22,7 +22,9 @@ class CreateSceneError extends CreateSceneState { class AddSceneTask extends CreateSceneState { final List tasksList; final List? automationTasksList; - const AddSceneTask({required this.tasksList, this.automationTasksList}); + final String? condition; + const AddSceneTask( + {required this.tasksList, this.automationTasksList, this.condition}); @override List get props => [tasksList]; diff --git a/lib/features/scene/bloc/scene_bloc/scene_bloc.dart b/lib/features/scene/bloc/scene_bloc/scene_bloc.dart index 98b36cc..c68f4e9 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_bloc.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_bloc.dart @@ -11,16 +11,20 @@ part 'scene_state.dart'; class SceneBloc extends Bloc { SceneBloc() : super(SceneInitial()) { on(_onLoadScenes); + on(_onLoadAutomation); on(_onSceneTrigger); } + List scenes = []; + List automationList = []; + Future _onLoadScenes(LoadScenes event, Emitter emit) async { emit(SceneLoading()); try { if (event.unitId.isNotEmpty) { - final scenes = await SceneApi.getScenesByUnitId(event.unitId); - emit(SceneLoaded(scenes)); + scenes = await SceneApi.getScenesByUnitId(event.unitId); + emit(SceneLoaded(scenes, automationList)); } else { const SceneError(message: ''); } @@ -29,16 +33,34 @@ class SceneBloc extends Bloc { } } - Future _onSceneTrigger(SceneTrigger event, Emitter emit) async { + Future _onLoadAutomation( + LoadAutomation event, Emitter emit) async { + emit(SceneLoading()); + + try { + if (event.unitId.isNotEmpty) { + automationList = await SceneApi.getAutomationByUnitId(event.unitId); + emit(SceneLoaded(scenes, automationList)); + } else { + emit(const SceneError(message: 'Unit ID is empty')); + } + } catch (e) { + emit(const SceneError(message: 'Something went wrong')); + } + } + + Future _onSceneTrigger( + SceneTrigger event, Emitter emit) async { final currentState = state; if (currentState is SceneLoaded) { - emit(SceneLoaded(currentState.scenes, loadingSceneId: event.sceneId)); + emit(SceneLoaded(currentState.scenes, currentState.automationList, + loadingSceneId: event.sceneId)); try { final success = await SceneApi.triggerScene(event.sceneId); if (success) { emit(SceneTriggerSuccess(event.name)); - emit(SceneLoaded(currentState.scenes)); + emit(SceneLoaded(currentState.scenes, currentState.automationList)); } else { emit(const SceneError(message: 'Something went wrong')); } diff --git a/lib/features/scene/bloc/scene_bloc/scene_event.dart b/lib/features/scene/bloc/scene_bloc/scene_event.dart index 7412afc..5a22fd5 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_event.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_event.dart @@ -16,6 +16,15 @@ class LoadScenes extends SceneEvent { List get props => [unitId]; } +class LoadAutomation extends SceneEvent { + final String unitId; + + const LoadAutomation(this.unitId); + + @override + List get props => [unitId]; +} + class SceneTrigger extends SceneEvent { final String sceneId; final String name; diff --git a/lib/features/scene/bloc/scene_bloc/scene_state.dart b/lib/features/scene/bloc/scene_bloc/scene_state.dart index 9685416..f6b42a3 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_state.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_state.dart @@ -13,12 +13,13 @@ class SceneLoading extends SceneState {} class SceneLoaded extends SceneState { final List scenes; + final List automationList; final String? loadingSceneId; - const SceneLoaded(this.scenes, {this.loadingSceneId}); + const SceneLoaded(this.scenes, this.automationList, {this.loadingSceneId}); @override - List get props => [scenes, loadingSceneId]; + List get props => [scenes, loadingSceneId, automationList]; } class SceneError extends SceneState { diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index f77da60..d05ee24 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -100,45 +100,56 @@ mixin SceneLogicHelper { Navigator.pop(context); } } else { - // Handle Scene Creation - final createSceneModel = CreateSceneModel( - unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '', - sceneName: sceneName.text, - decisionExpr: 'and', - actions: List.generate( - actions.length, - (index) { - final task = actions[index]; - if (task.deviceId == 'delay') { + if (isOnlyDelayOrDelayLast(actions)) { + Navigator.pop(context); + context.showCustomSnackbar( + message: 'A single delay or delay-last operations are NOT allowed.', + icon: const Icon( + Icons.error, + color: Colors.red, + ), + ); + } else { + // Handle Scene Creation + final createSceneModel = CreateSceneModel( + unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '', + sceneName: sceneName.text, + decisionExpr: 'and', + actions: List.generate( + actions.length, + (index) { + final task = actions[index]; + if (task.deviceId == 'delay') { + return CreateSceneAction( + entityId: actions[index].deviceId, + actionExecutor: 'delay', + executorProperty: CreateSceneExecutorProperty( + functionCode: '', + functionValue: '', + delaySeconds: task.functionValue, + ), + ); + } return CreateSceneAction( - entityId: actions[index].deviceId, - actionExecutor: 'delay', + entityId: task.deviceId, + actionExecutor: 'device_issue', executorProperty: CreateSceneExecutorProperty( - functionCode: '', - functionValue: '', - delaySeconds: task.functionValue, + functionCode: task.code, + functionValue: task.functionValue, + delaySeconds: 0, ), ); - } - return CreateSceneAction( - entityId: task.deviceId, - actionExecutor: 'device_issue', - executorProperty: CreateSceneExecutorProperty( - functionCode: task.code, - functionValue: task.functionValue, - delaySeconds: 0, - ), - ); - }, - ), - ); - sceneBloc.add(CreateSceneWithTasksEvent( - createSceneModel: createSceneModel, - createAutomationModel: null, - updateScene: updateScene, - sceneId: sceneId, - )); - Navigator.pop(context); + }, + ), + ); + sceneBloc.add(CreateSceneWithTasksEvent( + createSceneModel: createSceneModel, + createAutomationModel: null, + updateScene: updateScene, + sceneId: sceneId, + )); + Navigator.pop(context); + } } } diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index a00d6ce..0b0b759 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -13,6 +13,30 @@ import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart'; mixin SceneOperationsDataHelper { + final Map, String, String, dynamic, bool)> + _functionMap = { + DeviceType.LightBulb: lightBulbFunctions, + DeviceType.CeilingSensor: ceilingSensorFunctions, + DeviceType.WallSensor: wallSensorFunctions, + DeviceType.AC: acFunctions, + DeviceType.DoorLock: doorLockFunctions, + DeviceType.Curtain: curtainFunctions, + DeviceType.ThreeGang: threeGangFunctions, + DeviceType.Gateway: gatewayFunctions, + }; + + final Map _titleMap = { + DeviceType.LightBulb: 'Light Bulb Functions', + DeviceType.CeilingSensor: 'Presence Sensor Functions', + DeviceType.WallSensor: 'Human Presence Sensor Functions', + DeviceType.AC: 'AC Functions', + DeviceType.DoorLock: 'Door Lock Functions', + DeviceType.Curtain: 'Curtain Functions', + DeviceType.ThreeGang: '3G Light Switch Functions', + DeviceType.Gateway: 'Gateway Functions', + }; + List getFunctionsWithIcons({ DeviceType? type, required List functions, @@ -20,63 +44,18 @@ mixin SceneOperationsDataHelper { required String deviceName, required bool isAutomation, }) { - const functionValue = null; - - switch (type) { - case DeviceType.LightBulb: - return lightBulbFunctions( + final functionValue = null; + return _functionMap[type]?.call( + functions, deviceId, deviceName, functionValue, isAutomation) ?? + lightBulbFunctions( functions, deviceId, deviceName, functionValue, isAutomation); - case DeviceType.CeilingSensor: - return ceilingSensorFunctions( - functions, deviceId, deviceName, functionValue, isAutomation); - case DeviceType.WallSensor: - return wallSensorFunctions( - functions, deviceId, deviceName, functionValue, isAutomation); - case DeviceType.AC: - return acFunctions( - functions, deviceId, deviceName, functionValue, isAutomation); - case DeviceType.DoorLock: - return doorLockFunctions( - functions, deviceId, deviceName, functionValue, isAutomation); - case DeviceType.Curtain: - return curtainFunctions( - functions, deviceId, deviceName, functionValue, isAutomation); - case DeviceType.ThreeGang: - return threeGangFunctions( - functions, deviceId, deviceName, functionValue, isAutomation); - case DeviceType.Gateway: - return gatewayFunctions( - functions, deviceId, deviceName, functionValue, isAutomation); - default: - return lightBulbFunctions( - functions, deviceId, deviceName, functionValue, isAutomation); - } } String getTitle({DeviceType? type}) { - switch (type) { - case DeviceType.LightBulb: - return 'Light Bulb Functions'; - case DeviceType.CeilingSensor: - return 'Presence Sensor Functions'; - case DeviceType.WallSensor: - return 'Human Presence Sensor Functions'; - case DeviceType.AC: - return 'AC Functions'; - case DeviceType.DoorLock: - return 'Door Lock Functions'; - case DeviceType.Curtain: - return 'Curtain Functions'; - case DeviceType.ThreeGang: - return '3G Light Switch Functions'; - case DeviceType.Gateway: - return 'Gateway Functions'; - default: - return ''; - } + return _titleMap[type] ?? ''; } - List ceilingSensorFunctions( + static List ceilingSensorFunctions( List functions, String deviceId, String deviceName, @@ -90,7 +69,7 @@ mixin SceneOperationsDataHelper { deviceId, deviceName, functionValue); } - List curtainFunctions( + static List curtainFunctions( List functions, String deviceId, String deviceName, @@ -99,7 +78,7 @@ mixin SceneOperationsDataHelper { return []; } - List doorLockFunctions( + static List doorLockFunctions( List functions, String deviceId, String deviceName, @@ -113,7 +92,7 @@ mixin SceneOperationsDataHelper { deviceId, deviceName, functionValue); } - List wallSensorFunctions( + static List wallSensorFunctions( List functions, String deviceId, String deviceName, @@ -127,7 +106,7 @@ mixin SceneOperationsDataHelper { deviceId, deviceName, functionValue); } - List lightBulbFunctions( + static List lightBulbFunctions( List functions, String deviceId, String deviceName, @@ -136,7 +115,7 @@ mixin SceneOperationsDataHelper { return []; } - List gatewayFunctions( + static List gatewayFunctions( List functions, String deviceId, String deviceName, @@ -146,7 +125,7 @@ mixin SceneOperationsDataHelper { deviceId, deviceName, functionValue); } - List threeGangFunctions( + static List threeGangFunctions( List functions, String deviceId, String deviceName, @@ -160,7 +139,7 @@ mixin SceneOperationsDataHelper { deviceId, deviceName, functionValue); } - List acFunctions( + static List acFunctions( List functions, String deviceId, String deviceName, @@ -174,9 +153,14 @@ mixin SceneOperationsDataHelper { deviceId, deviceName, functionValue); } - List getTaskListFunctionsFromApi( - {required List actions, required bool isAutomation}) { + List getTaskListFunctionsFromApi({ + required List actions, + required bool isAutomation, + List? conditions, + }) { List functions = []; + + // Handle actions for (var action in actions) { if (action.entityId == 'delay') { functions.add( @@ -191,9 +175,10 @@ mixin SceneOperationsDataHelper { code: '', operationalValues: [ SceneOperationalValue( - icon: '', - description: "", - value: action.executorProperty.delaySeconds), + icon: '', + description: "", + value: action.executorProperty.delaySeconds, + ), ], ), ); @@ -202,413 +187,688 @@ mixin SceneOperationsDataHelper { .add(_mapExecutorPropertyToSceneFunction(action, isAutomation)); } } + + // Handle conditions + if (conditions != null) { + for (var condition in conditions) { + // Create a dummy Action from Condition to reuse _mapExecutorPropertyToSceneFunction + Action dummyAction = Action( + actionExecutor: 'device_report', + entityId: condition.entityId, + executorProperty: ExecutorProperty( + functionCode: condition.expr.statusCode, + functionValue: condition.expr.statusValue, + ), + ); + var conditionFunction = _mapExecutorPropertyToSceneFunction( + dummyAction, + isAutomation, + comparator: condition.expr.comparator, + ); + functions.add(conditionFunction); + } + } + return functions; } SceneStaticFunction _mapExecutorPropertyToSceneFunction( - Action action, bool isAutomation, - {String? comparator}) { - ExecutorProperty executorProperty = action.executorProperty; + Action action, + bool isAutomation, { + String? comparator, + }) { + final executorProperty = action.executorProperty; - switch (executorProperty.functionCode) { - case 'sensitivity': - return _createSceneFunction( - action, - 'Presence Sensor', - Assets.assetsIconsSensors, - 'Sensitivity', - isAutomation - ? OperationDialogType.integerSteps - : OperationDialogType.listOfOptions, - isAutomation - ? _createIntegerStepsOptions() - : _createSensitivityOptions(), - isAutomation, - comparator ?? '=='); - case 'normal_open_switch': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Set Door lock Normal Open', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'unlock_fingerprint': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Fingerprint Unlock', - OperationDialogType.integerSteps, - _createFingerprintUnlockOptions(), - isAutomation, - comparator ?? '=='); - case 'unlock_password': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Password Unlock', - OperationDialogType.integerSteps, - _createPasswordUnlockOptions(), - isAutomation, - comparator ?? '=='); - case 'unlock_card': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Card Unlock', - OperationDialogType.integerSteps, - _createCardUnlockOptions(), - isAutomation, - comparator ?? '=='); - case 'alarm_lock': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Lock Alarm', - OperationDialogType.listOfOptions, - _createLockAlarmOptions(), - isAutomation, - comparator ?? '=='); - case 'unlock_request': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Remote Unlock Request', - OperationDialogType.integerSteps, - _createUnlockRequestOptions(), - isAutomation, - comparator ?? '=='); - case 'residual_electricity': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Residual Electricity', - OperationDialogType.integerSteps, - _createResidualElectricityOptions(), - isAutomation, - comparator ?? '=='); - case 'reverse_lock': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Double Lock', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'unlock_app': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Remote Unlock Via App', - OperationDialogType.integerSteps, - _createUnlockAppOptions(), - isAutomation, - comparator ?? '=='); - case 'hijack': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Hijack Alarm', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'doorbell': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Doorbell', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'unlock_temporary': - return _createSceneFunction( - action, - 'WIFI LOCK PRO', - Assets.assetsIconsDoorLock, - 'Temporary Password Unlock', - OperationDialogType.integerSteps, - _createTemporaryPasswordUnlockOptions(), - isAutomation, - comparator ?? '=='); - case 'far_detection': - return _createSceneFunction( - action, - 'Human Presence Sensor', - Assets.assetsIconsSensors, - 'Far Detection', - OperationDialogType.listOfOptions, - _createFarDetectionOptions(), - isAutomation, - comparator ?? '=='); - case 'motion_sensitivity_value': - return _createSceneFunction( - action, - 'Human Presence Sensor', - Assets.assetsIconsSensors, - 'Motion Detection Sensitivity', - OperationDialogType.listOfOptions, - _createSensitivityOptions(), - isAutomation, - comparator ?? '=='); - case 'motionless_sensitivity': - return _createSceneFunction( - action, - 'Human Presence Sensor', - Assets.assetsIconsSensors, - 'Motionless Detection Sensitivity', - OperationDialogType.listOfOptions, - _createSensitivityOptions(), - isAutomation, - comparator ?? '=='); - case 'indicator': - return _createSceneFunction( - action, - 'Human Presence Sensor', - Assets.assetsIconsSensors, - 'Indicator', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'presence_time': - return _createSceneFunction( - action, - 'Human Presence Sensor', - Assets.assetsIconsSensors, - 'Nobody Time', - OperationDialogType.countdown, - _createCountdownOptions(), - isAutomation, - comparator ?? '=='); - case 'presence_state': - return _createSceneFunction( - action, - 'Human Presence Sensor', - Assets.assetsIconsSensors, - 'Presence State', - OperationDialogType.listOfOptions, - _createPresenceStateOptions(), - isAutomation, - comparator ?? '=='); - case 'dis_current': - return _createSceneFunction( - action, - 'Human Presence Sensor', - Assets.assetsIconsSensors, - 'Current Distance', - OperationDialogType.integerSteps, - _createCurrentDistanceOptions(), - isAutomation, - comparator ?? '=='); - case 'illuminance_value': - return _createSceneFunction( - action, - 'Human Presence Sensor', - Assets.assetsIconsSensors, - 'Illuminance Value', - OperationDialogType.integerSteps, - _createIlluminanceValueOptions(), - isAutomation, - comparator ?? '=='); - case 'checking_result': - return _createSceneFunction( - action, - 'Human Presence Sensor', - Assets.assetsIconsSensors, - 'Self-Test Result', - OperationDialogType.listOfOptions, - _createSelfTestResultOptions(), - isAutomation, - comparator ?? '=='); - case 'switch': - return _createSceneFunction( - action, - 'Smart AC Thermostat - Grey - Model A', - Assets.assetsIconsAC, - 'Power', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'temp_set': - return _createSceneFunction( - action, - 'Smart AC Thermostat - Grey - Model A', - Assets.assetsIconsAC, - 'Set Temperature', - isAutomation - ? OperationDialogType.integerSteps - : OperationDialogType.temperature, - isAutomation - ? _createAutomationTemperatureOptions() - : _createTemperatureOptions(), - isAutomation, - comparator ?? '=='); - case 'temp_current': - return _createSceneFunction( - action, - 'Smart AC Thermostat - Grey - Model A', - Assets.assetsIconsAC, - 'Current Temperature', - OperationDialogType.integerSteps, - _createCurrentTemperatureOptions(), - isAutomation, - comparator ?? '=='); + final Map + functionMap = { + 'sensitivity': _createSensitivityFunction, + 'normal_open_switch': _createNormalOpenSwitchFunction, + 'unlock_fingerprint': _createUnlockFingerprintFunction, + 'unlock_password': _createUnlockPasswordFunction, + 'unlock_card': _createUnlockCardFunction, + 'alarm_lock': _createAlarmLockFunction, + 'unlock_request': _createUnlockRequestFunction, + 'residual_electricity': _createResidualElectricityFunction, + 'reverse_lock': _createReverseLockFunction, + 'unlock_app': _createUnlockAppFunction, + 'hijack': _createHijackFunction, + 'doorbell': _createDoorbellFunction, + 'unlock_temporary': _createUnlockTemporaryFunction, + 'far_detection': _createFarDetectionFunction, + 'motion_sensitivity_value': _createMotionSensitivityFunction, + 'motionless_sensitivity': _createMotionlessSensitivityFunction, + 'indicator': _createIndicatorFunction, + 'presence_time': _createPresenceTimeFunction, + 'presence_state': _createPresenceStateFunction, + 'dis_current': _createDisCurrentFunction, + 'illuminance_value': _createIlluminanceValueFunction, + 'checking_result': _createCheckingResultFunction, + 'switch': _createSwitchFunction, + 'temp_set': _createTempSetFunction, + 'temp_current': _createTempCurrentFunction, + 'mode': _createModeFunction, + 'level': _createLevelFunction, + 'child_lock': _createChildLockFunction, + 'switch_1': _createSwitch1Function, + 'switch_2': _createSwitch2Function, + 'switch_3': _createSwitch3Function, + 'countdown_1': _createCountdown1Function, + 'countdown_2': _createCountdown2Function, + 'countdown_3': _createCountdown3Function, + 'switch_alarm_sound': _createSwitchAlarmSoundFunction, + 'master_state': _createMasterStateFunction, + 'factory_reset': _createFactoryResetFunction, + }; - case 'mode': - return _createSceneFunction( - action, - 'Smart AC Thermostat - Grey - Model A', - Assets.assetsIconsAC, - 'Mode', - OperationDialogType.listOfOptions, - _createAcModeOptions(), - isAutomation, - comparator ?? '=='); - case 'level': - return _createSceneFunction( - action, - 'Smart AC Thermostat - Grey - Model A', - Assets.assetsIconsAC, - 'Fan Speed', - OperationDialogType.listOfOptions, - _createFanSpeedOptions(), - isAutomation, - comparator ?? '=='); - case 'child_lock': - return _createSceneFunction( - action, - 'Smart AC Thermostat - Grey - Model A', - Assets.assetsIconsAC, - 'Child Lock', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'switch_1': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsIcons3GangSwitch, - 'Light 1 Switch', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'switch_2': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsIcons3GangSwitch, - 'Light 2 Switch', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'switch_3': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsIcons3GangSwitch, - 'Light 3 Switch', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - - case 'countdown_1': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsIcons3GangSwitch, - 'Light 1 CountDown', - isAutomation - ? OperationDialogType.integerSteps - : OperationDialogType.countdown, - isAutomation - ? _createAutomationCountDownOptions() - : _createCountdownOptions(), - isAutomation, - comparator ?? '=='); - case 'countdown_2': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsIcons3GangSwitch, - 'Light 2 CountDown', - isAutomation - ? OperationDialogType.integerSteps - : OperationDialogType.countdown, - isAutomation - ? _createAutomationCountDownOptions() - : _createCountdownOptions(), - isAutomation, - comparator ?? '=='); - case 'countdown_3': - return _createSceneFunction( - action, - '3 Gang Button Switch L-L', - Assets.assetsIcons3GangSwitch, - 'Light 3 CountDown', - isAutomation - ? OperationDialogType.integerSteps - : OperationDialogType.countdown, - isAutomation - ? _createAutomationCountDownOptions() - : _createCountdownOptions(), - isAutomation, - comparator ?? '=='); - case 'switch_alarm_sound': - return _createSceneFunction( - action, - 'Gateway', - Assets.assetsIconsGateway, - 'Switch Alarm Sound', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - case 'master_state': - return _createSceneFunction( - action, - 'Gateway', - Assets.assetsIconsGateway, - 'Master State', - OperationDialogType.listOfOptions, - _createMasterStateOptions(), - isAutomation, - comparator ?? '=='); - case 'factory_reset': - return _createSceneFunction( - action, - 'Gateway', - Assets.assetsIconsGateway, - 'Factory Reset', - OperationDialogType.onOff, - _createOnOffOptions(), - isAutomation, - comparator ?? '=='); - default: - throw ArgumentError( - 'Unsupported function code: ${executorProperty.functionCode}'); + final functionCode = executorProperty.functionCode ?? ''; + final createFunction = functionMap[functionCode]; + if (createFunction != null) { + return createFunction(action, isAutomation, comparator); + } else { + throw ArgumentError('Unsupported function code: $functionCode'); } } + SceneStaticFunction _createSceneFunction( + Action action, + String deviceName, + String icon, + String operationName, + OperationDialogType operationDialogType, + List operationalValues, + bool isAutomation, [ + String? comparator, + ]) { + final functionValue = action.executorProperty.functionValue; + return SceneStaticFunction( + deviceId: action.entityId, + deviceName: deviceName, + deviceIcon: icon, + icon: icon, + operationName: operationName, + functionValue: functionValue, + code: action.executorProperty.functionCode ?? '', + operationDialogType: operationDialogType, + operationalValues: operationalValues, + comparator: comparator ?? '==', + ); + } + + SceneStaticFunction _createSensitivityFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Presence Sensor', + Assets.assetsIconsSensors, + 'Sensitivity', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.listOfOptions, + isAutomation ? _createIntegerStepsOptions() : _createSensitivityOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createNormalOpenSwitchFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Set Door lock Normal Open', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + List _createIntegerStepsOptions() { + return [ + SceneOperationalValue( + icon: '', + value: 0.0, + description: "CM", + minValue: 1, + maxValue: 600, + stepValue: 1, + ), + ]; + } + + List _createSensitivityOptions() { + return List.generate( + 10, + (index) => SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: index + 1, + description: (index + 1).toString(), + ), + ); + } + + List _createOnOffOptions() { + return [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "ON", + value: true, + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "OFF", + value: false, + ), + ]; + } + + SceneStaticFunction _createUnlockFingerprintFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Fingerprint Unlock', + OperationDialogType.integerSteps, + _createFingerprintUnlockOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createUnlockPasswordFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Password Unlock', + OperationDialogType.integerSteps, + _createPasswordUnlockOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createUnlockCardFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Card Unlock', + OperationDialogType.integerSteps, + _createCardUnlockOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createAlarmLockFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Lock Alarm', + OperationDialogType.listOfOptions, + _createLockAlarmOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createUnlockRequestFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Remote Unlock Request', + OperationDialogType.integerSteps, + _createUnlockRequestOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createResidualElectricityFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Residual Electricity', + OperationDialogType.integerSteps, + _createResidualElectricityOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createReverseLockFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Double Lock', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createUnlockAppFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Remote Unlock Via App', + OperationDialogType.integerSteps, + _createUnlockAppOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createHijackFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Hijack Alarm', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createDoorbellFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Doorbell', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createUnlockTemporaryFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'WIFI LOCK PRO', + Assets.assetsIconsDoorLock, + 'Temporary Password Unlock', + OperationDialogType.integerSteps, + _createTemporaryPasswordUnlockOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createFarDetectionFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIconsSensors, + 'Far Detection', + OperationDialogType.listOfOptions, + _createFarDetectionOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createMotionSensitivityFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIconsSensors, + 'Motion Detection Sensitivity', + OperationDialogType.listOfOptions, + _createSensitivityOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createMotionlessSensitivityFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIconsSensors, + 'Motionless Detection Sensitivity', + OperationDialogType.listOfOptions, + _createSensitivityOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createIndicatorFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIconsSensors, + 'Indicator', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createPresenceTimeFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIconsSensors, + 'Nobody Time', + OperationDialogType.countdown, + _createCountdownOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createPresenceStateFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIconsSensors, + 'Presence State', + OperationDialogType.listOfOptions, + _createPresenceStateOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createDisCurrentFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIconsSensors, + 'Current Distance', + OperationDialogType.integerSteps, + _createCurrentDistanceOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createIlluminanceValueFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIconsSensors, + 'Illuminance Value', + OperationDialogType.integerSteps, + _createIlluminanceValueOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createCheckingResultFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Human Presence Sensor', + Assets.assetsIconsSensors, + 'Self-Test Result', + OperationDialogType.listOfOptions, + _createSelfTestResultOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createSwitchFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsIconsAC, + 'Power', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createTempSetFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsIconsAC, + 'Set Temperature', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.temperature, + isAutomation + ? _createAutomationTemperatureOptions() + : _createTemperatureOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createTempCurrentFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsIconsAC, + 'Current Temperature', + OperationDialogType.integerSteps, + _createCurrentTemperatureOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createModeFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsIconsAC, + 'Mode', + OperationDialogType.listOfOptions, + _createAcModeOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createLevelFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsIconsAC, + 'Fan Speed', + OperationDialogType.listOfOptions, + _createFanSpeedOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createChildLockFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Smart AC Thermostat - Grey - Model A', + Assets.assetsIconsAC, + 'Child Lock', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createSwitch1Function( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsIcons3GangSwitch, + 'Light 1 Switch', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createSwitch2Function( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsIcons3GangSwitch, + 'Light 2 Switch', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createSwitch3Function( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsIcons3GangSwitch, + 'Light 3 Switch', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createCountdown1Function( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsIcons3GangSwitch, + 'Light 1 CountDown', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.countdown, + isAutomation + ? _createAutomationCountDownOptions() + : _createCountdownOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createCountdown2Function( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsIcons3GangSwitch, + 'Light 2 CountDown', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.countdown, + isAutomation + ? _createAutomationCountDownOptions() + : _createCountdownOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createCountdown3Function( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + '3 Gang Button Switch L-L', + Assets.assetsIcons3GangSwitch, + 'Light 3 CountDown', + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.countdown, + isAutomation + ? _createAutomationCountDownOptions() + : _createCountdownOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createSwitchAlarmSoundFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Gateway', + Assets.assetsIconsGateway, + 'Switch Alarm Sound', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createMasterStateFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Gateway', + Assets.assetsIconsGateway, + 'Master State', + OperationDialogType.listOfOptions, + _createMasterStateOptions(), + isAutomation, + comparator, + ); + } + + SceneStaticFunction _createFactoryResetFunction( + Action action, bool isAutomation, String? comparator) { + return _createSceneFunction( + action, + 'Gateway', + Assets.assetsIconsGateway, + 'Factory Reset', + OperationDialogType.onOff, + _createOnOffOptions(), + isAutomation, + comparator, + ); + } + List _createFingerprintUnlockOptions() { return [ SceneOperationalValue( @@ -764,28 +1024,17 @@ mixin SceneOperationsDataHelper { List _createAutomationTemperatureOptions() { return [ SceneOperationalValue( - icon: Assets.assetsCelsiusDegrees, - value: 0.0, - description: '°C', - minValue: 20, - maxValue: 30, - stepValue: 0.5) + icon: Assets.assetsCelsiusDegrees, + value: 0.0, + description: '°C', + minValue: 20, + maxValue: 30, + stepValue: 0.5, + ), ]; } - List _createIntegerStepsOptions() { - return [ - SceneOperationalValue( - icon: '', - value: 0.0, - description: "CM", - minValue: 1, - maxValue: 600, - stepValue: 1) - ]; - } - - _createAutomationCountDownOptions() { + List _createAutomationCountDownOptions() { return [ SceneOperationalValue( icon: '', @@ -794,121 +1043,101 @@ mixin SceneOperationsDataHelper { minValue: 0, maxValue: 43200, stepValue: 1, - ) + ), ]; } - SceneStaticFunction _createSceneFunction( - Action action, - String deviceName, - String icon, - String operationName, - OperationDialogType operationDialogType, - List operationalValues, - bool isAutomation, - String comparator) { - final functionValue = action.executorProperty.functionValue; - return SceneStaticFunction( - deviceId: action.entityId, - deviceName: deviceName, - deviceIcon: icon, - icon: icon, - operationName: operationName, - functionValue: functionValue, - code: action.executorProperty.functionCode ?? '', - operationDialogType: operationDialogType, - operationalValues: operationalValues, - comparator: comparator, - ); - } - - List _createOnOffOptions() { - return [ - SceneOperationalValue( - icon: Assets.assetsAcPower, description: "ON", value: true), - SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), - ]; - } - - List _createSensitivityOptions() { - return List.generate( - 10, - (index) => SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: index + 1, - description: (index + 1).toString())); - } - List _createFarDetectionOptions() { final distances = [75, 150, 225, 300, 375, 450, 525, 600]; return distances - .map((distance) => SceneOperationalValue( + .map( + (distance) => SceneOperationalValue( icon: Assets.assetsFarDetectionFunction, value: distance, description: '${distance}cm', - iconValue: distance.toString())) + iconValue: distance.toString(), + ), + ) .toList(); } List _createTemperatureOptions() { return [ SceneOperationalValue( - icon: Assets.assetsCelsiusDegrees, value: 0, description: 'COOL TO') + icon: Assets.assetsCelsiusDegrees, + value: 0, + description: 'COOL TO', + ), ]; } List _createMasterStateOptions() { return [ SceneOperationalValue( - icon: Assets.assetsAcPower, description: "Alarm", value: 'alarm'), + icon: Assets.assetsAcPower, + description: "Alarm", + value: 'alarm', + ), SceneOperationalValue( - icon: Assets.assetsAcPowerOFF, - description: "Normal", - value: 'normal'), + icon: Assets.assetsAcPowerOFF, + description: "Normal", + value: 'normal', + ), ]; } List _createAcModeOptions() { return [ SceneOperationalValue( - icon: Assets.assetsAcCooling, - description: AcValuesEnums.Cooling.name, - value: TempModes.cold.name), + icon: Assets.assetsAcCooling, + description: AcValuesEnums.Cooling.name, + value: TempModes.cold.name, + ), SceneOperationalValue( - icon: Assets.assetsAcHeating, - description: AcValuesEnums.Heating.name, - value: TempModes.hot.name), + icon: Assets.assetsAcHeating, + description: AcValuesEnums.Heating.name, + value: TempModes.hot.name, + ), SceneOperationalValue( - icon: Assets.assetsFanSpeed, - description: AcValuesEnums.Ventilation.name, - value: TempModes.wind.name), + icon: Assets.assetsFanSpeed, + description: AcValuesEnums.Ventilation.name, + value: TempModes.wind.name, + ), ]; } List _createFanSpeedOptions() { return [ SceneOperationalValue( - icon: Assets.assetsAcFanLow, - description: ValueACRange.LOW.name, - value: FanSpeeds.low.name), + icon: Assets.assetsAcFanLow, + description: ValueACRange.LOW.name, + value: FanSpeeds.low.name, + ), SceneOperationalValue( - icon: Assets.assetsAcFanMiddle, - description: ValueACRange.MIDDLE.name, - value: FanSpeeds.middle.name), + icon: Assets.assetsAcFanMiddle, + description: ValueACRange.MIDDLE.name, + value: FanSpeeds.middle.name, + ), SceneOperationalValue( - icon: Assets.assetsAcFanHigh, - description: ValueACRange.HIGH.name, - value: FanSpeeds.high.name), + icon: Assets.assetsAcFanHigh, + description: ValueACRange.HIGH.name, + value: FanSpeeds.high.name, + ), SceneOperationalValue( - icon: Assets.assetsAcFanAuto, - description: ValueACRange.AUTO.name, - value: FanSpeeds.auto.name), + icon: Assets.assetsAcFanAuto, + description: ValueACRange.AUTO.name, + value: FanSpeeds.auto.name, + ), ]; } List _createCountdownOptions() { - return [SceneOperationalValue(icon: '', value: 0)]; + return [ + SceneOperationalValue( + icon: '', + value: 0, + ), + ]; } List getOperationsForOneFunction({ @@ -928,7 +1157,11 @@ mixin SceneOperationsDataHelper { code: '', operationDialogType: OperationDialogType.delay, operationalValues: [ - SceneOperationalValue(icon: '', description: "", value: 0) + SceneOperationalValue( + icon: '', + description: "", + value: 0, + ), ], ), ]; @@ -937,14 +1170,16 @@ mixin SceneOperationsDataHelper { return [ _mapExecutorPropertyToSceneFunction( Action( - entityId: deviceId, - executorProperty: ExecutorProperty( - functionCode: taskItem.code, - functionValue: taskItem.functionValue), - actionExecutor: ''), + entityId: deviceId, + executorProperty: ExecutorProperty( + functionCode: taskItem.code, + functionValue: taskItem.functionValue, + ), + actionExecutor: '', + ), isAutomation, comparator: taskItem.comparator, - ) + ), ]; } diff --git a/lib/features/scene/model/create_automation_model.dart b/lib/features/scene/model/create_automation_model.dart index 61fa472..a349dc2 100644 --- a/lib/features/scene/model/create_automation_model.dart +++ b/lib/features/scene/model/create_automation_model.dart @@ -37,9 +37,9 @@ class CreateAutomationModel { ); } - Map toMap() { + Map toMap([String? automationId]) { return { - 'unitUuid': unitUuid, + if (automationId == null) 'unitUuid': unitUuid, 'automationName': automationName, 'decisionExpr': decisionExpr, 'effectiveTime': effectiveTime.toMap(), @@ -61,7 +61,7 @@ class CreateAutomationModel { ); } - String toJson() => json.encode(toMap()); + String toJson([String? automationId]) => json.encode(toMap(automationId)); factory CreateAutomationModel.fromJson(String source) => CreateAutomationModel.fromMap(json.decode(source)); diff --git a/lib/features/scene/model/scene_details_model.dart b/lib/features/scene/model/scene_details_model.dart index 5ed5d1c..04b9827 100644 --- a/lib/features/scene/model/scene_details_model.dart +++ b/lib/features/scene/model/scene_details_model.dart @@ -6,6 +6,9 @@ class SceneDetailsModel { final String status; final String type; final List actions; + final List? conditions; + final String? decisionExpr; + final EffectiveTime? effectiveTime; SceneDetailsModel({ required this.id, @@ -13,6 +16,9 @@ class SceneDetailsModel { required this.status, required this.type, required this.actions, + this.conditions, + this.decisionExpr, + this.effectiveTime, }); factory SceneDetailsModel.fromRawJson(String str) => @@ -28,6 +34,14 @@ class SceneDetailsModel { type: json["type"], actions: List.from(json["actions"].map((x) => Action.fromJson(x))), + conditions: json["conditions"] != null + ? List.from( + json["conditions"].map((x) => Condition.fromJson(x))) + : null, + decisionExpr: json["decisionExpr"], + effectiveTime: json["effectiveTime"] != null + ? EffectiveTime.fromJson(json["effectiveTime"]) + : null, ); Map toJson() => { @@ -36,6 +50,11 @@ class SceneDetailsModel { "status": status, "type": type, "actions": List.from(actions.map((x) => x.toJson())), + "conditions": conditions != null + ? List.from(conditions!.map((x) => x.toJson())) + : null, + "decisionExpr": decisionExpr, + "effectiveTime": effectiveTime?.toJson(), }; } @@ -91,3 +110,93 @@ class ExecutorProperty { "delaySeconds": delaySeconds, }; } + +class Condition { + final int code; + final String entityId; + final String entityType; + final Expr expr; + + Condition({ + required this.code, + required this.entityId, + required this.entityType, + required this.expr, + }); + + factory Condition.fromRawJson(String str) => + Condition.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory Condition.fromJson(Map json) => Condition( + code: json["code"], + entityId: json["entityId"], + entityType: json["entityType"], + expr: Expr.fromJson(json["expr"]), + ); + + Map toJson() => { + "code": code, + "entityId": entityId, + "entityType": entityType, + "expr": expr.toJson(), + }; +} + +class Expr { + final String comparator; + final String statusCode; + final dynamic statusValue; + + Expr({ + required this.comparator, + required this.statusCode, + required this.statusValue, + }); + + factory Expr.fromRawJson(String str) => Expr.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory Expr.fromJson(Map json) => Expr( + comparator: json["comparator"], + statusCode: json["statusCode"], + statusValue: json["statusValue"], + ); + + Map toJson() => { + "comparator": comparator, + "statusCode": statusCode, + "statusValue": statusValue, + }; +} + +class EffectiveTime { + final String start; + final String end; + final String loops; + + EffectiveTime({ + required this.start, + required this.end, + required this.loops, + }); + + factory EffectiveTime.fromRawJson(String str) => + EffectiveTime.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory EffectiveTime.fromJson(Map json) => EffectiveTime( + start: json["start"], + end: json["end"], + loops: json["loops"], + ); + + Map toJson() => { + "start": start, + "end": end, + "loops": loops, + }; +} diff --git a/lib/features/scene/model/scenes_model.dart b/lib/features/scene/model/scenes_model.dart index 5d0b44c..10423cb 100644 --- a/lib/features/scene/model/scenes_model.dart +++ b/lib/features/scene/model/scenes_model.dart @@ -37,9 +37,10 @@ enum Status { ENABLE } final statusValues = EnumValues({"enable": Status.ENABLE}); -enum Type { TAP_TO_RUN } +enum Type { TAP_TO_RUN, automation } -final typeValues = EnumValues({"tap_to_run": Type.TAP_TO_RUN}); +final typeValues = + EnumValues({"tap_to_run": Type.TAP_TO_RUN, "automation": Type.automation}); class EnumValues { Map map; diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index 0d5736b..38e3ed3 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -20,7 +20,7 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class DeviceFunctionsView extends StatelessWidget with SceneOperationsDataHelper, SceneLogicHelper { - const DeviceFunctionsView({super.key}); + DeviceFunctionsView({super.key}); @override Widget build(BuildContext context) { @@ -54,7 +54,7 @@ class DeviceFunctionsView extends StatelessWidget context .read() .add(AddTaskEvent(isAutomation: isAutomation)); - navigateToRoute(context, Routes.sceneTasksRoute); + navigateToRoute(context, Routes.sceneTasksRoute); }, child: BodyMedium( text: 'Save', diff --git a/lib/features/scene/view/scene_tasks_view.dart b/lib/features/scene/view/scene_tasks_view.dart index 134916c..5401c9c 100644 --- a/lib/features/scene/view/scene_tasks_view.dart +++ b/lib/features/scene/view/scene_tasks_view.dart @@ -13,6 +13,8 @@ import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/navigation/navigate_to_route.dart'; +import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; @@ -24,6 +26,7 @@ class SceneTasksView extends StatelessWidget { Widget build(BuildContext context) { final sceneSettings = ModalRoute.of(context)!.settings.arguments as SceneSettingsRouteArguments; + return DefaultScaffold( title: sceneSettings.sceneName.isNotEmpty ? sceneSettings.sceneName @@ -107,8 +110,7 @@ class DeleteBottomSheetContent extends StatelessWidget { listener: (context, state) { if (state is DeleteSceneSuccess) { if (state.success) { - Navigator.pop(context); - Navigator.pop(context); + navigateToRoute(context, Routes.homeRoute); BlocProvider.of(context).add( LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)); } diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index 6c09439..9b3cc35 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -1,7 +1,6 @@ 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/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'; @@ -9,7 +8,9 @@ import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_ import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_header.dart'; import 'package:syncrow_app/features/shared_widgets/create_unit.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class SceneView extends StatelessWidget { final bool pageType; @@ -19,7 +20,8 @@ class SceneView extends StatelessWidget { Widget build(BuildContext context) { return BlocProvider( create: (BuildContext context) => SceneBloc() - ..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '')), + ..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '')) + ..add(LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? '')), child: BlocBuilder( builder: (context, state) { if (state is DeleteSceneSuccess) { @@ -32,6 +34,8 @@ class SceneView extends StatelessWidget { if (state.success == true) { BlocProvider.of(context) .add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)); + BlocProvider.of(context).add( + LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!)); } } return BlocListener( @@ -63,29 +67,69 @@ class SceneView extends StatelessWidget { ); } if (state is SceneLoaded) { - if (state.scenes.isNotEmpty) { - return pageType == false - ? Expanded( - child: SceneGrid( - scenes: state.scenes, - loadingSceneId: state.loadingSceneId, + final scenes = state.scenes; + final automationList = state.automationList; + + return Expanded( + child: ListView( + children: [ + ExpansionTile( + tilePadding: const EdgeInsets.symmetric( + horizontal: 6), + initiallyExpanded: true, + iconColor: ColorsManager.grayColor, + title: const BodySmall( + text: 'Tap to run routines'), + children: [ + scenes.isNotEmpty + ? SceneGrid( + scenes: scenes, + loadingSceneId: + state.loadingSceneId, + disablePLayButton: false, + ) + : const Center( + child: BodyMedium( + text: + 'No scenes have been added yet', + ), + ), + const SizedBox( + height: 10, ), - ) - : Expanded( - child: SceneListview( - scenes: state.scenes, - loadingSceneId: state.loadingSceneId, - ) - ); - } else { - return const Expanded( - child: Center( - child: BodyMedium( - text: 'No scenes have been added yet', + ], ), - ), - ); - } + ExpansionTile( + initiallyExpanded: true, + iconColor: ColorsManager.grayColor, + tilePadding: const EdgeInsets.symmetric( + horizontal: 6), + title: const BodySmall(text: 'Automation'), + children: [ + automationList.isNotEmpty + ? SceneGrid( + scenes: automationList, + loadingSceneId: + state.loadingSceneId, + disablePLayButton: true, + ) + : const Center( + child: BodyMedium( + text: + 'No automations have been added yet', + ), + ), + const SizedBox( + height: 10, + ), + ], + ), + const SizedBox( + height: 15, + ), + ], + ), + ); } return const SizedBox(); }, diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart index 2563b28..3f1632b 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart @@ -62,7 +62,7 @@ class _AlertDialogSliderStepsState extends State { double _normalizeValue(dynamic value) { if (widget.taskItem.code == "temp_set" || widget.taskItem.code == "temp_current") { - return (value as double) / 10; + return (value) / 10; } return value.toDouble(); } diff --git a/lib/features/scene/widgets/if_then_containers/if_container.dart b/lib/features/scene/widgets/if_then_containers/if_container.dart index 4639abf..ad7e14c 100644 --- a/lib/features/scene/widgets/if_then_containers/if_container.dart +++ b/lib/features/scene/widgets/if_then_containers/if_container.dart @@ -83,8 +83,12 @@ class IFDefaultContainer extends StatelessWidget { BlocBuilder( builder: (context, state) { String conditionText = "When any condition is met"; - if (state is ConditionSelectedState) { - conditionText = state.condition; + if (state is AddSceneTask) { + if (state.condition == 'or') { + conditionText = "When any condition is met"; + } else { + conditionText = "When all conditions are met"; + } } return SizedBox( width: context.width * 0.6, diff --git a/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart b/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart index e6e5faf..6004028 100644 --- a/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart +++ b/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart @@ -1,21 +1,22 @@ import 'package:flutter/material.dart'; -import 'package:syncrow_app/features/scene/model/scenes_model.dart'; import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_item.dart'; class SceneGrid extends StatelessWidget { - final List scenes; + final List scenes; final String? loadingSceneId; + final bool disablePLayButton; const SceneGrid({ required this.scenes, required this.loadingSceneId, super.key, + required this.disablePLayButton, }); @override Widget build(BuildContext context) { - return - GridView.builder( + return GridView.builder( shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 12, @@ -26,7 +27,10 @@ class SceneGrid extends StatelessWidget { itemBuilder: (context, index) { final scene = scenes[index]; final isLoading = loadingSceneId == scene.id; - return SceneItem(scene: scene, isLoading: isLoading); + return SceneItem( + scene: scene, + isLoading: isLoading, + disablePLayButton: disablePLayButton); }, ); } diff --git a/lib/features/scene/widgets/scene_view_widget/scene_header.dart b/lib/features/scene/widgets/scene_view_widget/scene_header.dart index 788c4c1..1be7542 100644 --- a/lib/features/scene/widgets/scene_view_widget/scene_header.dart +++ b/lib/features/scene/widgets/scene_view_widget/scene_header.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; @@ -20,10 +19,10 @@ class SceneHeader extends StatelessWidget { fontWeight: FontWeight.bold, ), ), - SizedBox(height: 20), - BodySmall( - text: StringsManager.tapToRunRoutine, - ), + // SizedBox(height: 20), + // BodySmall( + // text: StringsManager.tapToRunRoutine, + // ), ], ); } diff --git a/lib/features/scene/widgets/scene_view_widget/scene_item.dart b/lib/features/scene/widgets/scene_view_widget/scene_item.dart index 1830475..894f662 100644 --- a/lib/features/scene/widgets/scene_view_widget/scene_item.dart +++ b/lib/features/scene/widgets/scene_view_widget/scene_item.dart @@ -16,11 +16,13 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class SceneItem extends StatelessWidget { final ScenesModel scene; final bool isLoading; + final bool disablePLayButton; const SceneItem({ required this.scene, required this.isLoading, super.key, + required this.disablePLayButton, }); @override @@ -31,16 +33,28 @@ class SceneItem extends StatelessWidget { context, Routes.sceneTasksRoute, arguments: SceneSettingsRouteArguments( - sceneType: CreateSceneEnum.tabToRun.name, + sceneType: disablePLayButton == false + ? CreateSceneEnum.tabToRun.name + : CreateSceneEnum.deviceStatusChanges.name, sceneId: scene.id, sceneName: scene.name, ), ); - BlocProvider.of(context) - .add(FetchSceneTasksEvent(sceneId: scene.id)); + if (disablePLayButton == false) { + BlocProvider.of(context) + .add(const SceneTypeEvent(CreateSceneEnum.tabToRun)); + BlocProvider.of(context).add( + FetchSceneTasksEvent(sceneId: scene.id, isAutomation: false)); + } else { + BlocProvider.of(context) + .add(const SceneTypeEvent(CreateSceneEnum.deviceStatusChanges)); + BlocProvider.of(context) + .add(FetchSceneTasksEvent(sceneId: scene.id, isAutomation: true)); + } }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -52,22 +66,25 @@ class SceneItem extends StatelessWidget { Assets.assetsIconsLogo, fit: BoxFit.fill, ), - IconButton( - padding: EdgeInsets.zero, - onPressed: () { - context - .read() - .add(SceneTrigger(scene.id, scene.name)); - }, - icon: isLoading - ? const Center( - child: CircularProgressIndicator(), - ) - : const Icon( - Icons.play_circle, - size: 40, - color: ColorsManager.greyColor, - ), + Visibility( + visible: disablePLayButton == false, + child: IconButton( + padding: EdgeInsets.zero, + onPressed: () { + context + .read() + .add(SceneTrigger(scene.id, scene.name)); + }, + icon: isLoading + ? const Center( + child: CircularProgressIndicator(), + ) + : const Icon( + Icons.play_circle, + size: 40, + color: ColorsManager.greyColor, + ), + ), ), ], ), diff --git a/lib/navigation/router.dart b/lib/navigation/router.dart index 751d818..1baf285 100644 --- a/lib/navigation/router.dart +++ b/lib/navigation/router.dart @@ -24,54 +24,67 @@ class Router { static Route generateRoute(RouteSettings settings) { switch (settings.name) { case Routes.splash: - return MaterialPageRoute(builder: (_) => const SplashView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const SplashView(), settings: settings); // case Routes.devicesRoute: // return MaterialPageRoute( // builder: (_) => const DevicesView(), settings: settings); case Routes.profileRoute: - return MaterialPageRoute(builder: (_) => const ProfileView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const ProfileView(), settings: settings); case Routes.sceneRoute: - return MaterialPageRoute(builder: (_) => const SceneView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const SceneView(), settings: settings); case Routes.layoutRoute: - return MaterialPageRoute(builder: (_) => const LayoutPage(), settings: settings); + return MaterialPageRoute( + builder: (_) => const LayoutPage(), settings: settings); case Routes.authLogin: - return MaterialPageRoute(builder: (_) => const LoginView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const LoginView(), settings: settings); case Routes.otpRoute: - return MaterialPageRoute(builder: (_) => const OtpView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const OtpView(), settings: settings); case Routes.authSignUp: - return MaterialPageRoute(builder: (_) => const SignUpView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const SignUpView(), settings: settings); case Routes.dashboardRoute: - return MaterialPageRoute(builder: (_) => const DashboardView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const DashboardView(), settings: settings); case Routes.homeRoute: - return MaterialPageRoute(builder: (_) => const AppLayout(), settings: settings); + return MaterialPageRoute( + builder: (_) => const AppLayout(), settings: settings); case Routes.menuRoute: - return MaterialPageRoute(builder: (_) => const MenuView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const MenuView(), settings: settings); case Routes.createUnit: - return MaterialPageRoute(builder: (_) => const CreateUnitView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const CreateUnitView(), settings: settings); case Routes.sceneTasksRoute: - return MaterialPageRoute(builder: (_) => const SceneTasksView(), settings: settings); + return MaterialPageRoute( + builder: (_) => const SceneTasksView(), settings: settings); case Routes.sceneControlDevicesRoute: return MaterialPageRoute( builder: (_) => MultiBlocProvider( providers: [ BlocProvider( - create: (BuildContext context) => DeviceManagerBloc()..add(FetchAllDevices()), + create: (BuildContext context) => + DeviceManagerBloc()..add(FetchAllDevices()), ), BlocProvider( - create: (BuildContext context) => - TabBarBloc(context.read()) - ..add(const TabChanged(selectedIndex: 0, roomId: '-1')), + create: (BuildContext context) => TabBarBloc( + context.read()) + ..add(const TabChanged(selectedIndex: 0, roomId: '-1')), ), ], child: const SceneRoomsTabBarDevicesView(), @@ -79,7 +92,7 @@ class Router { settings: settings); case Routes.deviceFunctionsRoute: return MaterialPageRoute( - builder: (_) => const DeviceFunctionsView(), + builder: (_) => DeviceFunctionsView(), settings: settings, ); default: diff --git a/lib/services/api/api_links_endpoints.dart b/lib/services/api/api_links_endpoints.dart index 351d2d0..61198fe 100644 --- a/lib/services/api/api_links_endpoints.dart +++ b/lib/services/api/api_links_endpoints.dart @@ -129,7 +129,7 @@ abstract class ApiEndpoints { static const String assignDeviceToRoom = '$baseUrl/device/room'; - /// Scene API //////////////////// + /// Scene & Automation API //////////////////// /// POST static const String createScene = '$baseUrl/scene/tap-to-run'; static const String triggerScene = @@ -142,9 +142,16 @@ abstract class ApiEndpoints { static const String getScene = '$baseUrl/scene/tap-to-run/details/{sceneId}'; + static const String getUnitAutomation = '$baseUrl/automation/{unitUuid}'; + + static const String getAutomationDetails = '$baseUrl/automation/details/{automationId}'; + /// PUT static const String updateScene = '$baseUrl/scene/tap-to-run/{sceneId}'; + static const String updateAutomation = + '$baseUrl/automation/{automationId}'; + /// DELETE static const String deleteScene = '$baseUrl/scene/tap-to-run/{unitUuid}/{sceneId}'; diff --git a/lib/services/api/scene_api.dart b/lib/services/api/scene_api.dart index e8630c6..8bc0886 100644 --- a/lib/services/api/scene_api.dart +++ b/lib/services/api/scene_api.dart @@ -8,6 +8,7 @@ import 'package:syncrow_app/services/api/http_service.dart'; class SceneApi { static final HTTPService _httpService = HTTPService(); +//create scene static Future> createScene( CreateSceneModel createSceneModel) async { try { @@ -25,6 +26,7 @@ class SceneApi { } } +// create automation static Future> createAutomation( CreateAutomationModel createAutomationModel) async { try { @@ -42,6 +44,8 @@ class SceneApi { } } + //get scene by unit id + static Future> getScenesByUnitId(String unitId) async { try { final response = await _httpService.get( @@ -61,6 +65,27 @@ class SceneApi { } } + //getAutomation + + static Future> getAutomationByUnitId(String unitId) async { + try { + final response = await _httpService.get( + path: ApiEndpoints.getUnitAutomation.replaceAll('{unitUuid}', unitId), + showServerMessage: false, + expectedResponseModel: (json) { + List scenes = []; + for (var scene in json) { + scenes.add(ScenesModel.fromJson(scene)); + } + return scenes; + }, + ); + return response; + } catch (e) { + rethrow; + } + } + static Future triggerScene(String sceneId) async { try { final response = await _httpService.post( @@ -74,6 +99,22 @@ class SceneApi { } } +//automation details + static Future getAutomationDetails( + String automationId) async { + try { + final response = await _httpService.get( + path: ApiEndpoints.getAutomationDetails + .replaceAll('{automationId}', automationId), + showServerMessage: false, + expectedResponseModel: (json) => SceneDetailsModel.fromJson(json), + ); + return response; + } catch (e) { + rethrow; + } + } + //getScene static Future getSceneDetails(String sceneId) async { @@ -89,7 +130,7 @@ class SceneApi { } } - //updateScene + //update Scene static updateScene(CreateSceneModel createSceneModel, String sceneId) async { try { final response = await _httpService.put( @@ -106,7 +147,26 @@ class SceneApi { } } - //deleteScene + //update automation + static updateAutomation( + CreateAutomationModel createAutomationModel, String automationId) async { + try { + final response = await _httpService.put( + path: ApiEndpoints.updateAutomation + .replaceAll('{automationId}', automationId), + body: createAutomationModel + .toJson(automationId.isNotEmpty == true ? automationId : null), + expectedResponseModel: (json) { + return json; + }, + ); + return response; + } catch (e) { + rethrow; + } + } + + //delete Scene static Future deleteScene( {required String unitUuid, required String sceneId}) async { From 3e20ba8f42c2f531c48d895a071e7aef99056976 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Thu, 25 Jul 2024 00:34:00 +0300 Subject: [PATCH 15/30] push delete automation --- .../bloc/create_scene/create_scene_bloc.dart | 8 ++++++-- lib/features/scene/view/scene_tasks_view.dart | 17 ++++++++++++++--- lib/features/scene/view/scene_view.dart | 2 ++ lib/services/api/api_links_endpoints.dart | 9 ++++++--- lib/services/api/scene_api.dart | 17 +++++++++++++++++ lib/utils/resource_manager/strings_manager.dart | 1 + 6 files changed, 46 insertions(+), 8 deletions(-) diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index cf6de85..4a2ee5b 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -393,8 +393,12 @@ class CreateSceneBloc extends Bloc emit(DeleteSceneLoading()); try { - final response = await SceneApi.deleteScene( - sceneId: event.sceneId, unitUuid: event.unitUuid); + final response = + sceneType.name == CreateSceneEnum.deviceStatusChanges.name + ? await SceneApi.deleteAutomation( + automationId: event.sceneId, unitUuid: event.unitUuid) + : await SceneApi.deleteScene( + sceneId: event.sceneId, unitUuid: event.unitUuid); if (response == true) { emit(const DeleteSceneSuccess(true)); } else { diff --git a/lib/features/scene/view/scene_tasks_view.dart b/lib/features/scene/view/scene_tasks_view.dart index 5401c9c..86863c4 100644 --- a/lib/features/scene/view/scene_tasks_view.dart +++ b/lib/features/scene/view/scene_tasks_view.dart @@ -5,6 +5,7 @@ import 'package:syncrow_app/features/app_layout/bloc/home_cubit.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/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; import 'package:syncrow_app/features/scene/widgets/create_scene_save_button.dart'; import 'package:syncrow_app/features/scene/widgets/if_then_containers/if_container.dart'; @@ -27,6 +28,9 @@ class SceneTasksView extends StatelessWidget { final sceneSettings = ModalRoute.of(context)!.settings.arguments as SceneSettingsRouteArguments; + final isAutomation = + sceneSettings.sceneType == CreateSceneEnum.deviceStatusChanges.name; + return DefaultScaffold( title: sceneSettings.sceneName.isNotEmpty ? sceneSettings.sceneName @@ -41,7 +45,8 @@ class SceneTasksView extends StatelessWidget { : () { context.customBottomSheet( child: DeleteBottomSheetContent( - sceneId: sceneSettings.sceneId), + sceneId: sceneSettings.sceneId, + isAutomation: isAutomation), ); }, child: SvgPicture.asset( @@ -95,9 +100,11 @@ class SceneTasksView extends StatelessWidget { } class DeleteBottomSheetContent extends StatelessWidget { - const DeleteBottomSheetContent({super.key, required this.sceneId}); + const DeleteBottomSheetContent( + {super.key, required this.sceneId, required this.isAutomation}); final String sceneId; + final bool isAutomation; @override Widget build(BuildContext context) { @@ -113,6 +120,8 @@ class DeleteBottomSheetContent extends StatelessWidget { navigateToRoute(context, Routes.homeRoute); BlocProvider.of(context).add( LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)); + BlocProvider.of(context).add(LoadAutomation( + HomeCubit.getInstance().selectedSpace!.id!)); } } }, @@ -126,7 +135,9 @@ class DeleteBottomSheetContent extends StatelessWidget { )); }, child: SceneListTile( - titleString: StringsManager.deleteScene, + titleString: isAutomation + ? StringsManager.deleteAutomation + : StringsManager.deleteScene, leadingWidget: (state is DeleteSceneLoading) ? const SizedBox( height: 24, diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index 9b3cc35..82af686 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -28,6 +28,8 @@ class SceneView extends StatelessWidget { if (state.success) { BlocProvider.of(context) .add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)); + BlocProvider.of(context).add( + LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!)); } } if (state is CreateSceneWithTasks) { diff --git a/lib/services/api/api_links_endpoints.dart b/lib/services/api/api_links_endpoints.dart index 61198fe..513a9e6 100644 --- a/lib/services/api/api_links_endpoints.dart +++ b/lib/services/api/api_links_endpoints.dart @@ -144,18 +144,21 @@ abstract class ApiEndpoints { static const String getUnitAutomation = '$baseUrl/automation/{unitUuid}'; - static const String getAutomationDetails = '$baseUrl/automation/details/{automationId}'; + static const String getAutomationDetails = + '$baseUrl/automation/details/{automationId}'; /// PUT static const String updateScene = '$baseUrl/scene/tap-to-run/{sceneId}'; - static const String updateAutomation = - '$baseUrl/automation/{automationId}'; + static const String updateAutomation = '$baseUrl/automation/{automationId}'; /// DELETE static const String deleteScene = '$baseUrl/scene/tap-to-run/{unitUuid}/{sceneId}'; + static const String deleteAutomation = + '$baseUrl/automation/{unitUuid}/{automationId}'; + //////////////////////Door Lock ////////////////////// //online static const String addTemporaryPassword = diff --git a/lib/services/api/scene_api.dart b/lib/services/api/scene_api.dart index 8bc0886..6233b30 100644 --- a/lib/services/api/scene_api.dart +++ b/lib/services/api/scene_api.dart @@ -183,4 +183,21 @@ class SceneApi { rethrow; } } + + // delete automation + static Future deleteAutomation( + {required String unitUuid, required String automationId}) async { + try { + final response = await _httpService.delete( + path: ApiEndpoints.deleteAutomation + .replaceAll('{automationId}', automationId) + .replaceAll('{unitUuid}', unitUuid), + showServerMessage: false, + expectedResponseModel: (json) => json['statusCode'] == 200, + ); + return response; + } catch (e) { + rethrow; + } + } } diff --git a/lib/utils/resource_manager/strings_manager.dart b/lib/utils/resource_manager/strings_manager.dart index 1548bb5..421a0c3 100644 --- a/lib/utils/resource_manager/strings_manager.dart +++ b/lib/utils/resource_manager/strings_manager.dart @@ -40,4 +40,5 @@ class StringsManager { static const String functions = "Functions"; static const String firstLaunch = "firstLaunch"; static const String deleteScene = 'Delete Scene'; + static const String deleteAutomation = 'Delete Automation'; } From 91421c117e3d1104ac1e2a9b0ea8659fe5acc96c Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Thu, 25 Jul 2024 01:25:16 +0300 Subject: [PATCH 16/30] push automation --- lib/features/scene/view/scene_view.dart | 126 ++++++++++-------- .../if_then_containers/then_added_tasks.dart | 5 +- 2 files changed, 70 insertions(+), 61 deletions(-) diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index 82af686..96e5cdf 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -1,6 +1,7 @@ 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/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'; @@ -72,66 +73,75 @@ class SceneView extends StatelessWidget { final scenes = state.scenes; final automationList = state.automationList; - return Expanded( - child: ListView( - children: [ - ExpansionTile( - tilePadding: const EdgeInsets.symmetric( - horizontal: 6), - initiallyExpanded: true, - iconColor: ColorsManager.grayColor, - title: const BodySmall( - text: 'Tap to run routines'), - children: [ - scenes.isNotEmpty - ? SceneGrid( - scenes: scenes, - loadingSceneId: - state.loadingSceneId, - disablePLayButton: false, - ) - : const Center( - child: BodyMedium( - text: - 'No scenes have been added yet', - ), + return pageType + ? Expanded( + child: SceneListview( + scenes: state.scenes, + loadingSceneId: state.loadingSceneId, + )) + : Expanded( + child: ListView( + children: [ + ExpansionTile( + tilePadding: + const EdgeInsets.symmetric( + horizontal: 6), + initiallyExpanded: true, + iconColor: ColorsManager.grayColor, + title: const BodySmall( + text: 'Tap to run routines'), + children: [ + scenes.isNotEmpty + ? SceneGrid( + scenes: scenes, + loadingSceneId: + state.loadingSceneId, + disablePLayButton: false, + ) + : const Center( + child: BodyMedium( + text: + 'No scenes have been added yet', + ), + ), + const SizedBox( + height: 10, ), - const SizedBox( - height: 10, - ), - ], - ), - ExpansionTile( - initiallyExpanded: true, - iconColor: ColorsManager.grayColor, - tilePadding: const EdgeInsets.symmetric( - horizontal: 6), - title: const BodySmall(text: 'Automation'), - children: [ - automationList.isNotEmpty - ? SceneGrid( - scenes: automationList, - loadingSceneId: - state.loadingSceneId, - disablePLayButton: true, - ) - : const Center( - child: BodyMedium( - text: - 'No automations have been added yet', - ), + ], + ), + ExpansionTile( + initiallyExpanded: true, + iconColor: ColorsManager.grayColor, + tilePadding: + const EdgeInsets.symmetric( + horizontal: 6), + title: const BodySmall( + text: 'Automation'), + children: [ + automationList.isNotEmpty + ? SceneGrid( + scenes: automationList, + loadingSceneId: + state.loadingSceneId, + disablePLayButton: true, + ) + : const Center( + child: BodyMedium( + text: + 'No automations have been added yet', + ), + ), + const SizedBox( + height: 10, ), - const SizedBox( - height: 10, - ), - ], - ), - const SizedBox( - height: 15, - ), - ], - ), - ); + ], + ), + const SizedBox( + height: 15, + ), + ], + ), + ); } return const SizedBox(); }, diff --git a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart index 4c3f531..1e6384c 100644 --- a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart +++ b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart @@ -13,6 +13,7 @@ import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/helpers/snack_bar.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class ThenAddedTasksContainer extends StatelessWidget @@ -146,9 +147,7 @@ class ThenAddedTasksContainer extends StatelessWidget String removeFunction = "${taskItem.operationName} with value ${taskItem.operationalValues.first.value}"; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('$removeFunction removed')), - ); + CustomSnackBar.displaySnackBar('$removeFunction removed'); }, child: SceneListTile( padding: EdgeInsets.zero, From 6a128f9558380014a9313d0a8cfea50c9977737f Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sat, 27 Jul 2024 17:26:44 +0300 Subject: [PATCH 17/30] finished bugs --- .../bloc/create_scene/create_scene_bloc.dart | 74 +++++++++--- lib/features/scene/model/scenes_model.dart | 35 ++---- .../scene/view/device_functions_view.dart | 6 +- lib/features/scene/view/scene_view.dart | 110 ++++++++++-------- .../if_then_containers/if_container.dart | 40 ++++--- .../if_then_containers/then_added_tasks.dart | 3 +- 6 files changed, 158 insertions(+), 110 deletions(-) diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index 4a2ee5b..bf519fa 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -58,6 +58,7 @@ class CreateSceneBloc extends Bloc emit(AddSceneTask( automationTasksList: automationTasksList, tasksList: tasksList, + condition: conditionRule, )); } else { final copyList = List.from(tempTasksList); @@ -67,6 +68,7 @@ class CreateSceneBloc extends Bloc emit(AddSceneTask( tasksList: tasksList, automationTasksList: automationTasksList, + condition: conditionRule, )); } } @@ -129,7 +131,10 @@ class CreateSceneBloc extends Bloc } emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } void addToTempAutomationTaskList( @@ -186,7 +191,10 @@ class CreateSceneBloc extends Bloc event.deviceControlModel.value; } emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } FutureOr _selectedValue( @@ -211,7 +219,10 @@ class CreateSceneBloc extends Bloc emit(SelectedTaskValueState(value: event.value)); emit(AddSceneTask( tasksList: List.from(tasksList), - automationTasksList: List.from(automationTasksList), + automationTasksList: List.from( + automationTasksList, + ), + condition: conditionRule, )); } @@ -223,7 +234,10 @@ class CreateSceneBloc extends Bloc if (element.uniqueCustomId == event.taskId) { automationTasksList.remove(element); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); break; } } @@ -233,7 +247,10 @@ class CreateSceneBloc extends Bloc tasksList.remove(element); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); break; } } @@ -248,7 +265,10 @@ class CreateSceneBloc extends Bloc if (element.uniqueCustomId == event.code) { automationTempTasksList.remove(element); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); break; } } @@ -258,7 +278,10 @@ class CreateSceneBloc extends Bloc tempTasksList.remove(element); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); break; } @@ -299,7 +322,10 @@ class CreateSceneBloc extends Bloc } catch (e) { emit(const CreateSceneError(message: 'Something went wrong')); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } } @@ -309,7 +335,10 @@ class CreateSceneBloc extends Bloc automationTasksList.clear(); tasksList.clear(); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } FutureOr _fetchSceneTasks( @@ -333,6 +362,7 @@ class CreateSceneBloc extends Bloc emit(AddSceneTask( automationTasksList: automationTasksList, tasksList: tasksList, + condition: conditionRule, )); } else { tasksList = List.from( @@ -340,6 +370,7 @@ class CreateSceneBloc extends Bloc actions: response.actions, isAutomation: false)); emit(AddSceneTask( tasksList: tasksList, + condition: conditionRule, )); } } else { @@ -358,12 +389,18 @@ class CreateSceneBloc extends Bloc automationSelectedValues.clear(); automationComparatorValues.clear(); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } else { tempTasksList.clear(); selectedValues.clear(); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } } @@ -376,14 +413,20 @@ class CreateSceneBloc extends Bloc automationComparatorValues.remove(event.code); emit(const SelectedTaskValueState(value: null)); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } } else { if (selectedValues.containsKey(event.code)) { selectedValues.remove(event.code); emit(const SelectedTaskValueState(value: null)); emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } } } @@ -432,7 +475,10 @@ class CreateSceneBloc extends Bloc } } emit(AddSceneTask( - tasksList: tasksList, automationTasksList: automationTasksList)); + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } FutureOr _selectConditionRule( diff --git a/lib/features/scene/model/scenes_model.dart b/lib/features/scene/model/scenes_model.dart index 10423cb..4c0066c 100644 --- a/lib/features/scene/model/scenes_model.dart +++ b/lib/features/scene/model/scenes_model.dart @@ -3,8 +3,8 @@ import 'dart:convert'; class ScenesModel { final String id; final String name; - final Status status; - final Type type; + final String status; + final String type; ScenesModel({ required this.id, @@ -20,36 +20,15 @@ class ScenesModel { factory ScenesModel.fromJson(Map json) => ScenesModel( id: json["id"], - name: json["name"], - status: statusValues.map[json["status"]]!, - type: typeValues.map[json["type"]]!, + name: json["name"] ?? '', + status: json["status"] ?? '', + type: json["type"] ?? '', ); Map toJson() => { "id": id, "name": name, - "status": statusValues.reverse[status], - "type": typeValues.reverse[type], + "status": status, + "type": type, }; } - -enum Status { ENABLE } - -final statusValues = EnumValues({"enable": Status.ENABLE}); - -enum Type { TAP_TO_RUN, automation } - -final typeValues = - EnumValues({"tap_to_run": Type.TAP_TO_RUN, "automation": Type.automation}); - -class EnumValues { - Map map; - late Map reverseMap; - - EnumValues(this.map); - - Map get reverse { - reverseMap = map.map((k, v) => MapEntry(v, k)); - return reverseMap; - } -} diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index 38e3ed3..ddb9090 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -65,7 +65,7 @@ class DeviceFunctionsView extends StatelessWidget ], leading: TextButton( onPressed: () { - if (isAutomation) { + // if (isAutomation) { final automationSelectedValue = context.read().automationSelectedValues; for (var element in device.functions) { @@ -77,7 +77,7 @@ class DeviceFunctionsView extends StatelessWidget code: element.code!, isAutomation: true)); } } - } else { + // } else { final selectedValue = context.read().selectedValues; for (var element in device.functions) { @@ -90,7 +90,7 @@ class DeviceFunctionsView extends StatelessWidget .add(RemoveFromSelectedValueById(code: element.code!)); } } - } + // } Navigator.pop(context); }, diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index c924cbc..f181c8b 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -9,7 +9,6 @@ import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_ import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_header.dart'; import 'package:syncrow_app/features/shared_widgets/create_unit.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; @@ -29,23 +28,24 @@ class SceneView extends StatelessWidget { if (state.success) { BlocProvider.of(context) .add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)); - BlocProvider.of(context) - .add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!)); + BlocProvider.of(context).add( + LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!)); } } if (state is CreateSceneWithTasks) { if (state.success == true) { BlocProvider.of(context) .add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)); - BlocProvider.of(context) - .add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!)); + BlocProvider.of(context).add( + LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!)); } } 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 ?? true @@ -81,49 +81,67 @@ class SceneView extends StatelessWidget { : Expanded( child: ListView( children: [ - ExpansionTile( - tilePadding: const EdgeInsets.symmetric(horizontal: 6), - initiallyExpanded: true, - iconColor: ColorsManager.grayColor, - title: const BodySmall(text: 'Tap to run routines'), - children: [ - scenes.isNotEmpty - ? SceneGrid( - scenes: scenes, - loadingSceneId: state.loadingSceneId, - disablePLayButton: false, - ) - : const Center( - child: BodyMedium( - text: 'No scenes have been added yet', + 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, + ) + : const Center( + child: BodyMedium( + text: + 'No scenes have been added yet', + ), ), - ), - const SizedBox( - height: 10, - ), - ], + const SizedBox( + height: 10, + ), + ], + ), ), - ExpansionTile( - initiallyExpanded: true, - iconColor: ColorsManager.grayColor, - tilePadding: const EdgeInsets.symmetric(horizontal: 6), - title: const BodySmall(text: 'Automation'), - children: [ - automationList.isNotEmpty - ? SceneGrid( - scenes: automationList, - loadingSceneId: state.loadingSceneId, - disablePLayButton: true, - ) - : const Center( - child: BodyMedium( - text: 'No automations 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, + ) + : const Center( + child: BodyMedium( + text: + 'No automations have been added yet', + ), ), - ), - const SizedBox( - height: 10, - ), - ], + const SizedBox( + height: 10, + ), + ], + ), ), const SizedBox( height: 15, diff --git a/lib/features/scene/widgets/if_then_containers/if_container.dart b/lib/features/scene/widgets/if_then_containers/if_container.dart index ad7e14c..a68e660 100644 --- a/lib/features/scene/widgets/if_then_containers/if_container.dart +++ b/lib/features/scene/widgets/if_then_containers/if_container.dart @@ -27,6 +27,7 @@ class IFDefaultContainer extends StatelessWidget { @override Widget build(BuildContext context) { + final sceneType = context.read().sceneType; return DefaultContainer( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2), child: Column( @@ -35,7 +36,6 @@ class IFDefaultContainer extends StatelessWidget { SceneListTile( leadingWidget: InkWell( onTap: () { - final sceneType = context.read().sceneType; if (sceneType.name == CreateSceneEnum.deviceStatusChanges.name) { context.customAlertDialog( @@ -80,24 +80,28 @@ class IFDefaultContainer extends StatelessWidget { color: ColorsManager.primaryTextColor, ), ), - BlocBuilder( - builder: (context, state) { - String conditionText = "When any condition is met"; - if (state is AddSceneTask) { - if (state.condition == 'or') { - conditionText = "When any condition is met"; - } else { - conditionText = "When all conditions are met"; + Visibility( + visible: sceneType.name == + CreateSceneEnum.deviceStatusChanges.name, + child: BlocBuilder( + builder: (context, state) { + String conditionText = "When any condition is met"; + if (state is AddSceneTask) { + if (state.condition == 'or') { + conditionText = "When any condition is met"; + } else { + conditionText = "When all conditions are met"; + } } - } - return SizedBox( - width: context.width * 0.6, - child: Row(children: [ - BodySmall(text: conditionText), - const Icon(Icons.keyboard_arrow_down) - ]), - ); - }, + return SizedBox( + width: context.width * 0.6, + child: Row(children: [ + BodySmall(text: conditionText), + const Icon(Icons.keyboard_arrow_down) + ]), + ); + }, + ), ), ], ), diff --git a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart index 1e6384c..41595f8 100644 --- a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart +++ b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart @@ -43,7 +43,8 @@ class ThenAddedTasksContainer extends StatelessWidget Duration(seconds: int.tryParse(functionValue.toString()) ?? 0); operationValue = "${duration.inHours}h ${duration.inMinutes.remainder(60)}m "; - } else if (taskItem.code.contains('temp_set')) { + } else if (taskItem.code.contains('temp_set') || + taskItem.code.contains('temp_current')) { if (taskItem.functionValue != null || taskItem.functionValue != 0) { operationValue = '${((taskItem.functionValue / 10) as double).round().toString()}°C'; From 0cad30557d9235bda626f3bc9d7bf0a20a742fb4 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sat, 27 Jul 2024 17:28:01 +0300 Subject: [PATCH 18/30] fix alignemtn --- lib/features/scene/widgets/if_then_containers/if_container.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/features/scene/widgets/if_then_containers/if_container.dart b/lib/features/scene/widgets/if_then_containers/if_container.dart index a68e660..c7fe028 100644 --- a/lib/features/scene/widgets/if_then_containers/if_container.dart +++ b/lib/features/scene/widgets/if_then_containers/if_container.dart @@ -162,6 +162,7 @@ class IFDefaultContainer extends StatelessWidget { final sceneType = context.read().sceneType; if (sceneType.name == CreateSceneEnum.tabToRun.name) { return const SceneListTile( + padding: EdgeInsets.symmetric(horizontal: 2), assetPath: Assets.handClickIcon, titleString: StringsManager.tapToRun, subtitleString: '', From 0783f8dacdfe63ccdd8bb514e85f98ced34e9bfd Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sat, 27 Jul 2024 22:35:53 +0300 Subject: [PATCH 19/30] finished select period dialog design --- .../effective_period/effect_period_bloc.dart | 30 ++ .../effective_period/effect_period_event.dart | 36 ++ .../effective_period/effect_period_state.dart | 42 +++ .../scene/view/scene_auto_settings.dart | 62 ++++ lib/features/scene/view/scene_tasks_view.dart | 99 +++--- .../effective_period_bottom_sheet.dart | 314 ++++++++++++++++++ lib/navigation/router.dart | 6 + lib/navigation/routing_constants.dart | 5 +- 8 files changed, 541 insertions(+), 53 deletions(-) create mode 100644 lib/features/scene/bloc/effective_period/effect_period_bloc.dart create mode 100644 lib/features/scene/bloc/effective_period/effect_period_event.dart create mode 100644 lib/features/scene/bloc/effective_period/effect_period_state.dart create mode 100644 lib/features/scene/view/scene_auto_settings.dart create mode 100644 lib/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart diff --git a/lib/features/scene/bloc/effective_period/effect_period_bloc.dart b/lib/features/scene/bloc/effective_period/effect_period_bloc.dart new file mode 100644 index 0000000..710b124 --- /dev/null +++ b/lib/features/scene/bloc/effective_period/effect_period_bloc.dart @@ -0,0 +1,30 @@ +import 'package:bloc/bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart'; + +class EffectPeriodBloc extends Bloc { + EffectPeriodBloc() : super(EffectPeriodState.initial()) { + on(_onSetPeriod); + on(_onToggleDay); + on(_onSetCustomTime); + } + + void _onSetPeriod(SetPeriod event, Emitter emit) { + emit(state.copyWith(selectedPeriod: event.period)); + } + + void _onToggleDay(ToggleDay event, Emitter emit) { + final days = List.of(state.selectedDays); + if (days.contains(event.day)) { + days.remove(event.day); + } else { + days.add(event.day); + } + emit(state.copyWith(selectedDays: days)); + } + + void _onSetCustomTime(SetCustomTime event, Emitter emit) { + emit(state.copyWith( + customStartTime: event.startTime, customEndTime: event.endTime)); + } +} diff --git a/lib/features/scene/bloc/effective_period/effect_period_event.dart b/lib/features/scene/bloc/effective_period/effect_period_event.dart new file mode 100644 index 0000000..12ac37e --- /dev/null +++ b/lib/features/scene/bloc/effective_period/effect_period_event.dart @@ -0,0 +1,36 @@ +import 'package:equatable/equatable.dart'; + +abstract class EffectPeriodEvent extends Equatable { + const EffectPeriodEvent(); + + @override + List get props => []; +} + +class SetPeriod extends EffectPeriodEvent { + final String period; + + const SetPeriod(this.period); + + @override + List get props => [period]; +} + +class ToggleDay extends EffectPeriodEvent { + final String day; + + const ToggleDay(this.day); + + @override + List get props => [day]; +} + +class SetCustomTime extends EffectPeriodEvent { + final String startTime; + final String endTime; + + const SetCustomTime(this.startTime, this.endTime); + + @override + List get props => [startTime, endTime]; +} diff --git a/lib/features/scene/bloc/effective_period/effect_period_state.dart b/lib/features/scene/bloc/effective_period/effect_period_state.dart new file mode 100644 index 0000000..67c3424 --- /dev/null +++ b/lib/features/scene/bloc/effective_period/effect_period_state.dart @@ -0,0 +1,42 @@ +import 'package:equatable/equatable.dart'; + +class EffectPeriodState extends Equatable { + final String selectedPeriod; + final List selectedDays; + final String? customStartTime; + final String? customEndTime; + + const EffectPeriodState({ + required this.selectedPeriod, + required this.selectedDays, + this.customStartTime, + this.customEndTime, + }); + + factory EffectPeriodState.initial() { + return const EffectPeriodState( + selectedPeriod: 'All Day', + selectedDays: [], + customStartTime: null, + customEndTime: null, + ); + } + + EffectPeriodState copyWith({ + String? selectedPeriod, + List? selectedDays, + String? customStartTime, + String? customEndTime, + }) { + return EffectPeriodState( + selectedPeriod: selectedPeriod ?? this.selectedPeriod, + selectedDays: selectedDays ?? this.selectedDays, + customStartTime: customStartTime ?? this.customStartTime, + customEndTime: customEndTime ?? this.customEndTime, + ); + } + + @override + List get props => + [selectedPeriod, selectedDays, customStartTime, customEndTime]; +} diff --git a/lib/features/scene/view/scene_auto_settings.dart b/lib/features/scene/view/scene_auto_settings.dart new file mode 100644 index 0000000..cfffe92 --- /dev/null +++ b/lib/features/scene/view/scene_auto_settings.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart'; +import 'package:syncrow_app/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; +import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; + +class SceneAutoSettings extends StatelessWidget { + const SceneAutoSettings({super.key}); + + @override + Widget build(BuildContext context) { + final sceneSettings = + ModalRoute.of(context)!.settings.arguments as Map? ?? + {}; + final sceneId = sceneSettings['sceneId'] as String? ?? ''; + final isAutomation = sceneSettings['isAutomation'] as bool? ?? false; + final sceneName = sceneSettings['sceneName'] as String? ?? ''; + + return Scaffold( + backgroundColor: ColorsManager.backgroundColor, + appBar: AppBar( + centerTitle: true, + backgroundColor: ColorsManager.backgroundColor, + title: const BodyLarge( + text: "Settings", + fontColor: ColorsManager.secondaryColor, + fontWeight: FontsManager.bold, + ), + ), + body: DefaultContainer( + padding: EdgeInsets.zero, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SceneListTile( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + titleString: "Effective Period", + trailingWidget: const Icon(Icons.arrow_forward_ios_rounded), + onPressed: () { + context.customBottomSheet( + child: const EffectPeriodBottomSheetContent(), + ); + }, + ), + Visibility( + visible: sceneName.isNotEmpty, + child: DeleteBottomSheetContent( + isAutomation: isAutomation, + sceneId: sceneId, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/features/scene/view/scene_tasks_view.dart b/lib/features/scene/view/scene_tasks_view.dart index 86863c4..22371b4 100644 --- a/lib/features/scene/view/scene_tasks_view.dart +++ b/lib/features/scene/view/scene_tasks_view.dart @@ -40,15 +40,17 @@ class SceneTasksView extends StatelessWidget { SizedBox( width: 40, child: GestureDetector( - onTap: sceneSettings.sceneName.isEmpty - ? null - : () { - context.customBottomSheet( - child: DeleteBottomSheetContent( - sceneId: sceneSettings.sceneId, - isAutomation: isAutomation), - ); - }, + onTap: () { + Navigator.pushNamed( + context, + Routes.sceneAutoSettingsRoute, + arguments: { + "sceneId": sceneSettings.sceneId, + "isAutomation": isAutomation, + "sceneName": sceneSettings.sceneName, + }, + ); + }, child: SvgPicture.asset( Assets.assetsIconsSettings, colorFilter: const ColorFilter.mode( @@ -109,48 +111,43 @@ class DeleteBottomSheetContent extends StatelessWidget { @override Widget build(BuildContext context) { return DefaultContainer( - height: context.height * 0.2, - child: ListView( - shrinkWrap: true, - children: [ - BlocConsumer( - listener: (context, state) { - if (state is DeleteSceneSuccess) { - if (state.success) { - navigateToRoute(context, Routes.homeRoute); - BlocProvider.of(context).add( - LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)); - BlocProvider.of(context).add(LoadAutomation( - HomeCubit.getInstance().selectedSpace!.id!)); - } - } - }, - builder: (context, state) { - return DefaultContainer( - onTap: () { - context.read().add(DeleteSceneEvent( - sceneId: sceneId, - unitUuid: - HomeCubit.getInstance().selectedSpace!.id!, - )); - }, - child: SceneListTile( - titleString: isAutomation - ? StringsManager.deleteAutomation - : StringsManager.deleteScene, - leadingWidget: (state is DeleteSceneLoading) - ? const SizedBox( - height: 24, - width: 24, - child: CircularProgressIndicator()) - : SvgPicture.asset( - Assets.assetsDeleteIcon, - color: ColorsManager.red, - ), - )); - }, - ), - ], + padding: EdgeInsets.zero, + child: BlocConsumer( + listener: (context, state) { + if (state is DeleteSceneSuccess) { + if (state.success) { + navigateToRoute(context, Routes.homeRoute); + BlocProvider.of(context).add( + LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)); + BlocProvider.of(context).add( + LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!)); + } + } + }, + builder: (context, state) { + return DefaultContainer( + onTap: () { + context.read().add(DeleteSceneEvent( + sceneId: sceneId, + unitUuid: HomeCubit.getInstance().selectedSpace!.id!, + )); + }, + child: SceneListTile( + padding: const EdgeInsets.symmetric(horizontal: 8), + titleString: isAutomation + ? StringsManager.deleteAutomation + : StringsManager.deleteScene, + leadingWidget: (state is DeleteSceneLoading) + ? const SizedBox( + height: 24, + width: 24, + child: CircularProgressIndicator()) + : SvgPicture.asset( + Assets.assetsDeleteIcon, + color: ColorsManager.red, + ), + )); + }, )); } } diff --git a/lib/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart b/lib/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart new file mode 100644 index 0000000..c4c74e0 --- /dev/null +++ b/lib/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart @@ -0,0 +1,314 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; +import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; +import 'package:time_picker_spinner/time_picker_spinner.dart'; + +class EffectPeriodBottomSheetContent extends StatefulWidget { + const EffectPeriodBottomSheetContent({super.key}); + + @override + State createState() => + _EffectPeriodBottomSheetContentState(); +} + +class _EffectPeriodBottomSheetContentState + extends State { + Future?> showCustomTimePicker(BuildContext context) async { + String selectedStartTime = "00:00"; + String selectedEndTime = "23:59"; + PageController pageController = PageController(initialPage: 0); + + DateTime startDateTime = DateTime(2022, 1, 1, 0, 0); // Fixed 00:00 + DateTime endDateTime = DateTime(2022, 1, 1, 23, 59); // Fixed 23:59 + + context.customAlertDialog( + alertBody: SizedBox( + height: 250, + child: PageView( + controller: pageController, + physics: const NeverScrollableScrollPhysics(), + children: [ + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () {}, + child: BodyMedium( + text: "Start", + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColor, + ), + ), + ), + TextButton( + onPressed: () { + pageController.nextPage( + duration: const Duration(milliseconds: 300), + curve: Curves.easeIn, + ); + }, + child: const BodyMedium( + text: "End", + ), + ), + ], + ), + ), + TimePickerSpinner( + is24HourMode: false, + normalTextStyle: const TextStyle( + fontSize: 24, + color: Colors.grey, + ), + highlightedTextStyle: const TextStyle( + fontSize: 24, + color: ColorsManager.primaryColor, + ), + spacing: 20, + itemHeight: 50, + isForce2Digits: true, + time: startDateTime, + onTimeChange: (time) { + selectedStartTime = + "${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"; + }, + ), + const SizedBox(height: 16), + ], + ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () { + pageController.previousPage( + duration: const Duration(milliseconds: 300), + curve: Curves.easeIn, + ); + }, + child: const BodyMedium(text: "Start"), + ), + TextButton( + onPressed: () {}, + child: BodyMedium( + text: "End", + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColor, + ), + ), + ), + ], + ), + ), + TimePickerSpinner( + is24HourMode: false, + normalTextStyle: const TextStyle( + fontSize: 24, + color: Colors.grey, + ), + highlightedTextStyle: const TextStyle( + fontSize: 24, + color: ColorsManager.primaryColor, + ), + spacing: 20, + itemHeight: 50, + isForce2Digits: true, + time: endDateTime, + onTimeChange: (time) { + selectedEndTime = + "${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"; + }, + ), + const SizedBox(height: 16), + ], + ), + ], + ), + ), + title: "Custom", + onConfirm: () { + context.read().add( + SetCustomTime(selectedStartTime, selectedEndTime), + ); + context.read().add( + const SetPeriod('Custom'), + ); + + Navigator.of(context).pop(); + }, + ); + return null; + } + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => EffectPeriodBloc(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + BodyMedium( + text: 'Effective Period', + fontColor: ColorsManager.primaryColorWithOpacity, + fontWeight: FontsManager.bold, + ), + const Divider( + color: ColorsManager.backgroundColor, + ), + _buildPeriodOptions(context), + const SizedBox(height: 16), + _buildRepeatDays(context), + const SizedBox(height: 24), + ], + ), + ), + ); + } + + Widget _buildPeriodOptions(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Column( + children: [ + _buildRadioOption(context, 'All Day', '24 Hours'), + _buildRadioOption(context, 'Daytime', 'Sunrise to Sunset'), + _buildRadioOption(context, 'Night', 'Sunset to Sunrise'), + ListTile( + contentPadding: EdgeInsets.zero, + onTap: () => showCustomTimePicker(context), + title: BodyMedium( + text: 'Custom', + fontColor: ColorsManager.primaryColorWithOpacity, + ), + subtitle: + state.customStartTime != null && state.customEndTime != null + ? BodySmall( + text: + '${"${state.customStartTime} AM"} - ${"${state.customEndTime} PM"}', + style: context.bodySmall.copyWith(fontSize: 10), + ) + : BodySmall( + text: '00:00 AM - 11:59 PM', + style: context.bodySmall.copyWith(fontSize: 10), + ), + trailing: Radio( + value: 'Custom', + groupValue: state.selectedPeriod, + onChanged: (value) async {}, + ), + ), + ], + ); + }, + ); + } + + Widget _buildRadioOption( + BuildContext context, String value, String subtitle) { + return BlocBuilder( + builder: (context, state) { + return ListTile( + contentPadding: EdgeInsets.zero, + onTap: () { + context.read().add(SetPeriod(value)); + }, + title: BodyMedium(text: value), + subtitle: BodySmall( + text: subtitle, + style: context.bodySmall.copyWith(fontSize: 10), + ), + trailing: Radio( + value: value, + groupValue: state.selectedPeriod, + onChanged: (value) { + if (value != null) { + context.read().add(SetPeriod(value)); + } + }, + ), + ); + }, + ); + } + + Widget _buildRepeatDays(BuildContext context) { + final daysMap = { + 'Mon': 'M', + 'Tue': 'T', + 'Wed': 'W', + 'Thu': 'T', + 'Fri': 'F', + 'Sat': 'S', + 'Sun': 'S', + }; + + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const BodyMedium(text: 'Repeat'), + const SizedBox(width: 8), + BlocBuilder( + builder: (context, state) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: daysMap.entries.map((entry) { + final day = entry.key; + final abbreviation = entry.value; + final isSelected = state.selectedDays.contains(day); + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 3.0), + child: GestureDetector( + onTap: () { + context.read().add(ToggleDay(day)); + }, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: + isSelected ? Colors.grey : Colors.grey.shade300, + width: 1, + ), + ), + child: CircleAvatar( + radius: 15, + backgroundColor: Colors.white, + child: Text( + abbreviation, + style: TextStyle( + fontSize: 20, + color: + isSelected ? Colors.grey : Colors.grey.shade300, + ), + ), + ), + ), + ), + ); + }).toList(), + ); + }, + ), + ], + ); + } +} diff --git a/lib/navigation/router.dart b/lib/navigation/router.dart index 1baf285..8bc2839 100644 --- a/lib/navigation/router.dart +++ b/lib/navigation/router.dart @@ -14,6 +14,7 @@ import 'package:syncrow_app/features/menu/view/widgets/profile/profile_view.dart import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart'; import 'package:syncrow_app/features/scene/view/device_functions_view.dart'; +import 'package:syncrow_app/features/scene/view/scene_auto_settings.dart'; import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart'; import 'package:syncrow_app/features/scene/view/scene_rooms_tabbar.dart'; import 'package:syncrow_app/features/scene/view/scene_view.dart'; @@ -95,6 +96,11 @@ class Router { builder: (_) => DeviceFunctionsView(), settings: settings, ); + case Routes.sceneAutoSettingsRoute: + return MaterialPageRoute( + builder: (_) => const SceneAutoSettings(), + settings: settings, + ); default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/navigation/routing_constants.dart b/lib/navigation/routing_constants.dart index 86826ca..1d2d363 100644 --- a/lib/navigation/routing_constants.dart +++ b/lib/navigation/routing_constants.dart @@ -19,6 +19,7 @@ class Routes { static const String createUnit = '/create-unit'; static const String sceneTasksRoute = '/scene-tasks'; static const String sceneControlDevicesRoute = '/scene-control-devices'; -static const String deviceFunctionsRoute = '/device-functions'; - + static const String deviceFunctionsRoute = '/device-functions'; + static const String sceneAutoSettingsRoute = + '/scene-automation-settings'; } From b3b34eb4cee714267aadc4ea490e51a97b2bca27 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sat, 27 Jul 2024 22:45:59 +0300 Subject: [PATCH 20/30] refactor effective period dialog --- .../scene/helper/effect_period_helper.dart | 132 ++++++++ .../scene/view/scene_auto_settings.dart | 2 +- .../effective_period_bottom_sheet.dart | 314 ------------------ .../effective_period_bottom_sheet.dart | 43 +++ .../period_options.dart | 85 +++++ .../effective_period_setting/repeat_days.dart | 73 ++++ 6 files changed, 334 insertions(+), 315 deletions(-) create mode 100644 lib/features/scene/helper/effect_period_helper.dart delete mode 100644 lib/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart create mode 100644 lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart create mode 100644 lib/features/scene/widgets/effective_period_setting/period_options.dart create mode 100644 lib/features/scene/widgets/effective_period_setting/repeat_days.dart diff --git a/lib/features/scene/helper/effect_period_helper.dart b/lib/features/scene/helper/effect_period_helper.dart new file mode 100644 index 0000000..94499ea --- /dev/null +++ b/lib/features/scene/helper/effect_period_helper.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.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'; +import 'package:time_picker_spinner/time_picker_spinner.dart'; + +class EffectPeriodHelper { + static Future?> showCustomTimePicker( + BuildContext context) async { + String selectedStartTime = "00:00"; + String selectedEndTime = "23:59"; + PageController pageController = PageController(initialPage: 0); + + DateTime startDateTime = DateTime(2022, 1, 1, 0, 0); // Fixed 00:00 + DateTime endDateTime = DateTime(2022, 1, 1, 23, 59); // Fixed 23:59 + + context.customAlertDialog( + alertBody: SizedBox( + height: 250, + child: PageView( + controller: pageController, + physics: const NeverScrollableScrollPhysics(), + children: [ + _buildTimePickerPage( + context: context, + pageController: pageController, + isStartTime: true, + time: startDateTime, + onTimeChange: (time) { + selectedStartTime = + "${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"; + }, + ), + _buildTimePickerPage( + context: context, + pageController: pageController, + isStartTime: false, + time: endDateTime, + onTimeChange: (time) { + selectedEndTime = + "${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"; + }, + ), + ], + ), + ), + title: "Custom", + onConfirm: () { + context.read().add( + SetCustomTime(selectedStartTime, selectedEndTime), + ); + context.read().add( + const SetPeriod('Custom'), + ); + + Navigator.of(context).pop(); + }, + ); + return null; + } + + static Widget _buildTimePickerPage({ + required BuildContext context, + required PageController pageController, + required bool isStartTime, + required DateTime time, + required Function(DateTime) onTimeChange, + }) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (!isStartTime) + TextButton( + onPressed: () { + pageController.previousPage( + duration: const Duration(milliseconds: 300), + curve: Curves.easeIn, + ); + }, + child: const BodyMedium(text: "Start"), + ), + TextButton( + onPressed: () {}, + child: BodyMedium( + text: isStartTime ? "Start" : "End", + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColor, + ), + ), + ), + if (isStartTime) + TextButton( + onPressed: () { + pageController.nextPage( + duration: const Duration(milliseconds: 300), + curve: Curves.easeIn, + ); + }, + child: const BodyMedium(text: "End"), + ), + ], + ), + ), + TimePickerSpinner( + is24HourMode: false, + normalTextStyle: const TextStyle( + fontSize: 24, + color: Colors.grey, + ), + highlightedTextStyle: const TextStyle( + fontSize: 24, + color: ColorsManager.primaryColor, + ), + spacing: 20, + itemHeight: 50, + isForce2Digits: true, + time: time, + onTimeChange: onTimeChange, + ), + const SizedBox(height: 16), + ], + ); + } +} diff --git a/lib/features/scene/view/scene_auto_settings.dart b/lib/features/scene/view/scene_auto_settings.dart index cfffe92..9e117ac 100644 --- a/lib/features/scene/view/scene_auto_settings.dart +++ b/lib/features/scene/view/scene_auto_settings.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart'; -import 'package:syncrow_app/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart'; +import 'package:syncrow_app/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; diff --git a/lib/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart b/lib/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart deleted file mode 100644 index c4c74e0..0000000 --- a/lib/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart +++ /dev/null @@ -1,314 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; -import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart'; -import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; -import 'package:syncrow_app/utils/context_extension.dart'; -import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; -import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; -import 'package:time_picker_spinner/time_picker_spinner.dart'; - -class EffectPeriodBottomSheetContent extends StatefulWidget { - const EffectPeriodBottomSheetContent({super.key}); - - @override - State createState() => - _EffectPeriodBottomSheetContentState(); -} - -class _EffectPeriodBottomSheetContentState - extends State { - Future?> showCustomTimePicker(BuildContext context) async { - String selectedStartTime = "00:00"; - String selectedEndTime = "23:59"; - PageController pageController = PageController(initialPage: 0); - - DateTime startDateTime = DateTime(2022, 1, 1, 0, 0); // Fixed 00:00 - DateTime endDateTime = DateTime(2022, 1, 1, 23, 59); // Fixed 23:59 - - context.customAlertDialog( - alertBody: SizedBox( - height: 250, - child: PageView( - controller: pageController, - physics: const NeverScrollableScrollPhysics(), - children: [ - Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: () {}, - child: BodyMedium( - text: "Start", - style: context.bodyMedium.copyWith( - color: ColorsManager.primaryColor, - ), - ), - ), - TextButton( - onPressed: () { - pageController.nextPage( - duration: const Duration(milliseconds: 300), - curve: Curves.easeIn, - ); - }, - child: const BodyMedium( - text: "End", - ), - ), - ], - ), - ), - TimePickerSpinner( - is24HourMode: false, - normalTextStyle: const TextStyle( - fontSize: 24, - color: Colors.grey, - ), - highlightedTextStyle: const TextStyle( - fontSize: 24, - color: ColorsManager.primaryColor, - ), - spacing: 20, - itemHeight: 50, - isForce2Digits: true, - time: startDateTime, - onTimeChange: (time) { - selectedStartTime = - "${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"; - }, - ), - const SizedBox(height: 16), - ], - ), - Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: () { - pageController.previousPage( - duration: const Duration(milliseconds: 300), - curve: Curves.easeIn, - ); - }, - child: const BodyMedium(text: "Start"), - ), - TextButton( - onPressed: () {}, - child: BodyMedium( - text: "End", - style: context.bodyMedium.copyWith( - color: ColorsManager.primaryColor, - ), - ), - ), - ], - ), - ), - TimePickerSpinner( - is24HourMode: false, - normalTextStyle: const TextStyle( - fontSize: 24, - color: Colors.grey, - ), - highlightedTextStyle: const TextStyle( - fontSize: 24, - color: ColorsManager.primaryColor, - ), - spacing: 20, - itemHeight: 50, - isForce2Digits: true, - time: endDateTime, - onTimeChange: (time) { - selectedEndTime = - "${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"; - }, - ), - const SizedBox(height: 16), - ], - ), - ], - ), - ), - title: "Custom", - onConfirm: () { - context.read().add( - SetCustomTime(selectedStartTime, selectedEndTime), - ); - context.read().add( - const SetPeriod('Custom'), - ); - - Navigator.of(context).pop(); - }, - ); - return null; - } - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => EffectPeriodBloc(), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - BodyMedium( - text: 'Effective Period', - fontColor: ColorsManager.primaryColorWithOpacity, - fontWeight: FontsManager.bold, - ), - const Divider( - color: ColorsManager.backgroundColor, - ), - _buildPeriodOptions(context), - const SizedBox(height: 16), - _buildRepeatDays(context), - const SizedBox(height: 24), - ], - ), - ), - ); - } - - Widget _buildPeriodOptions(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return Column( - children: [ - _buildRadioOption(context, 'All Day', '24 Hours'), - _buildRadioOption(context, 'Daytime', 'Sunrise to Sunset'), - _buildRadioOption(context, 'Night', 'Sunset to Sunrise'), - ListTile( - contentPadding: EdgeInsets.zero, - onTap: () => showCustomTimePicker(context), - title: BodyMedium( - text: 'Custom', - fontColor: ColorsManager.primaryColorWithOpacity, - ), - subtitle: - state.customStartTime != null && state.customEndTime != null - ? BodySmall( - text: - '${"${state.customStartTime} AM"} - ${"${state.customEndTime} PM"}', - style: context.bodySmall.copyWith(fontSize: 10), - ) - : BodySmall( - text: '00:00 AM - 11:59 PM', - style: context.bodySmall.copyWith(fontSize: 10), - ), - trailing: Radio( - value: 'Custom', - groupValue: state.selectedPeriod, - onChanged: (value) async {}, - ), - ), - ], - ); - }, - ); - } - - Widget _buildRadioOption( - BuildContext context, String value, String subtitle) { - return BlocBuilder( - builder: (context, state) { - return ListTile( - contentPadding: EdgeInsets.zero, - onTap: () { - context.read().add(SetPeriod(value)); - }, - title: BodyMedium(text: value), - subtitle: BodySmall( - text: subtitle, - style: context.bodySmall.copyWith(fontSize: 10), - ), - trailing: Radio( - value: value, - groupValue: state.selectedPeriod, - onChanged: (value) { - if (value != null) { - context.read().add(SetPeriod(value)); - } - }, - ), - ); - }, - ); - } - - Widget _buildRepeatDays(BuildContext context) { - final daysMap = { - 'Mon': 'M', - 'Tue': 'T', - 'Wed': 'W', - 'Thu': 'T', - 'Fri': 'F', - 'Sat': 'S', - 'Sun': 'S', - }; - - return Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const BodyMedium(text: 'Repeat'), - const SizedBox(width: 8), - BlocBuilder( - builder: (context, state) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: daysMap.entries.map((entry) { - final day = entry.key; - final abbreviation = entry.value; - final isSelected = state.selectedDays.contains(day); - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 3.0), - child: GestureDetector( - onTap: () { - context.read().add(ToggleDay(day)); - }, - child: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - isSelected ? Colors.grey : Colors.grey.shade300, - width: 1, - ), - ), - child: CircleAvatar( - radius: 15, - backgroundColor: Colors.white, - child: Text( - abbreviation, - style: TextStyle( - fontSize: 20, - color: - isSelected ? Colors.grey : Colors.grey.shade300, - ), - ), - ), - ), - ), - ); - }).toList(), - ); - }, - ), - ], - ); - } -} diff --git a/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart b/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart new file mode 100644 index 0000000..747e028 --- /dev/null +++ b/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; +import 'package:syncrow_app/features/scene/widgets/effective_period_setting/period_options.dart'; +import 'package:syncrow_app/features/scene/widgets/effective_period_setting/repeat_days.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; +import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; + +import '../../helper/effect_period_helper.dart'; + +class EffectPeriodBottomSheetContent extends StatelessWidget { + const EffectPeriodBottomSheetContent({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => EffectPeriodBloc(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + BodyMedium( + text: 'Effective Period', + fontColor: ColorsManager.primaryColorWithOpacity, + fontWeight: FontsManager.bold, + ), + const Divider( + color: ColorsManager.backgroundColor, + ), + const PeriodOptions( + showCustomTimePicker: EffectPeriodHelper.showCustomTimePicker, + ), + const SizedBox(height: 16), + const RepeatDays(), + const SizedBox(height: 24), + ], + ), + ), + ); + } +} diff --git a/lib/features/scene/widgets/effective_period_setting/period_options.dart b/lib/features/scene/widgets/effective_period_setting/period_options.dart new file mode 100644 index 0000000..c1d36a5 --- /dev/null +++ b/lib/features/scene/widgets/effective_period_setting/period_options.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; + +class PeriodOptions extends StatelessWidget { + final Future?> Function(BuildContext) showCustomTimePicker; + + const PeriodOptions({ + required this.showCustomTimePicker, + super.key, + }); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Column( + children: [ + _buildRadioOption(context, 'All Day', '24 Hours'), + _buildRadioOption(context, 'Daytime', 'Sunrise to Sunset'), + _buildRadioOption(context, 'Night', 'Sunset to Sunrise'), + ListTile( + contentPadding: EdgeInsets.zero, + onTap: () => showCustomTimePicker(context), + title: BodyMedium( + text: 'Custom', + fontColor: ColorsManager.primaryColorWithOpacity, + ), + subtitle: + state.customStartTime != null && state.customEndTime != null + ? BodySmall( + text: + '${"${state.customStartTime} AM"} - ${"${state.customEndTime} PM"}', + style: context.bodySmall.copyWith(fontSize: 10), + ) + : BodySmall( + text: '00:00 AM - 11:59 PM', + style: context.bodySmall.copyWith(fontSize: 10), + ), + trailing: Radio( + value: 'Custom', + groupValue: state.selectedPeriod, + onChanged: (value) async {}, + ), + ), + ], + ); + }, + ); + } + + Widget _buildRadioOption( + BuildContext context, String value, String subtitle) { + return BlocBuilder( + builder: (context, state) { + return ListTile( + contentPadding: EdgeInsets.zero, + onTap: () { + context.read().add(SetPeriod(value)); + }, + title: BodyMedium(text: value), + subtitle: BodySmall( + text: subtitle, + style: context.bodySmall.copyWith(fontSize: 10), + ), + trailing: Radio( + value: value, + groupValue: state.selectedPeriod, + onChanged: (value) { + if (value != null) { + context.read().add(SetPeriod(value)); + } + }, + ), + ); + }, + ); + } +} diff --git a/lib/features/scene/widgets/effective_period_setting/repeat_days.dart b/lib/features/scene/widgets/effective_period_setting/repeat_days.dart new file mode 100644 index 0000000..d07e589 --- /dev/null +++ b/lib/features/scene/widgets/effective_period_setting/repeat_days.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; + +class RepeatDays extends StatelessWidget { + const RepeatDays({super.key}); + + @override + Widget build(BuildContext context) { + final daysMap = { + 'Mon': 'M', + 'Tue': 'T', + 'Wed': 'W', + 'Thu': 'T', + 'Fri': 'F', + 'Sat': 'S', + 'Sun': 'S', + }; + + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const BodyMedium(text: 'Repeat'), + const SizedBox(width: 8), + BlocBuilder( + builder: (context, state) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: daysMap.entries.map((entry) { + final day = entry.key; + final abbreviation = entry.value; + final isSelected = state.selectedDays.contains(day); + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 3.0), + child: GestureDetector( + onTap: () { + context.read().add(ToggleDay(day)); + }, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: + isSelected ? Colors.grey : Colors.grey.shade300, + width: 1, + ), + ), + child: CircleAvatar( + radius: 15, + backgroundColor: Colors.white, + child: Text( + abbreviation, + style: TextStyle( + fontSize: 16, + color: + isSelected ? Colors.grey : Colors.grey.shade300, + ), + ), + ), + ), + ), + ); + }).toList(), + ); + }, + ), + ], + ); + } +} From 8a1c583bffefdfaf3d6d7233a5ff0420ab423679 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sat, 27 Jul 2024 23:05:56 +0300 Subject: [PATCH 21/30] change string value to enum --- .../effective_period/effect_period_event.dart | 3 +- .../effective_period/effect_period_state.dart | 7 +++-- .../scene/enum/effective_period_options.dart | 7 +++++ .../scene/helper/effect_period_helper.dart | 24 ++++++++++++-- .../period_options.dart | 31 ++++++++++++------- 5 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 lib/features/scene/enum/effective_period_options.dart diff --git a/lib/features/scene/bloc/effective_period/effect_period_event.dart b/lib/features/scene/bloc/effective_period/effect_period_event.dart index 12ac37e..809bf82 100644 --- a/lib/features/scene/bloc/effective_period/effect_period_event.dart +++ b/lib/features/scene/bloc/effective_period/effect_period_event.dart @@ -1,4 +1,5 @@ import 'package:equatable/equatable.dart'; +import 'package:syncrow_app/features/scene/enum/effective_period_options.dart'; abstract class EffectPeriodEvent extends Equatable { const EffectPeriodEvent(); @@ -8,7 +9,7 @@ abstract class EffectPeriodEvent extends Equatable { } class SetPeriod extends EffectPeriodEvent { - final String period; + final EnumEffectivePeriodOptions period; const SetPeriod(this.period); diff --git a/lib/features/scene/bloc/effective_period/effect_period_state.dart b/lib/features/scene/bloc/effective_period/effect_period_state.dart index 67c3424..53d6a11 100644 --- a/lib/features/scene/bloc/effective_period/effect_period_state.dart +++ b/lib/features/scene/bloc/effective_period/effect_period_state.dart @@ -1,7 +1,8 @@ import 'package:equatable/equatable.dart'; +import 'package:syncrow_app/features/scene/enum/effective_period_options.dart'; class EffectPeriodState extends Equatable { - final String selectedPeriod; + final EnumEffectivePeriodOptions selectedPeriod; final List selectedDays; final String? customStartTime; final String? customEndTime; @@ -15,7 +16,7 @@ class EffectPeriodState extends Equatable { factory EffectPeriodState.initial() { return const EffectPeriodState( - selectedPeriod: 'All Day', + selectedPeriod: EnumEffectivePeriodOptions.allDay, selectedDays: [], customStartTime: null, customEndTime: null, @@ -23,7 +24,7 @@ class EffectPeriodState extends Equatable { } EffectPeriodState copyWith({ - String? selectedPeriod, + EnumEffectivePeriodOptions? selectedPeriod, List? selectedDays, String? customStartTime, String? customEndTime, diff --git a/lib/features/scene/enum/effective_period_options.dart b/lib/features/scene/enum/effective_period_options.dart new file mode 100644 index 0000000..97877b6 --- /dev/null +++ b/lib/features/scene/enum/effective_period_options.dart @@ -0,0 +1,7 @@ +enum EnumEffectivePeriodOptions { + allDay, + daytime, + night, + custom, + none, +} diff --git a/lib/features/scene/helper/effect_period_helper.dart b/lib/features/scene/helper/effect_period_helper.dart index 94499ea..2b54fa8 100644 --- a/lib/features/scene/helper/effect_period_helper.dart +++ b/lib/features/scene/helper/effect_period_helper.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; +import 'package:syncrow_app/features/scene/enum/effective_period_options.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'; @@ -14,8 +15,8 @@ class EffectPeriodHelper { String selectedEndTime = "23:59"; PageController pageController = PageController(initialPage: 0); - DateTime startDateTime = DateTime(2022, 1, 1, 0, 0); // Fixed 00:00 - DateTime endDateTime = DateTime(2022, 1, 1, 23, 59); // Fixed 23:59 + DateTime startDateTime = DateTime(2022, 1, 1, 0, 0); + DateTime endDateTime = DateTime(2022, 1, 1, 23, 59); context.customAlertDialog( alertBody: SizedBox( @@ -53,7 +54,7 @@ class EffectPeriodHelper { SetCustomTime(selectedStartTime, selectedEndTime), ); context.read().add( - const SetPeriod('Custom'), + const SetPeriod(EnumEffectivePeriodOptions.custom), ); Navigator.of(context).pop(); @@ -129,4 +130,21 @@ class EffectPeriodHelper { ], ); } + + static String formatEnumValue(EnumEffectivePeriodOptions value) { + switch (value) { + case EnumEffectivePeriodOptions.allDay: + return "All Day"; + case EnumEffectivePeriodOptions.daytime: + return "Daytime"; + case EnumEffectivePeriodOptions.night: + return "Night"; + case EnumEffectivePeriodOptions.custom: + return "Custom"; + case EnumEffectivePeriodOptions.none: + return "None"; + default: + return ""; + } +} } diff --git a/lib/features/scene/widgets/effective_period_setting/period_options.dart b/lib/features/scene/widgets/effective_period_setting/period_options.dart index c1d36a5..cdc4088 100644 --- a/lib/features/scene/widgets/effective_period_setting/period_options.dart +++ b/lib/features/scene/widgets/effective_period_setting/period_options.dart @@ -3,8 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart'; +import 'package:syncrow_app/features/scene/enum/effective_period_options.dart'; +import 'package:syncrow_app/features/scene/helper/effect_period_helper.dart'; import 'package:syncrow_app/utils/context_extension.dart'; -import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; @@ -22,15 +23,17 @@ class PeriodOptions extends StatelessWidget { builder: (context, state) { return Column( children: [ - _buildRadioOption(context, 'All Day', '24 Hours'), - _buildRadioOption(context, 'Daytime', 'Sunrise to Sunset'), - _buildRadioOption(context, 'Night', 'Sunset to Sunrise'), + _buildRadioOption( + context, EnumEffectivePeriodOptions.allDay, '24 Hours'), + _buildRadioOption(context, EnumEffectivePeriodOptions.daytime, + 'Sunrise to Sunset'), + _buildRadioOption( + context, EnumEffectivePeriodOptions.night, 'Sunset to Sunrise'), ListTile( contentPadding: EdgeInsets.zero, onTap: () => showCustomTimePicker(context), - title: BodyMedium( + title: const BodyMedium( text: 'Custom', - fontColor: ColorsManager.primaryColorWithOpacity, ), subtitle: state.customStartTime != null && state.customEndTime != null @@ -43,10 +46,14 @@ class PeriodOptions extends StatelessWidget { text: '00:00 AM - 11:59 PM', style: context.bodySmall.copyWith(fontSize: 10), ), - trailing: Radio( - value: 'Custom', + trailing: Radio( + value: EnumEffectivePeriodOptions.custom, groupValue: state.selectedPeriod, - onChanged: (value) async {}, + onChanged: (value) async { + if (value != null) { + context.read().add(SetPeriod(value)); + } + }, ), ), ], @@ -56,7 +63,7 @@ class PeriodOptions extends StatelessWidget { } Widget _buildRadioOption( - BuildContext context, String value, String subtitle) { + BuildContext context, EnumEffectivePeriodOptions value, String subtitle) { return BlocBuilder( builder: (context, state) { return ListTile( @@ -64,12 +71,12 @@ class PeriodOptions extends StatelessWidget { onTap: () { context.read().add(SetPeriod(value)); }, - title: BodyMedium(text: value), + title: BodyMedium(text: EffectPeriodHelper.formatEnumValue(value)), subtitle: BodySmall( text: subtitle, style: context.bodySmall.copyWith(fontSize: 10), ), - trailing: Radio( + trailing: Radio( value: value, groupValue: state.selectedPeriod, onChanged: (value) { From 0bda8281618d792183749555d504de9c27791c11 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sun, 28 Jul 2024 00:11:19 +0300 Subject: [PATCH 22/30] finished time period --- .../bloc/create_scene/create_scene_bloc.dart | 7 ++ .../bloc/create_scene/create_scene_event.dart | 5 ++ .../effective_period/effect_period_bloc.dart | 66 +++++++++++++++++-- .../effective_period/effect_period_state.dart | 16 ++--- .../functions_per_device/presence_sensor.dart | 20 +++--- .../scene/helper/scene_logic_helper.dart | 2 +- .../alert_dialog_slider_steps.dart | 4 +- .../effective_period_setting/repeat_days.dart | 8 ++- 8 files changed, 101 insertions(+), 27 deletions(-) diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index bf519fa..0a19efb 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -30,6 +30,7 @@ class CreateSceneBloc extends Bloc on(_updateTaskValue); on(_selectConditionRule); on(_sceneTypeEvent); + on(_onEffectiveTimeEvent); } CreateSceneEnum sceneType = CreateSceneEnum.none; @@ -45,6 +46,7 @@ class CreateSceneBloc extends Bloc final Map automationSelectedValues = {}; final Map automationComparatorValues = {}; String conditionRule = 'or'; + EffectiveTime? effectiveTime; FutureOr _onAddSceneTask( AddTaskEvent event, Emitter emit) { @@ -511,4 +513,9 @@ class CreateSceneBloc extends Bloc emit(SceneTypeState(event.type)); } + + FutureOr _onEffectiveTimeEvent( + EffectiveTimePeriodEvent event, Emitter emit) { + effectiveTime = event.period; + } } diff --git a/lib/features/scene/bloc/create_scene/create_scene_event.dart b/lib/features/scene/bloc/create_scene/create_scene_event.dart index 28953fe..74046bd 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_event.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_event.dart @@ -178,3 +178,8 @@ class SceneTypeEvent extends CreateSceneEvent { final CreateSceneEnum type; const SceneTypeEvent(this.type); } + +class EffectiveTimePeriodEvent extends CreateSceneEvent { + final EffectiveTime period; + const EffectiveTimePeriodEvent(this.period); +} diff --git a/lib/features/scene/bloc/effective_period/effect_period_bloc.dart b/lib/features/scene/bloc/effective_period/effect_period_bloc.dart index 710b124..7fa071c 100644 --- a/lib/features/scene/bloc/effective_period/effect_period_bloc.dart +++ b/lib/features/scene/bloc/effective_period/effect_period_bloc.dart @@ -1,6 +1,11 @@ import 'package:bloc/bloc.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart'; +import 'package:syncrow_app/features/scene/enum/effective_period_options.dart'; +import 'package:syncrow_app/features/scene/model/create_automation_model.dart'; +import 'package:syncrow_app/navigation/navigation_service.dart'; class EffectPeriodBloc extends Bloc { EffectPeriodBloc() : super(EffectPeriodState.initial()) { @@ -10,21 +15,72 @@ class EffectPeriodBloc extends Bloc { } void _onSetPeriod(SetPeriod event, Emitter emit) { + String startTime = ''; + String endTime = ''; + + switch (event.period) { + case EnumEffectivePeriodOptions.allDay: + startTime = '00:00'; + endTime = '23:59'; + break; + case EnumEffectivePeriodOptions.daytime: + startTime = '06:00'; + endTime = '18:00'; + break; + case EnumEffectivePeriodOptions.night: + startTime = '18:00'; + endTime = '06:00'; + break; + case EnumEffectivePeriodOptions.custom: + startTime = state.customStartTime ?? '00:00'; + endTime = state.customEndTime ?? '23:59'; + break; + default: + break; + } + + // Update CreateSceneBloc + BlocProvider.of( + NavigationService.navigatorKey.currentState!.context) + .add(EffectiveTimePeriodEvent(EffectiveTime( + start: startTime, end: endTime, loops: state.selectedDaysBinary))); + emit(state.copyWith(selectedPeriod: event.period)); } void _onToggleDay(ToggleDay event, Emitter emit) { - final days = List.of(state.selectedDays); - if (days.contains(event.day)) { - days.remove(event.day); + final daysList = state.selectedDaysBinary.split(''); + final dayIndex = _getDayIndex(event.day); + if (daysList[dayIndex] == '1') { + daysList[dayIndex] = '0'; } else { - days.add(event.day); + daysList[dayIndex] = '1'; } - emit(state.copyWith(selectedDays: days)); + final newDaysBinary = daysList.join(); + emit(state.copyWith(selectedDaysBinary: newDaysBinary)); + + BlocProvider.of( + NavigationService.navigatorKey.currentState!.context) + .add(EffectiveTimePeriodEvent(EffectiveTime( + start: state.customStartTime ?? '00:00', + end: state.customEndTime ?? '23:59', + loops: newDaysBinary))); } void _onSetCustomTime(SetCustomTime event, Emitter emit) { emit(state.copyWith( customStartTime: event.startTime, customEndTime: event.endTime)); + + BlocProvider.of( + NavigationService.navigatorKey.currentState!.context) + .add(EffectiveTimePeriodEvent(EffectiveTime( + start: event.startTime, + end: event.endTime, + loops: state.selectedDaysBinary))); + } + + int _getDayIndex(String day) { + const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; + return days.indexOf(day); } } diff --git a/lib/features/scene/bloc/effective_period/effect_period_state.dart b/lib/features/scene/bloc/effective_period/effect_period_state.dart index 53d6a11..029652b 100644 --- a/lib/features/scene/bloc/effective_period/effect_period_state.dart +++ b/lib/features/scene/bloc/effective_period/effect_period_state.dart @@ -3,13 +3,13 @@ import 'package:syncrow_app/features/scene/enum/effective_period_options.dart'; class EffectPeriodState extends Equatable { final EnumEffectivePeriodOptions selectedPeriod; - final List selectedDays; + final String selectedDaysBinary; final String? customStartTime; final String? customEndTime; const EffectPeriodState({ required this.selectedPeriod, - required this.selectedDays, + required this.selectedDaysBinary, this.customStartTime, this.customEndTime, }); @@ -17,21 +17,21 @@ class EffectPeriodState extends Equatable { factory EffectPeriodState.initial() { return const EffectPeriodState( selectedPeriod: EnumEffectivePeriodOptions.allDay, - selectedDays: [], - customStartTime: null, - customEndTime: null, + selectedDaysBinary: "1111111", // All days selected + customStartTime: "00:00", + customEndTime: "23:59", ); } EffectPeriodState copyWith({ EnumEffectivePeriodOptions? selectedPeriod, - List? selectedDays, + String? selectedDaysBinary, String? customStartTime, String? customEndTime, }) { return EffectPeriodState( selectedPeriod: selectedPeriod ?? this.selectedPeriod, - selectedDays: selectedDays ?? this.selectedDays, + selectedDaysBinary: selectedDaysBinary ?? this.selectedDaysBinary, customStartTime: customStartTime ?? this.customStartTime, customEndTime: customEndTime ?? this.customEndTime, ); @@ -39,5 +39,5 @@ class EffectPeriodState extends Equatable { @override List get props => - [selectedPeriod, selectedDays, customStartTime, customEndTime]; + [selectedPeriod, selectedDaysBinary, customStartTime, customEndTime]; } diff --git a/lib/features/scene/helper/functions_per_device/presence_sensor.dart b/lib/features/scene/helper/functions_per_device/presence_sensor.dart index ee7aa54..25354e6 100644 --- a/lib/features/scene/helper/functions_per_device/presence_sensor.dart +++ b/lib/features/scene/helper/functions_per_device/presence_sensor.dart @@ -87,16 +87,16 @@ class PresenceSensorHelperFunctions { value: 'none', description: 'None', ), - SceneOperationalValue( - icon: Assets.assetsPresence, - value: 'presence', - description: 'Presence', - ), - SceneOperationalValue( - icon: Assets.assetsMotion, - value: 'motion', - description: 'Motion', - ), + // SceneOperationalValue( + // icon: Assets.assetsPresence, + // value: 'presence', + // description: 'Presence', + // ), + // SceneOperationalValue( + // icon: Assets.assetsMotion, + // value: 'motion', + // description: 'Motion', + // ), ], ), SceneStaticFunction( diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index d05ee24..5fbe39c 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -46,7 +46,7 @@ mixin SceneLogicHelper { unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '', automationName: sceneName.text, decisionExpr: sceneBloc.conditionRule, - effectiveTime: + effectiveTime: sceneBloc.effectiveTime ?? EffectiveTime(start: '00:00', end: '23:59', loops: '1111111'), conditions: List.generate( conditions.length, diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart index 3f1632b..a38c71b 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart @@ -60,8 +60,8 @@ class _AlertDialogSliderStepsState extends State { } double _normalizeValue(dynamic value) { - if (widget.taskItem.code == "temp_set" || - widget.taskItem.code == "temp_current") { + if (((widget.taskItem.code == "temp_set" && value > 200) || + widget.taskItem.code == "temp_current")) { return (value) / 10; } return value.toDouble(); diff --git a/lib/features/scene/widgets/effective_period_setting/repeat_days.dart b/lib/features/scene/widgets/effective_period_setting/repeat_days.dart index d07e589..9f40165 100644 --- a/lib/features/scene/widgets/effective_period_setting/repeat_days.dart +++ b/lib/features/scene/widgets/effective_period_setting/repeat_days.dart @@ -32,7 +32,8 @@ class RepeatDays extends StatelessWidget { children: daysMap.entries.map((entry) { final day = entry.key; final abbreviation = entry.value; - final isSelected = state.selectedDays.contains(day); + final dayIndex = _getDayIndex(day); + final isSelected = state.selectedDaysBinary[dayIndex] == '1'; return Padding( padding: const EdgeInsets.symmetric(horizontal: 3.0), child: GestureDetector( @@ -70,4 +71,9 @@ class RepeatDays extends StatelessWidget { ], ); } + + int _getDayIndex(String day) { + const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; + return days.indexOf(day); + } } From 50b455b4ae3ce8b0b7f62467cc1f5dc9097448ce Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sun, 28 Jul 2024 05:04:57 +0300 Subject: [PATCH 23/30] push dialog changes in values --- .../bloc/create_scene/create_scene_bloc.dart | 1 + .../smart_scene_select_dart_bloc.dart | 30 ++ .../smart_scene_select_dart_event.dart | 21 ++ .../smart_scene_select_dart_state.dart | 19 ++ .../scene/helper/scene_logic_helper.dart | 14 +- .../scene/model/create_scene_model.dart | 5 +- .../scene/model/smart_scene_enable.dart | 23 ++ .../scene/view/device_functions_view.dart | 44 ++- .../view/smart_automation_select_route.dart | 70 +++++ .../scene/widgets/bottom_sheet_widget.dart | 4 +- .../smart_automation_list.dart | 260 ++++++++++++++++++ .../smart_enable_autoamtion.dart | 39 +++ .../smart_enable_tab_run.dart | 36 +++ .../smart_tab_run_list.dart | 92 +++++++ .../shared_widgets/default_scaffold.dart | 7 +- lib/my_app.dart | 2 + lib/navigation/router.dart | 7 + lib/navigation/routing_constants.dart | 4 +- 18 files changed, 645 insertions(+), 33 deletions(-) create mode 100644 lib/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart create mode 100644 lib/features/scene/bloc/smart_scene/smart_scene_select_dart_event.dart create mode 100644 lib/features/scene/bloc/smart_scene/smart_scene_select_dart_state.dart create mode 100644 lib/features/scene/model/smart_scene_enable.dart create mode 100644 lib/features/scene/view/smart_automation_select_route.dart create mode 100644 lib/features/scene/widgets/select_smart_scene/smart_automation_list.dart create mode 100644 lib/features/scene/widgets/select_smart_scene/smart_enable_autoamtion.dart create mode 100644 lib/features/scene/widgets/select_smart_scene/smart_enable_tab_run.dart create mode 100644 lib/features/scene/widgets/select_smart_scene/smart_tab_run_list.dart diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index 0a19efb..60bfc17 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -315,6 +315,7 @@ class CreateSceneBloc extends Bloc automationTempTasksList.clear(); automationSelectedValues.clear(); automationComparatorValues.clear(); + effectiveTime = null; sceneType = CreateSceneEnum.none; conditionRule = 'or'; emit(const CreateSceneWithTasks(success: true)); diff --git a/lib/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart b/lib/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart new file mode 100644 index 0000000..daf9e75 --- /dev/null +++ b/lib/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart @@ -0,0 +1,30 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_app/features/scene/model/smart_scene_enable.dart'; + +part 'smart_scene_select_dart_event.dart'; +part 'smart_scene_select_dart_state.dart'; + +class SmartSceneSelectBloc + extends Bloc { + SmartSceneSelectBloc() : super(SmartSceneSelectInitial()) { + on(_onSmartSceneEnable); + on(_smartSceneClear); + } + + SmartSceneEnable? smartSceneEnable; + + FutureOr _onSmartSceneEnable( + SmartSceneEnableEvent event, Emitter emit) { + smartSceneEnable = event.smartSceneEnable; + emit(SmartSceneSelected(smartSceneEnable: smartSceneEnable!)); + } + + FutureOr _smartSceneClear( + SmartSceneClearEvent event, Emitter emit) { + smartSceneEnable = null; + emit(SmartSceneSelectInitial()); + } +} \ No newline at end of file diff --git a/lib/features/scene/bloc/smart_scene/smart_scene_select_dart_event.dart b/lib/features/scene/bloc/smart_scene/smart_scene_select_dart_event.dart new file mode 100644 index 0000000..ecdf30a --- /dev/null +++ b/lib/features/scene/bloc/smart_scene/smart_scene_select_dart_event.dart @@ -0,0 +1,21 @@ +part of 'smart_scene_select_dart_bloc.dart'; + +sealed class SmartSceneSelectEvent extends Equatable { + const SmartSceneSelectEvent(); + + @override + List get props => []; +} + +class SmartSceneEnableEvent extends SmartSceneSelectEvent { + final SmartSceneEnable smartSceneEnable; + + const SmartSceneEnableEvent(this.smartSceneEnable); + + @override + List get props => [smartSceneEnable]; +} + +class SmartSceneClearEvent extends SmartSceneSelectEvent { + const SmartSceneClearEvent(); +} diff --git a/lib/features/scene/bloc/smart_scene/smart_scene_select_dart_state.dart b/lib/features/scene/bloc/smart_scene/smart_scene_select_dart_state.dart new file mode 100644 index 0000000..d29b748 --- /dev/null +++ b/lib/features/scene/bloc/smart_scene/smart_scene_select_dart_state.dart @@ -0,0 +1,19 @@ +part of 'smart_scene_select_dart_bloc.dart'; + +sealed class SmartSceneSelectState extends Equatable { + const SmartSceneSelectState(); + + @override + List get props => []; +} + +final class SmartSceneSelectInitial extends SmartSceneSelectState {} + +class SmartSceneSelected extends SmartSceneSelectState { + final SmartSceneEnable smartSceneEnable; + + const SmartSceneSelected({required this.smartSceneEnable}); + + @override + List get props => [smartSceneEnable]; +} diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 5fbe39c..328e089 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -2,6 +2,7 @@ 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/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart'; import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; import 'package:syncrow_app/features/scene/model/create_automation_model.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; @@ -29,6 +30,7 @@ mixin SceneLogicHelper { required List conditions, }) { final sceneBloc = context.read(); + final smartSceneBloc = context.read(); if (isAutomation) { // Handle Automation Creation @@ -89,7 +91,11 @@ mixin SceneLogicHelper { ), ); }, - ), + )..add(CreateSceneAction( + entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '', + actionExecutor: + smartSceneBloc.smartSceneEnable?.actionExecutor ?? '', + executorProperty: null)), ); sceneBloc.add(CreateSceneWithTasksEvent( createSceneModel: null, @@ -140,7 +146,11 @@ mixin SceneLogicHelper { ), ); }, - ), + )..add(CreateSceneAction( + entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '', + actionExecutor: + smartSceneBloc.smartSceneEnable?.actionExecutor ?? '', + executorProperty: null)), ); sceneBloc.add(CreateSceneWithTasksEvent( createSceneModel: createSceneModel, diff --git a/lib/features/scene/model/create_scene_model.dart b/lib/features/scene/model/create_scene_model.dart index ca7919a..0d19345 100644 --- a/lib/features/scene/model/create_scene_model.dart +++ b/lib/features/scene/model/create_scene_model.dart @@ -81,7 +81,7 @@ class CreateSceneModel { class CreateSceneAction { String entityId; String actionExecutor; - CreateSceneExecutorProperty executorProperty; + CreateSceneExecutorProperty? executorProperty; CreateSceneAction({ required this.entityId, @@ -105,7 +105,8 @@ class CreateSceneAction { return { 'entityId': entityId, 'actionExecutor': actionExecutor, - 'executorProperty': executorProperty.toMap(actionExecutor), + if (executorProperty != null) + 'executorProperty': executorProperty?.toMap(actionExecutor), }; } diff --git a/lib/features/scene/model/smart_scene_enable.dart b/lib/features/scene/model/smart_scene_enable.dart new file mode 100644 index 0000000..c855925 --- /dev/null +++ b/lib/features/scene/model/smart_scene_enable.dart @@ -0,0 +1,23 @@ +class SmartSceneEnable { + final String entityId; + final String actionExecutor; + + SmartSceneEnable({ + required this.entityId, + required this.actionExecutor, + }); + + factory SmartSceneEnable.fromJson(Map json) { + return SmartSceneEnable( + entityId: json['entityId'], + actionExecutor: json['actionExecutor'], + ); + } + + Map toJson() { + return { + 'entityId': entityId, + 'actionExecutor': actionExecutor, + }; + } +} diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index ddb9090..bb9c48f 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -65,32 +65,28 @@ class DeviceFunctionsView extends StatelessWidget ], leading: TextButton( onPressed: () { - // if (isAutomation) { - final automationSelectedValue = - context.read().automationSelectedValues; - for (var element in device.functions) { - if (automationSelectedValue.containsKey(element.code)) { - context.read().add(RemoveTempTaskByIdEvent( - code: element.code!, isAutomation: true)); - context.read().add( - RemoveFromSelectedValueById( - code: element.code!, isAutomation: true)); - } + final automationSelectedValue = + context.read().automationSelectedValues; + for (var element in device.functions) { + if (automationSelectedValue.containsKey(element.code)) { + context.read().add(RemoveTempTaskByIdEvent( + code: element.code!, isAutomation: true)); + context.read().add(RemoveFromSelectedValueById( + code: element.code!, isAutomation: true)); } - // } else { - final selectedValue = - context.read().selectedValues; - for (var element in device.functions) { - if (selectedValue.containsKey(element.code)) { - context - .read() - .add(RemoveTempTaskByIdEvent(code: element.code!)); - context - .read() - .add(RemoveFromSelectedValueById(code: element.code!)); - } + } + final selectedValue = + context.read().selectedValues; + for (var element in device.functions) { + if (selectedValue.containsKey(element.code)) { + context + .read() + .add(RemoveTempTaskByIdEvent(code: element.code!)); + context + .read() + .add(RemoveFromSelectedValueById(code: element.code!)); } - // } + } Navigator.pop(context); }, diff --git a/lib/features/scene/view/smart_automation_select_route.dart b/lib/features/scene/view/smart_automation_select_route.dart new file mode 100644 index 0000000..6b059ef --- /dev/null +++ b/lib/features/scene/view/smart_automation_select_route.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; +import 'package:syncrow_app/features/scene/widgets/select_smart_scene/smart_enable_autoamtion.dart'; +import 'package:syncrow_app/features/scene/widgets/select_smart_scene/smart_enable_tab_run.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; +import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/navigation/navigate_to_route.dart'; +import 'package:syncrow_app/navigation/routing_constants.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class SmartAutomationSelectView extends StatelessWidget { + const SmartAutomationSelectView({super.key}); + + @override + Widget build(BuildContext context) { + return DefaultScaffold( + title: "Select Smart Scene", + padding: const EdgeInsets.only(top: 24), + leading: IconButton( + onPressed: () { + navigateToRoute(context, Routes.sceneTasksRoute); + }, + icon: const Icon( + Icons.arrow_back_ios, + )), + height: 260, + child: DefaultContainer( + width: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SceneListTile( + assetPath: Assets.handClickIcon, + titleString: "Tap To Run", + subtitleString: '', + trailingWidget: const Icon( + Icons.arrow_forward_ios_rounded, + color: ColorsManager.greyColor, + ), + onPressed: () { + context.customBottomSheet( + child: const SmartEnableTabRun(), + ); + }, + ), + const Divider( + color: ColorsManager.dividerColor, + ), + SceneListTile( + assetPath: Assets.refreshIcon, + titleString: "Automation", + subtitleString: '', + trailingWidget: const Icon( + Icons.arrow_forward_ios_rounded, + color: ColorsManager.greyColor, + ), + onPressed: () { + context.customBottomSheet( + child: const SmartEnableAutomation(), + ); + }, + ), + ], + ), + ), + ); + } +} diff --git a/lib/features/scene/widgets/bottom_sheet_widget.dart b/lib/features/scene/widgets/bottom_sheet_widget.dart index 0efea4d..518ef86 100644 --- a/lib/features/scene/widgets/bottom_sheet_widget.dart +++ b/lib/features/scene/widgets/bottom_sheet_widget.dart @@ -67,7 +67,9 @@ class CustomBottomSheetWidget extends StatelessWidget { size: 16, color: ColorsManager.greyColor, ), - onPressed: () {}, + onPressed: () { + Navigator.pushNamed(context, Routes.smartAutomationSelectRoute); + }, ), SceneListTile( assetPath: Assets.delay, diff --git a/lib/features/scene/widgets/select_smart_scene/smart_automation_list.dart b/lib/features/scene/widgets/select_smart_scene/smart_automation_list.dart new file mode 100644 index 0000000..962645f --- /dev/null +++ b/lib/features/scene/widgets/select_smart_scene/smart_automation_list.dart @@ -0,0 +1,260 @@ +import 'dart:math'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/features/scene/model/scenes_model.dart'; +import 'package:syncrow_app/features/scene/model/smart_scene_enable.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class SmartSceneSelectAutomationList extends StatefulWidget { + const SmartSceneSelectAutomationList({ + super.key, + required this.automationList, + }); + + final List automationList; + + @override + State createState() => + _SmartSceneSelectAutomationListState(); +} + +class _SmartSceneSelectAutomationListState + extends State { + final List colorList = _generateDarkColors(100); + + static List _generateDarkColors(int count) { + final random = Random(); + final colors = []; + + while (colors.length < count) { + final color = + Color((random.nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0); + if (_isDark(color)) { + colors.add(color); + } + } + return colors; + } + + static bool _isDark(Color color) { + final brightness = + ((color.red * 299) + (color.green * 587) + (color.blue * 114)) / 1000; + return brightness < 128; + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: BodyMedium( + text: 'Automation', + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontWeight: FontWeight.bold), + ), + ), + const Divider( + color: ColorsManager.dividerColor, + ), + Expanded( + child: BlocBuilder( + builder: (context, state) { + final smartSceneEnable = ((state is SmartSceneSelected)) + ? state.smartSceneEnable + : context.read().smartSceneEnable; + + return ListView.builder( + shrinkWrap: true, + itemCount: widget.automationList.length, + itemBuilder: (context, index) { + final automation = widget.automationList[index]; + final isSelected = + smartSceneEnable?.entityId == automation.id; + final descriptionSelected = isSelected + ? (smartSceneEnable?.actionExecutor == 'rule_enable' + ? 'Enable' + : 'Disable') + : automation.status == 'enable' + ? 'Enable' + : 'Disable'; + + return SceneListTile( + padding: const EdgeInsets.symmetric(horizontal: 10), + leadingWidget: CircleAvatar( + backgroundColor: colorList[index % colorList.length], + radius: 15, + child: Text( + index.toString(), + style: context.bodyMedium.copyWith(color: Colors.white), + ), + ), + titleString: automation.name, + trailingWidget: TextButton.icon( + iconAlignment: IconAlignment.end, + onPressed: () { + context.customAlertDialog( + alertBody: EnableDisableAutomationDialog( + automationId: automation.id, + descriptionSelected: descriptionSelected, + ), + title: automation.name, + onConfirm: () { + Navigator.pop(context); + }, + onDismiss: () { + context + .read() + .add(const SmartSceneClearEvent()); + Navigator.pop(context); + }, + ); + }, + label: BodyMedium( + text: _capitalizeFirst(descriptionSelected), + style: context.bodyMedium + .copyWith(color: ColorsManager.greyColor), + ), + icon: const Icon( + Icons.arrow_forward_ios_rounded, + color: ColorsManager.greyColor, + size: 14, + ), + style: const ButtonStyle( + padding: WidgetStatePropertyAll(EdgeInsets.zero), + ), + ), + onPressed: () { + context.customAlertDialog( + alertBody: EnableDisableAutomationDialog( + automationId: automation.id, + descriptionSelected: descriptionSelected, + ), + title: automation.name, + onConfirm: () { + Navigator.pop(context); + }, + onDismiss: () { + context + .read() + .add(const SmartSceneClearEvent()); + Navigator.pop(context); + }, + ); + }, + ); + }, + ); + }, + ), + ), + ], + ); + } + + String _capitalizeFirst(String description) { + if (description.isEmpty) return description; + return '${description[0].toUpperCase()}${description.substring(1)}'; + } +} + +class EnableDisableAutomationDialog extends StatefulWidget { + const EnableDisableAutomationDialog({ + super.key, + required this.automationId, + required this.descriptionSelected, + }); + + final String automationId; + final String descriptionSelected; + + @override + State createState() => + _EnableDisableAutomationDialogState(); +} + +class _EnableDisableAutomationDialogState + extends State { + String? groupValue; + final List values = [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: 'Enable', + value: 'rule_enable', + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: 'Disable', + value: 'rule_disable', + ), + ]; + + @override + void initState() { + super.initState(); + groupValue = + widget.descriptionSelected == 'Enable' ? 'rule_enable' : 'rule_disable'; + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + ...values.map( + (operation) => SceneListTile( + iconsSize: 25, + minLeadingWidth: 15, + padding: const EdgeInsets.symmetric(horizontal: 16), + assetPath: operation.icon, + assetHeaderValue: operation.iconValue, + titleString: operation.description.toString(), + textAlign: TextAlign.start, + trailingWidget: Radio( + value: operation.value, + groupValue: groupValue, + onChanged: (value) { + setState(() { + groupValue = value; + }); + context + .read() + .add(SmartSceneEnableEvent( + SmartSceneEnable( + entityId: widget.automationId, + actionExecutor: value!, + ), + )); + }, + ), + onPressed: () { + setState(() { + groupValue = operation.value; + }); + context + .read() + .add(SmartSceneEnableEvent( + SmartSceneEnable( + entityId: widget.automationId, + actionExecutor: operation.value, + ), + )); + }, + ), + ), + ], + ); + }, + ); + } +} diff --git a/lib/features/scene/widgets/select_smart_scene/smart_enable_autoamtion.dart b/lib/features/scene/widgets/select_smart_scene/smart_enable_autoamtion.dart new file mode 100644 index 0000000..d4684f5 --- /dev/null +++ b/lib/features/scene/widgets/select_smart_scene/smart_enable_autoamtion.dart @@ -0,0 +1,39 @@ +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/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/widgets/select_smart_scene/smart_automation_list.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; + +import 'package:syncrow_app/utils/context_extension.dart'; + +class SmartEnableAutomation extends StatelessWidget { + const SmartEnableAutomation({super.key}); + + @override + Widget build(BuildContext context) { + return DefaultContainer( + height: context.height * 0.5, + width: double.infinity, + child: BlocBuilder( + bloc: context.read() + ..add( + LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? '')), + builder: (context, state) { + if (state is SceneLoading) { + return const Align( + alignment: Alignment.topCenter, + child: LinearProgressIndicator()); + } + if (state is SceneLoaded) { + return SmartSceneSelectAutomationList( + automationList: state.automationList); + } + return const SizedBox.shrink(); + }, + ), + ); + } +} diff --git a/lib/features/scene/widgets/select_smart_scene/smart_enable_tab_run.dart b/lib/features/scene/widgets/select_smart_scene/smart_enable_tab_run.dart new file mode 100644 index 0000000..37a5e7c --- /dev/null +++ b/lib/features/scene/widgets/select_smart_scene/smart_enable_tab_run.dart @@ -0,0 +1,36 @@ +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/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/widgets/select_smart_scene/smart_tab_run_list.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; + +class SmartEnableTabRun extends StatelessWidget { + const SmartEnableTabRun({super.key}); + + @override + Widget build(BuildContext context) { + return DefaultContainer( + height: context.height * 0.5, + width: double.infinity, + child: BlocBuilder( + bloc: context.read() + ..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '')), + builder: (context, state) { + if (state is SceneLoading) { + return const Align( + alignment: Alignment.topCenter, + child: LinearProgressIndicator()); + } + if (state is SceneLoaded) { + return SmartSceneSelectTabToRunList(scenes: state.scenes); + } + return const SizedBox.shrink(); + }, + ), + ); + } +} + diff --git a/lib/features/scene/widgets/select_smart_scene/smart_tab_run_list.dart b/lib/features/scene/widgets/select_smart_scene/smart_tab_run_list.dart new file mode 100644 index 0000000..6fbae23 --- /dev/null +++ b/lib/features/scene/widgets/select_smart_scene/smart_tab_run_list.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart'; +import 'package:syncrow_app/features/scene/model/scenes_model.dart'; +import 'package:syncrow_app/features/scene/model/smart_scene_enable.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class SmartSceneSelectTabToRunList extends StatefulWidget { + const SmartSceneSelectTabToRunList({ + super.key, + required this.scenes, + }); + final List scenes; + + @override + State createState() => + _SmartSceneSelectTabToRunListState(); +} + +class _SmartSceneSelectTabToRunListState + extends State { + String groupValue = ''; + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: BodyMedium( + text: 'Tab To Run', + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontWeight: FontWeight.bold), + ), + ), + const Divider( + color: ColorsManager.dividerColor, + ), + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: widget.scenes.length, + itemBuilder: (context, index) { + final scene = widget.scenes[index]; + return SceneListTile( + padding: const EdgeInsets.symmetric(horizontal: 10), + leadingWidget: Image.asset( + height: 32, + width: 32, + Assets.assetsIconsLogo, + fit: BoxFit.fill, + ), + titleString: scene.name, + trailingWidget: Radio( + value: scene.id, + groupValue: groupValue, + onChanged: (String? value) { + if (value != null) { + setState(() { + groupValue = value; + }); + context + .read() + .add(SmartSceneEnableEvent(SmartSceneEnable( + entityId: scene.id, + actionExecutor: 'rule_enable', + ))); + } + }), + onPressed: () { + setState(() { + groupValue = scene.id; + }); + context + .read() + .add(SmartSceneEnableEvent(SmartSceneEnable( + entityId: scene.id, + actionExecutor: 'rule_enable', + ))); + }, + ); + }), + ), + ], + ); + } +} diff --git a/lib/features/shared_widgets/default_scaffold.dart b/lib/features/shared_widgets/default_scaffold.dart index 080fbef..a88e828 100644 --- a/lib/features/shared_widgets/default_scaffold.dart +++ b/lib/features/shared_widgets/default_scaffold.dart @@ -17,6 +17,7 @@ class DefaultScaffold extends StatelessWidget { this.padding, this.leading, this.leadingWidth, + this.height, }); final Widget child; @@ -27,6 +28,7 @@ class DefaultScaffold extends StatelessWidget { final EdgeInsetsGeometry? padding; final Widget? leading; final double? leadingWidth; + final double? height; @override Widget build(BuildContext context) { return AnnotatedRegion( @@ -54,8 +56,9 @@ class DefaultScaffold extends StatelessWidget { ), body: Container( width: MediaQuery.sizeOf(context).width, - height: MediaQuery.sizeOf(context).height, - padding: padding ?? const EdgeInsets.symmetric(horizontal: Constants.defaultPadding), + height: height ?? MediaQuery.sizeOf(context).height, + padding: padding ?? + const EdgeInsets.symmetric(horizontal: Constants.defaultPadding), decoration: const BoxDecoration( image: DecorationImage( image: AssetImage( diff --git a/lib/my_app.dart b/lib/my_app.dart index a49fec7..0a253bf 100644 --- a/lib/my_app.dart +++ b/lib/my_app.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart'; import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart'; import 'package:syncrow_app/navigation/navigation_service.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart'; @@ -28,6 +29,7 @@ class MyApp extends StatelessWidget { BlocProvider(create: (context) => CreateSceneBloc()), BlocProvider(create: (context) => SceneBloc()), BlocProvider(create: (context) => ProfileBloc()), + BlocProvider(create: (context) => SmartSceneSelectBloc()), ], child: MaterialApp( diff --git a/lib/navigation/router.dart b/lib/navigation/router.dart index 8bc2839..990b7fb 100644 --- a/lib/navigation/router.dart +++ b/lib/navigation/router.dart @@ -18,6 +18,7 @@ import 'package:syncrow_app/features/scene/view/scene_auto_settings.dart'; import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart'; import 'package:syncrow_app/features/scene/view/scene_rooms_tabbar.dart'; import 'package:syncrow_app/features/scene/view/scene_view.dart'; +import 'package:syncrow_app/features/scene/view/smart_automation_select_route.dart'; import 'package:syncrow_app/features/splash/view/splash_view.dart'; import 'routing_constants.dart'; @@ -101,6 +102,12 @@ class Router { builder: (_) => const SceneAutoSettings(), settings: settings, ); + + case Routes.smartAutomationSelectRoute: + return MaterialPageRoute( + builder: (_) => const SmartAutomationSelectView(), + settings: settings, + ); default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/navigation/routing_constants.dart b/lib/navigation/routing_constants.dart index 1d2d363..b64849f 100644 --- a/lib/navigation/routing_constants.dart +++ b/lib/navigation/routing_constants.dart @@ -20,6 +20,6 @@ class Routes { static const String sceneTasksRoute = '/scene-tasks'; static const String sceneControlDevicesRoute = '/scene-control-devices'; static const String deviceFunctionsRoute = '/device-functions'; - static const String sceneAutoSettingsRoute = - '/scene-automation-settings'; + static const String sceneAutoSettingsRoute = '/scene-automation-settings'; + static const String smartAutomationSelectRoute = '/smart-automation-select'; } From eb8ad90dcb72010a450b1746612504dfb8dbca5c Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sun, 28 Jul 2024 06:57:33 +0300 Subject: [PATCH 24/30] push switch autoaomtion status update --- .../bloc/create_scene/create_scene_bloc.dart | 1 + .../scene/bloc/scene_bloc/scene_bloc.dart | 45 ++++++- .../scene/bloc/scene_bloc/scene_event.dart | 13 ++ .../scene/bloc/scene_bloc/scene_state.dart | 11 +- .../scene/helper/scene_logic_helper.dart | 112 ++++++++++-------- .../scene/model/scene_details_model.dart | 30 +++-- .../scene/model/update_automation.dart | 38 ++++++ lib/features/scene/view/scene_view.dart | 8 +- .../scene_view_widget/scene_grid_view.dart | 17 ++- .../widgets/scene_view_widget/scene_item.dart | 68 +++++++---- lib/services/api/api_links_endpoints.dart | 24 ++-- lib/services/api/scene_api.dart | 17 +++ 12 files changed, 280 insertions(+), 104 deletions(-) create mode 100644 lib/features/scene/model/update_automation.dart diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index 60bfc17..de6886e 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -362,6 +362,7 @@ class CreateSceneBloc extends Bloc tasksList = List.from( getTaskListFunctionsFromApi( actions: response.actions, isAutomation: false)); + emit(AddSceneTask( automationTasksList: automationTasksList, tasksList: tasksList, diff --git a/lib/features/scene/bloc/scene_bloc/scene_bloc.dart b/lib/features/scene/bloc/scene_bloc/scene_bloc.dart index c68f4e9..047e9cb 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_bloc.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_bloc.dart @@ -13,6 +13,7 @@ class SceneBloc extends Bloc { on(_onLoadScenes); on(_onLoadAutomation); on(_onSceneTrigger); + on(_onUpdateAutomationStatus); } List scenes = []; @@ -26,7 +27,7 @@ class SceneBloc extends Bloc { scenes = await SceneApi.getScenesByUnitId(event.unitId); emit(SceneLoaded(scenes, automationList)); } else { - const SceneError(message: ''); + emit(const SceneError(message: 'Unit ID is empty')); } } catch (e) { emit(const SceneError(message: 'Something went wrong')); @@ -53,8 +54,11 @@ class SceneBloc extends Bloc { SceneTrigger event, Emitter emit) async { final currentState = state; if (currentState is SceneLoaded) { - emit(SceneLoaded(currentState.scenes, currentState.automationList, - loadingSceneId: event.sceneId)); + emit(SceneLoaded( + currentState.scenes, + currentState.automationList, + loadingSceneId: event.sceneId, + )); try { final success = await SceneApi.triggerScene(event.sceneId); @@ -69,4 +73,39 @@ class SceneBloc extends Bloc { } } } + + Future _onUpdateAutomationStatus( + UpdateAutomationStatus event, Emitter emit) async { + final currentState = state; + if (currentState is SceneLoaded) { + final newLoadingStates = + Map.from(currentState.loadingStates) + ..[event.automationId] = true; + + emit(SceneLoaded( + currentState.scenes, + currentState.automationList, + loadingStates: newLoadingStates, + )); + + try { + final success = await SceneApi.updateAutomationStatus( + event.automationId, event.automationStatusUpdate); + if (success) { + automationList = await SceneApi.getAutomationByUnitId( + event.automationStatusUpdate.unitUuid); + newLoadingStates[event.automationId] = false; + emit(SceneLoaded( + currentState.scenes, + automationList, + loadingStates: newLoadingStates, + )); + } else { + emit(const SceneError(message: 'Something went wrong')); + } + } catch (e) { + emit(const SceneError(message: 'Something went wrong')); + } + } + } } diff --git a/lib/features/scene/bloc/scene_bloc/scene_event.dart b/lib/features/scene/bloc/scene_bloc/scene_event.dart index 5a22fd5..d580ed4 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_event.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_event.dart @@ -1,4 +1,5 @@ import 'package:equatable/equatable.dart'; +import 'package:syncrow_app/features/scene/model/update_automation.dart'; abstract class SceneEvent extends Equatable { const SceneEvent(); @@ -34,3 +35,15 @@ class SceneTrigger extends SceneEvent { @override List get props => [sceneId]; } + +//updateAutomationStatus +class UpdateAutomationStatus extends SceneEvent { + final String automationId; + final AutomationStatusUpdate automationStatusUpdate; + + const UpdateAutomationStatus( + {required this.automationStatusUpdate, required this.automationId}); + + @override + List get props => [automationStatusUpdate]; +} diff --git a/lib/features/scene/bloc/scene_bloc/scene_state.dart b/lib/features/scene/bloc/scene_bloc/scene_state.dart index f6b42a3..0b6ac85 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_state.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_state.dart @@ -15,11 +15,14 @@ class SceneLoaded extends SceneState { final List scenes; final List automationList; final String? loadingSceneId; + final Map loadingStates; - const SceneLoaded(this.scenes, this.automationList, {this.loadingSceneId}); + const SceneLoaded(this.scenes, this.automationList, + {this.loadingSceneId, this.loadingStates = const {}}); @override - List get props => [scenes, loadingSceneId, automationList]; + List get props => + [scenes, loadingSceneId, automationList, loadingStates]; } class SceneError extends SceneState { @@ -39,3 +42,7 @@ class SceneTriggerSuccess extends SceneState { @override List get props => [sceneName]; } + +class UpdateAutomationStatusLoading extends SceneState { + const UpdateAutomationStatusLoading(); +} diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 328e089..b1d3086 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -66,36 +66,40 @@ mixin SceneLogicHelper { ); }, ), - actions: List.generate( - actions.length, - (index) { - final task = actions[index]; - if (task.deviceId == 'delay') { + actions: [ + ...List.generate( + actions.length, + (index) { + final task = actions[index]; + if (task.deviceId == 'delay') { + return CreateSceneAction( + entityId: actions[index].deviceId, + actionExecutor: 'delay', + executorProperty: CreateSceneExecutorProperty( + functionCode: '', + functionValue: '', + delaySeconds: task.functionValue, + ), + ); + } return CreateSceneAction( - entityId: actions[index].deviceId, - actionExecutor: 'delay', + entityId: task.deviceId, + actionExecutor: 'device_issue', executorProperty: CreateSceneExecutorProperty( - functionCode: '', - functionValue: '', - delaySeconds: task.functionValue, + functionCode: task.code, + functionValue: task.functionValue, + delaySeconds: 0, ), ); - } - return CreateSceneAction( - entityId: task.deviceId, - actionExecutor: 'device_issue', - executorProperty: CreateSceneExecutorProperty( - functionCode: task.code, - functionValue: task.functionValue, - delaySeconds: 0, - ), - ); - }, - )..add(CreateSceneAction( - entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '', - actionExecutor: - smartSceneBloc.smartSceneEnable?.actionExecutor ?? '', - executorProperty: null)), + }, + ), + if (smartSceneBloc.smartSceneEnable != null) + CreateSceneAction( + entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '', + actionExecutor: + smartSceneBloc.smartSceneEnable?.actionExecutor ?? '', + executorProperty: null) + ], ); sceneBloc.add(CreateSceneWithTasksEvent( createSceneModel: null, @@ -121,36 +125,40 @@ mixin SceneLogicHelper { unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '', sceneName: sceneName.text, decisionExpr: 'and', - actions: List.generate( - actions.length, - (index) { - final task = actions[index]; - if (task.deviceId == 'delay') { + actions: [ + ...List.generate( + actions.length, + (index) { + final task = actions[index]; + if (task.deviceId == 'delay') { + return CreateSceneAction( + entityId: actions[index].deviceId, + actionExecutor: 'delay', + executorProperty: CreateSceneExecutorProperty( + functionCode: '', + functionValue: '', + delaySeconds: task.functionValue, + ), + ); + } return CreateSceneAction( - entityId: actions[index].deviceId, - actionExecutor: 'delay', + entityId: task.deviceId, + actionExecutor: 'device_issue', executorProperty: CreateSceneExecutorProperty( - functionCode: '', - functionValue: '', - delaySeconds: task.functionValue, + functionCode: task.code, + functionValue: task.functionValue, + delaySeconds: 0, ), ); - } - return CreateSceneAction( - entityId: task.deviceId, - actionExecutor: 'device_issue', - executorProperty: CreateSceneExecutorProperty( - functionCode: task.code, - functionValue: task.functionValue, - delaySeconds: 0, - ), - ); - }, - )..add(CreateSceneAction( - entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '', - actionExecutor: - smartSceneBloc.smartSceneEnable?.actionExecutor ?? '', - executorProperty: null)), + }, + ), + if (smartSceneBloc.smartSceneEnable != null) + CreateSceneAction( + entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '', + actionExecutor: + smartSceneBloc.smartSceneEnable?.actionExecutor ?? '', + executorProperty: null) + ], ); sceneBloc.add(CreateSceneWithTasksEvent( createSceneModel: createSceneModel, diff --git a/lib/features/scene/model/scene_details_model.dart b/lib/features/scene/model/scene_details_model.dart index 04b9827..3c40476 100644 --- a/lib/features/scene/model/scene_details_model.dart +++ b/lib/features/scene/model/scene_details_model.dart @@ -32,11 +32,15 @@ class SceneDetailsModel { name: json["name"], status: json["status"], type: json["type"], - actions: - List.from(json["actions"].map((x) => Action.fromJson(x))), + actions: (json["actions"] as List) + .map((x) => Action.fromJson(x)) + .where((x) => x != null) + .toList() + .cast(), conditions: json["conditions"] != null - ? List.from( - json["conditions"].map((x) => Condition.fromJson(x))) + ? (json["conditions"] as List) + .map((x) => Condition.fromJson(x)) + .toList() : null, decisionExpr: json["decisionExpr"], effectiveTime: json["effectiveTime"] != null @@ -69,15 +73,19 @@ class Action { required this.executorProperty, }); - factory Action.fromRawJson(String str) => Action.fromJson(json.decode(str)); - String toRawJson() => json.encode(toJson()); - factory Action.fromJson(Map json) => Action( - actionExecutor: json["actionExecutor"], - entityId: json["entityId"], - executorProperty: ExecutorProperty.fromJson(json["executorProperty"]), - ); + static Action? fromJson(Map json) { + if (json["executorProperty"] == null) { + return null; // Return null if executorProperty is not present + } + + return Action( + actionExecutor: json["actionExecutor"], + entityId: json["entityId"], + executorProperty: ExecutorProperty.fromJson(json["executorProperty"]), + ); + } Map toJson() => { "actionExecutor": actionExecutor, diff --git a/lib/features/scene/model/update_automation.dart b/lib/features/scene/model/update_automation.dart new file mode 100644 index 0000000..d15d191 --- /dev/null +++ b/lib/features/scene/model/update_automation.dart @@ -0,0 +1,38 @@ +import 'dart:convert'; + +class AutomationStatusUpdate { + final String unitUuid; + final bool isEnable; + + AutomationStatusUpdate({ + required this.unitUuid, + required this.isEnable, + }); + + factory AutomationStatusUpdate.fromRawJson(String str) => + AutomationStatusUpdate.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory AutomationStatusUpdate.fromJson(Map json) => + AutomationStatusUpdate( + unitUuid: json["unitUuid"], + isEnable: json["isEnable"], + ); + + Map toJson() => { + "unitUuid": unitUuid, + "isEnable": isEnable, + }; + + factory AutomationStatusUpdate.fromMap(Map map) => + AutomationStatusUpdate( + unitUuid: map["unitUuid"], + isEnable: map["isEnable"], + ); + + Map toMap() => { + "unitUuid": unitUuid, + "isEnable": isEnable, + }; +} diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index f181c8b..544b267 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -98,7 +98,9 @@ class SceneView extends StatelessWidget { scenes: scenes, loadingSceneId: state.loadingSceneId, - disablePLayButton: false, + disablePlayButton: false, + loadingStates: state + .loadingStates, // Add this line ) : const Center( child: BodyMedium( @@ -129,7 +131,9 @@ class SceneView extends StatelessWidget { scenes: automationList, loadingSceneId: state.loadingSceneId, - disablePLayButton: true, + disablePlayButton: true, + loadingStates: state + .loadingStates, // Add this line ) : const Center( child: BodyMedium( diff --git a/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart b/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart index 6004028..f690fbb 100644 --- a/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart +++ b/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart @@ -4,12 +4,15 @@ import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_item. class SceneGrid extends StatelessWidget { final List scenes; final String? loadingSceneId; - final bool disablePLayButton; + final bool disablePlayButton; + final Map loadingStates; + const SceneGrid({ required this.scenes, required this.loadingSceneId, + required this.disablePlayButton, + required this.loadingStates, super.key, - required this.disablePLayButton, }); @override @@ -27,10 +30,14 @@ class SceneGrid extends StatelessWidget { itemBuilder: (context, index) { final scene = scenes[index]; final isLoading = loadingSceneId == scene.id; + final isSwitchLoading = loadingStates[scene.id] ?? false; + return SceneItem( - scene: scene, - isLoading: isLoading, - disablePLayButton: disablePLayButton); + scene: scene, + isLoading: isLoading, + disablePlayButton: disablePlayButton, + isSwitchLoading: isSwitchLoading, + ); }, ); } diff --git a/lib/features/scene/widgets/scene_view_widget/scene_item.dart b/lib/features/scene/widgets/scene_view_widget/scene_item.dart index 894f662..0dc4fff 100644 --- a/lib/features/scene/widgets/scene_view_widget/scene_item.dart +++ b/lib/features/scene/widgets/scene_view_widget/scene_item.dart @@ -1,11 +1,14 @@ +import 'package:flutter/cupertino.dart'; 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/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/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/model/scenes_model.dart'; import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; +import 'package:syncrow_app/features/scene/model/update_automation.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; @@ -16,13 +19,15 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class SceneItem extends StatelessWidget { final ScenesModel scene; final bool isLoading; - final bool disablePLayButton; + final bool isSwitchLoading; + final bool disablePlayButton; const SceneItem({ required this.scene, required this.isLoading, super.key, - required this.disablePLayButton, + required this.disablePlayButton, + required this.isSwitchLoading, }); @override @@ -33,14 +38,14 @@ class SceneItem extends StatelessWidget { context, Routes.sceneTasksRoute, arguments: SceneSettingsRouteArguments( - sceneType: disablePLayButton == false + sceneType: disablePlayButton == false ? CreateSceneEnum.tabToRun.name : CreateSceneEnum.deviceStatusChanges.name, sceneId: scene.id, sceneName: scene.name, ), ); - if (disablePLayButton == false) { + if (disablePlayButton == false) { BlocProvider.of(context) .add(const SceneTypeEvent(CreateSceneEnum.tabToRun)); BlocProvider.of(context).add( @@ -66,26 +71,45 @@ class SceneItem extends StatelessWidget { Assets.assetsIconsLogo, fit: BoxFit.fill, ), - Visibility( - visible: disablePLayButton == false, - child: IconButton( - padding: EdgeInsets.zero, - onPressed: () { - context - .read() - .add(SceneTrigger(scene.id, scene.name)); - }, - icon: isLoading - ? const Center( - child: CircularProgressIndicator(), + disablePlayButton == false + ? IconButton( + padding: EdgeInsets.zero, + onPressed: () { + context + .read() + .add(SceneTrigger(scene.id, scene.name)); + }, + icon: isLoading + ? const Center( + child: CircularProgressIndicator(), + ) + : const Icon( + Icons.play_circle, + size: 40, + color: ColorsManager.greyColor, + ), + ) + : isSwitchLoading + ? Center( + child: CircularProgressIndicator( + color: ColorsManager.primaryColorWithOpacity, + ), ) - : const Icon( - Icons.play_circle, - size: 40, - color: ColorsManager.greyColor, + : CupertinoSwitch( + activeColor: ColorsManager.primaryColor, + value: scene.status == 'enable' ? true : false, + onChanged: (value) { + context.read().add( + UpdateAutomationStatus( + automationStatusUpdate: + AutomationStatusUpdate( + isEnable: value, + unitUuid: HomeCubit.getInstance() + .selectedSpace! + .id!), + automationId: scene.id)); + }, ), - ), - ), ], ), const SizedBox(height: 10), diff --git a/lib/services/api/api_links_endpoints.dart b/lib/services/api/api_links_endpoints.dart index 8e22e5d..c3c2e8c 100644 --- a/lib/services/api/api_links_endpoints.dart +++ b/lib/services/api/api_links_endpoints.dart @@ -81,7 +81,8 @@ abstract class ApiEndpoints { static const String controlGroup = '/group/control'; //GET static const String groupBySpace = '/group/{unitUuid}'; - static const String devicesByGroupName = '/group/{unitUuid}/devices/{groupName}'; + static const String devicesByGroupName = + '/group/{unitUuid}/devices/{groupName}'; static const String groupByUuid = '/group/{groupUuid}'; //DELETE @@ -93,7 +94,8 @@ abstract class ApiEndpoints { static const String addDeviceToRoom = '/device/room'; static const String addDeviceToGroup = '/device/group'; static const String controlDevice = '/device/{deviceUuid}/control'; - static const String firmwareDevice = '/device/{deviceUuid}/firmware/{firmwareVersion}'; + static const String firmwareDevice = + '/device/{deviceUuid}/firmware/{firmwareVersion}'; static const String getDevicesByUserId = '/device/user/{userId}'; static const String getDevicesByUnitId = '/device/unit/{unitUuid}'; @@ -102,7 +104,8 @@ abstract class ApiEndpoints { static const String deviceByUuid = '/device/{deviceUuid}'; static const String deviceFunctions = '/device/{deviceUuid}/functions'; static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices'; - static const String deviceFunctionsStatus = '/device/{deviceUuid}/functions/status'; + static const String deviceFunctionsStatus = + '/device/{deviceUuid}/functions/status'; ///Device Permission Module //POST @@ -127,22 +130,29 @@ abstract class ApiEndpoints { static const String getUnitAutomation = '/automation/{unitUuid}'; - static const String getAutomationDetails = '/automation/details/{automationId}'; + static const String getAutomationDetails = + '/automation/details/{automationId}'; /// PUT static const String updateScene = '/scene/tap-to-run/{sceneId}'; static const String updateAutomation = '/automation/{automationId}'; + static const String updateAutomationStatus = + '/automation/status/{automationId}'; + /// DELETE static const String deleteScene = '/scene/tap-to-run/{unitUuid}/{sceneId}'; - static const String deleteAutomation = '/automation/{unitUuid}/{automationId}'; + static const String deleteAutomation = + '/automation/{unitUuid}/{automationId}'; //////////////////////Door Lock ////////////////////// //online - static const String addTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}'; - static const String getTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}'; + static const String addTemporaryPassword = + '/door-lock/temporary-password/online/{doorLockUuid}'; + static const String getTemporaryPassword = + '/door-lock/temporary-password/online/{doorLockUuid}'; //one-time offline static const String addOneTimeTemporaryPassword = diff --git a/lib/services/api/scene_api.dart b/lib/services/api/scene_api.dart index 6233b30..e26920c 100644 --- a/lib/services/api/scene_api.dart +++ b/lib/services/api/scene_api.dart @@ -2,6 +2,7 @@ import 'package:syncrow_app/features/scene/model/create_automation_model.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; import 'package:syncrow_app/features/scene/model/scene_details_model.dart'; import 'package:syncrow_app/features/scene/model/scenes_model.dart'; +import 'package:syncrow_app/features/scene/model/update_automation.dart'; import 'package:syncrow_app/services/api/api_links_endpoints.dart'; import 'package:syncrow_app/services/api/http_service.dart'; @@ -115,6 +116,22 @@ class SceneApi { } } + //updateAutomationStatus + static Future updateAutomationStatus(String automationId, + AutomationStatusUpdate createAutomationEnable) async { + try { + final response = await _httpService.put( + path: ApiEndpoints.updateAutomationStatus + .replaceAll('{automationId}', automationId), + body: createAutomationEnable.toMap(), + expectedResponseModel: (json) => json['success'], + ); + return response; + } catch (e) { + rethrow; + } + } + //getScene static Future getSceneDetails(String sceneId) async { From cd704dcc6077e10068d9017982becc7e77ca8ec2 Mon Sep 17 00:00:00 2001 From: Abdullah Alassaf Date: Sun, 28 Jul 2024 12:04:22 +0300 Subject: [PATCH 25/30] Read decision expresion in the fetch scene method --- .../bloc/create_scene/create_scene_bloc.dart | 72 +++++++------------ 1 file changed, 25 insertions(+), 47 deletions(-) diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index de6886e..fbe4ca7 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -48,8 +48,7 @@ class CreateSceneBloc extends Bloc String conditionRule = 'or'; EffectiveTime? effectiveTime; - FutureOr _onAddSceneTask( - AddTaskEvent event, Emitter emit) { + FutureOr _onAddSceneTask(AddTaskEvent event, Emitter emit) { emit(CreateSceneLoading()); if (event.isAutomation == true) { final copyList = List.from(automationTempTasksList); @@ -84,8 +83,7 @@ class CreateSceneBloc extends Bloc } } - void addToTempTaskList( - TempHoldSceneTasksEvent event, Emitter emit) { + void addToTempTaskList(TempHoldSceneTasksEvent event, Emitter emit) { emit(CreateSceneLoading()); bool updated = false; for (var element in tempTasksList) { @@ -139,8 +137,7 @@ class CreateSceneBloc extends Bloc )); } - void addToTempAutomationTaskList( - TempHoldSceneTasksEvent event, Emitter emit) { + void addToTempAutomationTaskList(TempHoldSceneTasksEvent event, Emitter emit) { emit(CreateSceneLoading()); bool updated = false; for (var element in automationTempTasksList) { @@ -162,10 +159,8 @@ class CreateSceneBloc extends Bloc ], comparator: automationComparatorValues[element.code], ); - automationTempTasksList[automationTempTasksList.indexOf(element)] = - updatedElement; - automationSelectedValues[updatedElement.code] = - event.deviceControlModel.value; + automationTempTasksList[automationTempTasksList.indexOf(element)] = updatedElement; + automationSelectedValues[updatedElement.code] = event.deviceControlModel.value; updated = true; break; } @@ -185,12 +180,10 @@ class CreateSceneBloc extends Bloc icon: '', ), ], - comparator: - automationComparatorValues[event.deviceControlModel.code] ?? '==', + comparator: automationComparatorValues[event.deviceControlModel.code] ?? '==', ); automationTempTasksList.add(newElement); - automationSelectedValues[newElement.code] = - event.deviceControlModel.value; + automationSelectedValues[newElement.code] = event.deviceControlModel.value; } emit(AddSceneTask( tasksList: tasksList, @@ -199,8 +192,7 @@ class CreateSceneBloc extends Bloc )); } - FutureOr _selectedValue( - SelectedValueEvent event, Emitter emit) { + FutureOr _selectedValue(SelectedValueEvent event, Emitter emit) { if (event.isAutomation == true) { automationSelectedValues[event.code] = event.value; automationComparatorValues[event.code] = event.comparator ?? '=='; @@ -228,8 +220,7 @@ class CreateSceneBloc extends Bloc )); } - FutureOr _removeTaskById( - RemoveTaskByIdEvent event, Emitter emit) { + FutureOr _removeTaskById(RemoveTaskByIdEvent event, Emitter emit) { emit(CreateSceneLoading()); if (event.isAutomation == true) { for (var element in automationTasksList) { @@ -302,8 +293,7 @@ class CreateSceneBloc extends Bloc : await SceneApi.createScene(event.createSceneModel!); } else if (event.createAutomationModel != null) { response = event.updateScene - ? await SceneApi.updateAutomation( - event.createAutomationModel!, event.sceneId) + ? await SceneApi.updateAutomation(event.createAutomationModel!, event.sceneId) : await SceneApi.createAutomation(event.createAutomationModel!); } @@ -332,8 +322,7 @@ class CreateSceneBloc extends Bloc } } - FutureOr _clearTaskList( - ClearTaskListEvent event, Emitter emit) { + FutureOr _clearTaskList(ClearTaskListEvent event, Emitter emit) { emit(CreateSceneLoading()); automationTasksList.clear(); tasksList.clear(); @@ -354,14 +343,12 @@ class CreateSceneBloc extends Bloc : await SceneApi.getSceneDetails(event.sceneId); if (response.id.isNotEmpty) { if (event.isAutomation) { - automationTasksList = List.from( - getTaskListFunctionsFromApi( - actions: [], - isAutomation: true, - conditions: response.conditions)); + automationTasksList = List.from(getTaskListFunctionsFromApi( + actions: [], isAutomation: true, conditions: response.conditions)); tasksList = List.from( - getTaskListFunctionsFromApi( - actions: response.actions, isAutomation: false)); + getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false)); + + conditionRule = response.decisionExpr ?? conditionRule; emit(AddSceneTask( automationTasksList: automationTasksList, @@ -370,8 +357,7 @@ class CreateSceneBloc extends Bloc )); } else { tasksList = List.from( - getTaskListFunctionsFromApi( - actions: response.actions, isAutomation: false)); + getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false)); emit(AddSceneTask( tasksList: tasksList, condition: conditionRule, @@ -385,8 +371,7 @@ class CreateSceneBloc extends Bloc } } - FutureOr _clearTempTaskList( - ClearTempTaskListEvent event, Emitter emit) { + FutureOr _clearTempTaskList(ClearTempTaskListEvent event, Emitter emit) { emit(CreateSceneLoading()); if (event.isAutomation == true) { automationTempTasksList.clear(); @@ -435,17 +420,13 @@ class CreateSceneBloc extends Bloc } } - FutureOr _deleteScene( - DeleteSceneEvent event, Emitter emit) async { + FutureOr _deleteScene(DeleteSceneEvent event, Emitter emit) async { emit(DeleteSceneLoading()); try { - final response = - sceneType.name == CreateSceneEnum.deviceStatusChanges.name - ? await SceneApi.deleteAutomation( - automationId: event.sceneId, unitUuid: event.unitUuid) - : await SceneApi.deleteScene( - sceneId: event.sceneId, unitUuid: event.unitUuid); + final response = sceneType.name == CreateSceneEnum.deviceStatusChanges.name + ? await SceneApi.deleteAutomation(automationId: event.sceneId, unitUuid: event.unitUuid) + : await SceneApi.deleteScene(sceneId: event.sceneId, unitUuid: event.unitUuid); if (response == true) { emit(const DeleteSceneSuccess(true)); } else { @@ -456,8 +437,7 @@ class CreateSceneBloc extends Bloc } } - FutureOr _updateTaskValue( - UpdateTaskEvent event, Emitter emit) { + FutureOr _updateTaskValue(UpdateTaskEvent event, Emitter emit) { emit(CreateSceneLoading()); if (event.isAutomation == true) { for (var i = 0; i < automationTasksList.length; i++) { @@ -485,8 +465,7 @@ class CreateSceneBloc extends Bloc )); } - FutureOr _selectConditionRule( - SelectConditionEvent event, Emitter emit) { + FutureOr _selectConditionRule(SelectConditionEvent event, Emitter emit) { emit(CreateSceneInitial()); if (event.condition.contains('any')) { conditionRule = 'or'; @@ -501,8 +480,7 @@ class CreateSceneBloc extends Bloc )); } - FutureOr _sceneTypeEvent( - SceneTypeEvent event, Emitter emit) { + FutureOr _sceneTypeEvent(SceneTypeEvent event, Emitter emit) { emit(CreateSceneInitial()); if (event.type == CreateSceneEnum.tabToRun) { From e26b8f390bbe60500a051f7113f09c211d9943e6 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sun, 28 Jul 2024 12:32:43 +0300 Subject: [PATCH 26/30] clear smart scene status --- lib/features/app_layout/bloc/home_cubit.dart | 11 +++++++---- lib/features/scene/view/scene_view.dart | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/features/app_layout/bloc/home_cubit.dart b/lib/features/app_layout/bloc/home_cubit.dart index a313f02..9168283 100644 --- a/lib/features/app_layout/bloc/home_cubit.dart +++ b/lib/features/app_layout/bloc/home_cubit.dart @@ -18,6 +18,7 @@ import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view. import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart'; import 'package:syncrow_app/features/menu/view/menu_view.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart'; import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; import 'package:syncrow_app/features/scene/view/create_scene_view.dart'; @@ -57,13 +58,12 @@ class HomeCubit extends Cubit { return _instance!; } - - Future fetchUserInfo() async { + Future fetchUserInfo() async { try { - var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey); + var uuid = + await const FlutterSecureStorage().read(key: UserModel.userUuidKey); user = await ProfileApi().fetchUserInfo(uuid); emit(HomeUserInfoLoaded(user!)); // Emit state after fetching user info - } catch (e) { return; } @@ -382,6 +382,9 @@ class HomeCubit extends Cubit { NavigationService.navigatorKey.currentContext! .read() .add(const SceneTypeEvent(CreateSceneEnum.none)); + NavigationService.navigatorKey.currentContext! + .read() + .add(const SmartSceneClearEvent()); }, ), IconButton( diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index 544b267..75c16d4 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -5,8 +5,10 @@ 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/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/scene/widgets/select_smart_scene/smart_enable_autoamtion.dart'; import 'package:syncrow_app/features/shared_widgets/create_unit.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/utils/context_extension.dart'; @@ -38,6 +40,9 @@ class SceneView extends StatelessWidget { .add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)); BlocProvider.of(context).add( LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!)); + context + .read() + .add(const SmartSceneClearEvent()); } } return BlocListener( From 5364959c8deca353b78c0b101b3d34643461e66c Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sun, 28 Jul 2024 12:55:37 +0300 Subject: [PATCH 27/30] push settings visiblitty --- lib/features/scene/view/scene_tasks_view.dart | 41 ++++++++++--------- lib/features/scene/view/scene_view.dart | 1 - 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/lib/features/scene/view/scene_tasks_view.dart b/lib/features/scene/view/scene_tasks_view.dart index 22371b4..a41a191 100644 --- a/lib/features/scene/view/scene_tasks_view.dart +++ b/lib/features/scene/view/scene_tasks_view.dart @@ -37,25 +37,28 @@ class SceneTasksView extends StatelessWidget { : StringsManager.createScene, padding: EdgeInsets.zero, actions: [ - SizedBox( - width: 40, - child: GestureDetector( - onTap: () { - Navigator.pushNamed( - context, - Routes.sceneAutoSettingsRoute, - arguments: { - "sceneId": sceneSettings.sceneId, - "isAutomation": isAutomation, - "sceneName": sceneSettings.sceneName, - }, - ); - }, - child: SvgPicture.asset( - Assets.assetsIconsSettings, - colorFilter: const ColorFilter.mode( - ColorsManager.textPrimaryColor, - BlendMode.srcIn, + Visibility( + visible: sceneSettings.sceneType != CreateSceneEnum.none.name, + child: SizedBox( + width: 40, + child: GestureDetector( + onTap: () { + Navigator.pushNamed( + context, + Routes.sceneAutoSettingsRoute, + arguments: { + "sceneId": sceneSettings.sceneId, + "isAutomation": isAutomation, + "sceneName": sceneSettings.sceneName, + }, + ); + }, + child: SvgPicture.asset( + Assets.assetsIconsSettings, + colorFilter: const ColorFilter.mode( + ColorsManager.textPrimaryColor, + BlendMode.srcIn, + ), ), ), ), diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index 75c16d4..ce297ce 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -8,7 +8,6 @@ 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/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/scene/widgets/select_smart_scene/smart_enable_autoamtion.dart'; import 'package:syncrow_app/features/shared_widgets/create_unit.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/utils/context_extension.dart'; From 555d4bd8b4e6d982984ba83fd400308224abb78b Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sun, 28 Jul 2024 22:17:50 +0300 Subject: [PATCH 28/30] fix time period read from api and setting visibility --- .../bloc/create_scene/create_scene_bloc.dart | 84 ++++++++++++++----- .../helper/scene_operations_data_helper.dart | 4 +- lib/features/scene/view/scene_tasks_view.dart | 2 +- .../alert_dialog_slider_steps.dart | 6 +- .../effective_period_bottom_sheet.dart | 45 +++++----- .../if_then_containers/then_added_tasks.dart | 7 +- lib/my_app.dart | 7 +- 7 files changed, 101 insertions(+), 54 deletions(-) diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index fbe4ca7..6ebfcae 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -1,13 +1,17 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart'; import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart'; import 'package:syncrow_app/features/scene/model/create_automation_model.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/navigation/navigation_service.dart'; import 'package:syncrow_app/services/api/scene_api.dart'; part 'create_scene_event.dart'; @@ -48,7 +52,8 @@ class CreateSceneBloc extends Bloc String conditionRule = 'or'; EffectiveTime? effectiveTime; - FutureOr _onAddSceneTask(AddTaskEvent event, Emitter emit) { + FutureOr _onAddSceneTask( + AddTaskEvent event, Emitter emit) { emit(CreateSceneLoading()); if (event.isAutomation == true) { final copyList = List.from(automationTempTasksList); @@ -83,7 +88,8 @@ class CreateSceneBloc extends Bloc } } - void addToTempTaskList(TempHoldSceneTasksEvent event, Emitter emit) { + void addToTempTaskList( + TempHoldSceneTasksEvent event, Emitter emit) { emit(CreateSceneLoading()); bool updated = false; for (var element in tempTasksList) { @@ -137,7 +143,8 @@ class CreateSceneBloc extends Bloc )); } - void addToTempAutomationTaskList(TempHoldSceneTasksEvent event, Emitter emit) { + void addToTempAutomationTaskList( + TempHoldSceneTasksEvent event, Emitter emit) { emit(CreateSceneLoading()); bool updated = false; for (var element in automationTempTasksList) { @@ -159,8 +166,10 @@ class CreateSceneBloc extends Bloc ], comparator: automationComparatorValues[element.code], ); - automationTempTasksList[automationTempTasksList.indexOf(element)] = updatedElement; - automationSelectedValues[updatedElement.code] = event.deviceControlModel.value; + automationTempTasksList[automationTempTasksList.indexOf(element)] = + updatedElement; + automationSelectedValues[updatedElement.code] = + event.deviceControlModel.value; updated = true; break; } @@ -180,10 +189,12 @@ class CreateSceneBloc extends Bloc icon: '', ), ], - comparator: automationComparatorValues[event.deviceControlModel.code] ?? '==', + comparator: + automationComparatorValues[event.deviceControlModel.code] ?? '==', ); automationTempTasksList.add(newElement); - automationSelectedValues[newElement.code] = event.deviceControlModel.value; + automationSelectedValues[newElement.code] = + event.deviceControlModel.value; } emit(AddSceneTask( tasksList: tasksList, @@ -192,7 +203,8 @@ class CreateSceneBloc extends Bloc )); } - FutureOr _selectedValue(SelectedValueEvent event, Emitter emit) { + FutureOr _selectedValue( + SelectedValueEvent event, Emitter emit) { if (event.isAutomation == true) { automationSelectedValues[event.code] = event.value; automationComparatorValues[event.code] = event.comparator ?? '=='; @@ -220,7 +232,8 @@ class CreateSceneBloc extends Bloc )); } - FutureOr _removeTaskById(RemoveTaskByIdEvent event, Emitter emit) { + FutureOr _removeTaskById( + RemoveTaskByIdEvent event, Emitter emit) { emit(CreateSceneLoading()); if (event.isAutomation == true) { for (var element in automationTasksList) { @@ -293,7 +306,8 @@ class CreateSceneBloc extends Bloc : await SceneApi.createScene(event.createSceneModel!); } else if (event.createAutomationModel != null) { response = event.updateScene - ? await SceneApi.updateAutomation(event.createAutomationModel!, event.sceneId) + ? await SceneApi.updateAutomation( + event.createAutomationModel!, event.sceneId) : await SceneApi.createAutomation(event.createAutomationModel!); } @@ -322,7 +336,8 @@ class CreateSceneBloc extends Bloc } } - FutureOr _clearTaskList(ClearTaskListEvent event, Emitter emit) { + FutureOr _clearTaskList( + ClearTaskListEvent event, Emitter emit) { emit(CreateSceneLoading()); automationTasksList.clear(); tasksList.clear(); @@ -343,13 +358,27 @@ class CreateSceneBloc extends Bloc : await SceneApi.getSceneDetails(event.sceneId); if (response.id.isNotEmpty) { if (event.isAutomation) { - automationTasksList = List.from(getTaskListFunctionsFromApi( - actions: [], isAutomation: true, conditions: response.conditions)); + automationTasksList = List.from( + getTaskListFunctionsFromApi( + actions: [], + isAutomation: true, + conditions: response.conditions)); tasksList = List.from( - getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false)); + getTaskListFunctionsFromApi( + actions: response.actions, isAutomation: false)); conditionRule = response.decisionExpr ?? conditionRule; + if (response.effectiveTime != null) { + BlocProvider.of( + NavigationService.navigatorKey.currentState!.context) + .add(SetCustomTime(response.effectiveTime!.start, + response.effectiveTime!.end)); + BlocProvider.of( + NavigationService.navigatorKey.currentState!.context) + .add(ToggleDay(response.effectiveTime!.loops)); + } + emit(AddSceneTask( automationTasksList: automationTasksList, tasksList: tasksList, @@ -357,7 +386,8 @@ class CreateSceneBloc extends Bloc )); } else { tasksList = List.from( - getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false)); + getTaskListFunctionsFromApi( + actions: response.actions, isAutomation: false)); emit(AddSceneTask( tasksList: tasksList, condition: conditionRule, @@ -371,7 +401,8 @@ class CreateSceneBloc extends Bloc } } - FutureOr _clearTempTaskList(ClearTempTaskListEvent event, Emitter emit) { + FutureOr _clearTempTaskList( + ClearTempTaskListEvent event, Emitter emit) { emit(CreateSceneLoading()); if (event.isAutomation == true) { automationTempTasksList.clear(); @@ -420,13 +451,17 @@ class CreateSceneBloc extends Bloc } } - FutureOr _deleteScene(DeleteSceneEvent event, Emitter emit) async { + FutureOr _deleteScene( + DeleteSceneEvent event, Emitter emit) async { emit(DeleteSceneLoading()); try { - final response = sceneType.name == CreateSceneEnum.deviceStatusChanges.name - ? await SceneApi.deleteAutomation(automationId: event.sceneId, unitUuid: event.unitUuid) - : await SceneApi.deleteScene(sceneId: event.sceneId, unitUuid: event.unitUuid); + final response = + sceneType.name == CreateSceneEnum.deviceStatusChanges.name + ? await SceneApi.deleteAutomation( + automationId: event.sceneId, unitUuid: event.unitUuid) + : await SceneApi.deleteScene( + sceneId: event.sceneId, unitUuid: event.unitUuid); if (response == true) { emit(const DeleteSceneSuccess(true)); } else { @@ -437,7 +472,8 @@ class CreateSceneBloc extends Bloc } } - FutureOr _updateTaskValue(UpdateTaskEvent event, Emitter emit) { + FutureOr _updateTaskValue( + UpdateTaskEvent event, Emitter emit) { emit(CreateSceneLoading()); if (event.isAutomation == true) { for (var i = 0; i < automationTasksList.length; i++) { @@ -465,7 +501,8 @@ class CreateSceneBloc extends Bloc )); } - FutureOr _selectConditionRule(SelectConditionEvent event, Emitter emit) { + FutureOr _selectConditionRule( + SelectConditionEvent event, Emitter emit) { emit(CreateSceneInitial()); if (event.condition.contains('any')) { conditionRule = 'or'; @@ -480,7 +517,8 @@ class CreateSceneBloc extends Bloc )); } - FutureOr _sceneTypeEvent(SceneTypeEvent event, Emitter emit) { + FutureOr _sceneTypeEvent( + SceneTypeEvent event, Emitter emit) { emit(CreateSceneInitial()); if (event.type == CreateSceneEnum.tabToRun) { diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index 0b0b759..4b75b78 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -608,7 +608,9 @@ mixin SceneOperationsDataHelper { 'Human Presence Sensor', Assets.assetsIconsSensors, 'Current Distance', - OperationDialogType.integerSteps, + isAutomation + ? OperationDialogType.integerSteps + : OperationDialogType.countdown, _createCurrentDistanceOptions(), isAutomation, comparator, diff --git a/lib/features/scene/view/scene_tasks_view.dart b/lib/features/scene/view/scene_tasks_view.dart index a41a191..4ac5b4f 100644 --- a/lib/features/scene/view/scene_tasks_view.dart +++ b/lib/features/scene/view/scene_tasks_view.dart @@ -38,7 +38,7 @@ class SceneTasksView extends StatelessWidget { padding: EdgeInsets.zero, actions: [ Visibility( - visible: sceneSettings.sceneType != CreateSceneEnum.none.name, + visible: sceneSettings.sceneType.isNotEmpty, child: SizedBox( width: 40, child: GestureDetector( diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart index a38c71b..3e986e7 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart @@ -207,7 +207,7 @@ class _AlertDialogSliderStepsState extends State { : null, onChanged: (value) { setState(() { - groupValue = value; + groupValue = normalizeValue(value); }); context.read().add(SelectedValueEvent( value: _deNormalizeValue(groupValue), @@ -228,6 +228,10 @@ class _AlertDialogSliderStepsState extends State { ); } + double normalizeValue(double value) { + return double.parse(value.toStringAsFixed(1)); + } + double _deNormalizeValue(double? value) { if (widget.taskItem.code == "temp_set" || widget.taskItem.code == "temp_current") { diff --git a/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart b/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart index 747e028..66d7164 100644 --- a/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart +++ b/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart @@ -1,6 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; import 'package:syncrow_app/features/scene/widgets/effective_period_setting/period_options.dart'; import 'package:syncrow_app/features/scene/widgets/effective_period_setting/repeat_days.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; @@ -14,29 +12,26 @@ class EffectPeriodBottomSheetContent extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) => EffectPeriodBloc(), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - BodyMedium( - text: 'Effective Period', - fontColor: ColorsManager.primaryColorWithOpacity, - fontWeight: FontsManager.bold, - ), - const Divider( - color: ColorsManager.backgroundColor, - ), - const PeriodOptions( - showCustomTimePicker: EffectPeriodHelper.showCustomTimePicker, - ), - const SizedBox(height: 16), - const RepeatDays(), - const SizedBox(height: 24), - ], - ), + return Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + BodyMedium( + text: 'Effective Period', + fontColor: ColorsManager.primaryColorWithOpacity, + fontWeight: FontsManager.bold, + ), + const Divider( + color: ColorsManager.backgroundColor, + ), + const PeriodOptions( + showCustomTimePicker: EffectPeriodHelper.showCustomTimePicker, + ), + const SizedBox(height: 16), + const RepeatDays(), + const SizedBox(height: 24), + ], ), ); } diff --git a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart index 41595f8..8cbb450 100644 --- a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart +++ b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart @@ -52,8 +52,13 @@ class ThenAddedTasksContainer extends StatelessWidget operationValue = '0°C'; } } else { - final functionValue = + var functionValue = taskItem.functionValue ?? taskItem.operationalValues.first.value; + + if (functionValue is double) { + functionValue = double.parse(functionValue.toStringAsFixed(1)); + } + operationValue = functionValue.toString(); } return DefaultContainer( diff --git a/lib/my_app.dart b/lib/my_app.dart index 0a253bf..f6d7a5b 100644 --- a/lib/my_app.dart +++ b/lib/my_app.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart'; import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart'; import 'package:syncrow_app/navigation/navigation_service.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; @@ -29,8 +30,10 @@ class MyApp extends StatelessWidget { BlocProvider(create: (context) => CreateSceneBloc()), BlocProvider(create: (context) => SceneBloc()), BlocProvider(create: (context) => ProfileBloc()), - BlocProvider(create: (context) => SmartSceneSelectBloc()), - + BlocProvider(create: (context) => SmartSceneSelectBloc()), + BlocProvider( + create: (context) => EffectPeriodBloc(), + ), ], child: MaterialApp( navigatorKey: NavigationService.navigatorKey, From 7d44fa4f1e565e7968316c7a3269cb4fa8ca637d Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Mon, 29 Jul 2024 00:55:44 +0300 Subject: [PATCH 29/30] push hide period for only automation --- .../scene/view/scene_auto_settings.dart | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/features/scene/view/scene_auto_settings.dart b/lib/features/scene/view/scene_auto_settings.dart index 9e117ac..5bc8d44 100644 --- a/lib/features/scene/view/scene_auto_settings.dart +++ b/lib/features/scene/view/scene_auto_settings.dart @@ -37,15 +37,19 @@ class SceneAutoSettings extends StatelessWidget { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ - SceneListTile( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - titleString: "Effective Period", - trailingWidget: const Icon(Icons.arrow_forward_ios_rounded), - onPressed: () { - context.customBottomSheet( - child: const EffectPeriodBottomSheetContent(), - ); - }, + Visibility( + visible: isAutomation == true, + child: SceneListTile( + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + titleString: "Effective Period", + trailingWidget: const Icon(Icons.arrow_forward_ios_rounded), + onPressed: () { + context.customBottomSheet( + child: const EffectPeriodBottomSheetContent(), + ); + }, + ), ), Visibility( visible: sceneName.isNotEmpty, From 0aac9e0dc76692701f5aae1da2326d58f9b7a2d4 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Mon, 29 Jul 2024 01:03:57 +0300 Subject: [PATCH 30/30] push save bottom on teh bottom sheets --- .../effective_period_bottom_sheet.dart | 29 ++++++++++++--- .../smart_automation_list.dart | 36 ++++++++++++++----- .../smart_tab_run_list.dart | 36 ++++++++++++++----- 3 files changed, 81 insertions(+), 20 deletions(-) diff --git a/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart b/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart index 66d7164..659f163 100644 --- a/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart +++ b/lib/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:syncrow_app/features/scene/widgets/effective_period_setting/period_options.dart'; import 'package:syncrow_app/features/scene/widgets/effective_period_setting/repeat_days.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; @@ -17,10 +19,29 @@ class EffectPeriodBottomSheetContent extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - BodyMedium( - text: 'Effective Period', - fontColor: ColorsManager.primaryColorWithOpacity, - fontWeight: FontsManager.bold, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextButton( + onPressed: () => Navigator.pop(context), + child: BodySmall( + text: 'Save', + style: context.bodySmall.copyWith( + color: ColorsManager.primaryColorWithOpacity), + )), + ), + Expanded( + flex: 2, + child: BodyMedium( + text: 'Effective Period', + fontColor: ColorsManager.primaryColorWithOpacity, + fontWeight: FontsManager.bold, + textAlign: TextAlign.center, + ), + ), + const Spacer(), + ], ), const Divider( color: ColorsManager.backgroundColor, diff --git a/lib/features/scene/widgets/select_smart_scene/smart_automation_list.dart b/lib/features/scene/widgets/select_smart_scene/smart_automation_list.dart index 962645f..e987f4a 100644 --- a/lib/features/scene/widgets/select_smart_scene/smart_automation_list.dart +++ b/lib/features/scene/widgets/select_smart_scene/smart_automation_list.dart @@ -7,6 +7,7 @@ import 'package:syncrow_app/features/scene/model/scenes_model.dart'; import 'package:syncrow_app/features/scene/model/smart_scene_enable.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; @@ -53,14 +54,33 @@ class _SmartSceneSelectAutomationListState return Column( mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: BodyMedium( - text: 'Automation', - style: context.bodyMedium.copyWith( - color: ColorsManager.primaryColorWithOpacity, - fontWeight: FontWeight.bold), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextButton( + onPressed: () => Navigator.pop(context), + child: BodySmall( + text: 'Save', + style: context.bodySmall + .copyWith(color: ColorsManager.primaryColorWithOpacity), + )), + ), + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: BodyMedium( + text: 'Automation', + textAlign: TextAlign.center, + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontWeight: FontWeight.bold), + ), + ), + ), + const Spacer(), + ], ), const Divider( color: ColorsManager.dividerColor, diff --git a/lib/features/scene/widgets/select_smart_scene/smart_tab_run_list.dart b/lib/features/scene/widgets/select_smart_scene/smart_tab_run_list.dart index 6fbae23..15fc2b6 100644 --- a/lib/features/scene/widgets/select_smart_scene/smart_tab_run_list.dart +++ b/lib/features/scene/widgets/select_smart_scene/smart_tab_run_list.dart @@ -5,6 +5,7 @@ import 'package:syncrow_app/features/scene/model/scenes_model.dart'; import 'package:syncrow_app/features/scene/model/smart_scene_enable.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; @@ -29,14 +30,33 @@ class _SmartSceneSelectTabToRunListState return Column( mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: BodyMedium( - text: 'Tab To Run', - style: context.bodyMedium.copyWith( - color: ColorsManager.primaryColorWithOpacity, - fontWeight: FontWeight.bold), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextButton( + onPressed: () => Navigator.pop(context), + child: BodySmall( + text: 'Save', + style: context.bodySmall + .copyWith(color: ColorsManager.primaryColorWithOpacity), + )), + ), + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: BodyMedium( + text: 'Tab To Run', + textAlign: TextAlign.center, + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontWeight: FontWeight.bold), + ), + ), + ), + const Spacer(), + ], ), const Divider( color: ColorsManager.dividerColor,