diff --git a/assets/icons/functions_icons/automation_functions/card_unlock.svg b/assets/icons/functions_icons/automation_functions/card_unlock.svg
new file mode 100644
index 0000000..dd77680
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/card_unlock.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/current_temp.svg b/assets/icons/functions_icons/automation_functions/current_temp.svg
new file mode 100644
index 0000000..42cceb2
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/current_temp.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/doorbell.svg b/assets/icons/functions_icons/automation_functions/doorbell.svg
new file mode 100644
index 0000000..1dc515a
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/doorbell.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg b/assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg
new file mode 100644
index 0000000..8f4a590
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/double_lock.svg b/assets/icons/functions_icons/automation_functions/double_lock.svg
new file mode 100644
index 0000000..d8ad971
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/double_lock.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg b/assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg
new file mode 100644
index 0000000..f9f5b84
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg
@@ -0,0 +1,79 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/hijack_alarm.svg b/assets/icons/functions_icons/automation_functions/hijack_alarm.svg
new file mode 100644
index 0000000..e32997f
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/hijack_alarm.svg
@@ -0,0 +1,13 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/lock_alarm.svg b/assets/icons/functions_icons/automation_functions/lock_alarm.svg
new file mode 100644
index 0000000..8bd2dee
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/lock_alarm.svg
@@ -0,0 +1,149 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/motion.svg b/assets/icons/functions_icons/automation_functions/motion.svg
new file mode 100644
index 0000000..8d69463
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/motion.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/password_unlock.svg b/assets/icons/functions_icons/automation_functions/password_unlock.svg
new file mode 100644
index 0000000..1920b69
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/password_unlock.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/presence.svg b/assets/icons/functions_icons/automation_functions/presence.svg
new file mode 100644
index 0000000..d71a474
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/presence.svg
@@ -0,0 +1,18 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/presence_state.svg b/assets/icons/functions_icons/automation_functions/presence_state.svg
new file mode 100644
index 0000000..d5de48e
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/presence_state.svg
@@ -0,0 +1,18 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/remote_unlock_req.svg b/assets/icons/functions_icons/automation_functions/remote_unlock_req.svg
new file mode 100644
index 0000000..da128ff
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/remote_unlock_req.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg b/assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg
new file mode 100644
index 0000000..39fc859
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg
@@ -0,0 +1,40 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/residual_electricity.svg b/assets/icons/functions_icons/automation_functions/residual_electricity.svg
new file mode 100644
index 0000000..6a5b612
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/residual_electricity.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/self_test_result.svg b/assets/icons/functions_icons/automation_functions/self_test_result.svg
new file mode 100644
index 0000000..8739327
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/self_test_result.svg
@@ -0,0 +1,23 @@
+
diff --git a/assets/icons/functions_icons/automation_functions/temp_password_unlock.svg b/assets/icons/functions_icons/automation_functions/temp_password_unlock.svg
new file mode 100644
index 0000000..98d7573
--- /dev/null
+++ b/assets/icons/functions_icons/automation_functions/temp_password_unlock.svg
@@ -0,0 +1,16 @@
+
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 15d1180..ccc9375 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -44,9 +44,9 @@ PODS:
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.12)
- GoogleUtilities/Logger (~> 7.12)
- - FirebaseCoreExtension (10.27.0):
+ - FirebaseCoreExtension (10.29.0):
- FirebaseCore (~> 10.0)
- - FirebaseCoreInternal (10.27.0):
+ - FirebaseCoreInternal (10.29.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseCrashlytics (10.20.0):
- FirebaseCore (~> 10.5)
@@ -56,12 +56,12 @@ PODS:
- GoogleUtilities/Environment (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0)
- PromisesObjC (~> 2.1)
- - FirebaseInstallations (10.27.0):
+ - FirebaseInstallations (10.29.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- PromisesObjC (~> 2.1)
- - FirebaseSessions (10.27.0):
+ - FirebaseSessions (10.29.0):
- FirebaseCore (~> 10.5)
- FirebaseCoreExtension (~> 10.0)
- FirebaseInstallations (~> 10.0)
@@ -277,11 +277,11 @@ SPEC CHECKSUMS:
firebase_crashlytics: 012078b4eec6fc9716f97ba3da0f0e44a04e95b1
FirebaseAnalytics: a2731bf3670747ce8f65368b118d18aa8e368246
FirebaseCore: 28045c1560a2600d284b9c45a904fe322dc890b6
- FirebaseCoreExtension: 4ec89dd0c6de93d6becde32122d68b7c35f6bf5d
- FirebaseCoreInternal: 4b297a2d56063dbea2c1d0d04222d44a8d058862
+ FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f
+ FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934
FirebaseCrashlytics: 81530595edb6d99f1918f723a6c33766a24a4c86
- FirebaseInstallations: 766dabca09fd94aef922538aaf144cc4a6fb6869
- FirebaseSessions: 2fdf949f9e58295a57703ae8f2efc44f9fa3aa16
+ FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd
+ FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_localization: f43b18844a2b3d2c71fd64f04ffd6b1e64dd54d4
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
diff --git a/lib/features/app_layout/bloc/home_cubit.dart b/lib/features/app_layout/bloc/home_cubit.dart
index a964a53..9168283 100644
--- a/lib/features/app_layout/bloc/home_cubit.dart
+++ b/lib/features/app_layout/bloc/home_cubit.dart
@@ -17,10 +17,16 @@ import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
import 'package:syncrow_app/features/menu/view/menu_view.dart';
+import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
+import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
+import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
+import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
import 'package:syncrow_app/features/scene/view/create_scene_view.dart';
+import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
import 'package:syncrow_app/features/scene/view/scene_view.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigation_service.dart';
+import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/profile_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
@@ -52,13 +58,12 @@ class HomeCubit extends Cubit {
return _instance!;
}
-
- Future fetchUserInfo() async {
+ Future fetchUserInfo() async {
try {
- var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
+ var uuid =
+ await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
user = await ProfileApi().fetchUserInfo(uuid);
emit(HomeUserInfoLoaded(user!)); // Emit state after fetching user info
-
} catch (e) {
return;
}
@@ -77,9 +82,12 @@ class HomeCubit extends Cubit {
selectedSpace = null;
selectedRoom = null;
pageIndex = 0;
- OneSignal.User.pushSubscription.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
- OneSignal.Notifications.removePermissionObserver((permission) => oneSignalPermissionObserver);
- OneSignal.Notifications.removeClickListener((event) => oneSignalClickListenerObserver);
+ OneSignal.User.pushSubscription
+ .removeObserver((stateChanges) => oneSignalSubscriptionObserver);
+ OneSignal.Notifications.removePermissionObserver(
+ (permission) => oneSignalPermissionObserver);
+ OneSignal.Notifications.removeClickListener(
+ (event) => oneSignalClickListenerObserver);
return super.close();
}
@@ -121,7 +129,9 @@ class HomeCubit extends Cubit {
return;
}
- var userUuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
+ var userUuid =
+ await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
+ '';
if (userUuid.isNotEmpty) {
await OneSignal.login(userUuid);
}
@@ -129,21 +139,24 @@ class HomeCubit extends Cubit {
await OneSignal.User.pushSubscription.optIn();
//this function will be called once a user is subscribed
- oneSignalSubscriptionObserver = OneSignal.User.pushSubscription.addObserver((state) async {
+ oneSignalSubscriptionObserver =
+ OneSignal.User.pushSubscription.addObserver((state) async {
if (state.current.optedIn) {
await _sendSubscriptionId();
}
});
// Send the player id when a user allows notifications
- oneSignalPermissionObserver = OneSignal.Notifications.addPermissionObserver((state) async {
+ oneSignalPermissionObserver =
+ OneSignal.Notifications.addPermissionObserver((state) async {
await _sendSubscriptionId();
});
//check if the player id is sent, if not send it again
await _sendSubscriptionId();
- oneSignalClickListenerObserver = OneSignal.Notifications.addClickListener((event) async {
+ oneSignalClickListenerObserver =
+ OneSignal.Notifications.addClickListener((event) async {
//Once the user clicks on the notification
});
} catch (err) {
@@ -230,7 +243,9 @@ class HomeCubit extends Cubit {
Future joinAUnit(String code) async {
try {
- var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
+ var uuid =
+ await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
+ '';
Map body = {'userUuid': uuid, 'inviteCode': code};
final success = await SpacesAPI.joinUnit(body);
@@ -348,15 +363,28 @@ class HomeCubit extends Cubit {
size: 32,
),
style: ButtonStyle(
- foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
+ foregroundColor:
+ WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {
- Navigator.push(
+ Navigator.pushNamed(
NavigationService.navigatorKey.currentContext!,
- CustomPageRoute(
- builder: (context) => const CreateSceneView(),
+ Routes.sceneTasksRoute,
+ arguments: SceneSettingsRouteArguments(
+ sceneType: '',
+ sceneId: '',
+ sceneName: '',
),
);
+ NavigationService.navigatorKey.currentContext!
+ .read()
+ .add(const ClearTaskListEvent());
+ NavigationService.navigatorKey.currentContext!
+ .read()
+ .add(const SceneTypeEvent(CreateSceneEnum.none));
+ NavigationService.navigatorKey.currentContext!
+ .read()
+ .add(const SmartSceneClearEvent());
},
),
IconButton(
@@ -365,7 +393,8 @@ class HomeCubit extends Cubit {
size: 28,
),
style: ButtonStyle(
- foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
+ foregroundColor:
+ WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {},
),
@@ -398,7 +427,8 @@ class HomeCubit extends Cubit {
};
static var bottomNavItems = [
- defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
+ defaultBottomNavBarItem(
+ icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
@@ -424,7 +454,8 @@ class HomeCubit extends Cubit {
void updateDevice(String deviceId) async {
try {
- final response = await DevicesAPI.firmwareDevice(deviceId: deviceId, firmwareVersion: '0');
+ final response = await DevicesAPI.firmwareDevice(
+ deviceId: deviceId, firmwareVersion: '0');
if (response['success'] ?? false) {
CustomSnackBar.displaySnackBar('No updates available');
}
@@ -432,7 +463,8 @@ class HomeCubit extends Cubit {
}
}
-BottomNavigationBarItem defaultBottomNavBarItem({required String icon, required String label}) {
+BottomNavigationBarItem defaultBottomNavBarItem(
+ {required String icon, required String label}) {
return BottomNavigationBarItem(
icon: SvgPicture.asset(icon),
activeIcon: SvgPicture.asset(
diff --git a/lib/features/devices/model/device_model.dart b/lib/features/devices/model/device_model.dart
index 4a822be..82fac11 100644
--- a/lib/features/devices/model/device_model.dart
+++ b/lib/features/devices/model/device_model.dart
@@ -45,7 +45,8 @@ class DeviceModel {
if (type == DeviceType.LightBulb) {
tempIcon = Assets.assetsIconsLight;
- } else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
+ } else if (type == DeviceType.CeilingSensor ||
+ type == DeviceType.WallSensor) {
tempIcon = Assets.assetsIconsSensors;
} else if (type == DeviceType.AC) {
tempIcon = Assets.assetsIconsAC;
@@ -93,5 +94,6 @@ class DeviceModel {
};
}
- List getFunctions(DeviceType type) => devicesFunctionsMap[productType] ?? [];
+ List getFunctions(DeviceType type) =>
+ devicesFunctionsMap[productType] ?? [];
}
diff --git a/lib/features/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 f314088..6ebfcae 100644
--- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart
+++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart
@@ -1,10 +1,17 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
+import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
+import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
+import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
+import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart';
+import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
+import 'package:syncrow_app/navigation/navigation_service.dart';
import 'package:syncrow_app/services/api/scene_api.dart';
part 'create_scene_event.dart';
@@ -25,23 +32,65 @@ class CreateSceneBloc extends Bloc
on(_removeFromSelectedValueById);
on(_deleteScene);
on(_updateTaskValue);
+ on(_selectConditionRule);
+ on(_sceneTypeEvent);
+ on(_onEffectiveTimeEvent);
}
+ CreateSceneEnum sceneType = CreateSceneEnum.none;
+
+ /// tab to run values and list
List tasksList = [];
List tempTasksList = [];
final Map selectedValues = {};
+ /// automation values and list
+ List automationTasksList = [];
+ List automationTempTasksList = [];
+ final Map automationSelectedValues = {};
+ final Map automationComparatorValues = {};
+ String conditionRule = 'or';
+ EffectiveTime? effectiveTime;
+
FutureOr _onAddSceneTask(
AddTaskEvent event, Emitter emit) {
- final copyList = List.from(tempTasksList);
- tasksList.addAll(copyList);
- tempTasksList.clear();
- selectedValues.clear();
- emit(AddSceneTask(tasksList: tasksList));
+ emit(CreateSceneLoading());
+ if (event.isAutomation == true) {
+ final copyList = List.from(automationTempTasksList);
+ automationTasksList.addAll(copyList);
+ automationTempTasksList.clear();
+ automationSelectedValues.clear();
+ automationComparatorValues.clear();
+ emit(AddSceneTask(
+ automationTasksList: automationTasksList,
+ tasksList: tasksList,
+ condition: conditionRule,
+ ));
+ } else {
+ final copyList = List.from(tempTasksList);
+ tasksList.addAll(copyList);
+ tempTasksList.clear();
+ selectedValues.clear();
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
+ }
}
FutureOr _onTempHoldSceneTask(
TempHoldSceneTasksEvent event, Emitter emit) {
+ if (event.isAutomation == true) {
+ addToTempAutomationTaskList(event, emit);
+ } else {
+ addToTempTaskList(event, emit);
+ }
+ }
+
+ void addToTempTaskList(
+ TempHoldSceneTasksEvent event, Emitter emit) {
+ emit(CreateSceneLoading());
bool updated = false;
for (var element in tempTasksList) {
if (element.code == event.deviceControlModel.code) {
@@ -53,6 +102,7 @@ class CreateSceneBloc extends Bloc
code: event.deviceControlModel.code ?? '',
deviceId: event.deviceId,
functionValue: event.deviceControlModel.value,
+ operationDialogType: event.operationType,
operationalValues: [
SceneOperationalValue(
value: event.deviceControlModel.value,
@@ -67,12 +117,12 @@ class CreateSceneBloc extends Bloc
}
}
if (!updated) {
- // Add new function if not found
var newElement = SceneStaticFunction(
operationName: event.operation,
deviceName: event.deviceName,
icon: event.icon,
code: event.deviceControlModel.code ?? '',
+ operationDialogType: event.operationType,
deviceId: event.deviceId,
functionValue: event.deviceControlModel.value,
operationalValues: [
@@ -86,40 +136,161 @@ class CreateSceneBloc extends Bloc
selectedValues[newElement.code] = event.deviceControlModel.value;
}
- emit(TempHoldSceneTask(tempTasksList: tempTasksList));
- emit(AddSceneTask(tasksList: tasksList));
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
+ }
+
+ void addToTempAutomationTaskList(
+ TempHoldSceneTasksEvent event, Emitter emit) {
+ emit(CreateSceneLoading());
+ bool updated = false;
+ for (var element in automationTempTasksList) {
+ if (element.code == event.deviceControlModel.code) {
+ // Update the existing function with new values
+ var updatedElement = element.copyWith(
+ operationName: event.operation,
+ deviceName: event.deviceName,
+ icon: event.icon,
+ code: event.deviceControlModel.code ?? '',
+ deviceId: event.deviceId,
+ functionValue: event.deviceControlModel.value,
+ operationDialogType: event.operationType,
+ operationalValues: [
+ SceneOperationalValue(
+ value: event.deviceControlModel.value,
+ icon: '',
+ ),
+ ],
+ comparator: automationComparatorValues[element.code],
+ );
+ automationTempTasksList[automationTempTasksList.indexOf(element)] =
+ updatedElement;
+ automationSelectedValues[updatedElement.code] =
+ event.deviceControlModel.value;
+ updated = true;
+ break;
+ }
+ }
+ if (!updated) {
+ var newElement = SceneStaticFunction(
+ operationName: event.operation,
+ deviceName: event.deviceName,
+ icon: event.icon,
+ code: event.deviceControlModel.code ?? '',
+ operationDialogType: event.operationType,
+ deviceId: event.deviceId,
+ functionValue: event.deviceControlModel.value,
+ operationalValues: [
+ SceneOperationalValue(
+ value: event.deviceControlModel.value,
+ icon: '',
+ ),
+ ],
+ comparator:
+ automationComparatorValues[event.deviceControlModel.code] ?? '==',
+ );
+ automationTempTasksList.add(newElement);
+ automationSelectedValues[newElement.code] =
+ event.deviceControlModel.value;
+ }
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
}
FutureOr _selectedValue(
SelectedValueEvent event, Emitter emit) {
- selectedValues[event.code] = event.value;
+ if (event.isAutomation == true) {
+ automationSelectedValues[event.code] = event.value;
+ automationComparatorValues[event.code] = event.comparator ?? '==';
+
+ // Update the comparator value for the specific task in automationTasksList
+ for (int i = 0; i < automationTasksList.length; i++) {
+ if (automationTasksList[i].code == event.code) {
+ automationTasksList[i] = automationTasksList[i].copyWith(
+ comparator: event.comparator ?? '==',
+ functionValue: event.value,
+ );
+ break;
+ }
+ }
+ } else {
+ selectedValues[event.code] = event.value;
+ }
emit(SelectedTaskValueState(value: event.value));
- emit(AddSceneTask(tasksList: tasksList));
+ emit(AddSceneTask(
+ tasksList: List.from(tasksList),
+ automationTasksList: List.from(
+ automationTasksList,
+ ),
+ condition: conditionRule,
+ ));
}
FutureOr _removeTaskById(
RemoveTaskByIdEvent event, Emitter emit) {
emit(CreateSceneLoading());
+ if (event.isAutomation == true) {
+ for (var element in automationTasksList) {
+ if (element.uniqueCustomId == event.taskId) {
+ automationTasksList.remove(element);
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
+ break;
+ }
+ }
+ } else {
+ for (var element in tasksList) {
+ if (element.uniqueCustomId == event.taskId) {
+ tasksList.remove(element);
- for (var element in tasksList) {
- if (element.uniqueCustomId == event.taskId) {
- tasksList.remove(element);
-
- emit(AddSceneTask(tasksList: tasksList));
- break;
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
+ break;
+ }
}
}
}
FutureOr _removeTempTaskById(
RemoveTempTaskByIdEvent event, Emitter emit) {
- for (var element in tempTasksList) {
- if (element.code == event.code) {
- tempTasksList.remove(element);
+ emit(CreateSceneLoading());
+ if (event.isAutomation == true) {
+ for (var element in automationTempTasksList) {
+ if (element.uniqueCustomId == event.code) {
+ automationTempTasksList.remove(element);
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
+ break;
+ }
+ }
+ } else {
+ for (var element in tempTasksList) {
+ if (element.code == event.code) {
+ tempTasksList.remove(element);
- emit(AddSceneTask(tasksList: tasksList));
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
- break;
+ break;
+ }
}
}
}
@@ -128,27 +299,53 @@ class CreateSceneBloc extends Bloc
CreateSceneWithTasksEvent event, Emitter emit) async {
emit(CreateSceneLoading());
try {
- final response = event.updateScene
- ? await SceneApi.updateScene(event.createSceneModel, event.sceneId)
- : await SceneApi.createScene(event.createSceneModel);
+ dynamic response;
+ if (event.createSceneModel != null) {
+ response = event.updateScene
+ ? await SceneApi.updateScene(event.createSceneModel!, event.sceneId)
+ : await SceneApi.createScene(event.createSceneModel!);
+ } else if (event.createAutomationModel != null) {
+ response = event.updateScene
+ ? await SceneApi.updateAutomation(
+ event.createAutomationModel!, event.sceneId)
+ : await SceneApi.createAutomation(event.createAutomationModel!);
+ }
+
if (response['success'] == true) {
tasksList.clear();
tempTasksList.clear();
selectedValues.clear();
+ automationTasksList.clear();
+ automationTempTasksList.clear();
+ automationSelectedValues.clear();
+ automationComparatorValues.clear();
+ effectiveTime = null;
+ sceneType = CreateSceneEnum.none;
+ conditionRule = 'or';
emit(const CreateSceneWithTasks(success: true));
} else {
emit(const CreateSceneError(message: 'Something went wrong'));
}
} catch (e) {
emit(const CreateSceneError(message: 'Something went wrong'));
- emit(AddSceneTask(tasksList: tasksList));
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
}
}
FutureOr _clearTaskList(
ClearTaskListEvent event, Emitter emit) {
+ emit(CreateSceneLoading());
+ automationTasksList.clear();
tasksList.clear();
- emit(AddSceneTask(tasksList: tasksList));
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
}
FutureOr _fetchSceneTasks(
@@ -156,13 +353,46 @@ 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));
- 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));
+
+ conditionRule = response.decisionExpr ?? conditionRule;
+
+ if (response.effectiveTime != null) {
+ BlocProvider.of(
+ NavigationService.navigatorKey.currentState!.context)
+ .add(SetCustomTime(response.effectiveTime!.start,
+ response.effectiveTime!.end));
+ BlocProvider.of(
+ NavigationService.navigatorKey.currentState!.context)
+ .add(ToggleDay(response.effectiveTime!.loops));
+ }
+
+ emit(AddSceneTask(
+ automationTasksList: automationTasksList,
+ tasksList: tasksList,
+ condition: conditionRule,
+ ));
+ } else {
+ tasksList = List.from(
+ getTaskListFunctionsFromApi(
+ actions: response.actions, isAutomation: false));
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ condition: conditionRule,
+ ));
+ }
} else {
emit(const CreateSceneError(message: 'Something went wrong'));
}
@@ -173,17 +403,51 @@ class CreateSceneBloc extends Bloc
FutureOr _clearTempTaskList(
ClearTempTaskListEvent event, Emitter emit) {
- tempTasksList.clear();
- selectedValues.clear();
- emit(AddSceneTask(tasksList: tempTasksList));
+ emit(CreateSceneLoading());
+ if (event.isAutomation == true) {
+ 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,
+ ));
+ }
}
FutureOr _removeFromSelectedValueById(
RemoveFromSelectedValueById event, Emitter emit) {
- if (selectedValues.containsKey(event.code)) {
- selectedValues.remove(event.code);
- emit(const SelectedTaskValueState(value: null));
- emit(AddSceneTask(tasksList: tasksList));
+ emit(CreateSceneLoading());
+ if (event.isAutomation == true) {
+ if (automationSelectedValues.containsKey(event.code)) {
+ automationSelectedValues.remove(event.code);
+ automationComparatorValues.remove(event.code);
+ emit(const SelectedTaskValueState(value: null));
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
+ }
+ } else {
+ if (selectedValues.containsKey(event.code)) {
+ selectedValues.remove(event.code);
+ emit(const SelectedTaskValueState(value: null));
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
+ }
}
}
@@ -192,8 +456,12 @@ class CreateSceneBloc extends Bloc
emit(DeleteSceneLoading());
try {
- final response = await SceneApi.deleteScene(
- sceneId: event.sceneId, unitUuid: event.unitUuid);
+ final response =
+ sceneType.name == CreateSceneEnum.deviceStatusChanges.name
+ ? await SceneApi.deleteAutomation(
+ automationId: event.sceneId, unitUuid: event.unitUuid)
+ : await SceneApi.deleteScene(
+ sceneId: event.sceneId, unitUuid: event.unitUuid);
if (response == true) {
emit(const DeleteSceneSuccess(true));
} else {
@@ -206,14 +474,66 @@ class CreateSceneBloc extends Bloc
FutureOr _updateTaskValue(
UpdateTaskEvent event, Emitter emit) {
- for (var i = 0; i < tasksList.length; i++) {
- if (tasksList[i].uniqueCustomId == event.taskId) {
- tasksList[i] = tasksList[i].copyWith(
- functionValue: event.newValue,
- );
- break;
+ emit(CreateSceneLoading());
+ if (event.isAutomation == true) {
+ for (var i = 0; i < automationTasksList.length; i++) {
+ if (automationTasksList[i].uniqueCustomId == event.taskId) {
+ automationTasksList[i] = automationTasksList[i].copyWith(
+ functionValue: event.newValue,
+ );
+ break;
+ }
+ }
+ } else {
+ for (var i = 0; i < tasksList.length; i++) {
+ if (tasksList[i].uniqueCustomId == event.taskId) {
+ tasksList[i] = tasksList[i].copyWith(
+ functionValue: event.newValue,
+ );
+ break;
+ }
}
}
- emit(AddSceneTask(tasksList: tasksList));
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
+ }
+
+ FutureOr _selectConditionRule(
+ SelectConditionEvent event, Emitter emit) {
+ emit(CreateSceneInitial());
+ if (event.condition.contains('any')) {
+ conditionRule = 'or';
+ } else {
+ conditionRule = 'and';
+ }
+
+ emit(AddSceneTask(
+ tasksList: tasksList,
+ automationTasksList: automationTasksList,
+ condition: conditionRule,
+ ));
+ }
+
+ FutureOr _sceneTypeEvent(
+ SceneTypeEvent event, Emitter emit) {
+ emit(CreateSceneInitial());
+
+ if (event.type == CreateSceneEnum.tabToRun) {
+ sceneType = CreateSceneEnum.tabToRun;
+ } else if (event.type == CreateSceneEnum.deviceStatusChanges) {
+ sceneType = CreateSceneEnum.deviceStatusChanges;
+ } else {
+ sceneType = CreateSceneEnum.none;
+ }
+
+ emit(SceneTypeState(event.type));
+ }
+
+ FutureOr _onEffectiveTimeEvent(
+ EffectiveTimePeriodEvent event, Emitter emit) {
+ effectiveTime = event.period;
}
}
diff --git a/lib/features/scene/bloc/create_scene/create_scene_event.dart b/lib/features/scene/bloc/create_scene/create_scene_event.dart
index 60fd098..74046bd 100644
--- a/lib/features/scene/bloc/create_scene/create_scene_event.dart
+++ b/lib/features/scene/bloc/create_scene/create_scene_event.dart
@@ -8,6 +8,9 @@ sealed class CreateSceneEvent extends Equatable {
}
class AddTaskEvent extends CreateSceneEvent {
+ const AddTaskEvent({this.isAutomation});
+ final bool? isAutomation;
+
@override
List