diff --git a/lib/features/app_layout/bloc/home_cubit.dart b/lib/features/app_layout/bloc/home_cubit.dart index 9168283..bb1863c 100644 --- a/lib/features/app_layout/bloc/home_cubit.dart +++ b/lib/features/app_layout/bloc/home_cubit.dart @@ -18,8 +18,11 @@ 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/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/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/create_automation_model.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'; @@ -385,6 +388,9 @@ class HomeCubit extends Cubit { NavigationService.navigatorKey.currentContext! .read() .add(const SmartSceneClearEvent()); + BlocProvider.of( + NavigationService.navigatorKey.currentState!.context) + .add(ResetEffectivePeriod()); }, ), IconButton( diff --git a/lib/features/devices/view/widgets/scene_listview.dart b/lib/features/devices/view/widgets/scene_listview.dart index cbea49d..d825c6b 100644 --- a/lib/features/devices/view/widgets/scene_listview.dart +++ b/lib/features/devices/view/widgets/scene_listview.dart @@ -1,6 +1,9 @@ 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/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/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/model/scenes_model.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 6ebfcae..915d8af 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -92,30 +92,59 @@ class CreateSceneBloc extends Bloc TempHoldSceneTasksEvent event, Emitter emit) { emit(CreateSceneLoading()); bool updated = false; + + // Check and update if the task exists in tempTasksList for (var element in tempTasksList) { - 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: '', - ), - ], - ); - tempTasksList[tempTasksList.indexOf(element)] = updatedElement; - selectedValues[updatedElement.code] = event.deviceControlModel.value; - updated = true; - break; + 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: '', + ), + ], + ); + tempTasksList[tempTasksList.indexOf(element)] = updatedElement; + selectedValues[updatedElement.code] = event.deviceControlModel.value; + updated = true; + break; + } + + if (!updated) { + /// for smart scene add to view + for (var element in tasksList) { + if (element.deviceId == event.deviceControlModel.deviceId && + element.code == event.deviceControlModel.code) { + 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: '', + ), + ], + ); + tasksList[tasksList.indexOf(element)] = updatedElement; + selectedValues[updatedElement.code] = event.deviceControlModel.value; + updated = true; + break; + } } } + + // Add new element if it doesn't exist in either list if (!updated) { var newElement = SceneStaticFunction( operationName: event.operation, @@ -319,7 +348,8 @@ class CreateSceneBloc extends Bloc automationTempTasksList.clear(); automationSelectedValues.clear(); automationComparatorValues.clear(); - effectiveTime = null; + effectiveTime = + EffectiveTime(start: '00:00', end: '23:59', loops: '1111111'); sceneType = CreateSceneEnum.none; conditionRule = 'or'; emit(const CreateSceneWithTasks(success: true)); @@ -369,14 +399,31 @@ class CreateSceneBloc extends Bloc 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)); + effectiveTime = response.effectiveTime != null + ? EffectiveTime( + start: response.effectiveTime!.start, + end: response.effectiveTime!.end, + loops: response.effectiveTime!.loops, + ) + : EffectiveTime(start: '00:00', end: '23:59', loops: '1111111'); + + // Set Custom Time and reset days first + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(SetCustomTime(effectiveTime!.start, effectiveTime!.end)); + + // Reset all days to not selected before toggling + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(ResetDays()); + + // Iterate over the loops and toggle each day + for (int i = 0; i < effectiveTime!.loops.length; i++) { + if (effectiveTime!.loops[i] == '1') { + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(ToggleDay(_getDayFromIndex(i))); + } } emit(AddSceneTask( @@ -401,6 +448,11 @@ class CreateSceneBloc extends Bloc } } + String _getDayFromIndex(int index) { + const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; + return days[index]; + } + FutureOr _clearTempTaskList( ClearTempTaskListEvent event, Emitter emit) { emit(CreateSceneLoading()); @@ -408,20 +460,15 @@ class CreateSceneBloc extends Bloc automationTempTasksList.clear(); automationSelectedValues.clear(); automationComparatorValues.clear(); - emit(AddSceneTask( - tasksList: tasksList, - automationTasksList: automationTasksList, - condition: conditionRule, - )); } else { tempTasksList.clear(); selectedValues.clear(); - emit(AddSceneTask( - tasksList: tasksList, - automationTasksList: automationTasksList, - condition: conditionRule, - )); } + emit(AddSceneTask( + tasksList: tasksList, + automationTasksList: automationTasksList, + condition: conditionRule, + )); } FutureOr _removeFromSelectedValueById( 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 7fa071c..ea2c501 100644 --- a/lib/features/scene/bloc/effective_period/effect_period_bloc.dart +++ b/lib/features/scene/bloc/effective_period/effect_period_bloc.dart @@ -12,6 +12,8 @@ class EffectPeriodBloc extends Bloc { on(_onSetPeriod); on(_onToggleDay); on(_onSetCustomTime); + on(_onResetEffectivePeriod); + on(_onResetDays); } void _onSetPeriod(SetPeriod event, Emitter emit) { @@ -39,13 +41,15 @@ class EffectPeriodBloc extends Bloc { break; } - // Update CreateSceneBloc BlocProvider.of( - NavigationService.navigatorKey.currentState!.context) + NavigationService.navigatorKey.currentContext!) .add(EffectiveTimePeriodEvent(EffectiveTime( start: startTime, end: endTime, loops: state.selectedDaysBinary))); - emit(state.copyWith(selectedPeriod: event.period)); + emit(state.copyWith( + selectedPeriod: event.period, + customStartTime: startTime, + customEndTime: endTime)); } void _onToggleDay(ToggleDay event, Emitter emit) { @@ -60,7 +64,7 @@ class EffectPeriodBloc extends Bloc { emit(state.copyWith(selectedDaysBinary: newDaysBinary)); BlocProvider.of( - NavigationService.navigatorKey.currentState!.context) + NavigationService.navigatorKey.currentContext!) .add(EffectiveTimePeriodEvent(EffectiveTime( start: state.customStartTime ?? '00:00', end: state.customEndTime ?? '23:59', @@ -68,15 +72,48 @@ class EffectPeriodBloc extends Bloc { } void _onSetCustomTime(SetCustomTime event, Emitter emit) { + String startTime = event.startTime; + String endTime = event.endTime; + EnumEffectivePeriodOptions period; + + // Determine the period based on start and end times + if (startTime == '00:00' && endTime == '23:59') { + period = EnumEffectivePeriodOptions.allDay; + } else if (startTime == '06:00' && endTime == '18:00') { + period = EnumEffectivePeriodOptions.daytime; + } else if (startTime == '18:00' && endTime == '06:00') { + period = EnumEffectivePeriodOptions.night; + } else { + period = EnumEffectivePeriodOptions.custom; + } + emit(state.copyWith( - customStartTime: event.startTime, customEndTime: event.endTime)); + customStartTime: startTime, + customEndTime: endTime, + selectedPeriod: period)); BlocProvider.of( - NavigationService.navigatorKey.currentState!.context) + NavigationService.navigatorKey.currentContext!) .add(EffectiveTimePeriodEvent(EffectiveTime( - start: event.startTime, - end: event.endTime, - loops: state.selectedDaysBinary))); + start: startTime, end: endTime, loops: state.selectedDaysBinary))); + } + + void _onResetEffectivePeriod( + ResetEffectivePeriod event, Emitter emit) { + emit(state.copyWith( + selectedPeriod: EnumEffectivePeriodOptions.allDay, + customStartTime: '00:00', + customEndTime: '23:59', + selectedDaysBinary: '1111111')); + + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(EffectiveTimePeriodEvent( + EffectiveTime(start: '00:00', end: '23:59', loops: '1111111'))); + } + + void _onResetDays(ResetDays event, Emitter emit) { + emit(state.copyWith(selectedDaysBinary: '1111111')); } int _getDayIndex(String day) { 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 809bf82..c628983 100644 --- a/lib/features/scene/bloc/effective_period/effect_period_event.dart +++ b/lib/features/scene/bloc/effective_period/effect_period_event.dart @@ -35,3 +35,10 @@ class SetCustomTime extends EffectPeriodEvent { @override List get props => [startTime, endTime]; } + +class ResetEffectivePeriod extends EffectPeriodEvent {} + +class ResetDays extends EffectPeriodEvent { + @override + List get props => []; +} 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 029652b..2b00a45 100644 --- a/lib/features/scene/bloc/effective_period/effect_period_state.dart +++ b/lib/features/scene/bloc/effective_period/effect_period_state.dart @@ -37,6 +37,18 @@ class EffectPeriodState extends Equatable { ); } + EnumEffectivePeriodOptions getEffectivePeriod() { + if (customStartTime == '00:00' && customEndTime == '23:59') { + return EnumEffectivePeriodOptions.allDay; + } else if (customStartTime == '06:00' && customEndTime == '18:00') { + return EnumEffectivePeriodOptions.daytime; + } else if (customStartTime == '18:00' && customEndTime == '06:00') { + return EnumEffectivePeriodOptions.night; + } else { + return EnumEffectivePeriodOptions.custom; + } + } + @override List get props => [selectedPeriod, selectedDaysBinary, customStartTime, customEndTime]; 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 index 9ef5b8b..a6370d8 100644 --- 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 @@ -18,6 +18,7 @@ class SmartSceneSelectBloc SmartSceneSelectBloc() : super(SmartSceneSelectInitial()) { on(_onSmartSceneEnable); on(_smartSceneClear); + on(_smartSceneConfirmSelection); } SmartSceneEnable? smartSceneEnable; @@ -25,29 +26,6 @@ class SmartSceneSelectBloc FutureOr _onSmartSceneEnable( SmartSceneEnableEvent event, Emitter emit) { smartSceneEnable = event.smartSceneEnable; - NavigationService.navigatorKey.currentState!.context - .read() - .add(TempHoldSceneTasksEvent( - deviceControlModel: DeviceControlModel( - deviceId: smartSceneEnable?.entityId ?? '', - code: CreateSceneEnum.smartSceneSelect.name, - value: '', - ), - deviceId: smartSceneEnable?.sceneORAutomationName ?? '', - operation: smartSceneEnable?.actionExecutor ?? '', - icon: smartSceneEnable?.isAutomation == true - ? Assets.player - : Assets.handClickIcon, - deviceName: smartSceneEnable?.sceneORAutomationName ?? '', - uniqueId: '', - operationType: OperationDialogType.none, - isAutomation: false, - )); - - emit(SmartSceneSelected(smartSceneEnable: smartSceneEnable!)); - NavigationService.navigatorKey.currentState!.context - .read() - .add(const AddTaskEvent(isAutomation: false)); } FutureOr _smartSceneClear( @@ -55,4 +33,33 @@ class SmartSceneSelectBloc smartSceneEnable = null; emit(SmartSceneSelectInitial()); } + + FutureOr _smartSceneConfirmSelection( + SmartSceneConfirmSelectionEvent event, + Emitter emit) { + final createSceneBloc = NavigationService.navigatorKey.currentState!.context + .read(); + + createSceneBloc.add(TempHoldSceneTasksEvent( + deviceControlModel: DeviceControlModel( + deviceId: smartSceneEnable?.entityId ?? '', + code: CreateSceneEnum.smartSceneSelect.name, + value: smartSceneEnable?.actionExecutor ?? '', + ), + deviceId: smartSceneEnable?.entityId ?? '', + operation: smartSceneEnable?.type ?? '', + icon: smartSceneEnable?.isAutomation == true + ? Assets.player + : Assets.handClickIcon, + deviceName: smartSceneEnable?.sceneORAutomationName ?? '', + uniqueId: smartSceneEnable?.entityId ?? '', + operationType: OperationDialogType.none, + isAutomation: false, + )); + + emit(SmartSceneSelected(smartSceneEnable: smartSceneEnable!)); + NavigationService.navigatorKey.currentState!.context + .read() + .add(const AddTaskEvent(isAutomation: false)); + } } 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 index ecdf30a..ce70e65 100644 --- 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 @@ -19,3 +19,7 @@ class SmartSceneEnableEvent extends SmartSceneSelectEvent { class SmartSceneClearEvent extends SmartSceneSelectEvent { const SmartSceneClearEvent(); } + +class SmartSceneConfirmSelectionEvent extends SmartSceneSelectEvent { + const SmartSceneConfirmSelectionEvent(); +} diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 887370f..35dea80 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -2,7 +2,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/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/enum/operation_dialog_type.dart'; import 'package:syncrow_app/features/scene/model/create_automation_model.dart'; @@ -31,7 +30,6 @@ mixin SceneLogicHelper { required List conditions, }) { final sceneBloc = context.read(); - final smartSceneBloc = context.read(); if (isOnlyDelayOrDelayLast(actions)) { context.showCustomSnackbar( @@ -85,9 +83,8 @@ mixin SceneLogicHelper { } if (task.code == CreateSceneEnum.smartSceneSelect.name) { return CreateSceneAction( - entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '', - actionExecutor: - smartSceneBloc.smartSceneEnable?.actionExecutor ?? '', + entityId: actions[index].deviceId, + actionExecutor: actions[index].functionValue, executorProperty: null); } return CreateSceneAction( @@ -132,9 +129,8 @@ mixin SceneLogicHelper { } if (task.code == CreateSceneEnum.smartSceneSelect.name) { return CreateSceneAction( - entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '', - actionExecutor: - smartSceneBloc.smartSceneEnable?.actionExecutor ?? '', + entityId: actions[index].deviceId, + actionExecutor: actions[index].functionValue, executorProperty: null); } return CreateSceneAction( @@ -190,4 +186,16 @@ mixin SceneLogicHelper { isAutomation: isAutomation, ); } + + String getTaskDescription(SceneStaticFunction taskItem) { + if (taskItem.code == CreateSceneEnum.smartSceneSelect.name) { + if (taskItem.operationName == 'automation') { + return 'Automation: '; + } else { + return 'Tab-To-Run: '; + } + } else { + return "${taskItem.operationName}: "; + } + } } diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index 4b75b78..e2bb943 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/create_scene_enum.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'; @@ -171,13 +172,43 @@ mixin SceneOperationsDataHelper { icon: Assets.delay, operationName: 'delay', operationDialogType: OperationDialogType.delay, - functionValue: action.executorProperty.delaySeconds, + functionValue: action.executorProperty?.delaySeconds, code: '', operationalValues: [ SceneOperationalValue( icon: '', description: "", - value: action.executorProperty.delaySeconds, + value: action.executorProperty?.delaySeconds, + ), + ], + ), + ); + } else if (action.name != null && action.type != null) { + // Handle smart scenes + functions.add( + SceneStaticFunction( + deviceId: action.entityId, + deviceName: action.name.toString(), + deviceIcon: action.type == 'automation' + ? Assets.player + : Assets.handClickIcon, + icon: action.type == 'automation' + ? Assets.player + : Assets.handClickIcon, + operationName: action.type.toString(), + operationDialogType: OperationDialogType.onOff, + functionValue: action.actionExecutor, + code: CreateSceneEnum.smartSceneSelect.name, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "Enable", + value: 'rule_enable', + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "Disable", + value: 'rule_disable', ), ], ), @@ -260,7 +291,7 @@ mixin SceneOperationsDataHelper { 'factory_reset': _createFactoryResetFunction, }; - final functionCode = executorProperty.functionCode ?? ''; + final functionCode = executorProperty?.functionCode ?? ''; final createFunction = functionMap[functionCode]; if (createFunction != null) { return createFunction(action, isAutomation, comparator); @@ -279,7 +310,7 @@ mixin SceneOperationsDataHelper { bool isAutomation, [ String? comparator, ]) { - final functionValue = action.executorProperty.functionValue; + final functionValue = action.executorProperty?.functionValue; return SceneStaticFunction( deviceId: action.entityId, deviceName: deviceName, @@ -287,7 +318,7 @@ mixin SceneOperationsDataHelper { icon: icon, operationName: operationName, functionValue: functionValue, - code: action.executorProperty.functionCode ?? '', + code: action.executorProperty?.functionCode ?? '', operationDialogType: operationDialogType, operationalValues: operationalValues, comparator: comparator ?? '==', @@ -1168,7 +1199,36 @@ mixin SceneOperationsDataHelper { ), ]; } - + if (taskItem.code == CreateSceneEnum.smartSceneSelect.name) { + return [ + SceneStaticFunction( + deviceId: taskItem.deviceId, + deviceName: taskItem.deviceName.toString(), + deviceIcon: taskItem.operationName == 'automation' + ? Assets.player + : Assets.handClickIcon, + icon: taskItem.operationName == 'automation' + ? Assets.player + : Assets.handClickIcon, + operationName: taskItem.operationName, + operationDialogType: OperationDialogType.onOff, + functionValue: taskItem.functionValue == 'rule_enable' ? true : false, + code: CreateSceneEnum.smartSceneSelect.name, + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "Enable", + value: 'rule_enable', + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "Disable", + value: 'rule_disable', + ), + ], + ), + ]; + } return [ _mapExecutorPropertyToSceneFunction( Action( diff --git a/lib/features/scene/model/scene_details_model.dart b/lib/features/scene/model/scene_details_model.dart index 3c40476..646b3b1 100644 --- a/lib/features/scene/model/scene_details_model.dart +++ b/lib/features/scene/model/scene_details_model.dart @@ -65,19 +65,31 @@ class SceneDetailsModel { class Action { final String actionExecutor; final String entityId; - final ExecutorProperty executorProperty; + ExecutorProperty? executorProperty; + String? name; + String? type; Action({ required this.actionExecutor, required this.entityId, - required this.executorProperty, + this.executorProperty, + this.name, + this.type, }); String toRawJson() => json.encode(toJson()); static Action? fromJson(Map json) { + if (json['name'] != null && json['type'] != null) { + return Action( + actionExecutor: json["actionExecutor"], + entityId: json["entityId"], + name: json['name'], + type: json['type'], + ); + } if (json["executorProperty"] == null) { - return null; // Return null if executorProperty is not present + return null; } return Action( @@ -90,7 +102,7 @@ class Action { Map toJson() => { "actionExecutor": actionExecutor, "entityId": entityId, - "executorProperty": executorProperty.toJson(), + "executorProperty": executorProperty?.toJson(), }; } diff --git a/lib/features/scene/model/smart_scene_enable.dart b/lib/features/scene/model/smart_scene_enable.dart index 40a2d8c..0195b7f 100644 --- a/lib/features/scene/model/smart_scene_enable.dart +++ b/lib/features/scene/model/smart_scene_enable.dart @@ -3,12 +3,14 @@ class SmartSceneEnable { final String actionExecutor; final String sceneORAutomationName; final bool isAutomation; + final String type; SmartSceneEnable({ required this.entityId, required this.actionExecutor, required this.sceneORAutomationName, required this.isAutomation, + required this.type, }); factory SmartSceneEnable.fromJson(Map json) { @@ -17,6 +19,7 @@ class SmartSceneEnable { actionExecutor: json['actionExecutor'], sceneORAutomationName: json['sceneORAutomationName'], isAutomation: json['isAutomation'], + type: json['type'], ); } @@ -26,6 +29,7 @@ class SmartSceneEnable { 'actionExecutor': actionExecutor, 'sceneORAutomationName': sceneORAutomationName, 'isAutomation': isAutomation, + 'type': type, }; } } diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index bb9c48f..23a874b 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -24,17 +24,12 @@ class DeviceFunctionsView extends StatelessWidget @override Widget build(BuildContext context) { - /// this whole widget needs a refactor later - /// - /// static functions based on type 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 List functions = []; if (device.functions.isNotEmpty) { functions = getFunctionsWithIcons( @@ -47,128 +42,133 @@ class DeviceFunctionsView extends StatelessWidget } return DefaultScaffold( - title: getTitle(type: device.productType), - actions: [ - TextButton( - onPressed: () { - context - .read() - .add(AddTaskEvent(isAutomation: isAutomation)); - navigateToRoute(context, Routes.sceneTasksRoute); - }, - child: BodyMedium( - text: 'Save', - fontWeight: FontWeight.normal, - fontColor: ColorsManager.secondaryColor.withOpacity(0.6), - ), - ), - ], - leading: TextButton( + title: getTitle(type: device.productType), + actions: [ + TextButton( onPressed: () { - 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 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); + context + .read() + .add(AddTaskEvent(isAutomation: isAutomation)); + navigateToRoute(context, Routes.sceneTasksRoute); }, child: BodyMedium( - text: 'Cancel', + text: 'Save', fontWeight: FontWeight.normal, - fontColor: ColorsManager.textPrimaryColor.withOpacity(0.6), + fontColor: ColorsManager.secondaryColor.withOpacity(0.6), ), ), - leadingWidth: 80, - padding: EdgeInsets.zero, - child: ListView.builder( - shrinkWrap: true, - itemCount: functions.length, - padding: const EdgeInsets.only(top: 24.0), - 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: () { - if (isAutomation) { - _showAutomationDialog( - context, - functions[index], - device, - ); - } else { - _showTabToRunDialog( - context, - functions[index], - device, - ); - } - }, - ); - }, - ), - index != functions.length - 1 - ? SizedBox( - width: context.width * 0.8, - child: const LightDivider()) - : const SizedBox(), - ], - ), - ); - }, - )); + ], + leading: TextButton( + onPressed: () { + _cancelOperation(context, device, isAutomation); + }, + child: BodyMedium( + text: 'Cancel', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.textPrimaryColor.withOpacity(0.6), + ), + ), + leadingWidth: 80, + padding: EdgeInsets.zero, + child: ListView.builder( + shrinkWrap: true, + itemCount: functions.length, + padding: const EdgeInsets.only(top: 24.0), + 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: [ + Icon( + Icons.arrow_forward_ios_rounded, + color: ColorsManager.greyColor, + size: 16, + ), + ], + ), + onPressed: () { + if (isAutomation) { + _showAutomationDialog( + context, + functions[index], + device, + ); + } else { + _showTabToRunDialog( + context, + functions[index], + device, + ); + } + }, + ); + }, + ), + index != functions.length - 1 + ? SizedBox( + width: context.width * 0.8, child: const LightDivider()) + : const SizedBox(), + ], + ), + ); + }, + ), + ); + } + + void _cancelOperation( + BuildContext context, DeviceModel device, bool isAutomation) { + final createSceneBloc = context.read(); + final automationSelectedValue = createSceneBloc.automationSelectedValues; + if (automationSelectedValue.isNotEmpty) { + for (var element in device.functions) { + if (automationSelectedValue.containsKey(element.code)) { + createSceneBloc.add( + RemoveTempTaskByIdEvent(code: element.code!, isAutomation: true)); + createSceneBloc.add(RemoveFromSelectedValueById( + code: element.code!, isAutomation: true)); + } + } + } + + final selectedValue = createSceneBloc.selectedValues; + if (selectedValue.isNotEmpty) { + for (var element in device.functions) { + if (selectedValue.containsKey(element.code)) { + createSceneBloc.add(RemoveTempTaskByIdEvent(code: element.code!)); + createSceneBloc.add(RemoveFromSelectedValueById(code: element.code!)); + } + } + } + + Navigator.pop(context); + + createSceneBloc.add(const ClearTempTaskListEvent(isAutomation: false)); + createSceneBloc.add(const ClearTempTaskListEvent(isAutomation: true)); } void _showTabToRunDialog( diff --git a/lib/features/scene/view/scene_auto_settings.dart b/lib/features/scene/view/scene_auto_settings.dart index 5bc8d44..fe39b09 100644 --- a/lib/features/scene/view/scene_auto_settings.dart +++ b/lib/features/scene/view/scene_auto_settings.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/view/scene_tasks_view.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'; +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'; import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; @@ -17,7 +20,8 @@ class SceneAutoSettings extends StatelessWidget { ModalRoute.of(context)!.settings.arguments as Map? ?? {}; final sceneId = sceneSettings['sceneId'] as String? ?? ''; - final isAutomation = sceneSettings['isAutomation'] as bool? ?? false; + final isAutomation = context.read().sceneType == + CreateSceneEnum.deviceStatusChanges; final sceneName = sceneSettings['sceneName'] as String? ?? ''; return Scaffold( @@ -31,35 +35,79 @@ class SceneAutoSettings extends StatelessWidget { fontWeight: FontsManager.bold, ), ), - body: DefaultContainer( - padding: EdgeInsets.zero, - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - 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(), - ); - }, + body: Stack( + children: [ + Container( + width: double.infinity, + height: context.height, + decoration: const BoxDecoration( + color: ColorsManager.backgroundColor, + image: DecorationImage( + image: AssetImage( + Assets.assetsImagesBackground, + ), + fit: BoxFit.cover, + opacity: 0.4, ), ), - Visibility( - visible: sceneName.isNotEmpty, - child: DeleteBottomSheetContent( - isAutomation: isAutomation, - sceneId: sceneId, + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + constraints: const BoxConstraints( + maxWidth: 600, + maxHeight: 300, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const SizedBox( + height: 8, + ), + 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, + child: SizedBox( + width: context.width * 0.9, + child: const Divider( + color: ColorsManager.greyColor, + ), + ), + ), + Visibility( + visible: sceneName.isNotEmpty, + child: DeleteBottomSheetContent( + isAutomation: isAutomation, + sceneId: sceneId, + ), + ), + const SizedBox( + height: 16, + ), + ], ), ), - ], - ), + ), + ], ), ); } diff --git a/lib/features/scene/view/scene_tasks_view.dart b/lib/features/scene/view/scene_tasks_view.dart index 9cfea64..619353f 100644 --- a/lib/features/scene/view/scene_tasks_view.dart +++ b/lib/features/scene/view/scene_tasks_view.dart @@ -11,7 +11,6 @@ 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'; import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_container.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'; import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/navigation/navigate_to_route.dart'; @@ -125,44 +124,39 @@ class DeleteBottomSheetContent extends StatelessWidget { @override Widget build(BuildContext context) { - return DefaultContainer( - 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, - ), + return 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 SceneListTile( + onPressed: () { + context.read().add(DeleteSceneEvent( + sceneId: sceneId, + unitUuid: HomeCubit.getInstance().selectedSpace!.id!, )); }, - )); + 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/effective_period_setting/period_options.dart b/lib/features/scene/widgets/effective_period_setting/period_options.dart index cdc4088..4fed34c 100644 --- a/lib/features/scene/widgets/effective_period_setting/period_options.dart +++ b/lib/features/scene/widgets/effective_period_setting/period_options.dart @@ -39,11 +39,11 @@ class PeriodOptions extends StatelessWidget { state.customStartTime != null && state.customEndTime != null ? BodySmall( text: - '${"${state.customStartTime} AM"} - ${"${state.customEndTime} PM"}', + '${"${state.customStartTime}"} - ${"${state.customEndTime}"}', style: context.bodySmall.copyWith(fontSize: 10), ) : BodySmall( - text: '00:00 AM - 11:59 PM', + text: '00:00 - 23:59', style: context.bodySmall.copyWith(fontSize: 10), ), trailing: Radio( 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 8f7f4ee..1af98c4 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 @@ -4,12 +4,14 @@ 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/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/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/scene_list_tile.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/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/generated/assets.dart'; @@ -63,7 +65,8 @@ class ThenAddedTasksContainer extends StatelessWidget operationValue = functionValue.toString(); } return DefaultContainer( - onTap: taskItem.code == CreateSceneEnum.smartSceneSelect.name + onTap: taskItem.operationName == 'tap_to_run' || + taskItem.operationName == 'scene' ? null : () { List functionOperation = []; @@ -74,51 +77,77 @@ class ThenAddedTasksContainer extends StatelessWidget deviceId: taskItem.deviceId, isAutomation: isAutomation ?? false)); - /// show alert dialog based on type - context.customAlertDialog( - alertBody: getTheCorrectDialogBody( - functionOperation.first, null, - isAutomation: isAutomation ?? false), - title: functionOperation.first.operationName, - onConfirm: () { - final savedCode = - functionOperation.first.deviceId.contains('delay') - ? 'delay' - : functionOperation.first.code; - if (isAutomation == true) { - final automationSelectedValue = - createSceneBloc.automationSelectedValues[savedCode]; + if (taskItem.code == CreateSceneEnum.smartSceneSelect.name) { + context.customAlertDialog( + alertBody: EnableDisableAutomationDialog( + automationId: taskItem.deviceId, + descriptionSelected: taskItem.functionValue == 'rule_enable' + ? 'Enable' + : "Disable", + sceneORAutomationName: taskItem.deviceName, + type: taskItem.operationName, + ), + title: taskItem.deviceName, + onConfirm: () { + context + .read() + .add(const SmartSceneConfirmSelectionEvent()); + Navigator.pop(context); + }, + onDismiss: () { + context + .read() + .add(const SmartSceneClearEvent()); + Navigator.pop(context); + }, + ); + } else { + /// show alert dialog based on type + context.customAlertDialog( + alertBody: getTheCorrectDialogBody( + functionOperation.first, null, + isAutomation: isAutomation ?? false), + title: functionOperation.first.operationName, + onConfirm: () { + final savedCode = + functionOperation.first.deviceId.contains('delay') + ? 'delay' + : functionOperation.first.code; + if (isAutomation == true) { + final automationSelectedValue = + createSceneBloc.automationSelectedValues[savedCode]; - try { - createSceneBloc.add( - UpdateTaskEvent( - newValue: automationSelectedValue, - taskId: taskItem.uniqueCustomId, - isAutomation: true, - ), - ); - } 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'); + } } - } 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); - }, - ); + Navigator.pop(context); + }, + ); + } }, padding: EdgeInsets.zero, child: Dismissible( @@ -155,6 +184,9 @@ class ThenAddedTasksContainer extends StatelessWidget taskId: removeFunctionById, )); } + context + .read() + .add(const SmartSceneClearEvent()); String removeFunction = "${taskItem.operationName} with value ${taskItem.operationalValues.first.value}"; @@ -177,17 +209,13 @@ class ThenAddedTasksContainer extends StatelessWidget subtitleWidget: Row( children: [ BodyMedium( - text: taskItem.code == CreateSceneEnum.smartSceneSelect.name - ? taskItem.icon.contains('player') - ? 'Automation: ' - : "Tab-To-Run: " - : "${taskItem.operationName}: ", + text: getTaskDescription(taskItem), fontColor: ColorsManager.secondaryTextColor, fontWeight: FontWeight.normal, ), BodyMedium( text: taskItem.code == CreateSceneEnum.smartSceneSelect.name - ? taskItem.operationName == 'rule_enable' + ? taskItem.functionValue == 'rule_enable' ? 'Enable' : "Disable" : operationValue, 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 0dc4fff..b82d637 100644 --- a/lib/features/scene/widgets/scene_view_widget/scene_item.dart +++ b/lib/features/scene/widgets/scene_view_widget/scene_item.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/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/scenes_model.dart'; import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; @@ -45,6 +46,7 @@ class SceneItem extends StatelessWidget { sceneName: scene.name, ), ); + context.read().add(const SmartSceneClearEvent()); if (disablePlayButton == false) { BlocProvider.of(context) .add(const SceneTypeEvent(CreateSceneEnum.tabToRun)); 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 afdef0f..8ea2aaa 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 @@ -126,9 +126,13 @@ class _SmartSceneSelectAutomationListState automationId: automation.id, descriptionSelected: descriptionSelected, sceneORAutomationName: automation.name, + type: automation.type, ), title: automation.name, onConfirm: () { + context + .read() + .add(const SmartSceneConfirmSelectionEvent()); Navigator.pop(context); }, onDismiss: () { @@ -159,9 +163,13 @@ class _SmartSceneSelectAutomationListState automationId: automation.id, descriptionSelected: descriptionSelected, sceneORAutomationName: automation.name, + type: automation.type, ), title: automation.name, onConfirm: () { + context + .read() + .add(const SmartSceneConfirmSelectionEvent()); Navigator.pop(context); }, onDismiss: () { @@ -194,11 +202,13 @@ class EnableDisableAutomationDialog extends StatefulWidget { required this.automationId, required this.descriptionSelected, required this.sceneORAutomationName, + required this.type, }); final String automationId; final String descriptionSelected; final String sceneORAutomationName; + final String type; @override State createState() => @@ -226,6 +236,14 @@ class _EnableDisableAutomationDialogState super.initState(); groupValue = widget.descriptionSelected == 'Enable' ? 'rule_enable' : 'rule_disable'; + + context.read().add(SmartSceneEnableEvent( + SmartSceneEnable( + entityId: widget.automationId, + actionExecutor: groupValue!, + sceneORAutomationName: widget.sceneORAutomationName, + type: widget.type, + isAutomation: true))); } @override @@ -259,6 +277,7 @@ class _EnableDisableAutomationDialogState actionExecutor: value!, sceneORAutomationName: widget.sceneORAutomationName, + type: widget.type, isAutomation: true), )); }, @@ -274,6 +293,7 @@ class _EnableDisableAutomationDialogState entityId: widget.automationId, actionExecutor: operation.value, sceneORAutomationName: widget.sceneORAutomationName, + type: widget.type, isAutomation: true, ), )); 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 384b52a..6d6b65d 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 @@ -25,6 +25,7 @@ class SmartSceneSelectTabToRunList extends StatefulWidget { class _SmartSceneSelectTabToRunListState extends State { String groupValue = ''; + @override Widget build(BuildContext context) { return Column( @@ -67,6 +68,13 @@ class _SmartSceneSelectTabToRunListState itemCount: widget.scenes.length, itemBuilder: (context, index) { final scene = widget.scenes[index]; + final selectedScene = + context.read().smartSceneEnable; + if (selectedScene != null) { + if (scene.id == selectedScene.entityId) { + groupValue = scene.id; + } + } return SceneListTile( padding: const EdgeInsets.symmetric(horizontal: 10), leadingWidget: Image.asset( @@ -84,14 +92,19 @@ class _SmartSceneSelectTabToRunListState setState(() { groupValue = value; }); + context .read() .add(SmartSceneEnableEvent(SmartSceneEnable( entityId: scene.id, actionExecutor: 'rule_enable', sceneORAutomationName: scene.name, + type: scene.type, isAutomation: false, ))); + context + .read() + .add(const SmartSceneConfirmSelectionEvent()); } }), onPressed: () { @@ -104,8 +117,12 @@ class _SmartSceneSelectTabToRunListState entityId: scene.id, actionExecutor: 'rule_enable', sceneORAutomationName: scene.name, + type: scene.type, isAutomation: false, ))); + context + .read() + .add(const SmartSceneConfirmSelectionEvent()); }, ); }), diff --git a/lib/my_app.dart b/lib/my_app.dart index f6d7a5b..e3317d9 100644 --- a/lib/my_app.dart +++ b/lib/my_app.dart @@ -27,13 +27,13 @@ class MyApp extends StatelessWidget { return MultiBlocProvider( providers: [ BlocProvider(create: (context) => AuthCubit()), - BlocProvider(create: (context) => CreateSceneBloc()), - BlocProvider(create: (context) => SceneBloc()), - BlocProvider(create: (context) => ProfileBloc()), - BlocProvider(create: (context) => SmartSceneSelectBloc()), BlocProvider( create: (context) => EffectPeriodBloc(), ), + BlocProvider(create: (context) => SmartSceneSelectBloc()), + BlocProvider(create: (context) => CreateSceneBloc()), + BlocProvider(create: (context) => SceneBloc()), + BlocProvider(create: (context) => ProfileBloc()), ], child: MaterialApp( navigatorKey: NavigationService.navigatorKey,