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 {