rule_disable selected & CreateAutomation actionType

This commit is contained in:
mohammad
2024-12-02 16:49:44 +03:00
parent ff4ce8ed01
commit 2f5c5d7da1
4 changed files with 169 additions and 91 deletions

View File

@ -53,7 +53,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
TriggerSwitchTabsEvent event, TriggerSwitchTabsEvent event,
Emitter<RoutineState> emit, Emitter<RoutineState> emit,
) { ) {
emit(state.copyWith(routineTab: event.isRoutineTab, createRoutineView: false)); emit(state.copyWith(
routineTab: event.isRoutineTab, createRoutineView: false));
add(ResetRoutineState()); add(ResetRoutineState());
if (event.isRoutineTab) { if (event.isRoutineTab) {
add(const LoadScenes(spaceId, communityId)); add(const LoadScenes(spaceId, communityId));
@ -72,8 +73,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems); final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems);
// Find the index of the item in teh current itemsList // Find the index of the item in teh current itemsList
int index = int index = updatedIfItems.indexWhere(
updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
// Replace the map if the index is valid // Replace the map if the index is valid
if (index != -1) { if (index != -1) {
updatedIfItems[index] = event.item; updatedIfItems[index] = event.item;
@ -82,18 +83,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
if (event.isTabToRun) { if (event.isTabToRun) {
emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: true, isAutomation: false)); emit(state.copyWith(
ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
} else { } else {
emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: false, isAutomation: true)); emit(state.copyWith(
ifItems: updatedIfItems, isTabToRun: false, isAutomation: true));
} }
} }
void _onAddToThenContainer(AddToThenContainer event, Emitter<RoutineState> emit) { void _onAddToThenContainer(
AddToThenContainer event, Emitter<RoutineState> emit) {
final currentItems = List<Map<String, dynamic>>.from(state.thenItems); final currentItems = List<Map<String, dynamic>>.from(state.thenItems);
// Find the index of the item in teh current itemsList // Find the index of the item in teh current itemsList
int index = int index = currentItems.indexWhere(
currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
// Replace the map if the index is valid // Replace the map if the index is valid
if (index != -1) { if (index != -1) {
currentItems[index] = event.item; currentItems[index] = event.item;
@ -104,22 +108,26 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
emit(state.copyWith(thenItems: currentItems)); emit(state.copyWith(thenItems: currentItems));
} }
void _onAddFunctionsToRoutine(AddFunctionToRoutine event, Emitter<RoutineState> emit) { void _onAddFunctionsToRoutine(
AddFunctionToRoutine event, Emitter<RoutineState> emit) {
try { try {
if (event.functions.isEmpty) return; if (event.functions.isEmpty) return;
List<DeviceFunctionData> selectedFunction = List<DeviceFunctionData>.from(event.functions); List<DeviceFunctionData> selectedFunction =
List<DeviceFunctionData>.from(event.functions);
Map<String, List<DeviceFunctionData>> currentSelectedFunctions = Map<String, List<DeviceFunctionData>> currentSelectedFunctions =
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions); Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) { if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
List<DeviceFunctionData> currentFunctions = List<DeviceFunctionData> currentFunctions =
List<DeviceFunctionData>.from(currentSelectedFunctions[event.uniqueCustomId] ?? []); List<DeviceFunctionData>.from(
currentSelectedFunctions[event.uniqueCustomId] ?? []);
List<String> functionCode = []; List<String> functionCode = [];
for (int i = 0; i < selectedFunction.length; i++) { for (int i = 0; i < selectedFunction.length; i++) {
for (int j = 0; j < currentFunctions.length; j++) { for (int j = 0; j < currentFunctions.length; j++) {
if (selectedFunction[i].functionCode == currentFunctions[j].functionCode) { if (selectedFunction[i].functionCode ==
currentFunctions[j].functionCode) {
currentFunctions[j] = selectedFunction[i]; currentFunctions[j] = selectedFunction[i];
if (!functionCode.contains(currentFunctions[j].functionCode)) { if (!functionCode.contains(currentFunctions[j].functionCode)) {
functionCode.add(currentFunctions[j].functionCode); functionCode.add(currentFunctions[j].functionCode);
@ -129,13 +137,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
for (int i = 0; i < functionCode.length; i++) { for (int i = 0; i < functionCode.length; i++) {
selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]); selectedFunction
.removeWhere((code) => code.functionCode == functionCode[i]);
} }
currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions) currentSelectedFunctions[event.uniqueCustomId] =
..addAll(selectedFunction); List.from(currentFunctions)..addAll(selectedFunction);
} else { } else {
currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions); currentSelectedFunctions[event.uniqueCustomId] =
List.from(event.functions);
} }
emit(state.copyWith(selectedFunctions: currentSelectedFunctions)); emit(state.copyWith(selectedFunctions: currentSelectedFunctions));
@ -144,11 +154,13 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
Future<void> _onLoadScenes(LoadScenes event, Emitter<RoutineState> emit) async { Future<void> _onLoadScenes(
LoadScenes event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null)); emit(state.copyWith(isLoading: true, errorMessage: null));
try { try {
final scenes = await SceneApi.getScenesByUnitId(event.unitId, event.communityId); final scenes =
await SceneApi.getScenesByUnitId(event.unitId, event.communityId);
emit(state.copyWith( emit(state.copyWith(
scenes: scenes, scenes: scenes,
isLoading: false, isLoading: false,
@ -163,7 +175,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
Future<void> _onLoadAutomation(LoadAutomation event, Emitter<RoutineState> emit) async { Future<void> _onLoadAutomation(
LoadAutomation event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null)); emit(state.copyWith(isLoading: true, errorMessage: null));
try { try {
@ -191,14 +204,16 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
FutureOr<void> _onSearchRoutines(SearchRoutines event, Emitter<RoutineState> emit) async { FutureOr<void> _onSearchRoutines(
SearchRoutines event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null)); emit(state.copyWith(isLoading: true, errorMessage: null));
await Future.delayed(const Duration(seconds: 1)); await Future.delayed(const Duration(seconds: 1));
emit(state.copyWith(isLoading: false, errorMessage: null)); emit(state.copyWith(isLoading: false, errorMessage: null));
emit(state.copyWith(searchText: event.query)); emit(state.copyWith(searchText: event.query));
} }
FutureOr<void> _onAddSelectedIcon(AddSelectedIcon event, Emitter<RoutineState> emit) { FutureOr<void> _onAddSelectedIcon(
AddSelectedIcon event, Emitter<RoutineState> emit) {
emit(state.copyWith(selectedIcon: event.icon)); emit(state.copyWith(selectedIcon: event.icon));
} }
@ -212,7 +227,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
return actions.last['deviceId'] == 'delay'; return actions.last['deviceId'] == 'delay';
} }
Future<void> _onCreateScene(CreateSceneEvent event, Emitter<RoutineState> emit) async { Future<void> _onCreateScene(
CreateSceneEvent event, Emitter<RoutineState> emit) async {
try { try {
// Check if first action is delay // Check if first action is delay
if (_isFirstActionDelay(state.thenItems)) { if (_isFirstActionDelay(state.thenItems)) {
@ -238,6 +254,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
return functions.map((function) { return functions.map((function) {
if (function.functionCode == 'automation') { if (function.functionCode == 'automation') {
return CreateSceneAction( return CreateSceneAction(
actionType: 'automation',
entityId: function.entityId, entityId: function.entityId,
actionExecutor: function.value, actionExecutor: function.value,
executorProperty: null, executorProperty: null,
@ -257,6 +274,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
return CreateSceneAction( return CreateSceneAction(
actionType: 'scene',
entityId: function.entityId, entityId: function.entityId,
actionExecutor: 'device_issue', actionExecutor: 'device_issue',
executorProperty: CreateSceneExecutorProperty( executorProperty: CreateSceneExecutorProperty(
@ -296,7 +314,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
Future<void> _onCreateAutomation(CreateAutomationEvent event, Emitter<RoutineState> emit) async { Future<void> _onCreateAutomation(
CreateAutomationEvent event, Emitter<RoutineState> emit) async {
try { try {
if (state.routineName == null || state.routineName!.isEmpty) { if (state.routineName == null || state.routineName!.isEmpty) {
emit(state.copyWith( emit(state.copyWith(
@ -353,6 +372,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
return functions.map((function) { return functions.map((function) {
if (function.functionCode == 'automation') { if (function.functionCode == 'automation') {
return AutomationAction( return AutomationAction(
actionType: 'automation',
entityId: function.entityId,
actionExecutor: function.value,
);
}
if (function.functionCode == 'tap_to_run') {
return AutomationAction(
actionType: 'scene',
entityId: function.entityId, entityId: function.entityId,
actionExecutor: function.value, actionExecutor: function.value,
); );
@ -411,17 +439,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
FutureOr<void> _onRemoveDragCard(RemoveDragCard event, Emitter<RoutineState> emit) { FutureOr<void> _onRemoveDragCard(
RemoveDragCard event, Emitter<RoutineState> emit) {
if (event.isFromThen) { if (event.isFromThen) {
final thenItems = List<Map<String, dynamic>>.from(state.thenItems); final thenItems = List<Map<String, dynamic>>.from(state.thenItems);
final selectedFunctions = Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions); final selectedFunctions =
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
thenItems.removeAt(event.index); thenItems.removeAt(event.index);
selectedFunctions.remove(event.key); selectedFunctions.remove(event.key);
emit(state.copyWith(thenItems: thenItems, selectedFunctions: selectedFunctions)); emit(state.copyWith(
thenItems: thenItems, selectedFunctions: selectedFunctions));
} else { } else {
final ifItems = List<Map<String, dynamic>>.from(state.ifItems); final ifItems = List<Map<String, dynamic>>.from(state.ifItems);
final selectedFunctions = Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions); final selectedFunctions =
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
ifItems.removeAt(event.index); ifItems.removeAt(event.index);
selectedFunctions.remove(event.key); selectedFunctions.remove(event.key);
@ -432,7 +464,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
isAutomation: false, isAutomation: false,
isTabToRun: false)); isTabToRun: false));
} else { } else {
emit(state.copyWith(ifItems: ifItems, selectedFunctions: selectedFunctions)); emit(state.copyWith(
ifItems: ifItems, selectedFunctions: selectedFunctions));
} }
} }
} }
@ -444,18 +477,23 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
)); ));
} }
FutureOr<void> _onEffectiveTimeEvent(EffectiveTimePeriodEvent event, Emitter<RoutineState> emit) { FutureOr<void> _onEffectiveTimeEvent(
EffectiveTimePeriodEvent event, Emitter<RoutineState> emit) {
emit(state.copyWith(effectiveTime: event.effectiveTime)); emit(state.copyWith(effectiveTime: event.effectiveTime));
} }
FutureOr<void> _onSetRoutineName(SetRoutineName event, Emitter<RoutineState> emit) { FutureOr<void> _onSetRoutineName(
SetRoutineName event, Emitter<RoutineState> emit) {
emit(state.copyWith( emit(state.copyWith(
routineName: event.name, routineName: event.name,
)); ));
} }
(List<Map<String, dynamic>>, List<Map<String, dynamic>>, Map<String, List<DeviceFunctionData>>) (
_createCardData( List<Map<String, dynamic>>,
List<Map<String, dynamic>>,
Map<String, List<DeviceFunctionData>>
) _createCardData(
List<RoutineAction> actions, List<RoutineAction> actions,
List<RoutineCondition>? conditions, List<RoutineCondition>? conditions,
Map<String, List<DeviceFunctionData>> currentFunctions, Map<String, List<DeviceFunctionData>> currentFunctions,
@ -488,7 +526,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
'deviceId': condition.entityId, 'deviceId': condition.entityId,
'title': matchingDevice.name ?? condition.entityId, 'title': matchingDevice.name ?? condition.entityId,
'productType': condition.entityType, 'productType': condition.entityType,
'imagePath': matchingDevice.getDefaultIcon(condition.entityType), 'imagePath':
matchingDevice.getDefaultIcon(condition.entityType),
}; };
final functions = matchingDevice.functions; final functions = matchingDevice.functions;
@ -524,8 +563,11 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final cardData = { final cardData = {
'entityId': action.entityId, 'entityId': action.entityId,
'uniqueCustomId': const Uuid().v4(), 'uniqueCustomId': const Uuid().v4(),
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, 'deviceId':
'title': action.actionExecutor == 'delay' ? 'Delay' : (matchingDevice.name ?? 'Device'), action.actionExecutor == 'delay' ? 'delay' : action.entityId,
'title': action.actionExecutor == 'delay'
? 'Delay'
: (matchingDevice.name ?? 'Device'),
'productType': action.productType, 'productType': action.productType,
'imagePath': matchingDevice.getDefaultIcon(action.productType), 'imagePath': matchingDevice.getDefaultIcon(action.productType),
}; };
@ -568,7 +610,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
return (thenItems, ifItems, currentFunctions); return (thenItems, ifItems, currentFunctions);
} }
Future<void> _onGetSceneDetails(GetSceneDetails event, Emitter<RoutineState> emit) async { Future<void> _onGetSceneDetails(
GetSceneDetails event, Emitter<RoutineState> emit) async {
try { try {
emit(state.copyWith( emit(state.copyWith(
isLoading: true, isLoading: true,
@ -616,10 +659,12 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
if (!deviceCards.containsKey(deviceId)) { if (!deviceCards.containsKey(deviceId)) {
deviceCards[deviceId] = { deviceCards[deviceId] = {
'entityId': action.entityId, 'entityId': action.entityId,
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, 'deviceId':
'uniqueCustomId': action.type == 'automation' || action.actionExecutor == 'delay' action.actionExecutor == 'delay' ? 'delay' : action.entityId,
? const Uuid().v4() 'uniqueCustomId':
: action.entityId, action.type == 'automation' || action.actionExecutor == 'delay'
? const Uuid().v4()
: action.entityId,
'title': action.actionExecutor == 'delay' 'title': action.actionExecutor == 'delay'
? 'Delay' ? 'Delay'
: action.type == 'automation' : action.type == 'automation'
@ -654,7 +699,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
), ),
); );
emit(state.copyWith(automationActionExecutor: action.actionExecutor)); emit(state.copyWith(automationActionExecutor: action.actionExecutor));
} else if (action.executorProperty != null && action.actionExecutor != 'delay') { } else if (action.executorProperty != null &&
action.actionExecutor != 'delay') {
if (!updatedFunctions.containsKey(uniqueCustomId)) { if (!updatedFunctions.containsKey(uniqueCustomId)) {
updatedFunctions[uniqueCustomId] = []; updatedFunctions[uniqueCustomId] = [];
} }
@ -739,7 +785,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
thenItems: [], thenItems: [],
)); ));
final automationDetails = await SceneApi.getAutomationDetails(event.automationId); final automationDetails =
await SceneApi.getAutomationDetails(event.automationId);
final List<Map<String, dynamic>> thenItems; final List<Map<String, dynamic>> thenItems;
final List<Map<String, dynamic>> ifItems; final List<Map<String, dynamic>> ifItems;
@ -758,13 +805,16 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final cardData = { final cardData = {
'entityId': condition.entityId, 'entityId': condition.entityId,
'uniqueCustomId': const Uuid().v4(), 'uniqueCustomId': const Uuid().v4(),
'deviceId': condition.expr.statusCode == 'delay' ? 'delay' : condition.entityId, 'deviceId': condition.expr.statusCode == 'delay'
? 'delay'
: condition.entityId,
'title': condition.expr.statusCode == 'delay' 'title': condition.expr.statusCode == 'delay'
? 'Delay' ? 'Delay'
: (matchingDevice?.name ?? 'Device'), : (matchingDevice?.name ?? 'Device'),
'productType': condition.productType, 'productType': condition.productType,
'functions': matchingDevice?.functions ?? [], 'functions': matchingDevice?.functions ?? [],
'imagePath': matchingDevice?.getDefaultIcon(condition.productType) ?? '', 'imagePath':
matchingDevice?.getDefaultIcon(condition.productType) ?? '',
'device': matchingDevice, 'device': matchingDevice,
}; };
@ -801,15 +851,19 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final cardData = { final cardData = {
'entityId': action.entityId, 'entityId': action.entityId,
'uniqueCustomId': const Uuid().v4(), 'uniqueCustomId': const Uuid().v4(),
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, 'deviceId':
'title': action.actionExecutor == 'delay' ? 'Delay' : (matchingDevice.name ?? 'Device'), action.actionExecutor == 'delay' ? 'delay' : action.entityId,
'title': action.actionExecutor == 'delay'
? 'Delay'
: (matchingDevice.name ?? 'Device'),
'productType': action.productType, 'productType': action.productType,
'functions': matchingDevice.functions, 'functions': matchingDevice.functions,
'imagePath': matchingDevice.getDefaultIcon(action.productType), 'imagePath': matchingDevice.getDefaultIcon(action.productType),
'device': matchingDevice, 'device': matchingDevice,
}; };
if (action.executorProperty != null && action.actionExecutor != 'delay') { if (action.executorProperty != null &&
action.actionExecutor != 'delay') {
final functions = matchingDevice.functions; final functions = matchingDevice.functions;
final functionCode = action.executorProperty!.functionCode; final functionCode = action.executorProperty!.functionCode;
for (var function in functions) { for (var function in functions) {
@ -872,7 +926,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
FutureOr<void> _onResetRoutineState(ResetRoutineState event, Emitter<RoutineState> emit) { FutureOr<void> _onResetRoutineState(
ResetRoutineState event, Emitter<RoutineState> emit) {
emit(state.copyWith( emit(state.copyWith(
ifItems: [], ifItems: [],
thenItems: [], thenItems: [],
@ -900,7 +955,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
if (state.isTabToRun) { if (state.isTabToRun) {
SceneApi.deleteScene(unitUuid: spaceId, sceneId: state.sceneId ?? ''); SceneApi.deleteScene(unitUuid: spaceId, sceneId: state.sceneId ?? '');
} else { } else {
SceneApi.deleteAutomation(unitUuid: spaceId, automationId: state.automationId ?? ''); SceneApi.deleteAutomation(
unitUuid: spaceId, automationId: state.automationId ?? '');
} }
add(const LoadScenes(spaceId, communityId)); add(const LoadScenes(spaceId, communityId));
@ -929,7 +985,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
// } // }
// } // }
FutureOr<void> _fetchDevices(FetchDevicesInRoutine event, Emitter<RoutineState> emit) async { FutureOr<void> _fetchDevices(
FetchDevicesInRoutine event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true)); emit(state.copyWith(isLoading: true));
try { try {
final devices = await DevicesManagementApi().fetchDevices(); final devices = await DevicesManagementApi().fetchDevices();
@ -940,7 +997,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
FutureOr<void> _onUpdateScene(UpdateScene event, Emitter<RoutineState> emit) async { FutureOr<void> _onUpdateScene(
UpdateScene event, Emitter<RoutineState> emit) async {
try { try {
// Check if first action is delay // Check if first action is delay
if (_isFirstActionDelay(state.thenItems)) { if (_isFirstActionDelay(state.thenItems)) {
@ -967,6 +1025,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
return functions.map((function) { return functions.map((function) {
if (function.functionCode == 'automation') { if (function.functionCode == 'automation') {
return CreateSceneAction( return CreateSceneAction(
actionType: 'automation',
entityId: function.entityId, entityId: function.entityId,
actionExecutor: function.value, actionExecutor: function.value,
executorProperty: null, executorProperty: null,
@ -1006,7 +1065,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
actions: actions, actions: actions,
); );
final result = await SceneApi.updateScene(createSceneModel, state.sceneId ?? ''); final result =
await SceneApi.updateScene(createSceneModel, state.sceneId ?? '');
if (result['success']) { if (result['success']) {
add(ResetRoutineState()); add(ResetRoutineState());
add(const LoadScenes(spaceId, communityId)); add(const LoadScenes(spaceId, communityId));
@ -1025,7 +1085,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
FutureOr<void> _onUpdateAutomation(UpdateAutomation event, Emitter<RoutineState> emit) async { FutureOr<void> _onUpdateAutomation(
UpdateAutomation event, Emitter<RoutineState> emit) async {
if (_isFirstActionDelay(state.thenItems)) { if (_isFirstActionDelay(state.thenItems)) {
emit(state.copyWith( emit(state.copyWith(
errorMessage: 'Cannot have delay as the first action', errorMessage: 'Cannot have delay as the first action',
@ -1037,7 +1098,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
try { try {
final conditions = state.ifItems final conditions = state.ifItems
.map((item) { .map((item) {
final functions = state.selectedFunctions[item['uniqueCustomId']] ?? []; final functions =
state.selectedFunctions[item['uniqueCustomId']] ?? [];
if (functions.isEmpty) return null; if (functions.isEmpty) return null;
final function = functions.first; final function = functions.first;
@ -1057,18 +1119,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final actions = state.thenItems final actions = state.thenItems
.map((item) { .map((item) {
final functions = state.selectedFunctions[item['uniqueCustomId']] ?? []; final functions =
state.selectedFunctions[item['uniqueCustomId']] ?? [];
if (functions.isEmpty) return null; if (functions.isEmpty) return null;
final function = functions.first; final function = functions.first;
return AutomationAction( return AutomationAction(
actionType: 'automation',
entityId: function.entityId, entityId: function.entityId,
actionExecutor: function.actionExecutor, actionExecutor: function.actionExecutor,
executorProperty: ExecutorProperty( executorProperty: ExecutorProperty(
functionCode: function.functionCode, functionCode: function.functionCode,
functionValue: function.value, functionValue: function.value,
delaySeconds: delaySeconds: function.functionCode == 'delay'
function.functionCode == 'delay' ? (function.value as num).toInt() : null, ? (function.value as num).toInt()
: null,
), ),
); );
}) })
@ -1079,13 +1144,14 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
spaceUuid: spaceId, spaceUuid: spaceId,
automationName: state.routineName ?? '', automationName: state.routineName ?? '',
decisionExpr: state.selectedAutomationOperator, decisionExpr: state.selectedAutomationOperator,
effectiveTime: state.effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''), effectiveTime:
state.effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
conditions: conditions, conditions: conditions,
actions: actions, actions: actions,
); );
final result = final result = await SceneApi.updateAutomation(
await SceneApi.updateAutomation(createAutomationModel, state.automationId ?? ''); createAutomationModel, state.automationId ?? '');
if (result['success']) { if (result['success']) {
add(ResetRoutineState()); add(ResetRoutineState());
@ -1107,6 +1173,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
FutureOr<void> _onSetAutomationActionExecutor( FutureOr<void> _onSetAutomationActionExecutor(
SetAutomationActionExecutor event, Emitter<RoutineState> emit) { SetAutomationActionExecutor event, Emitter<RoutineState> emit) {
emit(state.copyWith(automationActionExecutor: event.automationActionExecutor)); emit(state.copyWith(
automationActionExecutor: event.automationActionExecutor));
} }
} }

View File

@ -137,11 +137,13 @@ class ConditionExpr {
class AutomationAction { class AutomationAction {
String entityId; String entityId;
String? actionType;
String actionExecutor; String actionExecutor;
ExecutorProperty? executorProperty; ExecutorProperty? executorProperty;
AutomationAction({ AutomationAction({
required this.entityId, required this.entityId,
this.actionType,
required this.actionExecutor, required this.actionExecutor,
this.executorProperty, this.executorProperty,
}); });
@ -151,11 +153,13 @@ class AutomationAction {
'entityId': entityId, 'entityId': entityId,
'actionExecutor': actionExecutor, 'actionExecutor': actionExecutor,
'executorProperty': executorProperty?.toMap(), 'executorProperty': executorProperty?.toMap(),
'actionType': actionType
}; };
} }
factory AutomationAction.fromMap(Map<String, dynamic> map) { factory AutomationAction.fromMap(Map<String, dynamic> map) {
return AutomationAction( return AutomationAction(
actionType: map['actionType'],
entityId: map['entityId'] ?? '', entityId: map['entityId'] ?? '',
actionExecutor: map['actionExecutor'] ?? '', actionExecutor: map['actionExecutor'] ?? '',
executorProperty: map['executorProperty'] != null executorProperty: map['executorProperty'] != null

View File

@ -95,10 +95,12 @@ class CreateSceneModel {
class CreateSceneAction { class CreateSceneAction {
String entityId; String entityId;
String? actionType;
String actionExecutor; String actionExecutor;
CreateSceneExecutorProperty? executorProperty; CreateSceneExecutorProperty? executorProperty;
CreateSceneAction({ CreateSceneAction({
this.actionType,
required this.entityId, required this.entityId,
required this.actionExecutor, required this.actionExecutor,
required this.executorProperty, required this.executorProperty,
@ -110,6 +112,7 @@ class CreateSceneAction {
CreateSceneExecutorProperty? executorProperty, CreateSceneExecutorProperty? executorProperty,
}) { }) {
return CreateSceneAction( return CreateSceneAction(
actionType: actionType ?? this.actionType,
entityId: entityId ?? this.entityId, entityId: entityId ?? this.entityId,
actionExecutor: actionExecutor ?? this.actionExecutor, actionExecutor: actionExecutor ?? this.actionExecutor,
executorProperty: executorProperty ?? this.executorProperty, executorProperty: executorProperty ?? this.executorProperty,
@ -125,6 +128,7 @@ class CreateSceneAction {
}; };
} else { } else {
return { return {
"actionType": actionType,
'entityId': entityId, 'entityId': entityId,
'actionExecutor': actionExecutor, 'actionExecutor': actionExecutor,
}; };
@ -133,6 +137,7 @@ class CreateSceneAction {
factory CreateSceneAction.fromMap(Map<String, dynamic> map) { factory CreateSceneAction.fromMap(Map<String, dynamic> map) {
return CreateSceneAction( return CreateSceneAction(
actionType: map['actionType'],
entityId: map['entityId'] ?? '', entityId: map['entityId'] ?? '',
actionExecutor: map['actionExecutor'] ?? '', actionExecutor: map['actionExecutor'] ?? '',
executorProperty: executorProperty:

View File

@ -23,7 +23,7 @@ class AutomationDialog extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<RoutineBloc, RoutineState>( return BlocBuilder<RoutineBloc, RoutineState>(
builder: (context, state) { builder: (context, state) {
final isEnabled = state.automationActionExecutor == 'rule_enable'; final String? initialSelection = state.automationActionExecutor;
return Dialog( return Dialog(
shape: shape:
@ -40,14 +40,14 @@ class AutomationDialog extends StatelessWidget {
leading: leading:
SvgPicture.asset(Assets.acPower, width: 24, height: 24), SvgPicture.asset(Assets.acPower, width: 24, height: 24),
title: const Text('Enable'), title: const Text('Enable'),
trailing: Radio<bool>( trailing: Radio<String?>(
value: true, value: 'rule_enable',
groupValue: isEnabled, groupValue: initialSelection,
onChanged: (bool? value) { onChanged: (String? value) {
if (value == true) { if (value != null) {
context.read<RoutineBloc>().add( context.read<RoutineBloc>().add(
const SetAutomationActionExecutor( SetAutomationActionExecutor(
automationActionExecutor: 'rule_enable', automationActionExecutor: value,
), ),
); );
} }
@ -58,14 +58,14 @@ class AutomationDialog extends StatelessWidget {
leading: SvgPicture.asset(Assets.acPowerOff, leading: SvgPicture.asset(Assets.acPowerOff,
width: 24, height: 24), width: 24, height: 24),
title: const Text('Disable'), title: const Text('Disable'),
trailing: Radio<bool>( trailing: Radio<String?>(
value: false, value: 'rule_disable',
groupValue: isEnabled, groupValue: initialSelection,
onChanged: (bool? value) { onChanged: (String? value) {
if (value == false) { if (value != null) {
context.read<RoutineBloc>().add( context.read<RoutineBloc>().add(
const SetAutomationActionExecutor( SetAutomationActionExecutor(
automationActionExecutor: 'rule_disable', automationActionExecutor: value,
), ),
); );
} }
@ -75,23 +75,25 @@ class AutomationDialog extends StatelessWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
DialogFooter( DialogFooter(
onConfirm: () { onConfirm: () {
context.read<RoutineBloc>().add( if (state.automationActionExecutor != null) {
AddFunctionToRoutine( context.read<RoutineBloc>().add(
[ AddFunctionToRoutine(
DeviceFunctionData( [
entityId: automationId, DeviceFunctionData(
functionCode: 'automation', entityId: automationId,
value: state.automationActionExecutor, functionCode: 'automation',
operationName: 'Automation', value: state.automationActionExecutor,
), operationName: 'Automation',
], ),
uniqueCustomId, ],
), uniqueCustomId,
); ),
Navigator.of(context).pop(true); );
Navigator.of(context).pop(true);
}
}, },
onCancel: () => Navigator.of(context).pop(false), onCancel: () => Navigator.of(context).pop(false),
isConfirmEnabled: true, isConfirmEnabled: state.automationActionExecutor != null,
dialogWidth: 400, dialogWidth: 400,
), ),
], ],