mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-15 17:47:28 +00:00
push autoamtion api connect
This commit is contained in:
@ -17,10 +17,15 @@ import 'package:syncrow_app/features/devices/model/status_model.dart';
|
|||||||
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.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/menu/view/menu_view.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
|
||||||
import 'package:syncrow_app/features/scene/view/create_scene_view.dart';
|
import 'package:syncrow_app/features/scene/view/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/features/scene/view/scene_view.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/navigation/navigation_service.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/devices_api.dart';
|
||||||
import 'package:syncrow_app/services/api/spaces_api.dart';
|
import 'package:syncrow_app/services/api/spaces_api.dart';
|
||||||
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
|
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
|
||||||
@ -63,9 +68,12 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
selectedSpace = null;
|
selectedSpace = null;
|
||||||
selectedRoom = null;
|
selectedRoom = null;
|
||||||
pageIndex = 0;
|
pageIndex = 0;
|
||||||
OneSignal.User.pushSubscription.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
|
OneSignal.User.pushSubscription
|
||||||
OneSignal.Notifications.removePermissionObserver((permission) => oneSignalPermissionObserver);
|
.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
|
||||||
OneSignal.Notifications.removeClickListener((event) => oneSignalClickListenerObserver);
|
OneSignal.Notifications.removePermissionObserver(
|
||||||
|
(permission) => oneSignalPermissionObserver);
|
||||||
|
OneSignal.Notifications.removeClickListener(
|
||||||
|
(event) => oneSignalClickListenerObserver);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +115,9 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userUuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
|
var userUuid =
|
||||||
|
await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
|
||||||
|
'';
|
||||||
if (userUuid.isNotEmpty) {
|
if (userUuid.isNotEmpty) {
|
||||||
await OneSignal.login(userUuid);
|
await OneSignal.login(userUuid);
|
||||||
}
|
}
|
||||||
@ -115,21 +125,24 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
await OneSignal.User.pushSubscription.optIn();
|
await OneSignal.User.pushSubscription.optIn();
|
||||||
|
|
||||||
//this function will be called once a user is subscribed
|
//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) {
|
if (state.current.optedIn) {
|
||||||
await _sendSubscriptionId();
|
await _sendSubscriptionId();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send the player id when a user allows notifications
|
// Send the player id when a user allows notifications
|
||||||
oneSignalPermissionObserver = OneSignal.Notifications.addPermissionObserver((state) async {
|
oneSignalPermissionObserver =
|
||||||
|
OneSignal.Notifications.addPermissionObserver((state) async {
|
||||||
await _sendSubscriptionId();
|
await _sendSubscriptionId();
|
||||||
});
|
});
|
||||||
|
|
||||||
//check if the player id is sent, if not send it again
|
//check if the player id is sent, if not send it again
|
||||||
await _sendSubscriptionId();
|
await _sendSubscriptionId();
|
||||||
|
|
||||||
oneSignalClickListenerObserver = OneSignal.Notifications.addClickListener((event) async {
|
oneSignalClickListenerObserver =
|
||||||
|
OneSignal.Notifications.addClickListener((event) async {
|
||||||
//Once the user clicks on the notification
|
//Once the user clicks on the notification
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -216,7 +229,9 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
|
|
||||||
Future<bool> joinAUnit(String code) async {
|
Future<bool> joinAUnit(String code) async {
|
||||||
try {
|
try {
|
||||||
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
|
var uuid =
|
||||||
|
await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
|
||||||
|
'';
|
||||||
Map<String, String> body = {'userUuid': uuid, 'inviteCode': code};
|
Map<String, String> body = {'userUuid': uuid, 'inviteCode': code};
|
||||||
|
|
||||||
final success = await SpacesAPI.joinUnit(body);
|
final success = await SpacesAPI.joinUnit(body);
|
||||||
@ -334,15 +349,25 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
size: 32,
|
size: 32,
|
||||||
),
|
),
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
foregroundColor:
|
||||||
|
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.push(
|
Navigator.pushNamed(
|
||||||
NavigationService.navigatorKey.currentContext!,
|
NavigationService.navigatorKey.currentContext!,
|
||||||
CustomPageRoute(
|
Routes.sceneTasksRoute,
|
||||||
builder: (context) => const CreateSceneView(),
|
arguments: SceneSettingsRouteArguments(
|
||||||
|
sceneType: '',
|
||||||
|
sceneId: '',
|
||||||
|
sceneName: '',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
NavigationService.navigatorKey.currentContext!
|
||||||
|
.read<CreateSceneBloc>()
|
||||||
|
.add(const ClearTaskListEvent());
|
||||||
|
NavigationService.navigatorKey.currentContext!
|
||||||
|
.read<CreateSceneBloc>()
|
||||||
|
.add(const SceneTypeEvent(CreateSceneEnum.none));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -351,7 +376,8 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
size: 28,
|
size: 28,
|
||||||
),
|
),
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
foregroundColor:
|
||||||
|
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||||
),
|
),
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
),
|
),
|
||||||
@ -384,7 +410,8 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static var bottomNavItems = [
|
static var bottomNavItems = [
|
||||||
defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
|
defaultBottomNavBarItem(
|
||||||
|
icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
|
||||||
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
|
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
|
||||||
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
|
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
|
||||||
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
|
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
|
||||||
@ -410,7 +437,8 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
|
|
||||||
void updateDevice(String deviceId) async {
|
void updateDevice(String deviceId) async {
|
||||||
try {
|
try {
|
||||||
final response = await DevicesAPI.firmwareDevice(deviceId: deviceId, firmwareVersion: '0');
|
final response = await DevicesAPI.firmwareDevice(
|
||||||
|
deviceId: deviceId, firmwareVersion: '0');
|
||||||
if (response['success'] ?? false) {
|
if (response['success'] ?? false) {
|
||||||
CustomSnackBar.displaySnackBar('No updates available');
|
CustomSnackBar.displaySnackBar('No updates available');
|
||||||
}
|
}
|
||||||
@ -418,7 +446,8 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BottomNavigationBarItem defaultBottomNavBarItem({required String icon, required String label}) {
|
BottomNavigationBarItem defaultBottomNavBarItem(
|
||||||
|
{required String icon, required String label}) {
|
||||||
return BottomNavigationBarItem(
|
return BottomNavigationBarItem(
|
||||||
icon: SvgPicture.asset(icon),
|
icon: SvgPicture.asset(icon),
|
||||||
activeIcon: SvgPicture.asset(
|
activeIcon: SvgPicture.asset(
|
||||||
|
@ -2,8 +2,10 @@ import 'dart:async';
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||||
import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.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/create_scene_model.dart';
|
||||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||||
import 'package:syncrow_app/services/api/scene_api.dart';
|
import 'package:syncrow_app/services/api/scene_api.dart';
|
||||||
@ -26,8 +28,12 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
on<RemoveFromSelectedValueById>(_removeFromSelectedValueById);
|
on<RemoveFromSelectedValueById>(_removeFromSelectedValueById);
|
||||||
on<DeleteSceneEvent>(_deleteScene);
|
on<DeleteSceneEvent>(_deleteScene);
|
||||||
on<UpdateTaskEvent>(_updateTaskValue);
|
on<UpdateTaskEvent>(_updateTaskValue);
|
||||||
|
on<SelectConditionEvent>(_selectConditionRule);
|
||||||
|
on<SceneTypeEvent>(_sceneTypeEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreateSceneEnum sceneType = CreateSceneEnum.none;
|
||||||
|
|
||||||
/// tab to run values and list
|
/// tab to run values and list
|
||||||
List<SceneStaticFunction> tasksList = [];
|
List<SceneStaticFunction> tasksList = [];
|
||||||
List<SceneStaticFunction> tempTasksList = [];
|
List<SceneStaticFunction> tempTasksList = [];
|
||||||
@ -37,6 +43,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
List<SceneStaticFunction> automationTasksList = [];
|
List<SceneStaticFunction> automationTasksList = [];
|
||||||
List<SceneStaticFunction> automationTempTasksList = [];
|
List<SceneStaticFunction> automationTempTasksList = [];
|
||||||
final Map<String, dynamic> automationSelectedValues = {};
|
final Map<String, dynamic> automationSelectedValues = {};
|
||||||
|
final Map<String, String> automationComparatorValues = {};
|
||||||
|
String conditionRule = 'or';
|
||||||
|
|
||||||
FutureOr<void> _onAddSceneTask(
|
FutureOr<void> _onAddSceneTask(
|
||||||
AddTaskEvent event, Emitter<CreateSceneState> emit) {
|
AddTaskEvent event, Emitter<CreateSceneState> emit) {
|
||||||
@ -46,6 +54,7 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
automationTasksList.addAll(copyList);
|
automationTasksList.addAll(copyList);
|
||||||
automationTempTasksList.clear();
|
automationTempTasksList.clear();
|
||||||
automationSelectedValues.clear();
|
automationSelectedValues.clear();
|
||||||
|
automationComparatorValues.clear();
|
||||||
emit(AddSceneTask(
|
emit(AddSceneTask(
|
||||||
automationTasksList: automationTasksList,
|
automationTasksList: automationTasksList,
|
||||||
tasksList: tasksList,
|
tasksList: tasksList,
|
||||||
@ -144,6 +153,7 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
icon: '',
|
icon: '',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
comparator: automationComparatorValues[element.code],
|
||||||
);
|
);
|
||||||
automationTempTasksList[automationTempTasksList.indexOf(element)] =
|
automationTempTasksList[automationTempTasksList.indexOf(element)] =
|
||||||
updatedElement;
|
updatedElement;
|
||||||
@ -168,6 +178,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
icon: '',
|
icon: '',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
comparator:
|
||||||
|
automationComparatorValues[event.deviceControlModel.code] ?? '==',
|
||||||
);
|
);
|
||||||
automationTempTasksList.add(newElement);
|
automationTempTasksList.add(newElement);
|
||||||
automationSelectedValues[newElement.code] =
|
automationSelectedValues[newElement.code] =
|
||||||
@ -182,6 +194,7 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
emit(CreateSceneLoading());
|
emit(CreateSceneLoading());
|
||||||
if (event.isAutomation == true) {
|
if (event.isAutomation == true) {
|
||||||
automationSelectedValues[event.code] = event.value;
|
automationSelectedValues[event.code] = event.value;
|
||||||
|
automationComparatorValues[event.code] = event.comparator ?? '==';
|
||||||
emit(SelectedTaskValueState(value: event.value));
|
emit(SelectedTaskValueState(value: event.value));
|
||||||
emit(AddSceneTask(
|
emit(AddSceneTask(
|
||||||
tasksList: tasksList, automationTasksList: automationTasksList));
|
tasksList: tasksList, automationTasksList: automationTasksList));
|
||||||
@ -248,13 +261,26 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
CreateSceneWithTasksEvent event, Emitter<CreateSceneState> emit) async {
|
CreateSceneWithTasksEvent event, Emitter<CreateSceneState> emit) async {
|
||||||
emit(CreateSceneLoading());
|
emit(CreateSceneLoading());
|
||||||
try {
|
try {
|
||||||
final response = event.updateScene
|
dynamic response;
|
||||||
? await SceneApi.updateScene(event.createSceneModel, event.sceneId)
|
if (event.createSceneModel != null) {
|
||||||
: await SceneApi.createScene(event.createSceneModel);
|
response = event.updateScene
|
||||||
|
? await SceneApi.updateScene(event.createSceneModel!, event.sceneId)
|
||||||
|
: await SceneApi.createScene(event.createSceneModel!);
|
||||||
|
} else if (event.createAutomationModel != null) {
|
||||||
|
response =
|
||||||
|
await SceneApi.createAutomation(event.createAutomationModel!);
|
||||||
|
}
|
||||||
|
|
||||||
if (response['success'] == true) {
|
if (response['success'] == true) {
|
||||||
tasksList.clear();
|
tasksList.clear();
|
||||||
tempTasksList.clear();
|
tempTasksList.clear();
|
||||||
selectedValues.clear();
|
selectedValues.clear();
|
||||||
|
automationTasksList.clear();
|
||||||
|
automationTempTasksList.clear();
|
||||||
|
automationSelectedValues.clear();
|
||||||
|
automationComparatorValues.clear();
|
||||||
|
sceneType = CreateSceneEnum.none;
|
||||||
|
conditionRule = 'or';
|
||||||
emit(const CreateSceneWithTasks(success: true));
|
emit(const CreateSceneWithTasks(success: true));
|
||||||
} else {
|
} else {
|
||||||
emit(const CreateSceneError(message: 'Something went wrong'));
|
emit(const CreateSceneError(message: 'Something went wrong'));
|
||||||
@ -301,6 +327,7 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
if (event.isAutomation == true) {
|
if (event.isAutomation == true) {
|
||||||
automationTempTasksList.clear();
|
automationTempTasksList.clear();
|
||||||
automationSelectedValues.clear();
|
automationSelectedValues.clear();
|
||||||
|
automationComparatorValues.clear();
|
||||||
emit(AddSceneTask(
|
emit(AddSceneTask(
|
||||||
tasksList: tasksList, automationTasksList: automationTasksList));
|
tasksList: tasksList, automationTasksList: automationTasksList));
|
||||||
} else {
|
} else {
|
||||||
@ -317,6 +344,7 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
if (event.isAutomation == true) {
|
if (event.isAutomation == true) {
|
||||||
if (automationSelectedValues.containsKey(event.code)) {
|
if (automationSelectedValues.containsKey(event.code)) {
|
||||||
automationSelectedValues.remove(event.code);
|
automationSelectedValues.remove(event.code);
|
||||||
|
automationComparatorValues.remove(event.code);
|
||||||
emit(const SelectedTaskValueState(value: null));
|
emit(const SelectedTaskValueState(value: null));
|
||||||
emit(AddSceneTask(
|
emit(AddSceneTask(
|
||||||
tasksList: tasksList, automationTasksList: automationTasksList));
|
tasksList: tasksList, automationTasksList: automationTasksList));
|
||||||
@ -373,4 +401,31 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
|||||||
emit(AddSceneTask(
|
emit(AddSceneTask(
|
||||||
tasksList: tasksList, automationTasksList: automationTasksList));
|
tasksList: tasksList, automationTasksList: automationTasksList));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FutureOr<void> _selectConditionRule(
|
||||||
|
SelectConditionEvent event, Emitter<CreateSceneState> emit) {
|
||||||
|
emit(CreateSceneInitial());
|
||||||
|
if (event.condition.contains('any')) {
|
||||||
|
conditionRule = 'or';
|
||||||
|
} else {
|
||||||
|
conditionRule = 'and';
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(ConditionSelectedState(event.condition));
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureOr<void> _sceneTypeEvent(
|
||||||
|
SceneTypeEvent event, Emitter<CreateSceneState> 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,12 +67,14 @@ class SelectedValueEvent extends CreateSceneEvent {
|
|||||||
final dynamic automationValue;
|
final dynamic automationValue;
|
||||||
final String code;
|
final String code;
|
||||||
final bool? isAutomation;
|
final bool? isAutomation;
|
||||||
|
final String? comparator;
|
||||||
|
|
||||||
const SelectedValueEvent({
|
const SelectedValueEvent({
|
||||||
this.value,
|
this.value,
|
||||||
required this.code,
|
required this.code,
|
||||||
this.isAutomation,
|
this.isAutomation,
|
||||||
this.automationValue,
|
this.automationValue,
|
||||||
|
this.comparator,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -110,19 +112,21 @@ class RemoveFromSelectedValueById extends CreateSceneEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CreateSceneWithTasksEvent extends CreateSceneEvent {
|
class CreateSceneWithTasksEvent extends CreateSceneEvent {
|
||||||
final CreateSceneModel createSceneModel;
|
final CreateSceneModel? createSceneModel;
|
||||||
final bool updateScene;
|
final bool updateScene;
|
||||||
final String sceneId;
|
final String sceneId;
|
||||||
|
final CreateAutomationModel? createAutomationModel;
|
||||||
//final bool isAutomation;
|
//final bool isAutomation;
|
||||||
const CreateSceneWithTasksEvent({
|
const CreateSceneWithTasksEvent({
|
||||||
required this.createSceneModel,
|
required this.createSceneModel,
|
||||||
required this.updateScene,
|
required this.updateScene,
|
||||||
required this.sceneId,
|
required this.sceneId,
|
||||||
|
required this.createAutomationModel,
|
||||||
// required this.isAutomation,
|
// required this.isAutomation,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [createSceneModel];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClearTaskListEvent extends CreateSceneEvent {
|
class ClearTaskListEvent extends CreateSceneEvent {
|
||||||
@ -160,3 +164,14 @@ class DeleteSceneEvent extends CreateSceneEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [sceneId, unitUuid];
|
List<Object> get props => [sceneId, unitUuid];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SelectConditionEvent extends CreateSceneEvent {
|
||||||
|
final String condition;
|
||||||
|
|
||||||
|
const SelectConditionEvent(this.condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SceneTypeEvent extends CreateSceneEvent {
|
||||||
|
final CreateSceneEnum type;
|
||||||
|
const SceneTypeEvent(this.type);
|
||||||
|
}
|
||||||
|
@ -71,3 +71,14 @@ class DeleteSceneError extends CreateSceneState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DeleteSceneLoading extends CreateSceneState {}
|
class DeleteSceneLoading extends CreateSceneState {}
|
||||||
|
|
||||||
|
class ConditionSelectedState extends CreateSceneState {
|
||||||
|
final String condition;
|
||||||
|
|
||||||
|
const ConditionSelectedState(this.condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SceneTypeState extends CreateSceneState {
|
||||||
|
final CreateSceneEnum type;
|
||||||
|
const SceneTypeState(this.type);
|
||||||
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
enum CreateSceneEnum {
|
enum CreateSceneEnum {
|
||||||
tabToRun,
|
tabToRun,
|
||||||
deviceStatusChanges,
|
deviceStatusChanges,
|
||||||
|
none,
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
import 'package:syncrow_app/features/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/create_scene/create_scene_bloc.dart';
|
||||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
|
||||||
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
|
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
|
||||||
|
|
||||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||||
|
|
||||||
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart';
|
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart';
|
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart';
|
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart';
|
||||||
@ -22,14 +20,19 @@ mixin SceneLogicHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handleSaveButtonPress(
|
void handleSaveButtonPress(
|
||||||
BuildContext context,
|
BuildContext context, {
|
||||||
TextEditingController sceneNameController,
|
|
||||||
List<SceneStaticFunction> tasks, {
|
|
||||||
required bool updateScene,
|
required bool updateScene,
|
||||||
required String sceneId,
|
required String sceneId,
|
||||||
|
required bool isAutomation,
|
||||||
|
required TextEditingController sceneName,
|
||||||
|
required List<SceneStaticFunction> actions,
|
||||||
|
required List<SceneStaticFunction> conditions,
|
||||||
}) {
|
}) {
|
||||||
if (isOnlyDelayOrDelayLast(tasks)) {
|
final sceneBloc = context.read<CreateSceneBloc>();
|
||||||
// Show snackbar indicating restriction
|
|
||||||
|
if (isAutomation) {
|
||||||
|
// Handle Automation Creation
|
||||||
|
if (isOnlyDelayOrDelayLast(actions)) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
context.showCustomSnackbar(
|
context.showCustomSnackbar(
|
||||||
message: 'A single delay or delay-last operations are NOT allowed.',
|
message: 'A single delay or delay-last operations are NOT allowed.',
|
||||||
@ -39,17 +42,65 @@ mixin SceneLogicHelper {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
final createAutomationModel = CreateAutomationModel(
|
||||||
|
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
||||||
|
automationName: sceneName.text,
|
||||||
|
decisionExpr: sceneBloc.conditionRule,
|
||||||
|
effectiveTime:
|
||||||
|
EffectiveTime(start: '00:00', end: '23:59', loops: '1111111'),
|
||||||
|
conditions: List.generate(
|
||||||
|
conditions.length,
|
||||||
|
(index) {
|
||||||
|
final task = conditions[index];
|
||||||
|
return CreateCondition(
|
||||||
|
code: index + 1,
|
||||||
|
entityId: task.deviceId,
|
||||||
|
entityType: 'device_report',
|
||||||
|
expr: ConditionExpr(
|
||||||
|
statusCode: task.code,
|
||||||
|
comparator: task.comparator ?? '==',
|
||||||
|
statusValue: task.functionValue,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
actions: List.generate(
|
||||||
|
actions.length,
|
||||||
|
(index) {
|
||||||
|
final task = actions[index];
|
||||||
|
return CreateSceneAction(
|
||||||
|
entityId: task.deviceId,
|
||||||
|
actionExecutor: 'device_issue',
|
||||||
|
executorProperty: CreateSceneExecutorProperty(
|
||||||
|
functionCode: task.code,
|
||||||
|
functionValue: task.functionValue,
|
||||||
|
delaySeconds: 0,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
sceneBloc.add(CreateSceneWithTasksEvent(
|
||||||
|
createSceneModel: null,
|
||||||
|
updateScene: updateScene,
|
||||||
|
sceneId: sceneId,
|
||||||
|
createAutomationModel: createAutomationModel,
|
||||||
|
));
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle Scene Creation
|
||||||
final createSceneModel = CreateSceneModel(
|
final createSceneModel = CreateSceneModel(
|
||||||
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
||||||
sceneName: sceneNameController.text,
|
sceneName: sceneName.text,
|
||||||
decisionExpr: 'and',
|
decisionExpr: 'and',
|
||||||
actions: List.generate(
|
actions: List.generate(
|
||||||
tasks.length,
|
actions.length,
|
||||||
(index) {
|
(index) {
|
||||||
final task = tasks[index];
|
final task = actions[index];
|
||||||
if (task.deviceId == 'delay') {
|
if (task.deviceId == 'delay') {
|
||||||
return CreateSceneAction(
|
return CreateSceneAction(
|
||||||
entityId: tasks[index].deviceId,
|
entityId: actions[index].deviceId,
|
||||||
actionExecutor: 'delay',
|
actionExecutor: 'delay',
|
||||||
executorProperty: CreateSceneExecutorProperty(
|
executorProperty: CreateSceneExecutorProperty(
|
||||||
functionCode: '',
|
functionCode: '',
|
||||||
@ -70,12 +121,12 @@ mixin SceneLogicHelper {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
context.read<CreateSceneBloc>().add(CreateSceneWithTasksEvent(
|
sceneBloc.add(CreateSceneWithTasksEvent(
|
||||||
createSceneModel: createSceneModel,
|
createSceneModel: createSceneModel,
|
||||||
|
createAutomationModel: null,
|
||||||
updateScene: updateScene,
|
updateScene: updateScene,
|
||||||
sceneId: sceneId,
|
sceneId: sceneId,
|
||||||
));
|
));
|
||||||
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,29 +206,9 @@ mixin SceneOperationsDataHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SceneStaticFunction _mapExecutorPropertyToSceneFunction(
|
SceneStaticFunction _mapExecutorPropertyToSceneFunction(
|
||||||
Action action, bool isAutomation) {
|
Action action, bool isAutomation,
|
||||||
|
{String? comparator}) {
|
||||||
ExecutorProperty executorProperty = action.executorProperty;
|
ExecutorProperty executorProperty = action.executorProperty;
|
||||||
/*
|
|
||||||
|
|
||||||
if (type == DeviceType.LightBulb) {
|
|
||||||
tempIcon = Assets.assetsIconsLight;
|
|
||||||
} else if (type == DeviceType.CeilingSensor ||
|
|
||||||
type == DeviceType.WallSensor) {
|
|
||||||
tempIcon = Assets.assetsIconsSensors;
|
|
||||||
} else if (type == DeviceType.AC) {
|
|
||||||
tempIcon = Assets.assetsIconsAC;
|
|
||||||
} else if (type == DeviceType.DoorLock) {
|
|
||||||
tempIcon = Assets.assetsIconsDoorLock;
|
|
||||||
} else if (type == DeviceType.Curtain) {
|
|
||||||
tempIcon = Assets.assetsIconsCurtain;
|
|
||||||
} else if (type == DeviceType.ThreeGang) {
|
|
||||||
tempIcon = Assets.assetsIcons3GangSwitch;
|
|
||||||
} else if (type == DeviceType.Gateway) {
|
|
||||||
tempIcon = Assets.assetsIconsGateway;
|
|
||||||
} else {
|
|
||||||
tempIcon = Assets.assetsIconsLogo;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch (executorProperty.functionCode) {
|
switch (executorProperty.functionCode) {
|
||||||
case 'sensitivity':
|
case 'sensitivity':
|
||||||
@ -243,7 +223,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
isAutomation
|
isAutomation
|
||||||
? _createIntegerStepsOptions()
|
? _createIntegerStepsOptions()
|
||||||
: _createSensitivityOptions(),
|
: _createSensitivityOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'normal_open_switch':
|
case 'normal_open_switch':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -252,7 +233,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Set Door lock Normal Open',
|
'Set Door lock Normal Open',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'unlock_fingerprint':
|
case 'unlock_fingerprint':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -261,7 +243,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Fingerprint Unlock',
|
'Fingerprint Unlock',
|
||||||
OperationDialogType.integerSteps,
|
OperationDialogType.integerSteps,
|
||||||
_createFingerprintUnlockOptions(),
|
_createFingerprintUnlockOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'unlock_password':
|
case 'unlock_password':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -270,7 +253,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Password Unlock',
|
'Password Unlock',
|
||||||
OperationDialogType.integerSteps,
|
OperationDialogType.integerSteps,
|
||||||
_createPasswordUnlockOptions(),
|
_createPasswordUnlockOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'unlock_card':
|
case 'unlock_card':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -279,7 +263,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Card Unlock',
|
'Card Unlock',
|
||||||
OperationDialogType.integerSteps,
|
OperationDialogType.integerSteps,
|
||||||
_createCardUnlockOptions(),
|
_createCardUnlockOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'alarm_lock':
|
case 'alarm_lock':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -288,7 +273,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Lock Alarm',
|
'Lock Alarm',
|
||||||
OperationDialogType.listOfOptions,
|
OperationDialogType.listOfOptions,
|
||||||
_createLockAlarmOptions(),
|
_createLockAlarmOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'unlock_request':
|
case 'unlock_request':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -297,7 +283,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Remote Unlock Request',
|
'Remote Unlock Request',
|
||||||
OperationDialogType.integerSteps,
|
OperationDialogType.integerSteps,
|
||||||
_createUnlockRequestOptions(),
|
_createUnlockRequestOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'residual_electricity':
|
case 'residual_electricity':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -306,7 +293,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Residual Electricity',
|
'Residual Electricity',
|
||||||
OperationDialogType.integerSteps,
|
OperationDialogType.integerSteps,
|
||||||
_createResidualElectricityOptions(),
|
_createResidualElectricityOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'reverse_lock':
|
case 'reverse_lock':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -315,7 +303,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Double Lock',
|
'Double Lock',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'unlock_app':
|
case 'unlock_app':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -324,7 +313,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Remote Unlock Via App',
|
'Remote Unlock Via App',
|
||||||
OperationDialogType.integerSteps,
|
OperationDialogType.integerSteps,
|
||||||
_createUnlockAppOptions(),
|
_createUnlockAppOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'hijack':
|
case 'hijack':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -333,7 +323,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Hijack Alarm',
|
'Hijack Alarm',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'doorbell':
|
case 'doorbell':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -342,7 +333,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Doorbell',
|
'Doorbell',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'unlock_temporary':
|
case 'unlock_temporary':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -351,7 +343,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Temporary Password Unlock',
|
'Temporary Password Unlock',
|
||||||
OperationDialogType.integerSteps,
|
OperationDialogType.integerSteps,
|
||||||
_createTemporaryPasswordUnlockOptions(),
|
_createTemporaryPasswordUnlockOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'far_detection':
|
case 'far_detection':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -360,7 +353,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Far Detection',
|
'Far Detection',
|
||||||
OperationDialogType.listOfOptions,
|
OperationDialogType.listOfOptions,
|
||||||
_createFarDetectionOptions(),
|
_createFarDetectionOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'motion_sensitivity_value':
|
case 'motion_sensitivity_value':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -369,7 +363,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Motion Detection Sensitivity',
|
'Motion Detection Sensitivity',
|
||||||
OperationDialogType.listOfOptions,
|
OperationDialogType.listOfOptions,
|
||||||
_createSensitivityOptions(),
|
_createSensitivityOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'motionless_sensitivity':
|
case 'motionless_sensitivity':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -378,7 +373,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Motionless Detection Sensitivity',
|
'Motionless Detection Sensitivity',
|
||||||
OperationDialogType.listOfOptions,
|
OperationDialogType.listOfOptions,
|
||||||
_createSensitivityOptions(),
|
_createSensitivityOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'indicator':
|
case 'indicator':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -387,7 +383,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Indicator',
|
'Indicator',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'presence_time':
|
case 'presence_time':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -396,7 +393,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Nobody Time',
|
'Nobody Time',
|
||||||
OperationDialogType.countdown,
|
OperationDialogType.countdown,
|
||||||
_createCountdownOptions(),
|
_createCountdownOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'presence_state':
|
case 'presence_state':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -405,7 +403,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Presence State',
|
'Presence State',
|
||||||
OperationDialogType.listOfOptions,
|
OperationDialogType.listOfOptions,
|
||||||
_createPresenceStateOptions(),
|
_createPresenceStateOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'dis_current':
|
case 'dis_current':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -414,7 +413,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Current Distance',
|
'Current Distance',
|
||||||
OperationDialogType.integerSteps,
|
OperationDialogType.integerSteps,
|
||||||
_createCurrentDistanceOptions(),
|
_createCurrentDistanceOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'illuminance_value':
|
case 'illuminance_value':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -423,7 +423,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Illuminance Value',
|
'Illuminance Value',
|
||||||
OperationDialogType.integerSteps,
|
OperationDialogType.integerSteps,
|
||||||
_createIlluminanceValueOptions(),
|
_createIlluminanceValueOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'checking_result':
|
case 'checking_result':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -432,7 +433,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Self-Test Result',
|
'Self-Test Result',
|
||||||
OperationDialogType.listOfOptions,
|
OperationDialogType.listOfOptions,
|
||||||
_createSelfTestResultOptions(),
|
_createSelfTestResultOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'switch':
|
case 'switch':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -441,7 +443,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Power',
|
'Power',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'temp_set':
|
case 'temp_set':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -454,7 +457,19 @@ mixin SceneOperationsDataHelper {
|
|||||||
isAutomation
|
isAutomation
|
||||||
? _createAutomationTemperatureOptions()
|
? _createAutomationTemperatureOptions()
|
||||||
: _createTemperatureOptions(),
|
: _createTemperatureOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
|
case 'temp_current':
|
||||||
|
return _createSceneFunction(
|
||||||
|
action,
|
||||||
|
'Smart AC Thermostat - Grey - Model A',
|
||||||
|
Assets.assetsIconsAC,
|
||||||
|
'Current Temperature',
|
||||||
|
OperationDialogType.integerSteps,
|
||||||
|
_createCurrentTemperatureOptions(),
|
||||||
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
|
|
||||||
case 'mode':
|
case 'mode':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -463,7 +478,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Mode',
|
'Mode',
|
||||||
OperationDialogType.listOfOptions,
|
OperationDialogType.listOfOptions,
|
||||||
_createAcModeOptions(),
|
_createAcModeOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'level':
|
case 'level':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -472,7 +488,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Fan Speed',
|
'Fan Speed',
|
||||||
OperationDialogType.listOfOptions,
|
OperationDialogType.listOfOptions,
|
||||||
_createFanSpeedOptions(),
|
_createFanSpeedOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'child_lock':
|
case 'child_lock':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -481,7 +498,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Child Lock',
|
'Child Lock',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'switch_1':
|
case 'switch_1':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -490,7 +508,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Light 1 Switch',
|
'Light 1 Switch',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'switch_2':
|
case 'switch_2':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -499,7 +518,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Light 2 Switch',
|
'Light 2 Switch',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'switch_3':
|
case 'switch_3':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -508,7 +528,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Light 3 Switch',
|
'Light 3 Switch',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
|
|
||||||
case 'countdown_1':
|
case 'countdown_1':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
@ -522,7 +543,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
isAutomation
|
isAutomation
|
||||||
? _createAutomationCountDownOptions()
|
? _createAutomationCountDownOptions()
|
||||||
: _createCountdownOptions(),
|
: _createCountdownOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'countdown_2':
|
case 'countdown_2':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -535,7 +557,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
isAutomation
|
isAutomation
|
||||||
? _createAutomationCountDownOptions()
|
? _createAutomationCountDownOptions()
|
||||||
: _createCountdownOptions(),
|
: _createCountdownOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'countdown_3':
|
case 'countdown_3':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -548,7 +571,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
isAutomation
|
isAutomation
|
||||||
? _createAutomationCountDownOptions()
|
? _createAutomationCountDownOptions()
|
||||||
: _createCountdownOptions(),
|
: _createCountdownOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'switch_alarm_sound':
|
case 'switch_alarm_sound':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -557,7 +581,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Switch Alarm Sound',
|
'Switch Alarm Sound',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'master_state':
|
case 'master_state':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -566,7 +591,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Master State',
|
'Master State',
|
||||||
OperationDialogType.listOfOptions,
|
OperationDialogType.listOfOptions,
|
||||||
_createMasterStateOptions(),
|
_createMasterStateOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
case 'factory_reset':
|
case 'factory_reset':
|
||||||
return _createSceneFunction(
|
return _createSceneFunction(
|
||||||
action,
|
action,
|
||||||
@ -575,7 +601,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
'Factory Reset',
|
'Factory Reset',
|
||||||
OperationDialogType.onOff,
|
OperationDialogType.onOff,
|
||||||
_createOnOffOptions(),
|
_createOnOffOptions(),
|
||||||
isAutomation);
|
isAutomation,
|
||||||
|
comparator ?? '==');
|
||||||
default:
|
default:
|
||||||
throw ArgumentError(
|
throw ArgumentError(
|
||||||
'Unsupported function code: ${executorProperty.functionCode}');
|
'Unsupported function code: ${executorProperty.functionCode}');
|
||||||
@ -778,7 +805,8 @@ mixin SceneOperationsDataHelper {
|
|||||||
String operationName,
|
String operationName,
|
||||||
OperationDialogType operationDialogType,
|
OperationDialogType operationDialogType,
|
||||||
List<SceneOperationalValue> operationalValues,
|
List<SceneOperationalValue> operationalValues,
|
||||||
bool isAutomation) {
|
bool isAutomation,
|
||||||
|
String comparator) {
|
||||||
final functionValue = action.executorProperty.functionValue;
|
final functionValue = action.executorProperty.functionValue;
|
||||||
return SceneStaticFunction(
|
return SceneStaticFunction(
|
||||||
deviceId: action.entityId,
|
deviceId: action.entityId,
|
||||||
@ -790,6 +818,7 @@ mixin SceneOperationsDataHelper {
|
|||||||
code: action.executorProperty.functionCode ?? '',
|
code: action.executorProperty.functionCode ?? '',
|
||||||
operationDialogType: operationDialogType,
|
operationDialogType: operationDialogType,
|
||||||
operationalValues: operationalValues,
|
operationalValues: operationalValues,
|
||||||
|
comparator: comparator,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,7 +942,22 @@ mixin SceneOperationsDataHelper {
|
|||||||
functionCode: taskItem.code,
|
functionCode: taskItem.code,
|
||||||
functionValue: taskItem.functionValue),
|
functionValue: taskItem.functionValue),
|
||||||
actionExecutor: ''),
|
actionExecutor: ''),
|
||||||
isAutomation)
|
isAutomation,
|
||||||
|
comparator: taskItem.comparator,
|
||||||
|
)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SceneOperationalValue> _createCurrentTemperatureOptions() {
|
||||||
|
return [
|
||||||
|
SceneOperationalValue(
|
||||||
|
icon: Assets.assetsCelsiusDegrees,
|
||||||
|
value: 0.0,
|
||||||
|
description: '°C',
|
||||||
|
minValue: -9.9,
|
||||||
|
maxValue: 99.9,
|
||||||
|
stepValue: 0.1,
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
172
lib/features/scene/model/create_automation_model.dart
Normal file
172
lib/features/scene/model/create_automation_model.dart
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
|
||||||
|
|
||||||
|
class CreateAutomationModel {
|
||||||
|
String unitUuid;
|
||||||
|
String automationName;
|
||||||
|
String decisionExpr;
|
||||||
|
EffectiveTime effectiveTime;
|
||||||
|
List<CreateCondition> conditions;
|
||||||
|
List<CreateSceneAction> actions;
|
||||||
|
|
||||||
|
CreateAutomationModel({
|
||||||
|
required this.unitUuid,
|
||||||
|
required this.automationName,
|
||||||
|
required this.decisionExpr,
|
||||||
|
required this.effectiveTime,
|
||||||
|
required this.conditions,
|
||||||
|
required this.actions,
|
||||||
|
});
|
||||||
|
|
||||||
|
CreateAutomationModel copyWith({
|
||||||
|
String? unitUuid,
|
||||||
|
String? automationName,
|
||||||
|
String? decisionExpr,
|
||||||
|
EffectiveTime? effectiveTime,
|
||||||
|
List<CreateCondition>? conditions,
|
||||||
|
List<CreateSceneAction>? actions,
|
||||||
|
}) {
|
||||||
|
return CreateAutomationModel(
|
||||||
|
unitUuid: unitUuid ?? this.unitUuid,
|
||||||
|
automationName: automationName ?? this.automationName,
|
||||||
|
decisionExpr: decisionExpr ?? this.decisionExpr,
|
||||||
|
effectiveTime: effectiveTime ?? this.effectiveTime,
|
||||||
|
conditions: conditions ?? this.conditions,
|
||||||
|
actions: actions ?? this.actions,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'unitUuid': unitUuid,
|
||||||
|
'automationName': automationName,
|
||||||
|
'decisionExpr': decisionExpr,
|
||||||
|
'effectiveTime': effectiveTime.toMap(),
|
||||||
|
'conditions': conditions.map((x) => x.toMap()).toList(),
|
||||||
|
'actions': actions.map((x) => x.toMap()).toList(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory CreateAutomationModel.fromMap(Map<String, dynamic> map) {
|
||||||
|
return CreateAutomationModel(
|
||||||
|
unitUuid: map['unitUuid'] ?? '',
|
||||||
|
automationName: map['automationName'] ?? '',
|
||||||
|
decisionExpr: map['decisionExpr'] ?? '',
|
||||||
|
effectiveTime: EffectiveTime.fromMap(map['effectiveTime']),
|
||||||
|
conditions: List<CreateCondition>.from(
|
||||||
|
map['conditions']?.map((x) => CreateCondition.fromMap(x))),
|
||||||
|
actions: List<CreateSceneAction>.from(
|
||||||
|
map['actions']?.map((x) => CreateSceneAction.fromMap(x))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String toJson() => json.encode(toMap());
|
||||||
|
|
||||||
|
factory CreateAutomationModel.fromJson(String source) =>
|
||||||
|
CreateAutomationModel.fromMap(json.decode(source));
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CreateAutomationModel(unitUuid: $unitUuid, automationName: $automationName, decisionExpr: $decisionExpr, effectiveTime: $effectiveTime, conditions: $conditions, actions: $actions)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EffectiveTime {
|
||||||
|
String start;
|
||||||
|
String end;
|
||||||
|
String loops;
|
||||||
|
|
||||||
|
EffectiveTime({
|
||||||
|
required this.start,
|
||||||
|
required this.end,
|
||||||
|
required this.loops,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'start': start,
|
||||||
|
'end': end,
|
||||||
|
'loops': loops,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory EffectiveTime.fromMap(Map<String, dynamic> map) {
|
||||||
|
return EffectiveTime(
|
||||||
|
start: map['start'] ?? '',
|
||||||
|
end: map['end'] ?? '',
|
||||||
|
loops: map['loops'] ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'EffectiveTime(start: $start, end: $end, loops: $loops)';
|
||||||
|
}
|
||||||
|
|
||||||
|
class CreateCondition {
|
||||||
|
int code;
|
||||||
|
String entityId;
|
||||||
|
String entityType;
|
||||||
|
ConditionExpr expr;
|
||||||
|
|
||||||
|
CreateCondition({
|
||||||
|
required this.code,
|
||||||
|
required this.entityId,
|
||||||
|
required this.entityType,
|
||||||
|
required this.expr,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'code': code,
|
||||||
|
'entityId': entityId,
|
||||||
|
'entityType': entityType,
|
||||||
|
'expr': expr.toMap(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory CreateCondition.fromMap(Map<String, dynamic> map) {
|
||||||
|
return CreateCondition(
|
||||||
|
code: map['code'] ?? 0,
|
||||||
|
entityId: map['entityId'] ?? '',
|
||||||
|
entityType: map['entityType'] ?? '',
|
||||||
|
expr: ConditionExpr.fromMap(map['expr']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() =>
|
||||||
|
'CreateCondition(code: $code, entityId: $entityId, entityType: $entityType, expr: $expr)';
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConditionExpr {
|
||||||
|
String statusCode;
|
||||||
|
String comparator;
|
||||||
|
dynamic statusValue;
|
||||||
|
|
||||||
|
ConditionExpr({
|
||||||
|
required this.statusCode,
|
||||||
|
required this.comparator,
|
||||||
|
required this.statusValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'statusCode': statusCode,
|
||||||
|
'comparator': comparator,
|
||||||
|
'statusValue': statusValue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory ConditionExpr.fromMap(Map<String, dynamic> map) {
|
||||||
|
return ConditionExpr(
|
||||||
|
statusCode: map['statusCode'] ?? '',
|
||||||
|
comparator: map['comparator'] ?? '',
|
||||||
|
statusValue: map['statusValue'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() =>
|
||||||
|
'ConditionExpr(statusCode: $statusCode, comparator: $comparator, statusValue: $statusValue)';
|
||||||
|
}
|
@ -15,6 +15,7 @@ class SceneStaticFunction {
|
|||||||
final dynamic functionValue;
|
final dynamic functionValue;
|
||||||
final String? deviceIcon;
|
final String? deviceIcon;
|
||||||
final OperationDialogType operationDialogType;
|
final OperationDialogType operationDialogType;
|
||||||
|
final String? comparator;
|
||||||
|
|
||||||
SceneStaticFunction({
|
SceneStaticFunction({
|
||||||
required this.icon,
|
required this.icon,
|
||||||
@ -26,6 +27,7 @@ class SceneStaticFunction {
|
|||||||
required this.functionValue,
|
required this.functionValue,
|
||||||
this.deviceIcon,
|
this.deviceIcon,
|
||||||
required this.operationDialogType,
|
required this.operationDialogType,
|
||||||
|
this.comparator,
|
||||||
}) : uniqueCustomId = const Uuid().v4();
|
}) : uniqueCustomId = const Uuid().v4();
|
||||||
|
|
||||||
SceneStaticFunction copyWith({
|
SceneStaticFunction copyWith({
|
||||||
@ -39,6 +41,7 @@ class SceneStaticFunction {
|
|||||||
String? deviceIcon,
|
String? deviceIcon,
|
||||||
String? deviceName,
|
String? deviceName,
|
||||||
OperationDialogType? operationDialogType,
|
OperationDialogType? operationDialogType,
|
||||||
|
String? comparator,
|
||||||
}) {
|
}) {
|
||||||
return SceneStaticFunction(
|
return SceneStaticFunction(
|
||||||
icon: icon ?? this.icon,
|
icon: icon ?? this.icon,
|
||||||
@ -50,6 +53,7 @@ class SceneStaticFunction {
|
|||||||
functionValue: functionValue ?? this.functionValue,
|
functionValue: functionValue ?? this.functionValue,
|
||||||
deviceIcon: deviceIcon ?? this.deviceIcon,
|
deviceIcon: deviceIcon ?? this.deviceIcon,
|
||||||
operationDialogType: operationDialogType ?? this.operationDialogType,
|
operationDialogType: operationDialogType ?? this.operationDialogType,
|
||||||
|
comparator: comparator ?? this.comparator,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +67,8 @@ class SceneStaticFunction {
|
|||||||
'operationName': operationName,
|
'operationName': operationName,
|
||||||
'functionValue': functionValue,
|
'functionValue': functionValue,
|
||||||
'deviceIcon': deviceIcon,
|
'deviceIcon': deviceIcon,
|
||||||
'operationDialogType': operationDialogType.name
|
'operationDialogType': operationDialogType.name,
|
||||||
|
'comparator': comparator
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +87,7 @@ class SceneStaticFunction {
|
|||||||
operationDialogType: map['operationDialogType'] != null
|
operationDialogType: map['operationDialogType'] != null
|
||||||
? OperationDialogType.values.byName(map['operationDialogType'])
|
? OperationDialogType.values.byName(map['operationDialogType'])
|
||||||
: OperationDialogType.none,
|
: OperationDialogType.none,
|
||||||
|
comparator: map['comparator'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +98,7 @@ class SceneStaticFunction {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SceneStaticFunction(icon: $icon, name: $deviceName, code: $code, operationalValues: $operationalValues, deviceId: $deviceId, operationName: $operationName, functionValue: $functionValue, deviceIcon: $deviceIcon, operationDialogType: $operationDialogType)';
|
return 'SceneStaticFunction(icon: $icon, name: $deviceName, code: $code, operationalValues: $operationalValues, deviceId: $deviceId, operationName: $operationName, functionValue: $functionValue, deviceIcon: $deviceIcon, operationDialogType: $operationDialogType, comparator: $comparator)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -106,6 +112,7 @@ class SceneStaticFunction {
|
|||||||
other.operationName == operationName &&
|
other.operationName == operationName &&
|
||||||
other.functionValue == functionValue &&
|
other.functionValue == functionValue &&
|
||||||
other.deviceIcon == deviceIcon &&
|
other.deviceIcon == deviceIcon &&
|
||||||
|
other.comparator == comparator &&
|
||||||
other.operationDialogType == operationDialogType &&
|
other.operationDialogType == operationDialogType &&
|
||||||
listEquals(other.operationalValues, operationalValues) &&
|
listEquals(other.operationalValues, operationalValues) &&
|
||||||
other.deviceId == deviceId;
|
other.deviceId == deviceId;
|
||||||
@ -120,6 +127,7 @@ class SceneStaticFunction {
|
|||||||
operationName.hashCode ^
|
operationName.hashCode ^
|
||||||
functionValue.hashCode ^
|
functionValue.hashCode ^
|
||||||
deviceIcon.hashCode ^
|
deviceIcon.hashCode ^
|
||||||
|
comparator.hashCode ^
|
||||||
operationDialogType.hashCode ^
|
operationDialogType.hashCode ^
|
||||||
operationalValues.hashCode;
|
operationalValues.hashCode;
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,9 @@ import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.
|
|||||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.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/features/shared_widgets/default_scaffold.dart';
|
||||||
|
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
|
import 'package:syncrow_app/navigation/navigate_to_route.dart';
|
||||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||||
|
|
||||||
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||||
|
|
||||||
class CreateSceneView extends StatelessWidget {
|
class CreateSceneView extends StatelessWidget {
|
||||||
@ -22,7 +21,7 @@ class CreateSceneView extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.only(top: 24),
|
padding: const EdgeInsets.only(top: 24),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
navigateToRoute(context, Routes.sceneTasksRoute);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.arrow_back_ios,
|
Icons.arrow_back_ios,
|
||||||
@ -48,6 +47,9 @@ class CreateSceneView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
context.read<CreateSceneBloc>().add(const ClearTaskListEvent());
|
context.read<CreateSceneBloc>().add(const ClearTaskListEvent());
|
||||||
|
context
|
||||||
|
.read<CreateSceneBloc>()
|
||||||
|
.add(const SceneTypeEvent(CreateSceneEnum.tabToRun));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
DefaultContainer(
|
DefaultContainer(
|
||||||
@ -71,6 +73,8 @@ class CreateSceneView extends StatelessWidget {
|
|||||||
context
|
context
|
||||||
.read<CreateSceneBloc>()
|
.read<CreateSceneBloc>()
|
||||||
.add(const ClearTaskListEvent(isAutomation: true));
|
.add(const ClearTaskListEvent(isAutomation: true));
|
||||||
|
context.read<CreateSceneBloc>().add(
|
||||||
|
const SceneTypeEvent(CreateSceneEnum.deviceStatusChanges));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -12,6 +12,7 @@ import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
|||||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/light_divider.dart';
|
import 'package:syncrow_app/features/shared_widgets/light_divider.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/navigation/navigate_to_route.dart';
|
||||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
|
||||||
@ -53,9 +54,7 @@ class DeviceFunctionsView extends StatelessWidget
|
|||||||
context
|
context
|
||||||
.read<CreateSceneBloc>()
|
.read<CreateSceneBloc>()
|
||||||
.add(AddTaskEvent(isAutomation: isAutomation));
|
.add(AddTaskEvent(isAutomation: isAutomation));
|
||||||
Navigator.popUntil(context, (route) {
|
navigateToRoute(context, Routes.sceneTasksRoute);
|
||||||
return route.settings.name == Routes.sceneTasksRoute;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
child: BodyMedium(
|
child: BodyMedium(
|
||||||
text: 'Save',
|
text: 'Save',
|
||||||
|
@ -8,6 +8,8 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart
|
|||||||
import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_body.dart';
|
import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_body.dart';
|
||||||
|
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
import 'package:syncrow_app/navigation/navigate_to_route.dart';
|
||||||
|
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||||
|
|
||||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||||
@ -16,10 +18,12 @@ class SceneRoomsTabBarDevicesView extends StatefulWidget {
|
|||||||
const SceneRoomsTabBarDevicesView({super.key});
|
const SceneRoomsTabBarDevicesView({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SceneRoomsTabBarDevicesView> createState() => _SceneRoomsTabBarDevicesViewState();
|
State<SceneRoomsTabBarDevicesView> createState() =>
|
||||||
|
_SceneRoomsTabBarDevicesViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesView>
|
class _SceneRoomsTabBarDevicesViewState
|
||||||
|
extends State<SceneRoomsTabBarDevicesView>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
late final TabController _tabController;
|
late final TabController _tabController;
|
||||||
List<RoomModel>? rooms = [];
|
List<RoomModel>? rooms = [];
|
||||||
@ -41,7 +45,8 @@ class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesVie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_tabController = TabController(length: rooms!.length, vsync: this, initialIndex: 0);
|
_tabController =
|
||||||
|
TabController(length: rooms!.length, vsync: this, initialIndex: 0);
|
||||||
_tabController.addListener(_handleTabSwitched);
|
_tabController.addListener(_handleTabSwitched);
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
@ -51,9 +56,8 @@ class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesVie
|
|||||||
final value = _tabController.index;
|
final value = _tabController.index;
|
||||||
|
|
||||||
/// select tab
|
/// select tab
|
||||||
context
|
context.read<TabBarBloc>().add(
|
||||||
.read<TabBarBloc>()
|
TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? ''));
|
||||||
.add(TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? ''));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,8 +76,7 @@ class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesVie
|
|||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
navigateToRoute(context, Routes.sceneTasksRoute);
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.arrow_back_ios,
|
Icons.arrow_back_ios,
|
||||||
|
@ -24,7 +24,7 @@ class AlertDialogSliderSteps extends StatefulWidget {
|
|||||||
|
|
||||||
class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
||||||
double? groupValue;
|
double? groupValue;
|
||||||
int selectedToggleIndex = 0;
|
int selectedToggleIndex = 1;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
@ -33,23 +33,53 @@ class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
|||||||
if (widget.isAutomation) {
|
if (widget.isAutomation) {
|
||||||
final automationTempTaskList =
|
final automationTempTaskList =
|
||||||
context.read<CreateSceneBloc>().automationTempTasksList;
|
context.read<CreateSceneBloc>().automationTempTasksList;
|
||||||
|
final automationComparatorValues =
|
||||||
|
context.read<CreateSceneBloc>().automationComparatorValues;
|
||||||
|
|
||||||
if (automationTempTaskList.isNotEmpty) {
|
if (automationTempTaskList.isNotEmpty) {
|
||||||
for (var element in automationTempTaskList) {
|
for (var element in automationTempTaskList) {
|
||||||
if (element.code == widget.taskItem.code) {
|
if (element.code == widget.taskItem.code) {
|
||||||
groupValue = element.functionValue;
|
groupValue = element.functionValue;
|
||||||
} else {
|
selectedToggleIndex =
|
||||||
context.read<CreateSceneBloc>().add(RemoveFromSelectedValueById(
|
_comparatorToIndex(automationComparatorValues[element.code]);
|
||||||
code: widget.taskItem.code, isAutomation: widget.isAutomation));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (widget.functionValue != null) {
|
if (widget.functionValue != null) {
|
||||||
setState(() {
|
|
||||||
groupValue = widget.functionValue;
|
groupValue = widget.functionValue;
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
groupValue = widget.taskItem.operationalValues[0].minValue;
|
groupValue = widget.taskItem.operationalValues[0].minValue;
|
||||||
}
|
}
|
||||||
|
if (widget.taskItem.comparator != null) {
|
||||||
|
selectedToggleIndex = _comparatorToIndex(widget.taskItem.comparator);
|
||||||
|
}
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int _comparatorToIndex(String? comparator) {
|
||||||
|
switch (comparator) {
|
||||||
|
case "<=":
|
||||||
|
return 0;
|
||||||
|
case "==":
|
||||||
|
return 1;
|
||||||
|
case ">=":
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _indexToComparator(int index) {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
return "<=";
|
||||||
|
case 1:
|
||||||
|
return "==";
|
||||||
|
case 2:
|
||||||
|
return ">=";
|
||||||
|
default:
|
||||||
|
return "==";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +98,10 @@ class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
selectedToggleIndex = index;
|
selectedToggleIndex = index;
|
||||||
});
|
});
|
||||||
|
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
||||||
|
code: widget.taskItem.code,
|
||||||
|
isAutomation: widget.isAutomation,
|
||||||
|
comparator: _indexToComparator(selectedToggleIndex)));
|
||||||
},
|
},
|
||||||
borderRadius: BorderRadius.circular(30),
|
borderRadius: BorderRadius.circular(30),
|
||||||
selectedColor: Colors.white,
|
selectedColor: Colors.white,
|
||||||
@ -164,7 +198,9 @@ class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
|||||||
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
||||||
value: groupValue,
|
value: groupValue,
|
||||||
code: widget.taskItem.code,
|
code: widget.taskItem.code,
|
||||||
isAutomation: widget.isAutomation));
|
isAutomation: widget.isAutomation,
|
||||||
|
comparator:
|
||||||
|
_indexToComparator(selectedToggleIndex)));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||||
import 'package:syncrow_app/features/scene/helper/scene_logic_helper.dart';
|
import 'package:syncrow_app/features/scene/helper/scene_logic_helper.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/navigation/navigate_to_route.dart';
|
||||||
|
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
@ -43,8 +46,7 @@ class _CreateSceneSaveButtonState extends State<CreateSceneSaveButton>
|
|||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state is CreateSceneWithTasks) {
|
if (state is CreateSceneWithTasks) {
|
||||||
if (state.success == true) {
|
if (state.success == true) {
|
||||||
Navigator.pop(context);
|
navigateToRoute(context, Routes.homeRoute);
|
||||||
Navigator.pop(context);
|
|
||||||
context.showCustomSnackbar(
|
context.showCustomSnackbar(
|
||||||
message: 'Scene created successfully',
|
message: 'Scene created successfully',
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
@ -66,29 +68,31 @@ class _CreateSceneSaveButtonState extends State<CreateSceneSaveButton>
|
|||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return DefaultButton(
|
return DefaultButton(
|
||||||
onPressed: widget.sceneName.isNotEmpty
|
onPressed: () {
|
||||||
? () {
|
final sceneBloc = context.read<CreateSceneBloc>();
|
||||||
final tasks = context.read<CreateSceneBloc>().tasksList;
|
final isAutomation =
|
||||||
|
sceneBloc.sceneType == CreateSceneEnum.deviceStatusChanges;
|
||||||
|
|
||||||
|
if (widget.sceneName.isNotEmpty) {
|
||||||
handleSaveButtonPress(
|
handleSaveButtonPress(
|
||||||
context,
|
context,
|
||||||
sceneNameController,
|
sceneName: sceneNameController,
|
||||||
tasks,
|
actions: sceneBloc.tasksList,
|
||||||
updateScene: true,
|
updateScene: true,
|
||||||
sceneId: widget.sceneId,
|
sceneId: widget.sceneId,
|
||||||
|
isAutomation: isAutomation,
|
||||||
|
conditions: sceneBloc.automationTasksList,
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
: () {
|
|
||||||
context.customAlertDialog(
|
context.customAlertDialog(
|
||||||
alertBody: Padding(
|
alertBody: Padding(
|
||||||
padding:
|
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
||||||
const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: SearchBar(
|
child: SearchBar(
|
||||||
controller: sceneNameController,
|
controller: sceneNameController,
|
||||||
elevation: WidgetStateProperty.all(0),
|
elevation: WidgetStateProperty.all(0),
|
||||||
textStyle:
|
textStyle: WidgetStateProperty.all(context.bodyMedium),
|
||||||
WidgetStateProperty.all(context.bodyMedium),
|
|
||||||
hintStyle: WidgetStateProperty.all(
|
hintStyle: WidgetStateProperty.all(
|
||||||
context.bodyMedium.copyWith(
|
context.bodyMedium.copyWith(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
@ -103,17 +107,19 @@ class _CreateSceneSaveButtonState extends State<CreateSceneSaveButton>
|
|||||||
title: 'Scene Name',
|
title: 'Scene Name',
|
||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
if (sceneNameController.text.isNotEmpty) {
|
if (sceneNameController.text.isNotEmpty) {
|
||||||
final tasks = context.read<CreateSceneBloc>().tasksList;
|
|
||||||
handleSaveButtonPress(
|
handleSaveButtonPress(
|
||||||
context,
|
context,
|
||||||
sceneNameController,
|
sceneName: sceneNameController,
|
||||||
tasks,
|
actions: sceneBloc.tasksList,
|
||||||
updateScene: false,
|
updateScene: false,
|
||||||
sceneId: widget.sceneId,
|
sceneId: widget.sceneId,
|
||||||
|
isAutomation: isAutomation,
|
||||||
|
conditions: sceneBloc.automationTasksList,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
customButtonStyle: ButtonStyle(
|
customButtonStyle: ButtonStyle(
|
||||||
backgroundColor: WidgetStateProperty.all<Color>(
|
backgroundColor: WidgetStateProperty.all<Color>(
|
||||||
|
@ -1,18 +1,24 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.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/create_scene/create_scene_bloc.dart';
|
||||||
import 'package:syncrow_app/features/scene/enum/create_scene_enum.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/scene_settings_route_arguments.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/view/create_scene_view.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_added_tasks.dart';
|
import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_added_tasks.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/light_divider.dart';
|
import 'package:syncrow_app/features/shared_widgets/light_divider.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||||
|
|
||||||
class IFDefaultContainer extends StatelessWidget {
|
class IFDefaultContainer extends StatelessWidget {
|
||||||
const IFDefaultContainer({
|
const IFDefaultContainer({
|
||||||
@ -27,30 +33,101 @@ class IFDefaultContainer extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
SceneListTile(
|
SceneListTile(
|
||||||
leadingWidget: BodyLarge(
|
leadingWidget: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
final sceneType = context.read<CreateSceneBloc>().sceneType;
|
||||||
|
if (sceneType.name ==
|
||||||
|
CreateSceneEnum.deviceStatusChanges.name) {
|
||||||
|
context.customAlertDialog(
|
||||||
|
hideConfirmButton: true,
|
||||||
|
alertBody: Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
title: const BodyMedium(
|
||||||
|
text: "When all conditions are met"),
|
||||||
|
onTap: () {
|
||||||
|
context.read<CreateSceneBloc>().add(
|
||||||
|
const SelectConditionEvent(
|
||||||
|
"When all conditions are met"));
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const BodyMedium(
|
||||||
|
text: "When any condition is met"),
|
||||||
|
onTap: () {
|
||||||
|
context.read<CreateSceneBloc>().add(
|
||||||
|
const SelectConditionEvent(
|
||||||
|
"When any condition is met"));
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
title: 'Conditions Rule',
|
||||||
|
onConfirm: () {},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
BodyLarge(
|
||||||
text: 'IF',
|
text: 'IF',
|
||||||
style: context.bodyLarge.copyWith(
|
style: context.bodyLarge.copyWith(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: ColorsManager.primaryTextColor,
|
color: ColorsManager.primaryTextColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
trailingWidget: GestureDetector(
|
BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||||
onTap: () => Navigator.pushNamed(
|
builder: (context, state) {
|
||||||
|
String conditionText = "When any condition is met";
|
||||||
|
if (state is ConditionSelectedState) {
|
||||||
|
conditionText = state.condition;
|
||||||
|
}
|
||||||
|
return SizedBox(
|
||||||
|
width: context.width * 0.6,
|
||||||
|
child: Row(children: [
|
||||||
|
BodySmall(text: conditionText),
|
||||||
|
const Icon(Icons.keyboard_arrow_down)
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailingWidget: BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
bool isClickable = false;
|
||||||
|
if (state is AddSceneTask) {
|
||||||
|
isClickable = state.automationTasksList?.isNotEmpty ?? false;
|
||||||
|
}
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: isClickable
|
||||||
|
? () => Navigator.pushNamed(
|
||||||
context,
|
context,
|
||||||
Routes.sceneControlDevicesRoute,
|
Routes.sceneControlDevicesRoute,
|
||||||
arguments: SceneSettingsRouteArguments(
|
arguments: SceneSettingsRouteArguments(
|
||||||
sceneType: CreateSceneEnum.deviceStatusChanges.name,
|
sceneType:
|
||||||
|
CreateSceneEnum.deviceStatusChanges.name,
|
||||||
sceneId: '',
|
sceneId: '',
|
||||||
sceneName: '',
|
sceneName: '',
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
|
: null,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.addIcon,
|
Assets.addIcon,
|
||||||
colorFilter: const ColorFilter.mode(
|
colorFilter: ColorFilter.mode(
|
||||||
ColorsManager.primaryColor,
|
isClickable
|
||||||
|
? ColorsManager.primaryColor
|
||||||
|
: ColorsManager.greyColor,
|
||||||
BlendMode.srcIn,
|
BlendMode.srcIn,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
@ -74,10 +151,26 @@ class IFDefaultContainer extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final sceneType = context.read<CreateSceneBloc>().sceneType;
|
||||||
|
if (sceneType.name == CreateSceneEnum.tabToRun.name) {
|
||||||
|
return const SceneListTile(
|
||||||
|
assetPath: Assets.handClickIcon,
|
||||||
|
titleString: StringsManager.tapToRun,
|
||||||
|
subtitleString: '',
|
||||||
|
);
|
||||||
|
}
|
||||||
return SceneListTile(
|
return SceneListTile(
|
||||||
titleString: '+ Add Condition',
|
titleString: '+ Add Condition',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
onPressed: () => Navigator.pushNamed(
|
onPressed: () {
|
||||||
|
final sceneType = context.read<CreateSceneBloc>().sceneType;
|
||||||
|
if (sceneType.name == CreateSceneEnum.none.name) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
CustomPageRoute(
|
||||||
|
builder: (context) => const CreateSceneView()));
|
||||||
|
} else {
|
||||||
|
Navigator.pushNamed(
|
||||||
context,
|
context,
|
||||||
Routes.sceneControlDevicesRoute,
|
Routes.sceneControlDevicesRoute,
|
||||||
arguments: SceneSettingsRouteArguments(
|
arguments: SceneSettingsRouteArguments(
|
||||||
@ -85,8 +178,9 @@ class IFDefaultContainer extends StatelessWidget {
|
|||||||
sceneId: '',
|
sceneId: '',
|
||||||
sceneName: '',
|
sceneName: '',
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.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/create_scene/create_scene_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/view/create_scene_view.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_added_tasks.dart';
|
import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_added_tasks.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/bottom_sheet_widget.dart';
|
import 'package:syncrow_app/features/scene/widgets/bottom_sheet_widget.dart';
|
||||||
@ -10,6 +12,7 @@ import 'package:syncrow_app/features/shared_widgets/light_divider.dart';
|
|||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
class ThenDefaultContainer extends StatelessWidget {
|
class ThenDefaultContainer extends StatelessWidget {
|
||||||
@ -35,17 +38,29 @@ class ThenDefaultContainer extends StatelessWidget {
|
|||||||
color: ColorsManager.primaryTextColor,
|
color: ColorsManager.primaryTextColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
trailingWidget: GestureDetector(
|
trailingWidget: BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||||
onTap: () => context.customBottomSheet(
|
builder: (context, state) {
|
||||||
|
bool isClickable = false;
|
||||||
|
if (state is AddSceneTask) {
|
||||||
|
isClickable = state.tasksList.isNotEmpty;
|
||||||
|
}
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: isClickable
|
||||||
|
? () => context.customBottomSheet(
|
||||||
child: const CustomBottomSheetWidget(),
|
child: const CustomBottomSheetWidget(),
|
||||||
),
|
)
|
||||||
|
: null,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.addIcon,
|
Assets.addIcon,
|
||||||
colorFilter: const ColorFilter.mode(
|
colorFilter: ColorFilter.mode(
|
||||||
ColorsManager.primaryColor,
|
isClickable
|
||||||
|
? ColorsManager.primaryColor
|
||||||
|
: ColorsManager.greyColor,
|
||||||
BlendMode.srcIn,
|
BlendMode.srcIn,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
@ -71,20 +86,23 @@ class ThenDefaultContainer extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return SceneListTile(
|
|
||||||
titleString: '+ Add Task',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
onPressed: () => context.customBottomSheet(
|
|
||||||
child: const CustomBottomSheetWidget(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return SceneListTile(
|
return SceneListTile(
|
||||||
titleString: '+ Add Task',
|
titleString: '+ Add Task',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
onPressed: () => context.customBottomSheet(
|
onPressed: () {
|
||||||
|
final sceneType = context.read<CreateSceneBloc>().sceneType;
|
||||||
|
if (sceneType.name == CreateSceneEnum.none.name) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
CustomPageRoute(
|
||||||
|
builder: (context) => const CreateSceneView()));
|
||||||
|
} else {
|
||||||
|
context.customBottomSheet(
|
||||||
child: const CustomBottomSheetWidget(),
|
child: const CustomBottomSheetWidget(),
|
||||||
),
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
17
lib/navigation/navigate_to_route.dart
Normal file
17
lib/navigation/navigate_to_route.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
void navigateToRoute(BuildContext context, String targetRoute) {
|
||||||
|
bool routeFound = false;
|
||||||
|
|
||||||
|
Navigator.popUntil(context, (route) {
|
||||||
|
if (route.settings.name == targetRoute) {
|
||||||
|
routeFound = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return route.isFirst;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!routeFound) {
|
||||||
|
Navigator.pushNamed(context, targetRoute);
|
||||||
|
}
|
||||||
|
}
|
@ -135,6 +135,8 @@ abstract class ApiEndpoints {
|
|||||||
static const String triggerScene =
|
static const String triggerScene =
|
||||||
'$baseUrl/scene/tap-to-run/trigger/{sceneId}';
|
'$baseUrl/scene/tap-to-run/trigger/{sceneId}';
|
||||||
|
|
||||||
|
static const String createAutomation = '$baseUrl/automation';
|
||||||
|
|
||||||
/// GET
|
/// GET
|
||||||
static const String getUnitScenes = '$baseUrl/scene/tap-to-run/{unitUuid}';
|
static const String getUnitScenes = '$baseUrl/scene/tap-to-run/{unitUuid}';
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
|
||||||
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
|
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
|
||||||
import 'package:syncrow_app/features/scene/model/scene_details_model.dart';
|
import 'package:syncrow_app/features/scene/model/scene_details_model.dart';
|
||||||
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
|
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
|
||||||
@ -24,6 +25,23 @@ class SceneApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<Map<String, dynamic>> createAutomation(
|
||||||
|
CreateAutomationModel createAutomationModel) async {
|
||||||
|
try {
|
||||||
|
final response = await _httpService.post(
|
||||||
|
path: ApiEndpoints.createAutomation,
|
||||||
|
body: createAutomationModel.toMap(),
|
||||||
|
showServerMessage: false,
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Future<List<ScenesModel>> getScenesByUnitId(String unitId) async {
|
static Future<List<ScenesModel>> getScenesByUnitId(String unitId) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
|
@ -65,6 +65,7 @@ extension ContextExtension on BuildContext {
|
|||||||
required String title,
|
required String title,
|
||||||
required VoidCallback onConfirm,
|
required VoidCallback onConfirm,
|
||||||
VoidCallback? onDismiss,
|
VoidCallback? onDismiss,
|
||||||
|
bool? hideConfirmButton,
|
||||||
}) {
|
}) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: this,
|
context: this,
|
||||||
@ -110,7 +111,8 @@ extension ContextExtension on BuildContext {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
color: ColorsManager.greyColor,
|
color: ColorsManager.greyColor,
|
||||||
),
|
),
|
||||||
Row(
|
hideConfirmButton != true
|
||||||
|
? Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
@ -137,12 +139,29 @@ extension ContextExtension on BuildContext {
|
|||||||
child: BodyMedium(
|
child: BodyMedium(
|
||||||
text: 'Confirm',
|
text: 'Confirm',
|
||||||
style: context.bodyMedium.copyWith(
|
style: context.bodyMedium.copyWith(
|
||||||
color: ColorsManager.primaryColorWithOpacity),
|
color:
|
||||||
|
ColorsManager.primaryColorWithOpacity),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: onDismiss ??
|
||||||
|
() {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Cancel',
|
||||||
|
style: context.bodyMedium
|
||||||
|
.copyWith(color: ColorsManager.greyColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Reference in New Issue
Block a user