mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2026-10-23 10:27:56 +00:00
@@ -17,10 +17,16 @@ import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
|
||||
import 'package:syncrow_app/features/menu/view/menu_view.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
|
||||
import 'package:syncrow_app/features/scene/view/create_scene_view.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_view.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/navigation/navigation_service.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/services/api/profile_api.dart';
|
||||
import 'package:syncrow_app/services/api/spaces_api.dart';
|
||||
@@ -52,13 +58,12 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
|
||||
Future fetchUserInfo() async {
|
||||
Future fetchUserInfo() async {
|
||||
try {
|
||||
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||
var uuid =
|
||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||
user = await ProfileApi().fetchUserInfo(uuid);
|
||||
emit(HomeUserInfoLoaded(user!)); // Emit state after fetching user info
|
||||
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
@@ -77,9 +82,12 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
selectedSpace = null;
|
||||
selectedRoom = null;
|
||||
pageIndex = 0;
|
||||
OneSignal.User.pushSubscription.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
|
||||
OneSignal.Notifications.removePermissionObserver((permission) => oneSignalPermissionObserver);
|
||||
OneSignal.Notifications.removeClickListener((event) => oneSignalClickListenerObserver);
|
||||
OneSignal.User.pushSubscription
|
||||
.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
|
||||
OneSignal.Notifications.removePermissionObserver(
|
||||
(permission) => oneSignalPermissionObserver);
|
||||
OneSignal.Notifications.removeClickListener(
|
||||
(event) => oneSignalClickListenerObserver);
|
||||
return super.close();
|
||||
}
|
||||
|
||||
@@ -121,7 +129,9 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
return;
|
||||
}
|
||||
|
||||
var userUuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
|
||||
var userUuid =
|
||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
|
||||
'';
|
||||
if (userUuid.isNotEmpty) {
|
||||
await OneSignal.login(userUuid);
|
||||
}
|
||||
@@ -129,21 +139,24 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
await OneSignal.User.pushSubscription.optIn();
|
||||
|
||||
//this function will be called once a user is subscribed
|
||||
oneSignalSubscriptionObserver = OneSignal.User.pushSubscription.addObserver((state) async {
|
||||
oneSignalSubscriptionObserver =
|
||||
OneSignal.User.pushSubscription.addObserver((state) async {
|
||||
if (state.current.optedIn) {
|
||||
await _sendSubscriptionId();
|
||||
}
|
||||
});
|
||||
|
||||
// Send the player id when a user allows notifications
|
||||
oneSignalPermissionObserver = OneSignal.Notifications.addPermissionObserver((state) async {
|
||||
oneSignalPermissionObserver =
|
||||
OneSignal.Notifications.addPermissionObserver((state) async {
|
||||
await _sendSubscriptionId();
|
||||
});
|
||||
|
||||
//check if the player id is sent, if not send it again
|
||||
await _sendSubscriptionId();
|
||||
|
||||
oneSignalClickListenerObserver = OneSignal.Notifications.addClickListener((event) async {
|
||||
oneSignalClickListenerObserver =
|
||||
OneSignal.Notifications.addClickListener((event) async {
|
||||
//Once the user clicks on the notification
|
||||
});
|
||||
} catch (err) {
|
||||
@@ -230,7 +243,9 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
|
||||
Future<bool> joinAUnit(String code) async {
|
||||
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};
|
||||
|
||||
final success = await SpacesAPI.joinUnit(body);
|
||||
@@ -348,15 +363,28 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
size: 32,
|
||||
),
|
||||
style: ButtonStyle(
|
||||
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||
foregroundColor:
|
||||
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
Navigator.pushNamed(
|
||||
NavigationService.navigatorKey.currentContext!,
|
||||
CustomPageRoute(
|
||||
builder: (context) => const CreateSceneView(),
|
||||
Routes.sceneTasksRoute,
|
||||
arguments: SceneSettingsRouteArguments(
|
||||
sceneType: '',
|
||||
sceneId: '',
|
||||
sceneName: '',
|
||||
),
|
||||
);
|
||||
NavigationService.navigatorKey.currentContext!
|
||||
.read<CreateSceneBloc>()
|
||||
.add(const ClearTaskListEvent());
|
||||
NavigationService.navigatorKey.currentContext!
|
||||
.read<CreateSceneBloc>()
|
||||
.add(const SceneTypeEvent(CreateSceneEnum.none));
|
||||
NavigationService.navigatorKey.currentContext!
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(const SmartSceneClearEvent());
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
@@ -365,7 +393,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
size: 28,
|
||||
),
|
||||
style: ButtonStyle(
|
||||
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||
foregroundColor:
|
||||
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||
),
|
||||
onPressed: () {},
|
||||
),
|
||||
@@ -398,7 +427,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
};
|
||||
|
||||
static var bottomNavItems = [
|
||||
defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
|
||||
defaultBottomNavBarItem(
|
||||
icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
|
||||
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
|
||||
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
|
||||
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
|
||||
@@ -424,7 +454,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
|
||||
void updateDevice(String deviceId) async {
|
||||
try {
|
||||
final response = await DevicesAPI.firmwareDevice(deviceId: deviceId, firmwareVersion: '0');
|
||||
final response = await DevicesAPI.firmwareDevice(
|
||||
deviceId: deviceId, firmwareVersion: '0');
|
||||
if (response['success'] ?? false) {
|
||||
CustomSnackBar.displaySnackBar('No updates available');
|
||||
}
|
||||
@@ -432,7 +463,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
}
|
||||
}
|
||||
|
||||
BottomNavigationBarItem defaultBottomNavBarItem({required String icon, required String label}) {
|
||||
BottomNavigationBarItem defaultBottomNavBarItem(
|
||||
{required String icon, required String label}) {
|
||||
return BottomNavigationBarItem(
|
||||
icon: SvgPicture.asset(icon),
|
||||
activeIcon: SvgPicture.asset(
|
||||
|
||||
@@ -45,7 +45,8 @@ class DeviceModel {
|
||||
|
||||
if (type == DeviceType.LightBulb) {
|
||||
tempIcon = Assets.assetsIconsLight;
|
||||
} else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
|
||||
} else if (type == DeviceType.CeilingSensor ||
|
||||
type == DeviceType.WallSensor) {
|
||||
tempIcon = Assets.assetsIconsSensors;
|
||||
} else if (type == DeviceType.AC) {
|
||||
tempIcon = Assets.assetsIconsAC;
|
||||
@@ -93,5 +94,6 @@ class DeviceModel {
|
||||
};
|
||||
}
|
||||
|
||||
List<FunctionModel> getFunctions(DeviceType type) => devicesFunctionsMap[productType] ?? [];
|
||||
List<FunctionModel> getFunctions(DeviceType type) =>
|
||||
devicesFunctionsMap[productType] ?? [];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
|
||||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
@@ -12,7 +9,6 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dar
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
|
||||
|
||||
class SceneListview extends StatelessWidget {
|
||||
final List<ScenesModel> scenes;
|
||||
final String? loadingSceneId;
|
||||
@@ -24,8 +20,7 @@ class SceneListview extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return
|
||||
ListView.builder(
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: scenes.length,
|
||||
@@ -34,7 +29,7 @@ class SceneListview extends StatelessWidget {
|
||||
final isLoading = loadingSceneId == scene.id;
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child:DefaultContainer(
|
||||
child: DefaultContainer(
|
||||
onTap: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
@@ -45,10 +40,11 @@ class SceneListview extends StatelessWidget {
|
||||
sceneName: scene.name,
|
||||
),
|
||||
);
|
||||
BlocProvider.of<CreateSceneBloc>(context).add(FetchSceneTasksEvent(sceneId: scene.id));
|
||||
BlocProvider.of<CreateSceneBloc>(context)
|
||||
.add(FetchSceneTasksEvent(sceneId: scene.id));
|
||||
},
|
||||
child:SizedBox(
|
||||
width: MediaQuery.of(context).size.width*0.4,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.4,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
@@ -73,8 +69,7 @@ class SceneListview extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import 'dart:async';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||
import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart';
|
||||
import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/navigation/navigation_service.dart';
|
||||
import 'package:syncrow_app/services/api/scene_api.dart';
|
||||
|
||||
part 'create_scene_event.dart';
|
||||
@@ -25,23 +32,65 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
on<RemoveFromSelectedValueById>(_removeFromSelectedValueById);
|
||||
on<DeleteSceneEvent>(_deleteScene);
|
||||
on<UpdateTaskEvent>(_updateTaskValue);
|
||||
on<SelectConditionEvent>(_selectConditionRule);
|
||||
on<SceneTypeEvent>(_sceneTypeEvent);
|
||||
on<EffectiveTimePeriodEvent>(_onEffectiveTimeEvent);
|
||||
}
|
||||
|
||||
CreateSceneEnum sceneType = CreateSceneEnum.none;
|
||||
|
||||
/// tab to run values and list
|
||||
List<SceneStaticFunction> tasksList = [];
|
||||
List<SceneStaticFunction> tempTasksList = [];
|
||||
final Map<String, dynamic> selectedValues = {};
|
||||
|
||||
/// automation values and list
|
||||
List<SceneStaticFunction> automationTasksList = [];
|
||||
List<SceneStaticFunction> automationTempTasksList = [];
|
||||
final Map<String, dynamic> automationSelectedValues = {};
|
||||
final Map<String, String> automationComparatorValues = {};
|
||||
String conditionRule = 'or';
|
||||
EffectiveTime? effectiveTime;
|
||||
|
||||
FutureOr<void> _onAddSceneTask(
|
||||
AddTaskEvent event, Emitter<CreateSceneState> emit) {
|
||||
final copyList = List<SceneStaticFunction>.from(tempTasksList);
|
||||
tasksList.addAll(copyList);
|
||||
tempTasksList.clear();
|
||||
selectedValues.clear();
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
final copyList = List<SceneStaticFunction>.from(automationTempTasksList);
|
||||
automationTasksList.addAll(copyList);
|
||||
automationTempTasksList.clear();
|
||||
automationSelectedValues.clear();
|
||||
automationComparatorValues.clear();
|
||||
emit(AddSceneTask(
|
||||
automationTasksList: automationTasksList,
|
||||
tasksList: tasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
} else {
|
||||
final copyList = List<SceneStaticFunction>.from(tempTasksList);
|
||||
tasksList.addAll(copyList);
|
||||
tempTasksList.clear();
|
||||
selectedValues.clear();
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onTempHoldSceneTask(
|
||||
TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
|
||||
if (event.isAutomation == true) {
|
||||
addToTempAutomationTaskList(event, emit);
|
||||
} else {
|
||||
addToTempTaskList(event, emit);
|
||||
}
|
||||
}
|
||||
|
||||
void addToTempTaskList(
|
||||
TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
bool updated = false;
|
||||
for (var element in tempTasksList) {
|
||||
if (element.code == event.deviceControlModel.code) {
|
||||
@@ -53,6 +102,7 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
code: event.deviceControlModel.code ?? '',
|
||||
deviceId: event.deviceId,
|
||||
functionValue: event.deviceControlModel.value,
|
||||
operationDialogType: event.operationType,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
value: event.deviceControlModel.value,
|
||||
@@ -67,12 +117,12 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
}
|
||||
}
|
||||
if (!updated) {
|
||||
// Add new function if not found
|
||||
var newElement = SceneStaticFunction(
|
||||
operationName: event.operation,
|
||||
deviceName: event.deviceName,
|
||||
icon: event.icon,
|
||||
code: event.deviceControlModel.code ?? '',
|
||||
operationDialogType: event.operationType,
|
||||
deviceId: event.deviceId,
|
||||
functionValue: event.deviceControlModel.value,
|
||||
operationalValues: [
|
||||
@@ -86,40 +136,161 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
selectedValues[newElement.code] = event.deviceControlModel.value;
|
||||
}
|
||||
|
||||
emit(TempHoldSceneTask(tempTasksList: tempTasksList));
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
|
||||
void addToTempAutomationTaskList(
|
||||
TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
bool updated = false;
|
||||
for (var element in automationTempTasksList) {
|
||||
if (element.code == event.deviceControlModel.code) {
|
||||
// Update the existing function with new values
|
||||
var updatedElement = element.copyWith(
|
||||
operationName: event.operation,
|
||||
deviceName: event.deviceName,
|
||||
icon: event.icon,
|
||||
code: event.deviceControlModel.code ?? '',
|
||||
deviceId: event.deviceId,
|
||||
functionValue: event.deviceControlModel.value,
|
||||
operationDialogType: event.operationType,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
value: event.deviceControlModel.value,
|
||||
icon: '',
|
||||
),
|
||||
],
|
||||
comparator: automationComparatorValues[element.code],
|
||||
);
|
||||
automationTempTasksList[automationTempTasksList.indexOf(element)] =
|
||||
updatedElement;
|
||||
automationSelectedValues[updatedElement.code] =
|
||||
event.deviceControlModel.value;
|
||||
updated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!updated) {
|
||||
var newElement = SceneStaticFunction(
|
||||
operationName: event.operation,
|
||||
deviceName: event.deviceName,
|
||||
icon: event.icon,
|
||||
code: event.deviceControlModel.code ?? '',
|
||||
operationDialogType: event.operationType,
|
||||
deviceId: event.deviceId,
|
||||
functionValue: event.deviceControlModel.value,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
value: event.deviceControlModel.value,
|
||||
icon: '',
|
||||
),
|
||||
],
|
||||
comparator:
|
||||
automationComparatorValues[event.deviceControlModel.code] ?? '==',
|
||||
);
|
||||
automationTempTasksList.add(newElement);
|
||||
automationSelectedValues[newElement.code] =
|
||||
event.deviceControlModel.value;
|
||||
}
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
|
||||
FutureOr<void> _selectedValue(
|
||||
SelectedValueEvent event, Emitter<CreateSceneState> emit) {
|
||||
selectedValues[event.code] = event.value;
|
||||
if (event.isAutomation == true) {
|
||||
automationSelectedValues[event.code] = event.value;
|
||||
automationComparatorValues[event.code] = event.comparator ?? '==';
|
||||
|
||||
// Update the comparator value for the specific task in automationTasksList
|
||||
for (int i = 0; i < automationTasksList.length; i++) {
|
||||
if (automationTasksList[i].code == event.code) {
|
||||
automationTasksList[i] = automationTasksList[i].copyWith(
|
||||
comparator: event.comparator ?? '==',
|
||||
functionValue: event.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selectedValues[event.code] = event.value;
|
||||
}
|
||||
emit(SelectedTaskValueState(value: event.value));
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
emit(AddSceneTask(
|
||||
tasksList: List.from(tasksList),
|
||||
automationTasksList: List.from(
|
||||
automationTasksList,
|
||||
),
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
|
||||
FutureOr<void> _removeTaskById(
|
||||
RemoveTaskByIdEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
for (var element in automationTasksList) {
|
||||
if (element.uniqueCustomId == event.taskId) {
|
||||
automationTasksList.remove(element);
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var element in tasksList) {
|
||||
if (element.uniqueCustomId == event.taskId) {
|
||||
tasksList.remove(element);
|
||||
|
||||
for (var element in tasksList) {
|
||||
if (element.uniqueCustomId == event.taskId) {
|
||||
tasksList.remove(element);
|
||||
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
break;
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _removeTempTaskById(
|
||||
RemoveTempTaskByIdEvent event, Emitter<CreateSceneState> emit) {
|
||||
for (var element in tempTasksList) {
|
||||
if (element.code == event.code) {
|
||||
tempTasksList.remove(element);
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
for (var element in automationTempTasksList) {
|
||||
if (element.uniqueCustomId == event.code) {
|
||||
automationTempTasksList.remove(element);
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var element in tempTasksList) {
|
||||
if (element.code == event.code) {
|
||||
tempTasksList.remove(element);
|
||||
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,27 +299,53 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
CreateSceneWithTasksEvent event, Emitter<CreateSceneState> emit) async {
|
||||
emit(CreateSceneLoading());
|
||||
try {
|
||||
final response = event.updateScene
|
||||
? await SceneApi.updateScene(event.createSceneModel, event.sceneId)
|
||||
: await SceneApi.createScene(event.createSceneModel);
|
||||
dynamic response;
|
||||
if (event.createSceneModel != null) {
|
||||
response = event.updateScene
|
||||
? await SceneApi.updateScene(event.createSceneModel!, event.sceneId)
|
||||
: await SceneApi.createScene(event.createSceneModel!);
|
||||
} else if (event.createAutomationModel != null) {
|
||||
response = event.updateScene
|
||||
? await SceneApi.updateAutomation(
|
||||
event.createAutomationModel!, event.sceneId)
|
||||
: await SceneApi.createAutomation(event.createAutomationModel!);
|
||||
}
|
||||
|
||||
if (response['success'] == true) {
|
||||
tasksList.clear();
|
||||
tempTasksList.clear();
|
||||
selectedValues.clear();
|
||||
automationTasksList.clear();
|
||||
automationTempTasksList.clear();
|
||||
automationSelectedValues.clear();
|
||||
automationComparatorValues.clear();
|
||||
effectiveTime = null;
|
||||
sceneType = CreateSceneEnum.none;
|
||||
conditionRule = 'or';
|
||||
emit(const CreateSceneWithTasks(success: true));
|
||||
} else {
|
||||
emit(const CreateSceneError(message: 'Something went wrong'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(const CreateSceneError(message: 'Something went wrong'));
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _clearTaskList(
|
||||
ClearTaskListEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
automationTasksList.clear();
|
||||
tasksList.clear();
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
|
||||
FutureOr<void> _fetchSceneTasks(
|
||||
@@ -156,13 +353,46 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
emit(CreateSceneLoading());
|
||||
|
||||
try {
|
||||
final response = await SceneApi.getSceneDetails(event.sceneId);
|
||||
final response = event.isAutomation
|
||||
? await SceneApi.getAutomationDetails(event.sceneId)
|
||||
: await SceneApi.getSceneDetails(event.sceneId);
|
||||
if (response.id.isNotEmpty) {
|
||||
tasksList = List<SceneStaticFunction>.from(
|
||||
getTaskListFunctionsFromApi(actions: response.actions));
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
));
|
||||
if (event.isAutomation) {
|
||||
automationTasksList = List<SceneStaticFunction>.from(
|
||||
getTaskListFunctionsFromApi(
|
||||
actions: [],
|
||||
isAutomation: true,
|
||||
conditions: response.conditions));
|
||||
tasksList = List<SceneStaticFunction>.from(
|
||||
getTaskListFunctionsFromApi(
|
||||
actions: response.actions, isAutomation: false));
|
||||
|
||||
conditionRule = response.decisionExpr ?? conditionRule;
|
||||
|
||||
if (response.effectiveTime != null) {
|
||||
BlocProvider.of<EffectPeriodBloc>(
|
||||
NavigationService.navigatorKey.currentState!.context)
|
||||
.add(SetCustomTime(response.effectiveTime!.start,
|
||||
response.effectiveTime!.end));
|
||||
BlocProvider.of<EffectPeriodBloc>(
|
||||
NavigationService.navigatorKey.currentState!.context)
|
||||
.add(ToggleDay(response.effectiveTime!.loops));
|
||||
}
|
||||
|
||||
emit(AddSceneTask(
|
||||
automationTasksList: automationTasksList,
|
||||
tasksList: tasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
} else {
|
||||
tasksList = List<SceneStaticFunction>.from(
|
||||
getTaskListFunctionsFromApi(
|
||||
actions: response.actions, isAutomation: false));
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
emit(const CreateSceneError(message: 'Something went wrong'));
|
||||
}
|
||||
@@ -173,17 +403,51 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
|
||||
FutureOr<void> _clearTempTaskList(
|
||||
ClearTempTaskListEvent event, Emitter<CreateSceneState> emit) {
|
||||
tempTasksList.clear();
|
||||
selectedValues.clear();
|
||||
emit(AddSceneTask(tasksList: tempTasksList));
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
automationTempTasksList.clear();
|
||||
automationSelectedValues.clear();
|
||||
automationComparatorValues.clear();
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
} else {
|
||||
tempTasksList.clear();
|
||||
selectedValues.clear();
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _removeFromSelectedValueById(
|
||||
RemoveFromSelectedValueById event, Emitter<CreateSceneState> emit) {
|
||||
if (selectedValues.containsKey(event.code)) {
|
||||
selectedValues.remove(event.code);
|
||||
emit(const SelectedTaskValueState(value: null));
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
if (automationSelectedValues.containsKey(event.code)) {
|
||||
automationSelectedValues.remove(event.code);
|
||||
automationComparatorValues.remove(event.code);
|
||||
emit(const SelectedTaskValueState(value: null));
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
if (selectedValues.containsKey(event.code)) {
|
||||
selectedValues.remove(event.code);
|
||||
emit(const SelectedTaskValueState(value: null));
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,8 +456,12 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
emit(DeleteSceneLoading());
|
||||
|
||||
try {
|
||||
final response = await SceneApi.deleteScene(
|
||||
sceneId: event.sceneId, unitUuid: event.unitUuid);
|
||||
final response =
|
||||
sceneType.name == CreateSceneEnum.deviceStatusChanges.name
|
||||
? await SceneApi.deleteAutomation(
|
||||
automationId: event.sceneId, unitUuid: event.unitUuid)
|
||||
: await SceneApi.deleteScene(
|
||||
sceneId: event.sceneId, unitUuid: event.unitUuid);
|
||||
if (response == true) {
|
||||
emit(const DeleteSceneSuccess(true));
|
||||
} else {
|
||||
@@ -206,14 +474,66 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
|
||||
FutureOr<void> _updateTaskValue(
|
||||
UpdateTaskEvent event, Emitter<CreateSceneState> emit) {
|
||||
for (var i = 0; i < tasksList.length; i++) {
|
||||
if (tasksList[i].uniqueCustomId == event.taskId) {
|
||||
tasksList[i] = tasksList[i].copyWith(
|
||||
functionValue: event.newValue,
|
||||
);
|
||||
break;
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
for (var i = 0; i < automationTasksList.length; i++) {
|
||||
if (automationTasksList[i].uniqueCustomId == event.taskId) {
|
||||
automationTasksList[i] = automationTasksList[i].copyWith(
|
||||
functionValue: event.newValue,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < tasksList.length; i++) {
|
||||
if (tasksList[i].uniqueCustomId == event.taskId) {
|
||||
tasksList[i] = tasksList[i].copyWith(
|
||||
functionValue: event.newValue,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
emit(AddSceneTask(tasksList: tasksList));
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
|
||||
FutureOr<void> _selectConditionRule(
|
||||
SelectConditionEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneInitial());
|
||||
if (event.condition.contains('any')) {
|
||||
conditionRule = 'or';
|
||||
} else {
|
||||
conditionRule = 'and';
|
||||
}
|
||||
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
automationTasksList: automationTasksList,
|
||||
condition: conditionRule,
|
||||
));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
FutureOr<void> _onEffectiveTimeEvent(
|
||||
EffectiveTimePeriodEvent event, Emitter<CreateSceneState> emit) {
|
||||
effectiveTime = event.period;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ sealed class CreateSceneEvent extends Equatable {
|
||||
}
|
||||
|
||||
class AddTaskEvent extends CreateSceneEvent {
|
||||
const AddTaskEvent({this.isAutomation});
|
||||
final bool? isAutomation;
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
@@ -19,6 +22,8 @@ class TempHoldSceneTasksEvent extends CreateSceneEvent {
|
||||
final String operation;
|
||||
final String deviceName;
|
||||
final String uniqueId;
|
||||
final bool? isAutomation;
|
||||
final OperationDialogType operationType;
|
||||
|
||||
const TempHoldSceneTasksEvent({
|
||||
required this.deviceControlModel,
|
||||
@@ -27,6 +32,8 @@ class TempHoldSceneTasksEvent extends CreateSceneEvent {
|
||||
required this.operation,
|
||||
required this.deviceName,
|
||||
required this.uniqueId,
|
||||
this.isAutomation,
|
||||
required this.operationType,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -38,23 +45,37 @@ class TempHoldSceneTasksEvent extends CreateSceneEvent {
|
||||
operation,
|
||||
uniqueId,
|
||||
deviceName,
|
||||
icon
|
||||
icon,
|
||||
];
|
||||
}
|
||||
|
||||
class UpdateTaskEvent extends CreateSceneEvent {
|
||||
final String taskId;
|
||||
final dynamic newValue;
|
||||
const UpdateTaskEvent({required this.taskId, required this.newValue});
|
||||
final bool? isAutomation;
|
||||
const UpdateTaskEvent({
|
||||
required this.taskId,
|
||||
required this.newValue,
|
||||
this.isAutomation,
|
||||
});
|
||||
@override
|
||||
List<Object> get props => [taskId, newValue];
|
||||
}
|
||||
|
||||
class SelectedValueEvent extends CreateSceneEvent {
|
||||
final dynamic value;
|
||||
final dynamic automationValue;
|
||||
final String code;
|
||||
final bool? isAutomation;
|
||||
final String? comparator;
|
||||
|
||||
const SelectedValueEvent({this.value, required this.code});
|
||||
const SelectedValueEvent({
|
||||
this.value,
|
||||
required this.code,
|
||||
this.isAutomation,
|
||||
this.automationValue,
|
||||
this.comparator,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value!, code];
|
||||
@@ -62,8 +83,11 @@ class SelectedValueEvent extends CreateSceneEvent {
|
||||
|
||||
class RemoveTaskByIdEvent extends CreateSceneEvent {
|
||||
final String taskId;
|
||||
|
||||
const RemoveTaskByIdEvent({required this.taskId});
|
||||
final bool? isAutomation;
|
||||
const RemoveTaskByIdEvent({
|
||||
required this.taskId,
|
||||
this.isAutomation,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [taskId];
|
||||
@@ -71,7 +95,8 @@ class RemoveTaskByIdEvent extends CreateSceneEvent {
|
||||
|
||||
class RemoveTempTaskByIdEvent extends CreateSceneEvent {
|
||||
final String code;
|
||||
const RemoveTempTaskByIdEvent({required this.code});
|
||||
final bool? isAutomation;
|
||||
const RemoveTempTaskByIdEvent({required this.code, this.isAutomation});
|
||||
|
||||
@override
|
||||
List<Object> get props => [code];
|
||||
@@ -79,36 +104,42 @@ class RemoveTempTaskByIdEvent extends CreateSceneEvent {
|
||||
|
||||
class RemoveFromSelectedValueById extends CreateSceneEvent {
|
||||
final String code;
|
||||
|
||||
const RemoveFromSelectedValueById({required this.code});
|
||||
final bool? isAutomation;
|
||||
const RemoveFromSelectedValueById({required this.code, this.isAutomation});
|
||||
|
||||
@override
|
||||
List<Object> get props => [code];
|
||||
}
|
||||
|
||||
class CreateSceneWithTasksEvent extends CreateSceneEvent {
|
||||
final CreateSceneModel createSceneModel;
|
||||
final CreateSceneModel? createSceneModel;
|
||||
final bool updateScene;
|
||||
final String sceneId;
|
||||
final CreateAutomationModel? createAutomationModel;
|
||||
//final bool isAutomation;
|
||||
const CreateSceneWithTasksEvent({
|
||||
required this.createSceneModel,
|
||||
required this.updateScene,
|
||||
required this.sceneId,
|
||||
required this.createAutomationModel,
|
||||
// required this.isAutomation,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [createSceneModel];
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class ClearTaskListEvent extends CreateSceneEvent {
|
||||
const ClearTaskListEvent();
|
||||
const ClearTaskListEvent({this.isAutomation});
|
||||
final bool? isAutomation;
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class ClearTempTaskListEvent extends CreateSceneEvent {
|
||||
const ClearTempTaskListEvent();
|
||||
const ClearTempTaskListEvent({this.isAutomation});
|
||||
final bool? isAutomation;
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
@@ -116,10 +147,13 @@ class ClearTempTaskListEvent extends CreateSceneEvent {
|
||||
|
||||
class FetchSceneTasksEvent extends CreateSceneEvent {
|
||||
final String sceneId;
|
||||
const FetchSceneTasksEvent({required this.sceneId});
|
||||
final bool isAutomation;
|
||||
|
||||
const FetchSceneTasksEvent(
|
||||
{this.isAutomation = false, required this.sceneId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
List<Object> get props => [sceneId, isAutomation];
|
||||
}
|
||||
|
||||
class DeleteSceneEvent extends CreateSceneEvent {
|
||||
@@ -133,3 +167,19 @@ class DeleteSceneEvent extends CreateSceneEvent {
|
||||
@override
|
||||
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);
|
||||
}
|
||||
|
||||
class EffectiveTimePeriodEvent extends CreateSceneEvent {
|
||||
final EffectiveTime period;
|
||||
const EffectiveTimePeriodEvent(this.period);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ class CreateSceneError extends CreateSceneState {
|
||||
|
||||
class AddSceneTask extends CreateSceneState {
|
||||
final List<SceneStaticFunction> tasksList;
|
||||
const AddSceneTask({required this.tasksList});
|
||||
final List<SceneStaticFunction>? automationTasksList;
|
||||
final String? condition;
|
||||
const AddSceneTask(
|
||||
{required this.tasksList, this.automationTasksList, this.condition});
|
||||
|
||||
@override
|
||||
List<Object> get props => [tasksList];
|
||||
@@ -29,7 +32,9 @@ class AddSceneTask extends CreateSceneState {
|
||||
|
||||
class TempHoldSceneTask extends CreateSceneState {
|
||||
final List<SceneStaticFunction> tempTasksList;
|
||||
const TempHoldSceneTask({required this.tempTasksList});
|
||||
final List<SceneStaticFunction>? automationTempTasksList;
|
||||
const TempHoldSceneTask(
|
||||
{required this.tempTasksList, this.automationTempTasksList});
|
||||
|
||||
@override
|
||||
List<Object> get props => [tempTasksList];
|
||||
@@ -68,3 +73,14 @@ class DeleteSceneError 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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
import 'package:bloc/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/effective_period/effect_period_event.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/effective_period_options.dart';
|
||||
import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
|
||||
import 'package:syncrow_app/navigation/navigation_service.dart';
|
||||
|
||||
class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {
|
||||
EffectPeriodBloc() : super(EffectPeriodState.initial()) {
|
||||
on<SetPeriod>(_onSetPeriod);
|
||||
on<ToggleDay>(_onToggleDay);
|
||||
on<SetCustomTime>(_onSetCustomTime);
|
||||
}
|
||||
|
||||
void _onSetPeriod(SetPeriod event, Emitter<EffectPeriodState> emit) {
|
||||
String startTime = '';
|
||||
String endTime = '';
|
||||
|
||||
switch (event.period) {
|
||||
case EnumEffectivePeriodOptions.allDay:
|
||||
startTime = '00:00';
|
||||
endTime = '23:59';
|
||||
break;
|
||||
case EnumEffectivePeriodOptions.daytime:
|
||||
startTime = '06:00';
|
||||
endTime = '18:00';
|
||||
break;
|
||||
case EnumEffectivePeriodOptions.night:
|
||||
startTime = '18:00';
|
||||
endTime = '06:00';
|
||||
break;
|
||||
case EnumEffectivePeriodOptions.custom:
|
||||
startTime = state.customStartTime ?? '00:00';
|
||||
endTime = state.customEndTime ?? '23:59';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Update CreateSceneBloc
|
||||
BlocProvider.of<CreateSceneBloc>(
|
||||
NavigationService.navigatorKey.currentState!.context)
|
||||
.add(EffectiveTimePeriodEvent(EffectiveTime(
|
||||
start: startTime, end: endTime, loops: state.selectedDaysBinary)));
|
||||
|
||||
emit(state.copyWith(selectedPeriod: event.period));
|
||||
}
|
||||
|
||||
void _onToggleDay(ToggleDay event, Emitter<EffectPeriodState> emit) {
|
||||
final daysList = state.selectedDaysBinary.split('');
|
||||
final dayIndex = _getDayIndex(event.day);
|
||||
if (daysList[dayIndex] == '1') {
|
||||
daysList[dayIndex] = '0';
|
||||
} else {
|
||||
daysList[dayIndex] = '1';
|
||||
}
|
||||
final newDaysBinary = daysList.join();
|
||||
emit(state.copyWith(selectedDaysBinary: newDaysBinary));
|
||||
|
||||
BlocProvider.of<CreateSceneBloc>(
|
||||
NavigationService.navigatorKey.currentState!.context)
|
||||
.add(EffectiveTimePeriodEvent(EffectiveTime(
|
||||
start: state.customStartTime ?? '00:00',
|
||||
end: state.customEndTime ?? '23:59',
|
||||
loops: newDaysBinary)));
|
||||
}
|
||||
|
||||
void _onSetCustomTime(SetCustomTime event, Emitter<EffectPeriodState> emit) {
|
||||
emit(state.copyWith(
|
||||
customStartTime: event.startTime, customEndTime: event.endTime));
|
||||
|
||||
BlocProvider.of<CreateSceneBloc>(
|
||||
NavigationService.navigatorKey.currentState!.context)
|
||||
.add(EffectiveTimePeriodEvent(EffectiveTime(
|
||||
start: event.startTime,
|
||||
end: event.endTime,
|
||||
loops: state.selectedDaysBinary)));
|
||||
}
|
||||
|
||||
int _getDayIndex(String day) {
|
||||
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
|
||||
return days.indexOf(day);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/effective_period_options.dart';
|
||||
|
||||
abstract class EffectPeriodEvent extends Equatable {
|
||||
const EffectPeriodEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class SetPeriod extends EffectPeriodEvent {
|
||||
final EnumEffectivePeriodOptions period;
|
||||
|
||||
const SetPeriod(this.period);
|
||||
|
||||
@override
|
||||
List<Object> get props => [period];
|
||||
}
|
||||
|
||||
class ToggleDay extends EffectPeriodEvent {
|
||||
final String day;
|
||||
|
||||
const ToggleDay(this.day);
|
||||
|
||||
@override
|
||||
List<Object> get props => [day];
|
||||
}
|
||||
|
||||
class SetCustomTime extends EffectPeriodEvent {
|
||||
final String startTime;
|
||||
final String endTime;
|
||||
|
||||
const SetCustomTime(this.startTime, this.endTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [startTime, endTime];
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/effective_period_options.dart';
|
||||
|
||||
class EffectPeriodState extends Equatable {
|
||||
final EnumEffectivePeriodOptions selectedPeriod;
|
||||
final String selectedDaysBinary;
|
||||
final String? customStartTime;
|
||||
final String? customEndTime;
|
||||
|
||||
const EffectPeriodState({
|
||||
required this.selectedPeriod,
|
||||
required this.selectedDaysBinary,
|
||||
this.customStartTime,
|
||||
this.customEndTime,
|
||||
});
|
||||
|
||||
factory EffectPeriodState.initial() {
|
||||
return const EffectPeriodState(
|
||||
selectedPeriod: EnumEffectivePeriodOptions.allDay,
|
||||
selectedDaysBinary: "1111111", // All days selected
|
||||
customStartTime: "00:00",
|
||||
customEndTime: "23:59",
|
||||
);
|
||||
}
|
||||
|
||||
EffectPeriodState copyWith({
|
||||
EnumEffectivePeriodOptions? selectedPeriod,
|
||||
String? selectedDaysBinary,
|
||||
String? customStartTime,
|
||||
String? customEndTime,
|
||||
}) {
|
||||
return EffectPeriodState(
|
||||
selectedPeriod: selectedPeriod ?? this.selectedPeriod,
|
||||
selectedDaysBinary: selectedDaysBinary ?? this.selectedDaysBinary,
|
||||
customStartTime: customStartTime ?? this.customStartTime,
|
||||
customEndTime: customEndTime ?? this.customEndTime,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props =>
|
||||
[selectedPeriod, selectedDaysBinary, customStartTime, customEndTime];
|
||||
}
|
||||
@@ -11,34 +11,95 @@ part 'scene_state.dart';
|
||||
class SceneBloc extends Bloc<SceneEvent, SceneState> {
|
||||
SceneBloc() : super(SceneInitial()) {
|
||||
on<LoadScenes>(_onLoadScenes);
|
||||
on<LoadAutomation>(_onLoadAutomation);
|
||||
on<SceneTrigger>(_onSceneTrigger);
|
||||
on<UpdateAutomationStatus>(_onUpdateAutomationStatus);
|
||||
}
|
||||
|
||||
List<ScenesModel> scenes = [];
|
||||
List<ScenesModel> automationList = [];
|
||||
|
||||
Future<void> _onLoadScenes(LoadScenes event, Emitter<SceneState> emit) async {
|
||||
emit(SceneLoading());
|
||||
|
||||
try {
|
||||
if (event.unitId.isNotEmpty) {
|
||||
final scenes = await SceneApi.getScenesByUnitId(event.unitId);
|
||||
emit(SceneLoaded(scenes));
|
||||
scenes = await SceneApi.getScenesByUnitId(event.unitId);
|
||||
emit(SceneLoaded(scenes, automationList));
|
||||
} else {
|
||||
const SceneError(message: '');
|
||||
emit(const SceneError(message: 'Unit ID is empty'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(const SceneError(message: 'Something went wrong'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onSceneTrigger(SceneTrigger event, Emitter<SceneState> emit) async {
|
||||
Future<void> _onLoadAutomation(
|
||||
LoadAutomation event, Emitter<SceneState> emit) async {
|
||||
emit(SceneLoading());
|
||||
|
||||
try {
|
||||
if (event.unitId.isNotEmpty) {
|
||||
automationList = await SceneApi.getAutomationByUnitId(event.unitId);
|
||||
emit(SceneLoaded(scenes, automationList));
|
||||
} else {
|
||||
emit(const SceneError(message: 'Unit ID is empty'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(const SceneError(message: 'Something went wrong'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onSceneTrigger(
|
||||
SceneTrigger event, Emitter<SceneState> emit) async {
|
||||
final currentState = state;
|
||||
if (currentState is SceneLoaded) {
|
||||
emit(SceneLoaded(currentState.scenes, loadingSceneId: event.sceneId));
|
||||
emit(SceneLoaded(
|
||||
currentState.scenes,
|
||||
currentState.automationList,
|
||||
loadingSceneId: event.sceneId,
|
||||
));
|
||||
|
||||
try {
|
||||
final success = await SceneApi.triggerScene(event.sceneId);
|
||||
if (success) {
|
||||
emit(SceneTriggerSuccess(event.name));
|
||||
emit(SceneLoaded(currentState.scenes));
|
||||
emit(SceneLoaded(currentState.scenes, currentState.automationList));
|
||||
} else {
|
||||
emit(const SceneError(message: 'Something went wrong'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(const SceneError(message: 'Something went wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onUpdateAutomationStatus(
|
||||
UpdateAutomationStatus event, Emitter<SceneState> emit) async {
|
||||
final currentState = state;
|
||||
if (currentState is SceneLoaded) {
|
||||
final newLoadingStates =
|
||||
Map<String, bool>.from(currentState.loadingStates)
|
||||
..[event.automationId] = true;
|
||||
|
||||
emit(SceneLoaded(
|
||||
currentState.scenes,
|
||||
currentState.automationList,
|
||||
loadingStates: newLoadingStates,
|
||||
));
|
||||
|
||||
try {
|
||||
final success = await SceneApi.updateAutomationStatus(
|
||||
event.automationId, event.automationStatusUpdate);
|
||||
if (success) {
|
||||
automationList = await SceneApi.getAutomationByUnitId(
|
||||
event.automationStatusUpdate.unitUuid);
|
||||
newLoadingStates[event.automationId] = false;
|
||||
emit(SceneLoaded(
|
||||
currentState.scenes,
|
||||
automationList,
|
||||
loadingStates: newLoadingStates,
|
||||
));
|
||||
} else {
|
||||
emit(const SceneError(message: 'Something went wrong'));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/scene/model/update_automation.dart';
|
||||
|
||||
abstract class SceneEvent extends Equatable {
|
||||
const SceneEvent();
|
||||
@@ -16,6 +17,15 @@ class LoadScenes extends SceneEvent {
|
||||
List<Object> get props => [unitId];
|
||||
}
|
||||
|
||||
class LoadAutomation extends SceneEvent {
|
||||
final String unitId;
|
||||
|
||||
const LoadAutomation(this.unitId);
|
||||
|
||||
@override
|
||||
List<Object> get props => [unitId];
|
||||
}
|
||||
|
||||
class SceneTrigger extends SceneEvent {
|
||||
final String sceneId;
|
||||
final String name;
|
||||
@@ -25,3 +35,15 @@ class SceneTrigger extends SceneEvent {
|
||||
@override
|
||||
List<Object> get props => [sceneId];
|
||||
}
|
||||
|
||||
//updateAutomationStatus
|
||||
class UpdateAutomationStatus extends SceneEvent {
|
||||
final String automationId;
|
||||
final AutomationStatusUpdate automationStatusUpdate;
|
||||
|
||||
const UpdateAutomationStatus(
|
||||
{required this.automationStatusUpdate, required this.automationId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [automationStatusUpdate];
|
||||
}
|
||||
|
||||
@@ -13,12 +13,16 @@ class SceneLoading extends SceneState {}
|
||||
|
||||
class SceneLoaded extends SceneState {
|
||||
final List<ScenesModel> scenes;
|
||||
final List<ScenesModel> automationList;
|
||||
final String? loadingSceneId;
|
||||
final Map<String, bool> loadingStates;
|
||||
|
||||
const SceneLoaded(this.scenes, {this.loadingSceneId});
|
||||
const SceneLoaded(this.scenes, this.automationList,
|
||||
{this.loadingSceneId, this.loadingStates = const {}});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [scenes, loadingSceneId];
|
||||
List<Object?> get props =>
|
||||
[scenes, loadingSceneId, automationList, loadingStates];
|
||||
}
|
||||
|
||||
class SceneError extends SceneState {
|
||||
@@ -38,3 +42,7 @@ class SceneTriggerSuccess extends SceneState {
|
||||
@override
|
||||
List<Object> get props => [sceneName];
|
||||
}
|
||||
|
||||
class UpdateAutomationStatusLoading extends SceneState {
|
||||
const UpdateAutomationStatusLoading();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/scene/model/smart_scene_enable.dart';
|
||||
|
||||
part 'smart_scene_select_dart_event.dart';
|
||||
part 'smart_scene_select_dart_state.dart';
|
||||
|
||||
class SmartSceneSelectBloc
|
||||
extends Bloc<SmartSceneSelectEvent, SmartSceneSelectState> {
|
||||
SmartSceneSelectBloc() : super(SmartSceneSelectInitial()) {
|
||||
on<SmartSceneEnableEvent>(_onSmartSceneEnable);
|
||||
on<SmartSceneClearEvent>(_smartSceneClear);
|
||||
}
|
||||
|
||||
SmartSceneEnable? smartSceneEnable;
|
||||
|
||||
FutureOr<void> _onSmartSceneEnable(
|
||||
SmartSceneEnableEvent event, Emitter<SmartSceneSelectState> emit) {
|
||||
smartSceneEnable = event.smartSceneEnable;
|
||||
emit(SmartSceneSelected(smartSceneEnable: smartSceneEnable!));
|
||||
}
|
||||
|
||||
FutureOr<void> _smartSceneClear(
|
||||
SmartSceneClearEvent event, Emitter<SmartSceneSelectState> emit) {
|
||||
smartSceneEnable = null;
|
||||
emit(SmartSceneSelectInitial());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
part of 'smart_scene_select_dart_bloc.dart';
|
||||
|
||||
sealed class SmartSceneSelectEvent extends Equatable {
|
||||
const SmartSceneSelectEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class SmartSceneEnableEvent extends SmartSceneSelectEvent {
|
||||
final SmartSceneEnable smartSceneEnable;
|
||||
|
||||
const SmartSceneEnableEvent(this.smartSceneEnable);
|
||||
|
||||
@override
|
||||
List<Object> get props => [smartSceneEnable];
|
||||
}
|
||||
|
||||
class SmartSceneClearEvent extends SmartSceneSelectEvent {
|
||||
const SmartSceneClearEvent();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
part of 'smart_scene_select_dart_bloc.dart';
|
||||
|
||||
sealed class SmartSceneSelectState extends Equatable {
|
||||
const SmartSceneSelectState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
final class SmartSceneSelectInitial extends SmartSceneSelectState {}
|
||||
|
||||
class SmartSceneSelected extends SmartSceneSelectState {
|
||||
final SmartSceneEnable smartSceneEnable;
|
||||
|
||||
const SmartSceneSelected({required this.smartSceneEnable});
|
||||
|
||||
@override
|
||||
List<Object> get props => [smartSceneEnable];
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
enum CreateSceneEnum {
|
||||
tabToRun,
|
||||
deviceStatusChanges,
|
||||
none,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
enum EnumEffectivePeriodOptions {
|
||||
allDay,
|
||||
daytime,
|
||||
night,
|
||||
custom,
|
||||
none,
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
enum OperationDialogType {
|
||||
countdown,
|
||||
delay,
|
||||
temperature,
|
||||
onOff,
|
||||
integerSteps,
|
||||
listOfOptions,
|
||||
none,
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/effective_period_options.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:time_picker_spinner/time_picker_spinner.dart';
|
||||
|
||||
class EffectPeriodHelper {
|
||||
static Future<List<String>?> showCustomTimePicker(
|
||||
BuildContext context) async {
|
||||
String selectedStartTime = "00:00";
|
||||
String selectedEndTime = "23:59";
|
||||
PageController pageController = PageController(initialPage: 0);
|
||||
|
||||
DateTime startDateTime = DateTime(2022, 1, 1, 0, 0);
|
||||
DateTime endDateTime = DateTime(2022, 1, 1, 23, 59);
|
||||
|
||||
context.customAlertDialog(
|
||||
alertBody: SizedBox(
|
||||
height: 250,
|
||||
child: PageView(
|
||||
controller: pageController,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
_buildTimePickerPage(
|
||||
context: context,
|
||||
pageController: pageController,
|
||||
isStartTime: true,
|
||||
time: startDateTime,
|
||||
onTimeChange: (time) {
|
||||
selectedStartTime =
|
||||
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}";
|
||||
},
|
||||
),
|
||||
_buildTimePickerPage(
|
||||
context: context,
|
||||
pageController: pageController,
|
||||
isStartTime: false,
|
||||
time: endDateTime,
|
||||
onTimeChange: (time) {
|
||||
selectedEndTime =
|
||||
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}";
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: "Custom",
|
||||
onConfirm: () {
|
||||
context.read<EffectPeriodBloc>().add(
|
||||
SetCustomTime(selectedStartTime, selectedEndTime),
|
||||
);
|
||||
context.read<EffectPeriodBloc>().add(
|
||||
const SetPeriod(EnumEffectivePeriodOptions.custom),
|
||||
);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
static Widget _buildTimePickerPage({
|
||||
required BuildContext context,
|
||||
required PageController pageController,
|
||||
required bool isStartTime,
|
||||
required DateTime time,
|
||||
required Function(DateTime) onTimeChange,
|
||||
}) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (!isStartTime)
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
pageController.previousPage(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeIn,
|
||||
);
|
||||
},
|
||||
child: const BodyMedium(text: "Start"),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
child: BodyMedium(
|
||||
text: isStartTime ? "Start" : "End",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isStartTime)
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
pageController.nextPage(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeIn,
|
||||
);
|
||||
},
|
||||
child: const BodyMedium(text: "End"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TimePickerSpinner(
|
||||
is24HourMode: false,
|
||||
normalTextStyle: const TextStyle(
|
||||
fontSize: 24,
|
||||
color: Colors.grey,
|
||||
),
|
||||
highlightedTextStyle: const TextStyle(
|
||||
fontSize: 24,
|
||||
color: ColorsManager.primaryColor,
|
||||
),
|
||||
spacing: 20,
|
||||
itemHeight: 50,
|
||||
isForce2Digits: true,
|
||||
time: time,
|
||||
onTimeChange: onTimeChange,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
static String formatEnumValue(EnumEffectivePeriodOptions value) {
|
||||
switch (value) {
|
||||
case EnumEffectivePeriodOptions.allDay:
|
||||
return "All Day";
|
||||
case EnumEffectivePeriodOptions.daytime:
|
||||
return "Daytime";
|
||||
case EnumEffectivePeriodOptions.night:
|
||||
return "Night";
|
||||
case EnumEffectivePeriodOptions.custom:
|
||||
return "Custom";
|
||||
case EnumEffectivePeriodOptions.none:
|
||||
return "None";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
import 'package:syncrow_app/features/scene/enum/ac_values.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class ACFunctionsHelper {
|
||||
static List<SceneStaticFunction> tabToRunAcFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsAcPower,
|
||||
operationName: 'Power',
|
||||
code: 'switch',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower,
|
||||
description: "ON",
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF,
|
||||
description: "OFF",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsFreezing,
|
||||
operationName: 'Mode',
|
||||
code: 'mode',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcCooling,
|
||||
description: AcValuesEnums.Cooling.name,
|
||||
value: TempModes.cold.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcHeating,
|
||||
description: AcValuesEnums.Heating.name,
|
||||
value: TempModes.hot.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFanSpeed,
|
||||
description: AcValuesEnums.Ventilation.name,
|
||||
value: TempModes.wind.name,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsTempreture,
|
||||
operationName: 'Set Temperature',
|
||||
code: 'temp_set',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.temperature,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsCelsiusDegrees,
|
||||
value: 0,
|
||||
description: 'COOL TO',
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsFanSpeed,
|
||||
operationName: 'Fan Speed',
|
||||
code: 'level',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanLow,
|
||||
description: ValueACRange.LOW.name,
|
||||
value: FanSpeeds.low.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanMiddle,
|
||||
description: ValueACRange.MIDDLE.name,
|
||||
value: FanSpeeds.middle.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanHigh,
|
||||
description: ValueACRange.HIGH.name,
|
||||
value: FanSpeeds.high.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanAuto,
|
||||
description: ValueACRange.AUTO.name,
|
||||
value: FanSpeeds.auto.name,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsChildLock,
|
||||
operationName: 'Child Lock',
|
||||
code: 'child_lock',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneChildLock,
|
||||
description: 'Lock',
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneChildUnlock,
|
||||
description: 'Unlock',
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
static List<SceneStaticFunction> automationAcFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsAcPower,
|
||||
operationName: 'Power',
|
||||
code: 'switch',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower,
|
||||
description: "ON",
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF,
|
||||
description: "OFF",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsFreezing,
|
||||
operationName: 'Mode',
|
||||
code: 'mode',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcCooling,
|
||||
description: AcValuesEnums.Cooling.name,
|
||||
value: TempModes.cold.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcHeating,
|
||||
description: AcValuesEnums.Heating.name,
|
||||
value: TempModes.hot.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFanSpeed,
|
||||
description: AcValuesEnums.Ventilation.name,
|
||||
value: TempModes.wind.name,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsTempreture,
|
||||
operationName: 'Set Temperature',
|
||||
code: 'temp_set',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsCelsiusDegrees,
|
||||
value: 0.0,
|
||||
description: '°C',
|
||||
minValue: 20,
|
||||
maxValue: 30,
|
||||
stepValue: 0.5,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsCurrentTemp,
|
||||
operationName: 'Current Temperature',
|
||||
code: 'temp_current',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsCelsiusDegrees,
|
||||
value: 0.0,
|
||||
description: '°C',
|
||||
minValue: -9.9,
|
||||
maxValue: 99.9,
|
||||
stepValue: 0.1,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsFanSpeed,
|
||||
operationName: 'Fan Speed',
|
||||
code: 'level',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanLow,
|
||||
description: ValueACRange.LOW.name,
|
||||
value: FanSpeeds.low.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanMiddle,
|
||||
description: ValueACRange.MIDDLE.name,
|
||||
value: FanSpeeds.middle.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanHigh,
|
||||
description: ValueACRange.HIGH.name,
|
||||
value: FanSpeeds.high.name,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcFanAuto,
|
||||
description: ValueACRange.AUTO.name,
|
||||
value: FanSpeeds.auto.name,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsChildLock,
|
||||
operationName: 'Child Lock',
|
||||
code: 'child_lock',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneChildLock,
|
||||
description: 'Lock',
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneChildUnlock,
|
||||
description: 'Unlock',
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class DoorLockHelperFunctions {
|
||||
/// tab to run functions
|
||||
static List<SceneStaticFunction> doorLockTapToRunFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsIconsDoorLock,
|
||||
operationName: 'Set Door lock Normal Open',
|
||||
functionValue: functionValue,
|
||||
code: 'normal_open_switch',
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
//// automation functions
|
||||
static List<SceneStaticFunction> doorLockAutomationFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsFingerprintUnlock,
|
||||
operationName: 'Fingerprint Unlock',
|
||||
functionValue: functionValue,
|
||||
code: 'unlock_fingerprint',
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "",
|
||||
value: 0.0,
|
||||
minValue: 0.0,
|
||||
maxValue: 999,
|
||||
stepValue: 1.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsPasswordUnlock,
|
||||
operationName: 'Password Unlock',
|
||||
functionValue: functionValue,
|
||||
code: 'unlock_password',
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "",
|
||||
value: 0.0,
|
||||
minValue: 0.0,
|
||||
maxValue: 999,
|
||||
stepValue: 1.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsCardUnlock,
|
||||
operationName: 'Card Unlock',
|
||||
functionValue: functionValue,
|
||||
code: 'unlock_card',
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "",
|
||||
value: 0.0,
|
||||
minValue: 0.0,
|
||||
maxValue: 999,
|
||||
stepValue: 1.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsLockAlarm,
|
||||
operationName: 'Lock Alarm',
|
||||
functionValue: functionValue,
|
||||
code: 'alarm_lock',
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFingerprintUnlock,
|
||||
description: "Fingerprint Mismatch",
|
||||
value: 0,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsRemoteUnlockReq,
|
||||
operationName: 'Remote Unlock Request',
|
||||
functionValue: functionValue,
|
||||
code: 'unlock_request',
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "",
|
||||
value: 0.0,
|
||||
minValue: 0,
|
||||
maxValue: 90,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsResidualElectricity,
|
||||
operationName: 'Residual Electricity',
|
||||
functionValue: functionValue,
|
||||
code: 'residual_electricity',
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "",
|
||||
value: 0.0,
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsDoubleLock,
|
||||
operationName: 'Double Lock',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
code: 'reverse_lock',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower,
|
||||
description: "ON",
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF,
|
||||
description: "OFF",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsRemoteUnlockViaApp,
|
||||
operationName: 'Remote Unlock Via App',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
code: 'unlock_app',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "",
|
||||
value: 0.0,
|
||||
minValue: 0,
|
||||
maxValue: 999,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsHijackAlarm,
|
||||
operationName: 'Hijack Alarm',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
code: 'hijack',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower,
|
||||
description: "ON",
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF,
|
||||
description: "OFF",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsDoorlockNormalOpen,
|
||||
operationName: 'Set Door Lock Normal Open',
|
||||
functionValue: functionValue,
|
||||
code: 'normal_open_switch',
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower,
|
||||
description: "ON",
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF,
|
||||
description: "OFF",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsDoorlockNormalOpen,
|
||||
operationName: 'Doorbell',
|
||||
functionValue: functionValue,
|
||||
code: 'doorbell',
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower,
|
||||
description: "ON",
|
||||
value: true,
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF,
|
||||
description: "OFF",
|
||||
value: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsTempPasswordUnlock,
|
||||
operationName: 'Temporary Password Unlock',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
code: 'unlock_temporary',
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "",
|
||||
value: 0.0,
|
||||
minValue: 0,
|
||||
maxValue: 999,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class GatewayHelperFunctions {
|
||||
static List<SceneStaticFunction> tabToRunGatewayFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsSwitchAlarmSound,
|
||||
operationName: 'Switch Alarm Sound',
|
||||
code: 'switch_alarm_sound',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsMasterState,
|
||||
operationName: 'Master State',
|
||||
code: 'master_state',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower,
|
||||
description: "Alarm",
|
||||
value: 'alarm',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF,
|
||||
description: "Normal",
|
||||
value: 'normal',
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsFactoryReset,
|
||||
operationName: 'Factory Reset',
|
||||
code: 'factory_reset',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSceneRefresh, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsResetOff, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class HumanPresenceHelperFunctions {
|
||||
static List<SceneStaticFunction> tabToRunHumanPresenceFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsFarDetection,
|
||||
operationName: 'Far Detection',
|
||||
code: 'far_detection',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 75,
|
||||
description: '75cm',
|
||||
iconValue: '75',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 150,
|
||||
description: '150cm',
|
||||
iconValue: '150',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 225,
|
||||
description: '225cm',
|
||||
iconValue: '225',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 300,
|
||||
description: '300cm',
|
||||
iconValue: '300',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 375,
|
||||
description: '375cm',
|
||||
iconValue: '375',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 450,
|
||||
description: '450cm',
|
||||
iconValue: '450',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 525,
|
||||
description: '525cm',
|
||||
iconValue: '525',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 600,
|
||||
description: '600cm',
|
||||
iconValue: '600',
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsMotionDetection,
|
||||
operationName: 'Motion Detection Sensitivity',
|
||||
code: 'motion_sensitivity_value',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 1,
|
||||
description: 1.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 2,
|
||||
description: 2.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 3,
|
||||
description: 3.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 4,
|
||||
description: 4.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 5,
|
||||
description: 5.toString(),
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsMotionlessDetection,
|
||||
operationName: 'Motionless Detection Sensitivity',
|
||||
code: 'motionless_sensitivity',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
iconValue: '1',
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 1,
|
||||
description: '1',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 2,
|
||||
description: '2',
|
||||
iconValue: '2',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 3,
|
||||
description: '3',
|
||||
iconValue: '3',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 4,
|
||||
description: '4',
|
||||
iconValue: '4',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsFarDetectionFunction,
|
||||
value: 5,
|
||||
description: '5',
|
||||
iconValue: '5',
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsIndicator,
|
||||
operationName: 'Indicator',
|
||||
code: 'indicator',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
static List<SceneStaticFunction> automationHumanPresenceFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsPresenceState,
|
||||
operationName: 'Presence State',
|
||||
code: 'presence_state',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsIconsPresenceSensorAssetsEmpty,
|
||||
value: 'none',
|
||||
description: 'None',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsPresence,
|
||||
value: 'presence',
|
||||
description: 'Presence',
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsIconsPresenceSensorAssetsDistance,
|
||||
operationName: 'Current Distance',
|
||||
code: 'dis_current',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
value: 0.0,
|
||||
description: "CM",
|
||||
minValue: 1,
|
||||
maxValue: 600,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsIconsPresenceSensorAssetsIlluminanceValue,
|
||||
operationName: 'Illuminance Value',
|
||||
code: 'illuminance_value',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
value: 0.0,
|
||||
description: "Lux",
|
||||
minValue: 0,
|
||||
maxValue: 10000,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsIndicator,
|
||||
operationName: 'Indicator',
|
||||
code: 'indicator',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsIconsPresenceSensorAssetsTime,
|
||||
operationName: 'Presence Time',
|
||||
code: 'presence_time',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
value: 0.0,
|
||||
minValue: 0.0,
|
||||
maxValue: 65535,
|
||||
stepValue: 1,
|
||||
description: 'min'),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class PresenceSensorHelperFunctions {
|
||||
static List<SceneStaticFunction> tabToRunPresenceSensorFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsSensitivityFunction,
|
||||
operationName: 'Sensitivity',
|
||||
code: 'sensitivity',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 1,
|
||||
description: 1.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 2,
|
||||
description: 2.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 3,
|
||||
description: 3.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 4,
|
||||
description: 4.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 5,
|
||||
description: 5.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 6,
|
||||
description: 6.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 7,
|
||||
description: 7.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 8,
|
||||
description: 8.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 9,
|
||||
description: 9.toString(),
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSensitivityOperationIcon,
|
||||
value: 10,
|
||||
description: 10.toString(),
|
||||
),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
static List<SceneStaticFunction> automationPresenceSensorFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsIconsSensors,
|
||||
operationName: 'Presence Status',
|
||||
code: 'presence_state',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsIconsPresenceSensorAssetsEmpty,
|
||||
value: 'none',
|
||||
description: 'None',
|
||||
),
|
||||
// SceneOperationalValue(
|
||||
// icon: Assets.assetsPresence,
|
||||
// value: 'presence',
|
||||
// description: 'Presence',
|
||||
// ),
|
||||
// SceneOperationalValue(
|
||||
// icon: Assets.assetsMotion,
|
||||
// value: 'motion',
|
||||
// description: 'Motion',
|
||||
// ),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsSensitivityFunction,
|
||||
operationName: 'Sensitivity',
|
||||
code: 'sensitivity',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "",
|
||||
value: 0.0,
|
||||
minValue: 0,
|
||||
maxValue: 10,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsSelfTestResult,
|
||||
operationName: 'Self-Test Result',
|
||||
code: 'checking_result',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.listOfOptions,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsSelfTestResult,
|
||||
value: 'check_success',
|
||||
description: 'Self Testing Success',
|
||||
),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class ThreeGangHelperFunctions {
|
||||
static List<SceneStaticFunction> threeGangHelperFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsAcPower,
|
||||
operationName: 'Light 1 Switch',
|
||||
code: 'switch_1',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsAcPower,
|
||||
operationName: 'Light 2 Switch',
|
||||
code: 'switch_2',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsAcPower,
|
||||
operationName: 'Light 3 Switch',
|
||||
code: 'switch_3',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsLightCountdown,
|
||||
operationName: 'Light 1 CountDown',
|
||||
code: 'countdown_1',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.countdown,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: '', value: 0),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsLightCountdown,
|
||||
operationName: 'Light 2 CountDown',
|
||||
code: 'countdown_2',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.countdown,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: '', value: 0),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsLightCountdown,
|
||||
operationName: 'Light 3 CountDown',
|
||||
code: 'countdown_3',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.countdown,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: '', value: 0),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
static List<SceneStaticFunction> threeGangAutomationFunctions(
|
||||
String deviceId, String deviceName, functionValue) {
|
||||
return [
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsAcPower,
|
||||
operationName: 'Light 1 Switch',
|
||||
code: 'switch_1',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsAcPower,
|
||||
operationName: 'Light 2 Switch',
|
||||
code: 'switch_2',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsAcPower,
|
||||
operationName: 'Light 3 Switch',
|
||||
code: 'switch_3',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.onOff,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower, description: "ON", value: true),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsLightCountdown,
|
||||
operationName: 'Light 1 CountDown',
|
||||
code: 'countdown_1',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "sec",
|
||||
value: 0.0,
|
||||
minValue: 0,
|
||||
maxValue: 43200,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsLightCountdown,
|
||||
operationName: 'Light 2 CountDown',
|
||||
code: 'countdown_2',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "sec",
|
||||
value: 0.0,
|
||||
minValue: 0,
|
||||
maxValue: 43200,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
SceneStaticFunction(
|
||||
deviceId: deviceId,
|
||||
deviceName: deviceName,
|
||||
icon: Assets.assetsLightCountdown,
|
||||
operationName: 'Light 3 CountDown',
|
||||
code: 'countdown_3',
|
||||
functionValue: functionValue,
|
||||
operationDialogType: OperationDialogType.integerSteps,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(
|
||||
icon: '',
|
||||
description: "sec",
|
||||
value: 0.0,
|
||||
minValue: 0,
|
||||
maxValue: 43200,
|
||||
stepValue: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,14 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
|
||||
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/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/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_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_temperature_body.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
|
||||
@@ -20,84 +21,185 @@ mixin SceneLogicHelper {
|
||||
}
|
||||
|
||||
void handleSaveButtonPress(
|
||||
BuildContext context,
|
||||
TextEditingController sceneNameController,
|
||||
List<SceneStaticFunction> tasks, {
|
||||
BuildContext context, {
|
||||
required bool updateScene,
|
||||
required String sceneId,
|
||||
required bool isAutomation,
|
||||
required TextEditingController sceneName,
|
||||
required List<SceneStaticFunction> actions,
|
||||
required List<SceneStaticFunction> conditions,
|
||||
}) {
|
||||
if (isOnlyDelayOrDelayLast(tasks)) {
|
||||
// Show snackbar indicating restriction
|
||||
Navigator.pop(context);
|
||||
context.showCustomSnackbar(
|
||||
message: 'A single delay or delay-last operations are NOT allowed.',
|
||||
icon: const Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final createSceneModel = CreateSceneModel(
|
||||
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
||||
sceneName: sceneNameController.text,
|
||||
decisionExpr: 'and',
|
||||
actions: List.generate(
|
||||
tasks.length,
|
||||
(index) {
|
||||
final task = tasks[index];
|
||||
if (task.deviceId == 'delay') {
|
||||
return CreateSceneAction(
|
||||
entityId: tasks[index].deviceId,
|
||||
actionExecutor: 'delay',
|
||||
executorProperty: CreateSceneExecutorProperty(
|
||||
functionCode: '',
|
||||
functionValue: '',
|
||||
delaySeconds: task.functionValue,
|
||||
final sceneBloc = context.read<CreateSceneBloc>();
|
||||
final smartSceneBloc = context.read<SmartSceneSelectBloc>();
|
||||
|
||||
if (isAutomation) {
|
||||
// Handle Automation Creation
|
||||
if (isOnlyDelayOrDelayLast(actions)) {
|
||||
Navigator.pop(context);
|
||||
context.showCustomSnackbar(
|
||||
message: 'A single delay or delay-last operations are NOT allowed.',
|
||||
icon: const Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final createAutomationModel = CreateAutomationModel(
|
||||
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
||||
automationName: sceneName.text,
|
||||
decisionExpr: sceneBloc.conditionRule,
|
||||
effectiveTime: sceneBloc.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,
|
||||
),
|
||||
);
|
||||
}
|
||||
return CreateSceneAction(
|
||||
entityId: task.deviceId,
|
||||
actionExecutor: 'device_issue',
|
||||
executorProperty: CreateSceneExecutorProperty(
|
||||
functionCode: task.code,
|
||||
functionValue: task.functionValue,
|
||||
delaySeconds: 0,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
context.read<CreateSceneBloc>().add(CreateSceneWithTasksEvent(
|
||||
createSceneModel: createSceneModel,
|
||||
updateScene: updateScene,
|
||||
sceneId: sceneId,
|
||||
));
|
||||
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
...List.generate(
|
||||
actions.length,
|
||||
(index) {
|
||||
final task = actions[index];
|
||||
if (task.deviceId == 'delay') {
|
||||
return CreateSceneAction(
|
||||
entityId: actions[index].deviceId,
|
||||
actionExecutor: 'delay',
|
||||
executorProperty: CreateSceneExecutorProperty(
|
||||
functionCode: '',
|
||||
functionValue: '',
|
||||
delaySeconds: task.functionValue,
|
||||
),
|
||||
);
|
||||
}
|
||||
return CreateSceneAction(
|
||||
entityId: task.deviceId,
|
||||
actionExecutor: 'device_issue',
|
||||
executorProperty: CreateSceneExecutorProperty(
|
||||
functionCode: task.code,
|
||||
functionValue: task.functionValue,
|
||||
delaySeconds: 0,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (smartSceneBloc.smartSceneEnable != null)
|
||||
CreateSceneAction(
|
||||
entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '',
|
||||
actionExecutor:
|
||||
smartSceneBloc.smartSceneEnable?.actionExecutor ?? '',
|
||||
executorProperty: null)
|
||||
],
|
||||
);
|
||||
sceneBloc.add(CreateSceneWithTasksEvent(
|
||||
createSceneModel: null,
|
||||
updateScene: updateScene,
|
||||
sceneId: sceneId,
|
||||
createAutomationModel: createAutomationModel,
|
||||
));
|
||||
Navigator.pop(context);
|
||||
}
|
||||
} else {
|
||||
if (isOnlyDelayOrDelayLast(actions)) {
|
||||
Navigator.pop(context);
|
||||
context.showCustomSnackbar(
|
||||
message: 'A single delay or delay-last operations are NOT allowed.',
|
||||
icon: const Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// Handle Scene Creation
|
||||
final createSceneModel = CreateSceneModel(
|
||||
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
||||
sceneName: sceneName.text,
|
||||
decisionExpr: 'and',
|
||||
actions: [
|
||||
...List.generate(
|
||||
actions.length,
|
||||
(index) {
|
||||
final task = actions[index];
|
||||
if (task.deviceId == 'delay') {
|
||||
return CreateSceneAction(
|
||||
entityId: actions[index].deviceId,
|
||||
actionExecutor: 'delay',
|
||||
executorProperty: CreateSceneExecutorProperty(
|
||||
functionCode: '',
|
||||
functionValue: '',
|
||||
delaySeconds: task.functionValue,
|
||||
),
|
||||
);
|
||||
}
|
||||
return CreateSceneAction(
|
||||
entityId: task.deviceId,
|
||||
actionExecutor: 'device_issue',
|
||||
executorProperty: CreateSceneExecutorProperty(
|
||||
functionCode: task.code,
|
||||
functionValue: task.functionValue,
|
||||
delaySeconds: 0,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (smartSceneBloc.smartSceneEnable != null)
|
||||
CreateSceneAction(
|
||||
entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '',
|
||||
actionExecutor:
|
||||
smartSceneBloc.smartSceneEnable?.actionExecutor ?? '',
|
||||
executorProperty: null)
|
||||
],
|
||||
);
|
||||
sceneBloc.add(CreateSceneWithTasksEvent(
|
||||
createSceneModel: createSceneModel,
|
||||
createAutomationModel: null,
|
||||
updateScene: updateScene,
|
||||
sceneId: sceneId,
|
||||
));
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget getTheCorrectDialogBody(
|
||||
SceneStaticFunction taskItem,
|
||||
) {
|
||||
if (taskItem.code.contains('temp_set')) {
|
||||
SceneStaticFunction taskItem, dynamic functionValue,
|
||||
{required bool isAutomation}) {
|
||||
if (taskItem.operationDialogType == OperationDialogType.temperature) {
|
||||
return AlertDialogTemperatureBody(
|
||||
taskItem: taskItem,
|
||||
functionValue: taskItem.functionValue,
|
||||
functionValue: functionValue ?? taskItem.functionValue,
|
||||
);
|
||||
} else if (taskItem.code.contains('countdown') ||
|
||||
taskItem.deviceId.contains('delay')) {
|
||||
} else if ((taskItem.operationDialogType ==
|
||||
OperationDialogType.countdown) ||
|
||||
(taskItem.operationDialogType == OperationDialogType.delay)) {
|
||||
return AlertDialogCountdown(
|
||||
durationValue: taskItem.functionValue,
|
||||
functionValue: taskItem.functionValue,
|
||||
durationValue: taskItem.functionValue ?? 0,
|
||||
functionValue: functionValue ?? taskItem.functionValue,
|
||||
function: taskItem,
|
||||
);
|
||||
} else if (taskItem.operationDialogType ==
|
||||
OperationDialogType.integerSteps) {
|
||||
return AlertDialogSliderSteps(
|
||||
taskItem: taskItem,
|
||||
functionValue: functionValue ?? taskItem.functionValue,
|
||||
isAutomation: isAutomation,
|
||||
);
|
||||
}
|
||||
|
||||
return AlertDialogFunctionsOperationsBody(
|
||||
taskItem: taskItem,
|
||||
functionValue: taskItem.functionValue,
|
||||
functionValue: functionValue ?? taskItem.functionValue,
|
||||
isAutomation: isAutomation,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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([String? automationId]) {
|
||||
return {
|
||||
if (automationId == null) '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([String? automationId]) => json.encode(toMap(automationId));
|
||||
|
||||
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)';
|
||||
}
|
||||
@@ -3,29 +3,11 @@ import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class CreateSceneModel {
|
||||
/*
|
||||
{
|
||||
"unitUuid": "string",
|
||||
"sceneName": "string",
|
||||
"decisionExpr": "string",
|
||||
"actions": [
|
||||
{
|
||||
"entityId": "string",
|
||||
"actionExecutor": "string",
|
||||
"executorProperty": {
|
||||
"functionCode": "string",
|
||||
"functionValue": {},
|
||||
"delaySeconds": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
String unitUuid;
|
||||
String sceneName;
|
||||
String decisionExpr;
|
||||
List<CreateSceneAction> actions;
|
||||
|
||||
CreateSceneModel({
|
||||
required this.unitUuid,
|
||||
required this.sceneName,
|
||||
@@ -99,7 +81,8 @@ class CreateSceneModel {
|
||||
class CreateSceneAction {
|
||||
String entityId;
|
||||
String actionExecutor;
|
||||
CreateSceneExecutorProperty executorProperty;
|
||||
CreateSceneExecutorProperty? executorProperty;
|
||||
|
||||
CreateSceneAction({
|
||||
required this.entityId,
|
||||
required this.actionExecutor,
|
||||
@@ -122,7 +105,8 @@ class CreateSceneAction {
|
||||
return {
|
||||
'entityId': entityId,
|
||||
'actionExecutor': actionExecutor,
|
||||
'executorProperty': executorProperty.toMap(),
|
||||
if (executorProperty != null)
|
||||
'executorProperty': executorProperty?.toMap(actionExecutor),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -163,6 +147,7 @@ class CreateSceneExecutorProperty {
|
||||
String functionCode;
|
||||
dynamic functionValue;
|
||||
int delaySeconds;
|
||||
|
||||
CreateSceneExecutorProperty({
|
||||
required this.functionCode,
|
||||
required this.functionValue,
|
||||
@@ -181,12 +166,14 @@ class CreateSceneExecutorProperty {
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
if (functionCode.isNotEmpty == true) 'functionCode': functionCode,
|
||||
if (functionValue != '') 'functionValue': functionValue,
|
||||
if (delaySeconds > 0) 'delaySeconds': delaySeconds,
|
||||
};
|
||||
Map<String, dynamic> toMap(String actionExecutor) {
|
||||
final map = <String, dynamic>{};
|
||||
if (functionCode.isNotEmpty) map['functionCode'] = functionCode;
|
||||
if (functionValue != null) map['functionValue'] = functionValue;
|
||||
if (actionExecutor == 'delay' && delaySeconds > 0) {
|
||||
map['delaySeconds'] = delaySeconds;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
factory CreateSceneExecutorProperty.fromMap(Map<String, dynamic> map) {
|
||||
@@ -197,7 +184,7 @@ class CreateSceneExecutorProperty {
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
String toJson(String actionExecutor) => json.encode(toMap(actionExecutor));
|
||||
|
||||
factory CreateSceneExecutorProperty.fromJson(String source) =>
|
||||
CreateSceneExecutorProperty.fromMap(json.decode(source));
|
||||
|
||||
@@ -6,6 +6,9 @@ class SceneDetailsModel {
|
||||
final String status;
|
||||
final String type;
|
||||
final List<Action> actions;
|
||||
final List<Condition>? conditions;
|
||||
final String? decisionExpr;
|
||||
final EffectiveTime? effectiveTime;
|
||||
|
||||
SceneDetailsModel({
|
||||
required this.id,
|
||||
@@ -13,6 +16,9 @@ class SceneDetailsModel {
|
||||
required this.status,
|
||||
required this.type,
|
||||
required this.actions,
|
||||
this.conditions,
|
||||
this.decisionExpr,
|
||||
this.effectiveTime,
|
||||
});
|
||||
|
||||
factory SceneDetailsModel.fromRawJson(String str) =>
|
||||
@@ -26,8 +32,20 @@ class SceneDetailsModel {
|
||||
name: json["name"],
|
||||
status: json["status"],
|
||||
type: json["type"],
|
||||
actions:
|
||||
List<Action>.from(json["actions"].map((x) => Action.fromJson(x))),
|
||||
actions: (json["actions"] as List)
|
||||
.map((x) => Action.fromJson(x))
|
||||
.where((x) => x != null)
|
||||
.toList()
|
||||
.cast<Action>(),
|
||||
conditions: json["conditions"] != null
|
||||
? (json["conditions"] as List)
|
||||
.map((x) => Condition.fromJson(x))
|
||||
.toList()
|
||||
: null,
|
||||
decisionExpr: json["decisionExpr"],
|
||||
effectiveTime: json["effectiveTime"] != null
|
||||
? EffectiveTime.fromJson(json["effectiveTime"])
|
||||
: null,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
@@ -36,6 +54,11 @@ class SceneDetailsModel {
|
||||
"status": status,
|
||||
"type": type,
|
||||
"actions": List<dynamic>.from(actions.map((x) => x.toJson())),
|
||||
"conditions": conditions != null
|
||||
? List<dynamic>.from(conditions!.map((x) => x.toJson()))
|
||||
: null,
|
||||
"decisionExpr": decisionExpr,
|
||||
"effectiveTime": effectiveTime?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,15 +73,19 @@ class Action {
|
||||
required this.executorProperty,
|
||||
});
|
||||
|
||||
factory Action.fromRawJson(String str) => Action.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory Action.fromJson(Map<String, dynamic> json) => Action(
|
||||
actionExecutor: json["actionExecutor"],
|
||||
entityId: json["entityId"],
|
||||
executorProperty: ExecutorProperty.fromJson(json["executorProperty"]),
|
||||
);
|
||||
static Action? fromJson(Map<String, dynamic> json) {
|
||||
if (json["executorProperty"] == null) {
|
||||
return null; // Return null if executorProperty is not present
|
||||
}
|
||||
|
||||
return Action(
|
||||
actionExecutor: json["actionExecutor"],
|
||||
entityId: json["entityId"],
|
||||
executorProperty: ExecutorProperty.fromJson(json["executorProperty"]),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"actionExecutor": actionExecutor,
|
||||
@@ -91,3 +118,93 @@ class ExecutorProperty {
|
||||
"delaySeconds": delaySeconds,
|
||||
};
|
||||
}
|
||||
|
||||
class Condition {
|
||||
final int code;
|
||||
final String entityId;
|
||||
final String entityType;
|
||||
final Expr expr;
|
||||
|
||||
Condition({
|
||||
required this.code,
|
||||
required this.entityId,
|
||||
required this.entityType,
|
||||
required this.expr,
|
||||
});
|
||||
|
||||
factory Condition.fromRawJson(String str) =>
|
||||
Condition.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory Condition.fromJson(Map<String, dynamic> json) => Condition(
|
||||
code: json["code"],
|
||||
entityId: json["entityId"],
|
||||
entityType: json["entityType"],
|
||||
expr: Expr.fromJson(json["expr"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"code": code,
|
||||
"entityId": entityId,
|
||||
"entityType": entityType,
|
||||
"expr": expr.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class Expr {
|
||||
final String comparator;
|
||||
final String statusCode;
|
||||
final dynamic statusValue;
|
||||
|
||||
Expr({
|
||||
required this.comparator,
|
||||
required this.statusCode,
|
||||
required this.statusValue,
|
||||
});
|
||||
|
||||
factory Expr.fromRawJson(String str) => Expr.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory Expr.fromJson(Map<String, dynamic> json) => Expr(
|
||||
comparator: json["comparator"],
|
||||
statusCode: json["statusCode"],
|
||||
statusValue: json["statusValue"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"comparator": comparator,
|
||||
"statusCode": statusCode,
|
||||
"statusValue": statusValue,
|
||||
};
|
||||
}
|
||||
|
||||
class EffectiveTime {
|
||||
final String start;
|
||||
final String end;
|
||||
final String loops;
|
||||
|
||||
EffectiveTime({
|
||||
required this.start,
|
||||
required this.end,
|
||||
required this.loops,
|
||||
});
|
||||
|
||||
factory EffectiveTime.fromRawJson(String str) =>
|
||||
EffectiveTime.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory EffectiveTime.fromJson(Map<String, dynamic> json) => EffectiveTime(
|
||||
start: json["start"],
|
||||
end: json["end"],
|
||||
loops: json["loops"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"start": start,
|
||||
"end": end,
|
||||
"loops": loops,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class SceneStaticFunction {
|
||||
@@ -13,6 +14,8 @@ class SceneStaticFunction {
|
||||
final String uniqueCustomId;
|
||||
final dynamic functionValue;
|
||||
final String? deviceIcon;
|
||||
final OperationDialogType operationDialogType;
|
||||
final String? comparator;
|
||||
|
||||
SceneStaticFunction({
|
||||
required this.icon,
|
||||
@@ -23,6 +26,8 @@ class SceneStaticFunction {
|
||||
required this.operationName,
|
||||
required this.functionValue,
|
||||
this.deviceIcon,
|
||||
required this.operationDialogType,
|
||||
this.comparator,
|
||||
}) : uniqueCustomId = const Uuid().v4();
|
||||
|
||||
SceneStaticFunction copyWith({
|
||||
@@ -35,6 +40,8 @@ class SceneStaticFunction {
|
||||
dynamic functionValue,
|
||||
String? deviceIcon,
|
||||
String? deviceName,
|
||||
OperationDialogType? operationDialogType,
|
||||
String? comparator,
|
||||
}) {
|
||||
return SceneStaticFunction(
|
||||
icon: icon ?? this.icon,
|
||||
@@ -45,6 +52,8 @@ class SceneStaticFunction {
|
||||
operationName: operationName ?? this.operationName,
|
||||
functionValue: functionValue ?? this.functionValue,
|
||||
deviceIcon: deviceIcon ?? this.deviceIcon,
|
||||
operationDialogType: operationDialogType ?? this.operationDialogType,
|
||||
comparator: comparator ?? this.comparator,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,8 +66,9 @@ class SceneStaticFunction {
|
||||
'deviceId': deviceId,
|
||||
'operationName': operationName,
|
||||
'functionValue': functionValue,
|
||||
'deviceIcon': deviceIcon
|
||||
|
||||
'deviceIcon': deviceIcon,
|
||||
'operationDialogType': operationDialogType.name,
|
||||
'comparator': comparator
|
||||
};
|
||||
}
|
||||
|
||||
@@ -74,6 +84,10 @@ class SceneStaticFunction {
|
||||
operationName: map['operationName'] ?? '',
|
||||
functionValue: map['functionValue'] ?? '',
|
||||
deviceIcon: map['deviceIcon'] ?? '',
|
||||
operationDialogType: map['operationDialogType'] != null
|
||||
? OperationDialogType.values.byName(map['operationDialogType'])
|
||||
: OperationDialogType.none,
|
||||
comparator: map['comparator'],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -84,7 +98,7 @@ class SceneStaticFunction {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SceneStaticFunction(icon: $icon, name: $deviceName, code: $code, operationalValues: $operationalValues, deviceId: $deviceId, operationName: $operationName, functionValue: $functionValue, deviceIcon: $deviceIcon)';
|
||||
return 'SceneStaticFunction(icon: $icon, name: $deviceName, code: $code, operationalValues: $operationalValues, deviceId: $deviceId, operationName: $operationName, functionValue: $functionValue, deviceIcon: $deviceIcon, operationDialogType: $operationDialogType, comparator: $comparator)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -98,6 +112,8 @@ class SceneStaticFunction {
|
||||
other.operationName == operationName &&
|
||||
other.functionValue == functionValue &&
|
||||
other.deviceIcon == deviceIcon &&
|
||||
other.comparator == comparator &&
|
||||
other.operationDialogType == operationDialogType &&
|
||||
listEquals(other.operationalValues, operationalValues) &&
|
||||
other.deviceId == deviceId;
|
||||
}
|
||||
@@ -111,6 +127,8 @@ class SceneStaticFunction {
|
||||
operationName.hashCode ^
|
||||
functionValue.hashCode ^
|
||||
deviceIcon.hashCode ^
|
||||
comparator.hashCode ^
|
||||
operationDialogType.hashCode ^
|
||||
operationalValues.hashCode;
|
||||
}
|
||||
}
|
||||
@@ -120,12 +138,18 @@ class SceneOperationalValue {
|
||||
final dynamic value;
|
||||
final String? description;
|
||||
final String? iconValue;
|
||||
final double? minValue;
|
||||
final double? maxValue;
|
||||
final double? stepValue;
|
||||
|
||||
SceneOperationalValue({
|
||||
required this.icon,
|
||||
required this.value,
|
||||
this.description,
|
||||
this.iconValue,
|
||||
this.minValue,
|
||||
this.maxValue,
|
||||
this.stepValue,
|
||||
});
|
||||
|
||||
SceneOperationalValue copyWith({
|
||||
@@ -133,12 +157,18 @@ class SceneOperationalValue {
|
||||
dynamic value,
|
||||
String? description,
|
||||
String? iconValue,
|
||||
double? minValue,
|
||||
double? maxValue,
|
||||
double? stepValue,
|
||||
}) {
|
||||
return SceneOperationalValue(
|
||||
icon: icon ?? this.icon,
|
||||
value: value ?? this.value,
|
||||
description: description ?? this.description,
|
||||
iconValue: iconValue ?? this.iconValue,
|
||||
minValue: minValue ?? this.minValue,
|
||||
maxValue: maxValue ?? this.maxValue,
|
||||
stepValue: stepValue ?? this.stepValue,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -147,7 +177,10 @@ class SceneOperationalValue {
|
||||
'icon': icon,
|
||||
'value': value,
|
||||
'description': description,
|
||||
'iconValue': iconValue
|
||||
'iconValue': iconValue,
|
||||
'minValue': minValue,
|
||||
'maxValue': maxValue,
|
||||
'stepValue': stepValue
|
||||
};
|
||||
}
|
||||
|
||||
@@ -157,6 +190,9 @@ class SceneOperationalValue {
|
||||
value: map['value'],
|
||||
description: map['description'],
|
||||
iconValue: map['iconValue'] ?? '',
|
||||
minValue: map['minValue'],
|
||||
maxValue: map['maxValue'],
|
||||
stepValue: map['stepValue'],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -167,7 +203,7 @@ class SceneOperationalValue {
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'StaticFunctionOperationHelper(icon: $icon, value: $value, description: $description, iconValue: $iconValue)';
|
||||
'StaticFunctionOperationHelper(icon: $icon, value: $value, description: $description, iconValue: $iconValue, minValue: $minValue, maxValue: $maxValue, stepValue: $stepValue)';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
@@ -177,6 +213,9 @@ class SceneOperationalValue {
|
||||
other.icon == icon &&
|
||||
other.description == description &&
|
||||
other.iconValue == iconValue &&
|
||||
other.minValue == minValue &&
|
||||
other.maxValue == maxValue &&
|
||||
other.stepValue == stepValue &&
|
||||
other.value == value;
|
||||
}
|
||||
|
||||
@@ -186,5 +225,8 @@ class SceneOperationalValue {
|
||||
value.hashCode ^
|
||||
description.hashCode ^
|
||||
iconValue.hashCode ^
|
||||
minValue.hashCode ^
|
||||
maxValue.hashCode ^
|
||||
stepValue.hashCode ^
|
||||
description.hashCode;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import 'dart:convert';
|
||||
class ScenesModel {
|
||||
final String id;
|
||||
final String name;
|
||||
final Status status;
|
||||
final Type type;
|
||||
final String status;
|
||||
final String type;
|
||||
|
||||
ScenesModel({
|
||||
required this.id,
|
||||
@@ -20,35 +20,15 @@ class ScenesModel {
|
||||
|
||||
factory ScenesModel.fromJson(Map<String, dynamic> json) => ScenesModel(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
status: statusValues.map[json["status"]]!,
|
||||
type: typeValues.map[json["type"]]!,
|
||||
name: json["name"] ?? '',
|
||||
status: json["status"] ?? '',
|
||||
type: json["type"] ?? '',
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"status": statusValues.reverse[status],
|
||||
"type": typeValues.reverse[type],
|
||||
"status": status,
|
||||
"type": type,
|
||||
};
|
||||
}
|
||||
|
||||
enum Status { ENABLE }
|
||||
|
||||
final statusValues = EnumValues({"enable": Status.ENABLE});
|
||||
|
||||
enum Type { TAP_TO_RUN }
|
||||
|
||||
final typeValues = EnumValues({"tap_to_run": Type.TAP_TO_RUN});
|
||||
|
||||
class EnumValues<T> {
|
||||
Map<String, T> map;
|
||||
late Map<T, String> reverseMap;
|
||||
|
||||
EnumValues(this.map);
|
||||
|
||||
Map<T, String> get reverse {
|
||||
reverseMap = map.map((k, v) => MapEntry(v, k));
|
||||
return reverseMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
class SmartSceneEnable {
|
||||
final String entityId;
|
||||
final String actionExecutor;
|
||||
|
||||
SmartSceneEnable({
|
||||
required this.entityId,
|
||||
required this.actionExecutor,
|
||||
});
|
||||
|
||||
factory SmartSceneEnable.fromJson(Map<String, dynamic> json) {
|
||||
return SmartSceneEnable(
|
||||
entityId: json['entityId'],
|
||||
actionExecutor: json['actionExecutor'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'entityId': entityId,
|
||||
'actionExecutor': actionExecutor,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class AutomationStatusUpdate {
|
||||
final String unitUuid;
|
||||
final bool isEnable;
|
||||
|
||||
AutomationStatusUpdate({
|
||||
required this.unitUuid,
|
||||
required this.isEnable,
|
||||
});
|
||||
|
||||
factory AutomationStatusUpdate.fromRawJson(String str) =>
|
||||
AutomationStatusUpdate.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory AutomationStatusUpdate.fromJson(Map<String, dynamic> json) =>
|
||||
AutomationStatusUpdate(
|
||||
unitUuid: json["unitUuid"],
|
||||
isEnable: json["isEnable"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"unitUuid": unitUuid,
|
||||
"isEnable": isEnable,
|
||||
};
|
||||
|
||||
factory AutomationStatusUpdate.fromMap(Map<String, dynamic> map) =>
|
||||
AutomationStatusUpdate(
|
||||
unitUuid: map["unitUuid"],
|
||||
isEnable: map["isEnable"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"unitUuid": unitUuid,
|
||||
"isEnable": isEnable,
|
||||
};
|
||||
}
|
||||
@@ -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/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/navigation/navigate_to_route.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
|
||||
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||
|
||||
class CreateSceneView extends StatelessWidget {
|
||||
@@ -22,7 +21,7 @@ class CreateSceneView extends StatelessWidget {
|
||||
padding: const EdgeInsets.only(top: 24),
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
navigateToRoute(context, Routes.sceneTasksRoute);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
@@ -48,6 +47,9 @@ class CreateSceneView extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
context.read<CreateSceneBloc>().add(const ClearTaskListEvent());
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(const SceneTypeEvent(CreateSceneEnum.tabToRun));
|
||||
},
|
||||
),
|
||||
DefaultContainer(
|
||||
@@ -58,7 +60,22 @@ class CreateSceneView extends StatelessWidget {
|
||||
titleString: StringsManager.whenDeviceStatusChanges,
|
||||
subtitleString: StringsManager.whenUnusualActivityIsDetected,
|
||||
),
|
||||
onTap: () {},
|
||||
onTap: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
Routes.sceneControlDevicesRoute,
|
||||
arguments: SceneSettingsRouteArguments(
|
||||
sceneType: CreateSceneEnum.deviceStatusChanges.name,
|
||||
sceneId: '',
|
||||
sceneName: '',
|
||||
),
|
||||
);
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(const ClearTaskListEvent(isAutomation: true));
|
||||
context.read<CreateSceneBloc>().add(
|
||||
const SceneTypeEvent(CreateSceneEnum.deviceStatusChanges));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,33 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/helper/scene_logic_helper.dart';
|
||||
import 'package:syncrow_app/features/scene/helper/scene_operations_data_helper.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/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_temperature_body.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/light_divider.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/utils/context_extension.dart';
|
||||
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class DeviceFunctionsView extends StatelessWidget
|
||||
with SceneOperationsDataHelper {
|
||||
const DeviceFunctionsView({super.key});
|
||||
with SceneOperationsDataHelper, SceneLogicHelper {
|
||||
DeviceFunctionsView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
/// this whole widget needs a refactor later
|
||||
///
|
||||
/// static functions based on type
|
||||
final device = ModalRoute.of(context)?.settings.arguments as DeviceModel;
|
||||
final device = (ModalRoute.of(context)?.settings.arguments as Map)['device']
|
||||
as DeviceModel;
|
||||
|
||||
final isAutomation = (ModalRoute.of(context)?.settings.arguments
|
||||
as Map)['isAutomationDeviceStatus'] as bool;
|
||||
|
||||
/// static custom functions based on type
|
||||
/// used for now until later backend fixes
|
||||
@@ -38,6 +42,7 @@ class DeviceFunctionsView extends StatelessWidget
|
||||
functions: device.functions,
|
||||
deviceId: device.uuid ?? '',
|
||||
deviceName: device.name ?? '',
|
||||
isAutomation: isAutomation,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -46,10 +51,10 @@ class DeviceFunctionsView extends StatelessWidget
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.read<CreateSceneBloc>().add(AddTaskEvent());
|
||||
Navigator.popUntil(context, (route) {
|
||||
return route.settings.name == Routes.sceneTasksRoute;
|
||||
});
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(AddTaskEvent(isAutomation: isAutomation));
|
||||
navigateToRoute(context, Routes.sceneTasksRoute);
|
||||
},
|
||||
child: BodyMedium(
|
||||
text: 'Save',
|
||||
@@ -60,6 +65,16 @@ class DeviceFunctionsView extends StatelessWidget
|
||||
],
|
||||
leading: TextButton(
|
||||
onPressed: () {
|
||||
final automationSelectedValue =
|
||||
context.read<CreateSceneBloc>().automationSelectedValues;
|
||||
for (var element in device.functions) {
|
||||
if (automationSelectedValue.containsKey(element.code)) {
|
||||
context.read<CreateSceneBloc>().add(RemoveTempTaskByIdEvent(
|
||||
code: element.code!, isAutomation: true));
|
||||
context.read<CreateSceneBloc>().add(RemoveFromSelectedValueById(
|
||||
code: element.code!, isAutomation: true));
|
||||
}
|
||||
}
|
||||
final selectedValue =
|
||||
context.read<CreateSceneBloc>().selectedValues;
|
||||
for (var element in device.functions) {
|
||||
@@ -83,136 +98,180 @@ class DeviceFunctionsView extends StatelessWidget
|
||||
),
|
||||
leadingWidth: 80,
|
||||
padding: EdgeInsets.zero,
|
||||
child: Padding(
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: functions.length,
|
||||
padding: const EdgeInsets.only(top: 24.0),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: functions.length,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return DefaultContainer(
|
||||
padding: index == 0
|
||||
? const EdgeInsets.only(top: 8)
|
||||
: index == functions.length - 1
|
||||
? const EdgeInsets.only(bottom: 8)
|
||||
: EdgeInsets.zero,
|
||||
margin: EdgeInsets.zero,
|
||||
borderRadius: index == 0
|
||||
? const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20))
|
||||
: index == functions.length - 1
|
||||
? const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(20),
|
||||
bottomRight: Radius.circular(20))
|
||||
: BorderRadius.zero,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||
builder: (context, state) {
|
||||
return SceneListTile(
|
||||
iconsSize: 22,
|
||||
minLeadingWidth: 20,
|
||||
assetPath: functions[index].icon,
|
||||
titleString: functions[index].operationName,
|
||||
trailingWidget: const Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
/// selected value or the default value
|
||||
// BodyMedium(text: ),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 16,
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
final functionValues = context
|
||||
.read<CreateSceneBloc>()
|
||||
.selectedValues[functions[index].code];
|
||||
|
||||
context.customAlertDialog(
|
||||
alertBody: functions[index].code == 'temp_set'
|
||||
? AlertDialogTemperatureBody(
|
||||
taskItem: functions[index],
|
||||
functionValue: functionValues,
|
||||
)
|
||||
: (functions[index]
|
||||
.code
|
||||
.contains('countdown') ||
|
||||
functions[index]
|
||||
.code
|
||||
.contains('presence_time'))
|
||||
? AlertDialogCountdown(
|
||||
durationValue: functions[index]
|
||||
.operationalValues
|
||||
.first
|
||||
.value,
|
||||
function: functions[index],
|
||||
functionValue: functionValues,
|
||||
)
|
||||
: AlertDialogFunctionsOperationsBody(
|
||||
taskItem: functions[index],
|
||||
functionValue: functionValues,
|
||||
),
|
||||
title: functions[index].operationName,
|
||||
onConfirm: () {
|
||||
final selectedValue = context
|
||||
.read<CreateSceneBloc>()
|
||||
.selectedValues[functions[index].code];
|
||||
if (selectedValue == null) {
|
||||
return;
|
||||
}
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(TempHoldSceneTasksEvent(
|
||||
deviceControlModel: DeviceControlModel(
|
||||
deviceId: device.uuid,
|
||||
code: functions[index].code,
|
||||
value: selectedValue,
|
||||
),
|
||||
deviceId: device.uuid ?? '',
|
||||
operation: functions[index].operationName,
|
||||
icon: device.icon ?? '',
|
||||
deviceName: device.name ?? '',
|
||||
uniqueId: functions[index].uniqueCustomId,
|
||||
));
|
||||
Navigator.pop(context);
|
||||
},
|
||||
onDismiss: () {
|
||||
final tempTaskList = context
|
||||
.read<CreateSceneBloc>()
|
||||
.tempTasksList;
|
||||
for (var element in tempTaskList) {
|
||||
if (element.code == functions[index].code) {
|
||||
context.read<CreateSceneBloc>().add(
|
||||
RemoveTempTaskByIdEvent(
|
||||
code: functions[index].code));
|
||||
context.read<CreateSceneBloc>().add(
|
||||
RemoveFromSelectedValueById(
|
||||
code: functions[index].code));
|
||||
}
|
||||
}
|
||||
Navigator.pop(context);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
return DefaultContainer(
|
||||
padding: index == 0
|
||||
? const EdgeInsets.only(top: 8)
|
||||
: index == functions.length - 1
|
||||
? const EdgeInsets.only(bottom: 8)
|
||||
: EdgeInsets.zero,
|
||||
margin: EdgeInsets.zero,
|
||||
borderRadius: index == 0
|
||||
? const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20))
|
||||
: index == functions.length - 1
|
||||
? const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(20),
|
||||
bottomRight: Radius.circular(20))
|
||||
: BorderRadius.zero,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||
builder: (context, state) {
|
||||
return SceneListTile(
|
||||
iconsSize: 22,
|
||||
minLeadingWidth: 20,
|
||||
assetPath: functions[index].icon,
|
||||
titleString: functions[index].operationName,
|
||||
trailingWidget: const Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
/// selected value or the default value
|
||||
// BodyMedium(text: ),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 16,
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
if (isAutomation) {
|
||||
_showAutomationDialog(
|
||||
context,
|
||||
functions[index],
|
||||
device,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
index != functions.length - 1
|
||||
? SizedBox(
|
||||
width: context.width * 0.8,
|
||||
child: const LightDivider())
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
} else {
|
||||
_showTabToRunDialog(
|
||||
context,
|
||||
functions[index],
|
||||
device,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
index != functions.length - 1
|
||||
? SizedBox(
|
||||
width: context.width * 0.8,
|
||||
child: const LightDivider())
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
void _showTabToRunDialog(
|
||||
BuildContext context,
|
||||
SceneStaticFunction function,
|
||||
DeviceModel device,
|
||||
) {
|
||||
final functionValues =
|
||||
context.read<CreateSceneBloc>().selectedValues[function.code];
|
||||
|
||||
context.customAlertDialog(
|
||||
alertBody: getTheCorrectDialogBody(
|
||||
function,
|
||||
functionValues,
|
||||
isAutomation: false,
|
||||
),
|
||||
title: function.operationName,
|
||||
onConfirm: () {
|
||||
final selectedValue =
|
||||
context.read<CreateSceneBloc>().selectedValues[function.code];
|
||||
if (selectedValue == null) {
|
||||
return;
|
||||
}
|
||||
context.read<CreateSceneBloc>().add(TempHoldSceneTasksEvent(
|
||||
deviceControlModel: DeviceControlModel(
|
||||
deviceId: device.uuid,
|
||||
code: function.code,
|
||||
value: selectedValue,
|
||||
),
|
||||
deviceId: device.uuid ?? '',
|
||||
operation: function.operationName,
|
||||
icon: device.icon ?? '',
|
||||
deviceName: device.name ?? '',
|
||||
uniqueId: function.uniqueCustomId,
|
||||
operationType: function.operationDialogType,
|
||||
));
|
||||
Navigator.pop(context);
|
||||
},
|
||||
onDismiss: () {
|
||||
final tempTaskList = context.read<CreateSceneBloc>().tempTasksList;
|
||||
for (var element in tempTaskList) {
|
||||
if (element.code == function.code) {
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(RemoveTempTaskByIdEvent(code: function.code));
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(RemoveFromSelectedValueById(code: function.code));
|
||||
}
|
||||
}
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _showAutomationDialog(
|
||||
BuildContext context, SceneStaticFunction function, DeviceModel device) {
|
||||
final automationFunctionValues =
|
||||
context.read<CreateSceneBloc>().automationSelectedValues[function.code];
|
||||
|
||||
context.customAlertDialog(
|
||||
alertBody: getTheCorrectDialogBody(
|
||||
function,
|
||||
automationFunctionValues,
|
||||
isAutomation: true,
|
||||
),
|
||||
title: function.operationName,
|
||||
onConfirm: () {
|
||||
final automationFunctionValues = context
|
||||
.read<CreateSceneBloc>()
|
||||
.automationSelectedValues[function.code];
|
||||
if (automationFunctionValues == null) {
|
||||
return;
|
||||
}
|
||||
context.read<CreateSceneBloc>().add(TempHoldSceneTasksEvent(
|
||||
deviceControlModel: DeviceControlModel(
|
||||
deviceId: device.uuid,
|
||||
code: function.code,
|
||||
value: automationFunctionValues,
|
||||
),
|
||||
deviceId: device.uuid ?? '',
|
||||
operation: function.operationName,
|
||||
icon: device.icon ?? '',
|
||||
deviceName: device.name ?? '',
|
||||
uniqueId: function.uniqueCustomId,
|
||||
operationType: function.operationDialogType,
|
||||
isAutomation: true,
|
||||
));
|
||||
Navigator.pop(context);
|
||||
},
|
||||
onDismiss: () {
|
||||
final automationTempTaskList =
|
||||
context.read<CreateSceneBloc>().automationTempTasksList;
|
||||
for (var element in automationTempTaskList) {
|
||||
if (element.code == function.code) {
|
||||
context.read<CreateSceneBloc>().add(RemoveTempTaskByIdEvent(
|
||||
code: function.code, isAutomation: true));
|
||||
context.read<CreateSceneBloc>().add(RemoveFromSelectedValueById(
|
||||
code: function.code, isAutomation: true));
|
||||
}
|
||||
}
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class SceneAutoSettings extends StatelessWidget {
|
||||
const SceneAutoSettings({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final sceneSettings =
|
||||
ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>? ??
|
||||
{};
|
||||
final sceneId = sceneSettings['sceneId'] as String? ?? '';
|
||||
final isAutomation = sceneSettings['isAutomation'] as bool? ?? false;
|
||||
final sceneName = sceneSettings['sceneName'] as String? ?? '';
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: ColorsManager.backgroundColor,
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
backgroundColor: ColorsManager.backgroundColor,
|
||||
title: const BodyLarge(
|
||||
text: "Settings",
|
||||
fontColor: ColorsManager.secondaryColor,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
),
|
||||
body: DefaultContainer(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: isAutomation == true,
|
||||
child: SceneListTile(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
titleString: "Effective Period",
|
||||
trailingWidget: const Icon(Icons.arrow_forward_ios_rounded),
|
||||
onPressed: () {
|
||||
context.customBottomSheet(
|
||||
child: const EffectPeriodBottomSheetContent(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: sceneName.isNotEmpty,
|
||||
child: DeleteBottomSheetContent(
|
||||
isAutomation: isAutomation,
|
||||
sceneId: sceneId,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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/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/strings_manager.dart';
|
||||
@@ -16,10 +18,12 @@ class SceneRoomsTabBarDevicesView extends StatefulWidget {
|
||||
const SceneRoomsTabBarDevicesView({super.key});
|
||||
|
||||
@override
|
||||
State<SceneRoomsTabBarDevicesView> createState() => _SceneRoomsTabBarDevicesViewState();
|
||||
State<SceneRoomsTabBarDevicesView> createState() =>
|
||||
_SceneRoomsTabBarDevicesViewState();
|
||||
}
|
||||
|
||||
class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesView>
|
||||
class _SceneRoomsTabBarDevicesViewState
|
||||
extends State<SceneRoomsTabBarDevicesView>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final TabController _tabController;
|
||||
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);
|
||||
super.initState();
|
||||
}
|
||||
@@ -51,9 +56,8 @@ class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesVie
|
||||
final value = _tabController.index;
|
||||
|
||||
/// select tab
|
||||
context
|
||||
.read<TabBarBloc>()
|
||||
.add(TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? ''));
|
||||
context.read<TabBarBloc>().add(
|
||||
TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? ''));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -72,8 +76,7 @@ class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesVie
|
||||
padding: EdgeInsets.zero,
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(context);
|
||||
navigateToRoute(context, Routes.sceneTasksRoute);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/create_scene_save_button.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/if_then_containers/if_container.dart';
|
||||
@@ -13,6 +14,8 @@ import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/navigation/navigate_to_route.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||
@@ -24,28 +27,38 @@ class SceneTasksView extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final sceneSettings = ModalRoute.of(context)!.settings.arguments
|
||||
as SceneSettingsRouteArguments;
|
||||
|
||||
final isAutomation =
|
||||
sceneSettings.sceneType == CreateSceneEnum.deviceStatusChanges.name;
|
||||
|
||||
return DefaultScaffold(
|
||||
title: sceneSettings.sceneName.isNotEmpty
|
||||
? sceneSettings.sceneName
|
||||
: StringsManager.createScene,
|
||||
padding: EdgeInsets.zero,
|
||||
actions: [
|
||||
SizedBox(
|
||||
width: 40,
|
||||
child: GestureDetector(
|
||||
onTap: sceneSettings.sceneName.isEmpty
|
||||
? null
|
||||
: () {
|
||||
context.customBottomSheet(
|
||||
child: DeleteBottomSheetContent(
|
||||
sceneId: sceneSettings.sceneId),
|
||||
);
|
||||
Visibility(
|
||||
visible: sceneSettings.sceneType.isNotEmpty,
|
||||
child: SizedBox(
|
||||
width: 40,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
Routes.sceneAutoSettingsRoute,
|
||||
arguments: {
|
||||
"sceneId": sceneSettings.sceneId,
|
||||
"isAutomation": isAutomation,
|
||||
"sceneName": sceneSettings.sceneName,
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsIconsSettings,
|
||||
colorFilter: const ColorFilter.mode(
|
||||
ColorsManager.textPrimaryColor,
|
||||
BlendMode.srcIn,
|
||||
);
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsIconsSettings,
|
||||
colorFilter: const ColorFilter.mode(
|
||||
ColorsManager.textPrimaryColor,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -92,52 +105,52 @@ class SceneTasksView extends StatelessWidget {
|
||||
}
|
||||
|
||||
class DeleteBottomSheetContent extends StatelessWidget {
|
||||
const DeleteBottomSheetContent({super.key, required this.sceneId});
|
||||
const DeleteBottomSheetContent(
|
||||
{super.key, required this.sceneId, required this.isAutomation});
|
||||
|
||||
final String sceneId;
|
||||
final bool isAutomation;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultContainer(
|
||||
height: context.height * 0.2,
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
BlocConsumer<CreateSceneBloc, CreateSceneState>(
|
||||
listener: (context, state) {
|
||||
if (state is DeleteSceneSuccess) {
|
||||
if (state.success) {
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(context);
|
||||
BlocProvider.of<SceneBloc>(context).add(
|
||||
LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
}
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
return DefaultContainer(
|
||||
onTap: () {
|
||||
context.read<CreateSceneBloc>().add(DeleteSceneEvent(
|
||||
sceneId: sceneId,
|
||||
unitUuid:
|
||||
HomeCubit.getInstance().selectedSpace!.id!,
|
||||
));
|
||||
},
|
||||
child: SceneListTile(
|
||||
titleString: StringsManager.deleteScene,
|
||||
leadingWidget: (state is DeleteSceneLoading)
|
||||
? const SizedBox(
|
||||
height: 24,
|
||||
width: 24,
|
||||
child: CircularProgressIndicator())
|
||||
: SvgPicture.asset(
|
||||
Assets.assetsDeleteIcon,
|
||||
color: ColorsManager.red,
|
||||
),
|
||||
));
|
||||
},
|
||||
),
|
||||
],
|
||||
padding: EdgeInsets.zero,
|
||||
child: BlocConsumer<CreateSceneBloc, CreateSceneState>(
|
||||
listener: (context, state) {
|
||||
if (state is DeleteSceneSuccess) {
|
||||
if (state.success) {
|
||||
navigateToRoute(context, Routes.homeRoute);
|
||||
BlocProvider.of<SceneBloc>(context).add(
|
||||
LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
BlocProvider.of<SceneBloc>(context).add(
|
||||
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
}
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
return DefaultContainer(
|
||||
onTap: () {
|
||||
context.read<CreateSceneBloc>().add(DeleteSceneEvent(
|
||||
sceneId: sceneId,
|
||||
unitUuid: HomeCubit.getInstance().selectedSpace!.id!,
|
||||
));
|
||||
},
|
||||
child: SceneListTile(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
titleString: isAutomation
|
||||
? StringsManager.deleteAutomation
|
||||
: StringsManager.deleteScene,
|
||||
leadingWidget: (state is DeleteSceneLoading)
|
||||
? const SizedBox(
|
||||
height: 24,
|
||||
width: 24,
|
||||
child: CircularProgressIndicator())
|
||||
: SvgPicture.asset(
|
||||
Assets.assetsDeleteIcon,
|
||||
color: ColorsManager.red,
|
||||
),
|
||||
));
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ import 'package:syncrow_app/features/devices/view/widgets/scene_listview.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_view.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_header.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/create_unit.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class SceneView extends StatelessWidget {
|
||||
final bool pageType;
|
||||
@@ -19,19 +21,27 @@ class SceneView extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) => SceneBloc()
|
||||
..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '')),
|
||||
..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? ''))
|
||||
..add(LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? '')),
|
||||
child: BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||
builder: (context, state) {
|
||||
if (state is DeleteSceneSuccess) {
|
||||
if (state.success) {
|
||||
BlocProvider.of<SceneBloc>(context)
|
||||
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
BlocProvider.of<SceneBloc>(context).add(
|
||||
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
}
|
||||
}
|
||||
if (state is CreateSceneWithTasks) {
|
||||
if (state.success == true) {
|
||||
BlocProvider.of<SceneBloc>(context)
|
||||
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
BlocProvider.of<SceneBloc>(context).add(
|
||||
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(const SmartSceneClearEvent());
|
||||
}
|
||||
}
|
||||
return BlocListener<SceneBloc, SceneState>(
|
||||
@@ -63,29 +73,90 @@ class SceneView extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
if (state is SceneLoaded) {
|
||||
if (state.scenes.isNotEmpty) {
|
||||
return pageType == false
|
||||
? Expanded(
|
||||
child: SceneGrid(
|
||||
scenes: state.scenes,
|
||||
loadingSceneId: state.loadingSceneId,
|
||||
),
|
||||
)
|
||||
: Expanded(
|
||||
final scenes = state.scenes;
|
||||
final automationList = state.automationList;
|
||||
|
||||
return pageType
|
||||
? Expanded(
|
||||
child: SceneListview(
|
||||
scenes: state.scenes,
|
||||
loadingSceneId: state.loadingSceneId,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return const Expanded(
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'No scenes have been added yet',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
scenes: scenes,
|
||||
loadingSceneId: state.loadingSceneId,
|
||||
))
|
||||
: Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
Theme(
|
||||
data: ThemeData().copyWith(
|
||||
dividerColor: Colors.transparent),
|
||||
child: ExpansionTile(
|
||||
tilePadding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 6),
|
||||
initiallyExpanded: true,
|
||||
iconColor: ColorsManager.grayColor,
|
||||
title: const BodyMedium(
|
||||
text: 'Tap to run routines'),
|
||||
children: [
|
||||
scenes.isNotEmpty
|
||||
? SceneGrid(
|
||||
scenes: scenes,
|
||||
loadingSceneId:
|
||||
state.loadingSceneId,
|
||||
disablePlayButton: false,
|
||||
loadingStates: state
|
||||
.loadingStates, // Add this line
|
||||
)
|
||||
: const Center(
|
||||
child: BodyMedium(
|
||||
text:
|
||||
'No scenes have been added yet',
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Theme(
|
||||
data: ThemeData().copyWith(
|
||||
dividerColor: Colors.transparent),
|
||||
child: ExpansionTile(
|
||||
initiallyExpanded: true,
|
||||
iconColor: ColorsManager.grayColor,
|
||||
tilePadding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 6),
|
||||
title: const BodyMedium(
|
||||
text: 'Automation'),
|
||||
children: [
|
||||
automationList.isNotEmpty
|
||||
? SceneGrid(
|
||||
scenes: automationList,
|
||||
loadingSceneId:
|
||||
state.loadingSceneId,
|
||||
disablePlayButton: true,
|
||||
loadingStates: state
|
||||
.loadingStates, // Add this line
|
||||
)
|
||||
: const Center(
|
||||
child: BodyMedium(
|
||||
text:
|
||||
'No automations have been added yet',
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox();
|
||||
},
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/select_smart_scene/smart_enable_autoamtion.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/select_smart_scene/smart_enable_tab_run.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/navigation/navigate_to_route.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class SmartAutomationSelectView extends StatelessWidget {
|
||||
const SmartAutomationSelectView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: "Select Smart Scene",
|
||||
padding: const EdgeInsets.only(top: 24),
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
navigateToRoute(context, Routes.sceneTasksRoute);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
)),
|
||||
height: 260,
|
||||
child: DefaultContainer(
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SceneListTile(
|
||||
assetPath: Assets.handClickIcon,
|
||||
titleString: "Tap To Run",
|
||||
subtitleString: '',
|
||||
trailingWidget: const Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
onPressed: () {
|
||||
context.customBottomSheet(
|
||||
child: const SmartEnableTabRun(),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.dividerColor,
|
||||
),
|
||||
SceneListTile(
|
||||
assetPath: Assets.refreshIcon,
|
||||
titleString: "Automation",
|
||||
subtitleString: '',
|
||||
trailingWidget: const Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
onPressed: () {
|
||||
context.customBottomSheet(
|
||||
child: const SmartEnableAutomation(),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ class _AlertDialogCountdownState extends State<AlertDialogCountdown> {
|
||||
@override
|
||||
didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
final tempTaskList = context.read<CreateSceneBloc>().tempTasksList;
|
||||
|
||||
for (var element in tempTaskList) {
|
||||
|
||||
@@ -11,10 +11,12 @@ class AlertDialogFunctionsOperationsBody extends StatefulWidget {
|
||||
super.key,
|
||||
this.functionValue,
|
||||
required this.taskItem,
|
||||
required this.isAutomation,
|
||||
});
|
||||
|
||||
dynamic functionValue;
|
||||
final SceneStaticFunction taskItem;
|
||||
final bool isAutomation;
|
||||
|
||||
@override
|
||||
State<AlertDialogFunctionsOperationsBody> createState() =>
|
||||
@@ -26,24 +28,46 @@ class _AlertDialogFunctionsOperationsBodyState
|
||||
@override
|
||||
didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final tempTaskList = context.read<CreateSceneBloc>().tempTasksList;
|
||||
if (widget.isAutomation) {
|
||||
final automationTempTasksList =
|
||||
context.read<CreateSceneBloc>().automationTempTasksList;
|
||||
|
||||
if (tempTaskList.isNotEmpty) {
|
||||
for (var element in tempTaskList) {
|
||||
if (element.code == widget.taskItem.code) {
|
||||
groupValue = element.functionValue;
|
||||
} else {
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(RemoveFromSelectedValueById(code: widget.taskItem.code));
|
||||
if (automationTempTasksList.isNotEmpty) {
|
||||
for (var element in automationTempTasksList) {
|
||||
if (element.code == widget.taskItem.code) {
|
||||
groupValue = element.functionValue;
|
||||
} else {
|
||||
context.read<CreateSceneBloc>().add(RemoveFromSelectedValueById(
|
||||
code: widget.taskItem.code, isAutomation: widget.isAutomation));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (widget.functionValue != null) {
|
||||
setState(() {
|
||||
groupValue = widget.functionValue;
|
||||
});
|
||||
if (widget.functionValue != null) {
|
||||
setState(() {
|
||||
groupValue = widget.functionValue;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
final tempTaskList = context.read<CreateSceneBloc>().tempTasksList;
|
||||
|
||||
if (tempTaskList.isNotEmpty) {
|
||||
for (var element in tempTaskList) {
|
||||
if (element.code == widget.taskItem.code) {
|
||||
groupValue = element.functionValue;
|
||||
} else {
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(RemoveFromSelectedValueById(code: widget.taskItem.code));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (widget.functionValue != null) {
|
||||
setState(() {
|
||||
groupValue = widget.functionValue;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +100,9 @@ class _AlertDialogFunctionsOperationsBodyState
|
||||
groupValue = value;
|
||||
});
|
||||
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
||||
value: value!, code: widget.taskItem.code));
|
||||
value: value!,
|
||||
code: widget.taskItem.code,
|
||||
isAutomation: widget.isAutomation));
|
||||
},
|
||||
),
|
||||
onPressed: () {
|
||||
@@ -84,7 +110,9 @@ class _AlertDialogFunctionsOperationsBodyState
|
||||
groupValue = operation.value;
|
||||
});
|
||||
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
||||
value: groupValue, code: widget.taskItem.code));
|
||||
value: groupValue,
|
||||
code: widget.taskItem.code,
|
||||
isAutomation: widget.isAutomation));
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class AlertDialogSliderSteps extends StatefulWidget {
|
||||
const AlertDialogSliderSteps({
|
||||
super.key,
|
||||
this.functionValue,
|
||||
required this.taskItem,
|
||||
required this.isAutomation,
|
||||
});
|
||||
|
||||
final dynamic functionValue;
|
||||
final SceneStaticFunction taskItem;
|
||||
final bool isAutomation;
|
||||
|
||||
@override
|
||||
State<AlertDialogSliderSteps> createState() => _AlertDialogSliderStepsState();
|
||||
}
|
||||
|
||||
class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
||||
double? groupValue;
|
||||
int selectedToggleIndex = 1;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final createSceneBloc = context.read<CreateSceneBloc>();
|
||||
|
||||
if (widget.isAutomation) {
|
||||
final automationTempTaskList = createSceneBloc.automationTempTasksList;
|
||||
final automationComparatorValues =
|
||||
createSceneBloc.automationComparatorValues;
|
||||
|
||||
for (var element in automationTempTaskList) {
|
||||
if (element.code == widget.taskItem.code) {
|
||||
groupValue = element.functionValue;
|
||||
selectedToggleIndex =
|
||||
_comparatorToIndex(automationComparatorValues[element.code]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (widget.functionValue != null) {
|
||||
groupValue = _normalizeValue(widget.functionValue);
|
||||
} else {
|
||||
groupValue =
|
||||
_normalizeValue(widget.taskItem.operationalValues[0].minValue);
|
||||
}
|
||||
|
||||
if (widget.taskItem.comparator != null) {
|
||||
selectedToggleIndex = _comparatorToIndex(widget.taskItem.comparator);
|
||||
}
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
double _normalizeValue(dynamic value) {
|
||||
if (((widget.taskItem.code == "temp_set" && value > 200) ||
|
||||
widget.taskItem.code == "temp_current")) {
|
||||
return (value) / 10;
|
||||
}
|
||||
return value.toDouble();
|
||||
}
|
||||
|
||||
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 "==";
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ToggleButtons(
|
||||
isSelected: [
|
||||
selectedToggleIndex == 0,
|
||||
selectedToggleIndex == 1,
|
||||
selectedToggleIndex == 2
|
||||
],
|
||||
onPressed: (index) {
|
||||
setState(() {
|
||||
selectedToggleIndex = index;
|
||||
});
|
||||
context.read<CreateSceneBloc>().add(
|
||||
SelectedValueEvent(
|
||||
value: _deNormalizeValue(groupValue),
|
||||
code: widget.taskItem.code,
|
||||
isAutomation: widget.isAutomation,
|
||||
comparator: _indexToComparator(selectedToggleIndex),
|
||||
),
|
||||
);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
selectedColor: Colors.white,
|
||||
color: ColorsManager.blackColor,
|
||||
fillColor: ColorsManager.primaryColorWithOpacity,
|
||||
borderColor: ColorsManager.greyColor,
|
||||
constraints: BoxConstraints.tight(const Size(70, 30)),
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 70,
|
||||
height: 30,
|
||||
child: Container(
|
||||
color: selectedToggleIndex == 0
|
||||
? ColorsManager.primaryColorWithOpacity
|
||||
: ColorsManager.greyColor,
|
||||
alignment: Alignment.center,
|
||||
child: const Text("<"),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 70,
|
||||
height: 30,
|
||||
child: Container(
|
||||
color: selectedToggleIndex == 1
|
||||
? ColorsManager.primaryColorWithOpacity
|
||||
: ColorsManager.greyColor,
|
||||
alignment: Alignment.center,
|
||||
child: const Text("="),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 70,
|
||||
height: 30,
|
||||
child: Container(
|
||||
color: selectedToggleIndex == 2
|
||||
? ColorsManager.primaryColorWithOpacity
|
||||
: ColorsManager.greyColor,
|
||||
alignment: Alignment.center,
|
||||
child: const Text(">"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
...widget.taskItem.operationalValues.map(
|
||||
(operation) => BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
TitleMedium(
|
||||
text: groupValue != null
|
||||
? (groupValue! % 1 == 0
|
||||
? groupValue!.toStringAsFixed(0)
|
||||
: groupValue!.toStringAsFixed(1))
|
||||
: "0",
|
||||
style: context.titleMedium.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
fontSize: 30,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
TitleMedium(
|
||||
text: operation.description.toString(),
|
||||
style: context.titleMedium.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
fontSize: 30,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Slider(
|
||||
value: groupValue ?? 0,
|
||||
min: operation.minValue ?? 0,
|
||||
max: operation.maxValue ?? 0,
|
||||
inactiveColor: ColorsManager.primaryColorWithOpacity
|
||||
.withOpacity(0.2),
|
||||
divisions: operation.stepValue != null
|
||||
? ((operation.maxValue!.toDouble() -
|
||||
operation.minValue!.toDouble()) /
|
||||
operation.stepValue!.toDouble())
|
||||
.round()
|
||||
: null,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
groupValue = normalizeValue(value);
|
||||
});
|
||||
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
||||
value: _deNormalizeValue(groupValue),
|
||||
code: widget.taskItem.code,
|
||||
isAutomation: widget.isAutomation,
|
||||
comparator:
|
||||
_indexToComparator(selectedToggleIndex)));
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
double normalizeValue(double value) {
|
||||
return double.parse(value.toStringAsFixed(1));
|
||||
}
|
||||
|
||||
double _deNormalizeValue(double? value) {
|
||||
if (widget.taskItem.code == "temp_set" ||
|
||||
widget.taskItem.code == "temp_current") {
|
||||
return (value ?? 0) * 10;
|
||||
}
|
||||
return value ?? 0;
|
||||
}
|
||||
}
|
||||
@@ -14,14 +14,10 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
class AlertDialogTemperatureBody extends StatefulWidget {
|
||||
AlertDialogTemperatureBody({
|
||||
super.key,
|
||||
//required this.index,
|
||||
// required this.functions,
|
||||
this.functionValue,
|
||||
required this.taskItem,
|
||||
});
|
||||
|
||||
//final List<SceneStaticFunction> functions;
|
||||
// final int index;
|
||||
final SceneStaticFunction taskItem;
|
||||
dynamic functionValue;
|
||||
|
||||
@@ -32,14 +28,16 @@ class AlertDialogTemperatureBody extends StatefulWidget {
|
||||
|
||||
class _AlertDialogTemperatureBodyState
|
||||
extends State<AlertDialogTemperatureBody> {
|
||||
int temperature = 24;
|
||||
|
||||
@override
|
||||
didChangeDependencies() {
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final tempTaskList = context.read<CreateSceneBloc>().tempTasksList;
|
||||
|
||||
for (var element in tempTaskList) {
|
||||
if (element.code == widget.taskItem.code) {
|
||||
temperature = element.functionValue;
|
||||
temperature = _normalizeTemperature(element.functionValue);
|
||||
} else {
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
@@ -48,12 +46,18 @@ class _AlertDialogTemperatureBodyState
|
||||
}
|
||||
if (widget.functionValue != null) {
|
||||
setState(() {
|
||||
temperature = widget.functionValue;
|
||||
temperature = _normalizeTemperature(widget.functionValue);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
int temperature = 24;
|
||||
int _normalizeTemperature(dynamic value) {
|
||||
if (value is int && value >= 100) {
|
||||
return value ~/ 10;
|
||||
}
|
||||
return value as int? ?? 24;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
@@ -98,8 +102,7 @@ class _AlertDialogTemperatureBodyState
|
||||
],
|
||||
),
|
||||
subtitle: BodyLarge(
|
||||
text: widget.taskItem.operationalValues[0].description
|
||||
.toString(),
|
||||
text: widget.taskItem.operationalValues[0].description.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
trailing: IconButton(
|
||||
@@ -110,8 +113,7 @@ class _AlertDialogTemperatureBodyState
|
||||
}
|
||||
});
|
||||
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
||||
value: temperature * 10,
|
||||
code: widget.taskItem.code));
|
||||
value: temperature * 10, code: widget.taskItem.code));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.add,
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.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/scene_list_tile.dart';
|
||||
@@ -66,7 +67,9 @@ class CustomBottomSheetWidget extends StatelessWidget {
|
||||
size: 16,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, Routes.smartAutomationSelectRoute);
|
||||
},
|
||||
),
|
||||
SceneListTile(
|
||||
assetPath: Assets.delay,
|
||||
@@ -97,6 +100,7 @@ class CustomBottomSheetWidget extends StatelessWidget {
|
||||
operationName: 'Delay The Action',
|
||||
code: '',
|
||||
functionValue: 0,
|
||||
operationDialogType: OperationDialogType.delay,
|
||||
operationalValues: [
|
||||
SceneOperationalValue(icon: '', value: 0),
|
||||
],
|
||||
@@ -123,8 +127,9 @@ class CustomBottomSheetWidget extends StatelessWidget {
|
||||
icon: Assets.delay,
|
||||
deviceName: 'Delay The Action',
|
||||
uniqueId: functions[0].uniqueCustomId,
|
||||
operationType: functions[0].operationDialogType,
|
||||
));
|
||||
context.read<CreateSceneBloc>().add(AddTaskEvent());
|
||||
context.read<CreateSceneBloc>().add(const AddTaskEvent());
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||
import 'package:syncrow_app/features/scene/helper/scene_logic_helper.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/navigation/navigate_to_route.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
@@ -43,8 +46,7 @@ class _CreateSceneSaveButtonState extends State<CreateSceneSaveButton>
|
||||
listener: (context, state) {
|
||||
if (state is CreateSceneWithTasks) {
|
||||
if (state.success == true) {
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(context);
|
||||
navigateToRoute(context, Routes.homeRoute);
|
||||
context.showCustomSnackbar(
|
||||
message: 'Scene created successfully',
|
||||
icon: const Icon(
|
||||
@@ -66,55 +68,59 @@ class _CreateSceneSaveButtonState extends State<CreateSceneSaveButton>
|
||||
},
|
||||
builder: (context, state) {
|
||||
return DefaultButton(
|
||||
onPressed: widget.sceneName.isNotEmpty
|
||||
? () {
|
||||
final tasks = context.read<CreateSceneBloc>().tasksList;
|
||||
handleSaveButtonPress(
|
||||
context,
|
||||
sceneNameController,
|
||||
tasks,
|
||||
updateScene: true,
|
||||
sceneId: widget.sceneId,
|
||||
);
|
||||
}
|
||||
: () {
|
||||
context.customAlertDialog(
|
||||
alertBody: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: SearchBar(
|
||||
controller: sceneNameController,
|
||||
elevation: WidgetStateProperty.all(0),
|
||||
textStyle:
|
||||
WidgetStateProperty.all(context.bodyMedium),
|
||||
hintStyle: WidgetStateProperty.all(
|
||||
context.bodyMedium.copyWith(
|
||||
fontSize: 14,
|
||||
color: ColorsManager.secondaryTextColor),
|
||||
),
|
||||
hintText: 'Enter scene name',
|
||||
backgroundColor: WidgetStateProperty.all(
|
||||
ColorsManager.backgroundColor),
|
||||
),
|
||||
onPressed: () {
|
||||
final sceneBloc = context.read<CreateSceneBloc>();
|
||||
final isAutomation =
|
||||
sceneBloc.sceneType == CreateSceneEnum.deviceStatusChanges;
|
||||
|
||||
if (widget.sceneName.isNotEmpty) {
|
||||
handleSaveButtonPress(
|
||||
context,
|
||||
sceneName: sceneNameController,
|
||||
actions: sceneBloc.tasksList,
|
||||
updateScene: true,
|
||||
sceneId: widget.sceneId,
|
||||
isAutomation: isAutomation,
|
||||
conditions: sceneBloc.automationTasksList,
|
||||
);
|
||||
} else {
|
||||
context.customAlertDialog(
|
||||
alertBody: Padding(
|
||||
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: SearchBar(
|
||||
controller: sceneNameController,
|
||||
elevation: WidgetStateProperty.all(0),
|
||||
textStyle: WidgetStateProperty.all(context.bodyMedium),
|
||||
hintStyle: WidgetStateProperty.all(
|
||||
context.bodyMedium.copyWith(
|
||||
fontSize: 14,
|
||||
color: ColorsManager.secondaryTextColor),
|
||||
),
|
||||
hintText: 'Enter scene name',
|
||||
backgroundColor: WidgetStateProperty.all(
|
||||
ColorsManager.backgroundColor),
|
||||
),
|
||||
title: 'Scene Name',
|
||||
onConfirm: () {
|
||||
if (sceneNameController.text.isNotEmpty) {
|
||||
final tasks = context.read<CreateSceneBloc>().tasksList;
|
||||
handleSaveButtonPress(
|
||||
context,
|
||||
sceneNameController,
|
||||
tasks,
|
||||
updateScene: false,
|
||||
sceneId: widget.sceneId,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
),
|
||||
),
|
||||
title: 'Scene Name',
|
||||
onConfirm: () {
|
||||
if (sceneNameController.text.isNotEmpty) {
|
||||
handleSaveButtonPress(
|
||||
context,
|
||||
sceneName: sceneNameController,
|
||||
actions: sceneBloc.tasksList,
|
||||
updateScene: false,
|
||||
sceneId: widget.sceneId,
|
||||
isAutomation: isAutomation,
|
||||
conditions: sceneBloc.automationTasksList,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
customButtonStyle: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all<Color>(
|
||||
ColorsManager.primaryColor,
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/effective_period_setting/period_options.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/effective_period_setting/repeat_days.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
import '../../helper/effect_period_helper.dart';
|
||||
|
||||
class EffectPeriodBottomSheetContent extends StatelessWidget {
|
||||
const EffectPeriodBottomSheetContent({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: BodySmall(
|
||||
text: 'Save',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity),
|
||||
)),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: BodyMedium(
|
||||
text: 'Effective Period',
|
||||
fontColor: ColorsManager.primaryColorWithOpacity,
|
||||
fontWeight: FontsManager.bold,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.backgroundColor,
|
||||
),
|
||||
const PeriodOptions(
|
||||
showCustomTimePicker: EffectPeriodHelper.showCustomTimePicker,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const RepeatDays(),
|
||||
const SizedBox(height: 24),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/effective_period_options.dart';
|
||||
import 'package:syncrow_app/features/scene/helper/effect_period_helper.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.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';
|
||||
|
||||
class PeriodOptions extends StatelessWidget {
|
||||
final Future<List<String>?> Function(BuildContext) showCustomTimePicker;
|
||||
|
||||
const PeriodOptions({
|
||||
required this.showCustomTimePicker,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
children: [
|
||||
_buildRadioOption(
|
||||
context, EnumEffectivePeriodOptions.allDay, '24 Hours'),
|
||||
_buildRadioOption(context, EnumEffectivePeriodOptions.daytime,
|
||||
'Sunrise to Sunset'),
|
||||
_buildRadioOption(
|
||||
context, EnumEffectivePeriodOptions.night, 'Sunset to Sunrise'),
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
onTap: () => showCustomTimePicker(context),
|
||||
title: const BodyMedium(
|
||||
text: 'Custom',
|
||||
),
|
||||
subtitle:
|
||||
state.customStartTime != null && state.customEndTime != null
|
||||
? BodySmall(
|
||||
text:
|
||||
'${"${state.customStartTime} AM"} - ${"${state.customEndTime} PM"}',
|
||||
style: context.bodySmall.copyWith(fontSize: 10),
|
||||
)
|
||||
: BodySmall(
|
||||
text: '00:00 AM - 11:59 PM',
|
||||
style: context.bodySmall.copyWith(fontSize: 10),
|
||||
),
|
||||
trailing: Radio<EnumEffectivePeriodOptions>(
|
||||
value: EnumEffectivePeriodOptions.custom,
|
||||
groupValue: state.selectedPeriod,
|
||||
onChanged: (value) async {
|
||||
if (value != null) {
|
||||
context.read<EffectPeriodBloc>().add(SetPeriod(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRadioOption(
|
||||
BuildContext context, EnumEffectivePeriodOptions value, String subtitle) {
|
||||
return BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
||||
builder: (context, state) {
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
onTap: () {
|
||||
context.read<EffectPeriodBloc>().add(SetPeriod(value));
|
||||
},
|
||||
title: BodyMedium(text: EffectPeriodHelper.formatEnumValue(value)),
|
||||
subtitle: BodySmall(
|
||||
text: subtitle,
|
||||
style: context.bodySmall.copyWith(fontSize: 10),
|
||||
),
|
||||
trailing: Radio<EnumEffectivePeriodOptions>(
|
||||
value: value,
|
||||
groupValue: state.selectedPeriod,
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
context.read<EffectPeriodBloc>().add(SetPeriod(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
|
||||
class RepeatDays extends StatelessWidget {
|
||||
const RepeatDays({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final daysMap = {
|
||||
'Mon': 'M',
|
||||
'Tue': 'T',
|
||||
'Wed': 'W',
|
||||
'Thu': 'T',
|
||||
'Fri': 'F',
|
||||
'Sat': 'S',
|
||||
'Sun': 'S',
|
||||
};
|
||||
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const BodyMedium(text: 'Repeat'),
|
||||
const SizedBox(width: 8),
|
||||
BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
||||
builder: (context, state) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: daysMap.entries.map((entry) {
|
||||
final day = entry.key;
|
||||
final abbreviation = entry.value;
|
||||
final dayIndex = _getDayIndex(day);
|
||||
final isSelected = state.selectedDaysBinary[dayIndex] == '1';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<EffectPeriodBloc>().add(ToggleDay(day));
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color:
|
||||
isSelected ? Colors.grey : Colors.grey.shade300,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: CircleAvatar(
|
||||
radius: 15,
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
abbreviation,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isSelected ? Colors.grey : Colors.grey.shade300,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
int _getDayIndex(String day) {
|
||||
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
|
||||
return days.indexOf(day);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,22 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/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/widgets/if_then_containers/then_added_tasks.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/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_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/navigation/routing_constants.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/strings_manager.dart';
|
||||
|
||||
@@ -16,32 +27,173 @@ class IFDefaultContainer extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final sceneType = context.read<CreateSceneBloc>().sceneType;
|
||||
return DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SceneListTile(
|
||||
leadingWidget: BodyLarge(
|
||||
text: 'IF',
|
||||
style: context.bodyLarge.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: ColorsManager.primaryTextColor,
|
||||
leadingWidget: InkWell(
|
||||
onTap: () {
|
||||
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',
|
||||
style: context.bodyLarge.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: ColorsManager.primaryTextColor,
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: sceneType.name ==
|
||||
CreateSceneEnum.deviceStatusChanges.name,
|
||||
child: BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||
builder: (context, state) {
|
||||
String conditionText = "When any condition is met";
|
||||
if (state is AddSceneTask) {
|
||||
if (state.condition == 'or') {
|
||||
conditionText = "When any condition is met";
|
||||
} else {
|
||||
conditionText = "When all conditions are met";
|
||||
}
|
||||
}
|
||||
return SizedBox(
|
||||
width: context.width * 0.6,
|
||||
child: Row(children: [
|
||||
BodySmall(text: conditionText),
|
||||
const Icon(Icons.keyboard_arrow_down)
|
||||
]),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
trailingWidget: SvgPicture.asset(Assets.addIcon),
|
||||
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,
|
||||
Routes.sceneControlDevicesRoute,
|
||||
arguments: SceneSettingsRouteArguments(
|
||||
sceneType:
|
||||
CreateSceneEnum.deviceStatusChanges.name,
|
||||
sceneId: '',
|
||||
sceneName: '',
|
||||
),
|
||||
)
|
||||
: null,
|
||||
child: SvgPicture.asset(
|
||||
Assets.addIcon,
|
||||
colorFilter: ColorFilter.mode(
|
||||
isClickable
|
||||
? ColorsManager.primaryColor
|
||||
: ColorsManager.greyColor,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
const LightDivider(),
|
||||
const SceneListTile(
|
||||
assetPath: Assets.handClickIcon,
|
||||
titleString: StringsManager.tapToRun,
|
||||
padding: EdgeInsets.zero,
|
||||
BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||
builder: (context, state) {
|
||||
if (state is AddSceneTask) {
|
||||
final automationTasksList = state.automationTasksList;
|
||||
if (automationTasksList?.isNotEmpty == true) {
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: automationTasksList?.length,
|
||||
reverse: true,
|
||||
itemBuilder: (context, index) {
|
||||
return ThenAddedTasksContainer(
|
||||
taskItem: automationTasksList![index],
|
||||
isAutomation: true,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
final sceneType = context.read<CreateSceneBloc>().sceneType;
|
||||
if (sceneType.name == CreateSceneEnum.tabToRun.name) {
|
||||
return const SceneListTile(
|
||||
padding: EdgeInsets.symmetric(horizontal: 2),
|
||||
assetPath: Assets.handClickIcon,
|
||||
titleString: StringsManager.tapToRun,
|
||||
subtitleString: '',
|
||||
);
|
||||
}
|
||||
return SceneListTile(
|
||||
titleString: '+ Add Condition',
|
||||
textAlign: TextAlign.center,
|
||||
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,
|
||||
Routes.sceneControlDevicesRoute,
|
||||
arguments: SceneSettingsRouteArguments(
|
||||
sceneType: CreateSceneEnum.deviceStatusChanges.name,
|
||||
sceneId: '',
|
||||
sceneName: '',
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class ThenAddedTasksContainer extends StatelessWidget
|
||||
@@ -22,17 +23,19 @@ class ThenAddedTasksContainer extends StatelessWidget
|
||||
required this.taskItem,
|
||||
this.sceneId,
|
||||
this.index,
|
||||
this.isAutomation,
|
||||
});
|
||||
|
||||
final SceneStaticFunction taskItem;
|
||||
String? sceneId;
|
||||
int? index;
|
||||
bool? isAutomation;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final createSceneBloc = context.read<CreateSceneBloc>();
|
||||
String operationValue = '';
|
||||
if (taskItem.code.contains('countdown') ||
|
||||
if ((taskItem.code.contains('countdown') && isAutomation != true) ||
|
||||
taskItem.deviceId.contains('delay')) {
|
||||
final functionValue =
|
||||
taskItem.functionValue ?? taskItem.operationalValues.first.value;
|
||||
@@ -40,7 +43,8 @@ class ThenAddedTasksContainer extends StatelessWidget
|
||||
Duration(seconds: int.tryParse(functionValue.toString()) ?? 0);
|
||||
operationValue =
|
||||
"${duration.inHours}h ${duration.inMinutes.remainder(60)}m ";
|
||||
} else if (taskItem.code.contains('temp_set')) {
|
||||
} else if (taskItem.code.contains('temp_set') ||
|
||||
taskItem.code.contains('temp_current')) {
|
||||
if (taskItem.functionValue != null || taskItem.functionValue != 0) {
|
||||
operationValue =
|
||||
'${((taskItem.functionValue / 10) as double).round().toString()}°C';
|
||||
@@ -48,8 +52,13 @@ class ThenAddedTasksContainer extends StatelessWidget
|
||||
operationValue = '0°C';
|
||||
}
|
||||
} else {
|
||||
final functionValue =
|
||||
var functionValue =
|
||||
taskItem.functionValue ?? taskItem.operationalValues.first.value;
|
||||
|
||||
if (functionValue is double) {
|
||||
functionValue = double.parse(functionValue.toStringAsFixed(1));
|
||||
}
|
||||
|
||||
operationValue = functionValue.toString();
|
||||
}
|
||||
return DefaultContainer(
|
||||
@@ -58,28 +67,49 @@ class ThenAddedTasksContainer extends StatelessWidget
|
||||
|
||||
/// get the task functions
|
||||
functionOperation = List.from(getOperationsForOneFunction(
|
||||
taskItem: taskItem, deviceId: taskItem.deviceId));
|
||||
taskItem: taskItem,
|
||||
deviceId: taskItem.deviceId,
|
||||
isAutomation: isAutomation ?? false));
|
||||
|
||||
/// show alert dialog based on type
|
||||
context.customAlertDialog(
|
||||
alertBody: getTheCorrectDialogBody(functionOperation.first),
|
||||
alertBody: getTheCorrectDialogBody(functionOperation.first, null,
|
||||
isAutomation: isAutomation ?? false),
|
||||
title: functionOperation.first.operationName,
|
||||
onConfirm: () {
|
||||
final savedCode = functionOperation.first.deviceId.contains('delay')
|
||||
? 'delay'
|
||||
: functionOperation.first.code;
|
||||
final selectedValue = createSceneBloc.selectedValues[savedCode];
|
||||
if (isAutomation == true) {
|
||||
final automationSelectedValue =
|
||||
createSceneBloc.automationSelectedValues[savedCode];
|
||||
|
||||
try {
|
||||
createSceneBloc.add(
|
||||
UpdateTaskEvent(
|
||||
newValue: selectedValue,
|
||||
taskId: taskItem.uniqueCustomId,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Error adding UpdateTaskEvent: $e');
|
||||
try {
|
||||
createSceneBloc.add(
|
||||
UpdateTaskEvent(
|
||||
newValue: automationSelectedValue,
|
||||
taskId: taskItem.uniqueCustomId,
|
||||
isAutomation: true,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Error adding UpdateTaskEvent: $e');
|
||||
}
|
||||
} else {
|
||||
final selectedValue = createSceneBloc.selectedValues[savedCode];
|
||||
|
||||
try {
|
||||
createSceneBloc.add(
|
||||
UpdateTaskEvent(
|
||||
newValue: selectedValue,
|
||||
taskId: taskItem.uniqueCustomId,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Error adding UpdateTaskEvent: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
@@ -109,16 +139,21 @@ class ThenAddedTasksContainer extends StatelessWidget
|
||||
onDismissed: (direction) {
|
||||
String removeFunctionById = taskItem.uniqueCustomId;
|
||||
|
||||
context
|
||||
.read<CreateSceneBloc>()
|
||||
.add(RemoveTaskByIdEvent(taskId: removeFunctionById));
|
||||
if (isAutomation == true) {
|
||||
context.read<CreateSceneBloc>().add(RemoveTaskByIdEvent(
|
||||
taskId: removeFunctionById,
|
||||
isAutomation: true,
|
||||
));
|
||||
} else {
|
||||
context.read<CreateSceneBloc>().add(RemoveTaskByIdEvent(
|
||||
taskId: removeFunctionById,
|
||||
));
|
||||
}
|
||||
|
||||
String removeFunction =
|
||||
"${taskItem.operationName} with value ${taskItem.operationalValues.first.value}";
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('$removeFunction removed')),
|
||||
);
|
||||
CustomSnackBar.displaySnackBar('$removeFunction removed');
|
||||
},
|
||||
child: SceneListTile(
|
||||
padding: EdgeInsets.zero,
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/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/scene_list_tile.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/generated/assets.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';
|
||||
|
||||
class ThenDefaultContainer extends StatelessWidget {
|
||||
@@ -35,17 +38,29 @@ class ThenDefaultContainer extends StatelessWidget {
|
||||
color: ColorsManager.primaryTextColor,
|
||||
),
|
||||
),
|
||||
trailingWidget: GestureDetector(
|
||||
onTap: () => context.customBottomSheet(
|
||||
child: const CustomBottomSheetWidget(),
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
Assets.addIcon,
|
||||
colorFilter: const ColorFilter.mode(
|
||||
ColorsManager.primaryColor,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
trailingWidget: BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||
builder: (context, state) {
|
||||
bool isClickable = false;
|
||||
if (state is AddSceneTask) {
|
||||
isClickable = state.tasksList.isNotEmpty;
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap: isClickable
|
||||
? () => context.customBottomSheet(
|
||||
child: const CustomBottomSheetWidget(),
|
||||
)
|
||||
: null,
|
||||
child: SvgPicture.asset(
|
||||
Assets.addIcon,
|
||||
colorFilter: ColorFilter.mode(
|
||||
isClickable
|
||||
? ColorsManager.primaryColor
|
||||
: ColorsManager.greyColor,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
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(
|
||||
titleString: '+ Add Task',
|
||||
textAlign: TextAlign.center,
|
||||
onPressed: () => context.customBottomSheet(
|
||||
child: const CustomBottomSheetWidget(),
|
||||
),
|
||||
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(),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
|
||||
@@ -6,6 +6,8 @@ import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_man
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.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/widgets/scene_list_tile.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
@@ -26,6 +28,11 @@ class SceneDevicesBody extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isAutomationDeviceStatus = ((ModalRoute.of(context)
|
||||
?.settings
|
||||
.arguments as SceneSettingsRouteArguments?)
|
||||
?.sceneType ==
|
||||
CreateSceneEnum.deviceStatusChanges.name);
|
||||
return BlocBuilder<TabBarBloc, TabBarState>(
|
||||
builder: (context, tabState) {
|
||||
return Column(
|
||||
@@ -56,7 +63,10 @@ class SceneDevicesBody extends StatelessWidget {
|
||||
child: TabBarView(
|
||||
controller: _tabController,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: rooms!.map((e) => _buildRoomTab(e, context)).toList(),
|
||||
children: rooms!
|
||||
.map((e) =>
|
||||
_buildRoomTab(e, context, isAutomationDeviceStatus))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -65,7 +75,8 @@ class SceneDevicesBody extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRoomTab(RoomModel room, BuildContext context) {
|
||||
Widget _buildRoomTab(
|
||||
RoomModel room, BuildContext context, bool isAutomationDeviceStatus) {
|
||||
return BlocBuilder<DeviceManagerBloc, DeviceManagerState>(
|
||||
builder: (context, state) {
|
||||
if (state.loading && state.devices == null) {
|
||||
@@ -96,7 +107,10 @@ class SceneDevicesBody extends StatelessWidget {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
Routes.deviceFunctionsRoute,
|
||||
arguments: device,
|
||||
arguments: {
|
||||
"device": device,
|
||||
"isAutomationDeviceStatus": isAutomationDeviceStatus
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_item.dart';
|
||||
|
||||
class SceneGrid extends StatelessWidget {
|
||||
final List<ScenesModel> scenes;
|
||||
final List<dynamic> scenes;
|
||||
final String? loadingSceneId;
|
||||
final bool disablePlayButton;
|
||||
final Map<String, bool> loadingStates;
|
||||
|
||||
const SceneGrid({
|
||||
required this.scenes,
|
||||
required this.loadingSceneId,
|
||||
required this.disablePlayButton,
|
||||
required this.loadingStates,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return
|
||||
GridView.builder(
|
||||
return GridView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 12,
|
||||
@@ -26,7 +30,14 @@ class SceneGrid extends StatelessWidget {
|
||||
itemBuilder: (context, index) {
|
||||
final scene = scenes[index];
|
||||
final isLoading = loadingSceneId == scene.id;
|
||||
return SceneItem(scene: scene, isLoading: isLoading);
|
||||
final isSwitchLoading = loadingStates[scene.id] ?? false;
|
||||
|
||||
return SceneItem(
|
||||
scene: scene,
|
||||
isLoading: isLoading,
|
||||
disablePlayButton: disablePlayButton,
|
||||
isSwitchLoading: isSwitchLoading,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
|
||||
|
||||
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||
@@ -20,10 +19,10 @@ class SceneHeader extends StatelessWidget {
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
BodySmall(
|
||||
text: StringsManager.tapToRunRoutine,
|
||||
),
|
||||
// SizedBox(height: 20),
|
||||
// BodySmall(
|
||||
// text: StringsManager.tapToRunRoutine,
|
||||
// ),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
|
||||
import 'package:syncrow_app/features/scene/model/update_automation.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
|
||||
@@ -16,11 +19,15 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
class SceneItem extends StatelessWidget {
|
||||
final ScenesModel scene;
|
||||
final bool isLoading;
|
||||
final bool isSwitchLoading;
|
||||
final bool disablePlayButton;
|
||||
|
||||
const SceneItem({
|
||||
required this.scene,
|
||||
required this.isLoading,
|
||||
super.key,
|
||||
required this.disablePlayButton,
|
||||
required this.isSwitchLoading,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -31,16 +38,28 @@ class SceneItem extends StatelessWidget {
|
||||
context,
|
||||
Routes.sceneTasksRoute,
|
||||
arguments: SceneSettingsRouteArguments(
|
||||
sceneType: CreateSceneEnum.tabToRun.name,
|
||||
sceneType: disablePlayButton == false
|
||||
? CreateSceneEnum.tabToRun.name
|
||||
: CreateSceneEnum.deviceStatusChanges.name,
|
||||
sceneId: scene.id,
|
||||
sceneName: scene.name,
|
||||
),
|
||||
);
|
||||
BlocProvider.of<CreateSceneBloc>(context)
|
||||
.add(FetchSceneTasksEvent(sceneId: scene.id));
|
||||
if (disablePlayButton == false) {
|
||||
BlocProvider.of<CreateSceneBloc>(context)
|
||||
.add(const SceneTypeEvent(CreateSceneEnum.tabToRun));
|
||||
BlocProvider.of<CreateSceneBloc>(context).add(
|
||||
FetchSceneTasksEvent(sceneId: scene.id, isAutomation: false));
|
||||
} else {
|
||||
BlocProvider.of<CreateSceneBloc>(context)
|
||||
.add(const SceneTypeEvent(CreateSceneEnum.deviceStatusChanges));
|
||||
BlocProvider.of<CreateSceneBloc>(context)
|
||||
.add(FetchSceneTasksEvent(sceneId: scene.id, isAutomation: true));
|
||||
}
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
@@ -52,23 +71,45 @@ class SceneItem extends StatelessWidget {
|
||||
Assets.assetsIconsLogo,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () {
|
||||
context
|
||||
.read<SceneBloc>()
|
||||
.add(SceneTrigger(scene.id, scene.name));
|
||||
},
|
||||
icon: isLoading
|
||||
? const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: const Icon(
|
||||
Icons.play_circle,
|
||||
size: 40,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
),
|
||||
disablePlayButton == false
|
||||
? IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () {
|
||||
context
|
||||
.read<SceneBloc>()
|
||||
.add(SceneTrigger(scene.id, scene.name));
|
||||
},
|
||||
icon: isLoading
|
||||
? const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: const Icon(
|
||||
Icons.play_circle,
|
||||
size: 40,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
)
|
||||
: isSwitchLoading
|
||||
? Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
),
|
||||
)
|
||||
: CupertinoSwitch(
|
||||
activeColor: ColorsManager.primaryColor,
|
||||
value: scene.status == 'enable' ? true : false,
|
||||
onChanged: (value) {
|
||||
context.read<SceneBloc>().add(
|
||||
UpdateAutomationStatus(
|
||||
automationStatusUpdate:
|
||||
AutomationStatusUpdate(
|
||||
isEnable: value,
|
||||
unitUuid: HomeCubit.getInstance()
|
||||
.selectedSpace!
|
||||
.id!),
|
||||
automationId: scene.id));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/smart_scene_enable.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.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/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class SmartSceneSelectAutomationList extends StatefulWidget {
|
||||
const SmartSceneSelectAutomationList({
|
||||
super.key,
|
||||
required this.automationList,
|
||||
});
|
||||
|
||||
final List<ScenesModel> automationList;
|
||||
|
||||
@override
|
||||
State<SmartSceneSelectAutomationList> createState() =>
|
||||
_SmartSceneSelectAutomationListState();
|
||||
}
|
||||
|
||||
class _SmartSceneSelectAutomationListState
|
||||
extends State<SmartSceneSelectAutomationList> {
|
||||
final List<Color> colorList = _generateDarkColors(100);
|
||||
|
||||
static List<Color> _generateDarkColors(int count) {
|
||||
final random = Random();
|
||||
final colors = <Color>[];
|
||||
|
||||
while (colors.length < count) {
|
||||
final color =
|
||||
Color((random.nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0);
|
||||
if (_isDark(color)) {
|
||||
colors.add(color);
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
static bool _isDark(Color color) {
|
||||
final brightness =
|
||||
((color.red * 299) + (color.green * 587) + (color.blue * 114)) / 1000;
|
||||
return brightness < 128;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: BodySmall(
|
||||
text: 'Save',
|
||||
style: context.bodySmall
|
||||
.copyWith(color: ColorsManager.primaryColorWithOpacity),
|
||||
)),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: BodyMedium(
|
||||
text: 'Automation',
|
||||
textAlign: TextAlign.center,
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.dividerColor,
|
||||
),
|
||||
Expanded(
|
||||
child: BlocBuilder<SmartSceneSelectBloc, SmartSceneSelectState>(
|
||||
builder: (context, state) {
|
||||
final smartSceneEnable = ((state is SmartSceneSelected))
|
||||
? state.smartSceneEnable
|
||||
: context.read<SmartSceneSelectBloc>().smartSceneEnable;
|
||||
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: widget.automationList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final automation = widget.automationList[index];
|
||||
final isSelected =
|
||||
smartSceneEnable?.entityId == automation.id;
|
||||
final descriptionSelected = isSelected
|
||||
? (smartSceneEnable?.actionExecutor == 'rule_enable'
|
||||
? 'Enable'
|
||||
: 'Disable')
|
||||
: automation.status == 'enable'
|
||||
? 'Enable'
|
||||
: 'Disable';
|
||||
|
||||
return SceneListTile(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
leadingWidget: CircleAvatar(
|
||||
backgroundColor: colorList[index % colorList.length],
|
||||
radius: 15,
|
||||
child: Text(
|
||||
index.toString(),
|
||||
style: context.bodyMedium.copyWith(color: Colors.white),
|
||||
),
|
||||
),
|
||||
titleString: automation.name,
|
||||
trailingWidget: TextButton.icon(
|
||||
iconAlignment: IconAlignment.end,
|
||||
onPressed: () {
|
||||
context.customAlertDialog(
|
||||
alertBody: EnableDisableAutomationDialog(
|
||||
automationId: automation.id,
|
||||
descriptionSelected: descriptionSelected,
|
||||
),
|
||||
title: automation.name,
|
||||
onConfirm: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
onDismiss: () {
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(const SmartSceneClearEvent());
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
},
|
||||
label: BodyMedium(
|
||||
text: _capitalizeFirst(descriptionSelected),
|
||||
style: context.bodyMedium
|
||||
.copyWith(color: ColorsManager.greyColor),
|
||||
),
|
||||
icon: const Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 14,
|
||||
),
|
||||
style: const ButtonStyle(
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
context.customAlertDialog(
|
||||
alertBody: EnableDisableAutomationDialog(
|
||||
automationId: automation.id,
|
||||
descriptionSelected: descriptionSelected,
|
||||
),
|
||||
title: automation.name,
|
||||
onConfirm: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
onDismiss: () {
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(const SmartSceneClearEvent());
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
String _capitalizeFirst(String description) {
|
||||
if (description.isEmpty) return description;
|
||||
return '${description[0].toUpperCase()}${description.substring(1)}';
|
||||
}
|
||||
}
|
||||
|
||||
class EnableDisableAutomationDialog extends StatefulWidget {
|
||||
const EnableDisableAutomationDialog({
|
||||
super.key,
|
||||
required this.automationId,
|
||||
required this.descriptionSelected,
|
||||
});
|
||||
|
||||
final String automationId;
|
||||
final String descriptionSelected;
|
||||
|
||||
@override
|
||||
State<EnableDisableAutomationDialog> createState() =>
|
||||
_EnableDisableAutomationDialogState();
|
||||
}
|
||||
|
||||
class _EnableDisableAutomationDialogState
|
||||
extends State<EnableDisableAutomationDialog> {
|
||||
String? groupValue;
|
||||
final List<SceneOperationalValue> values = [
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPower,
|
||||
description: 'Enable',
|
||||
value: 'rule_enable',
|
||||
),
|
||||
SceneOperationalValue(
|
||||
icon: Assets.assetsAcPowerOFF,
|
||||
description: 'Disable',
|
||||
value: 'rule_disable',
|
||||
),
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
groupValue =
|
||||
widget.descriptionSelected == 'Enable' ? 'rule_enable' : 'rule_disable';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<SmartSceneSelectBloc, SmartSceneSelectState>(
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
...values.map(
|
||||
(operation) => SceneListTile(
|
||||
iconsSize: 25,
|
||||
minLeadingWidth: 15,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
assetPath: operation.icon,
|
||||
assetHeaderValue: operation.iconValue,
|
||||
titleString: operation.description.toString(),
|
||||
textAlign: TextAlign.start,
|
||||
trailingWidget: Radio(
|
||||
value: operation.value,
|
||||
groupValue: groupValue,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
groupValue = value;
|
||||
});
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(SmartSceneEnableEvent(
|
||||
SmartSceneEnable(
|
||||
entityId: widget.automationId,
|
||||
actionExecutor: value!,
|
||||
),
|
||||
));
|
||||
},
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
groupValue = operation.value;
|
||||
});
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(SmartSceneEnableEvent(
|
||||
SmartSceneEnable(
|
||||
entityId: widget.automationId,
|
||||
actionExecutor: operation.value,
|
||||
),
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
|
||||
|
||||
import 'package:syncrow_app/features/scene/widgets/select_smart_scene/smart_automation_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
|
||||
class SmartEnableAutomation extends StatelessWidget {
|
||||
const SmartEnableAutomation({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultContainer(
|
||||
height: context.height * 0.5,
|
||||
width: double.infinity,
|
||||
child: BlocBuilder<SceneBloc, SceneState>(
|
||||
bloc: context.read<SceneBloc>()
|
||||
..add(
|
||||
LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? '')),
|
||||
builder: (context, state) {
|
||||
if (state is SceneLoading) {
|
||||
return const Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: LinearProgressIndicator());
|
||||
}
|
||||
if (state is SceneLoaded) {
|
||||
return SmartSceneSelectAutomationList(
|
||||
automationList: state.automationList);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/select_smart_scene/smart_tab_run_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
|
||||
class SmartEnableTabRun extends StatelessWidget {
|
||||
const SmartEnableTabRun({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultContainer(
|
||||
height: context.height * 0.5,
|
||||
width: double.infinity,
|
||||
child: BlocBuilder<SceneBloc, SceneState>(
|
||||
bloc: context.read<SceneBloc>()
|
||||
..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '')),
|
||||
builder: (context, state) {
|
||||
if (state is SceneLoading) {
|
||||
return const Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: LinearProgressIndicator());
|
||||
}
|
||||
if (state is SceneLoaded) {
|
||||
return SmartSceneSelectTabToRunList(scenes: state.scenes);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/smart_scene_enable.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.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/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class SmartSceneSelectTabToRunList extends StatefulWidget {
|
||||
const SmartSceneSelectTabToRunList({
|
||||
super.key,
|
||||
required this.scenes,
|
||||
});
|
||||
final List<ScenesModel> scenes;
|
||||
|
||||
@override
|
||||
State<SmartSceneSelectTabToRunList> createState() =>
|
||||
_SmartSceneSelectTabToRunListState();
|
||||
}
|
||||
|
||||
class _SmartSceneSelectTabToRunListState
|
||||
extends State<SmartSceneSelectTabToRunList> {
|
||||
String groupValue = '';
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: BodySmall(
|
||||
text: 'Save',
|
||||
style: context.bodySmall
|
||||
.copyWith(color: ColorsManager.primaryColorWithOpacity),
|
||||
)),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: BodyMedium(
|
||||
text: 'Tab To Run',
|
||||
textAlign: TextAlign.center,
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.dividerColor,
|
||||
),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: widget.scenes.length,
|
||||
itemBuilder: (context, index) {
|
||||
final scene = widget.scenes[index];
|
||||
return SceneListTile(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
leadingWidget: Image.asset(
|
||||
height: 32,
|
||||
width: 32,
|
||||
Assets.assetsIconsLogo,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
titleString: scene.name,
|
||||
trailingWidget: Radio(
|
||||
value: scene.id,
|
||||
groupValue: groupValue,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
setState(() {
|
||||
groupValue = value;
|
||||
});
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(SmartSceneEnableEvent(SmartSceneEnable(
|
||||
entityId: scene.id,
|
||||
actionExecutor: 'rule_enable',
|
||||
)));
|
||||
}
|
||||
}),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
groupValue = scene.id;
|
||||
});
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(SmartSceneEnableEvent(SmartSceneEnable(
|
||||
entityId: scene.id,
|
||||
actionExecutor: 'rule_enable',
|
||||
)));
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ class DefaultScaffold extends StatelessWidget {
|
||||
this.padding,
|
||||
this.leading,
|
||||
this.leadingWidth,
|
||||
this.height,
|
||||
});
|
||||
|
||||
final Widget child;
|
||||
@@ -27,6 +28,7 @@ class DefaultScaffold extends StatelessWidget {
|
||||
final EdgeInsetsGeometry? padding;
|
||||
final Widget? leading;
|
||||
final double? leadingWidth;
|
||||
final double? height;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnnotatedRegion(
|
||||
@@ -54,8 +56,9 @@ class DefaultScaffold extends StatelessWidget {
|
||||
),
|
||||
body: Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
padding: padding ?? const EdgeInsets.symmetric(horizontal: Constants.defaultPadding),
|
||||
height: height ?? MediaQuery.sizeOf(context).height,
|
||||
padding: padding ??
|
||||
const EdgeInsets.symmetric(horizontal: Constants.defaultPadding),
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
|
||||
+227
-71
@@ -3,7 +3,8 @@ class Assets {
|
||||
|
||||
/// Assets for assetsFontsAftikaRegular
|
||||
/// assets/fonts/AftikaRegular.ttf
|
||||
static const String assetsFontsAftikaRegular = "assets/fonts/AftikaRegular.ttf";
|
||||
static const String assetsFontsAftikaRegular =
|
||||
"assets/fonts/AftikaRegular.ttf";
|
||||
|
||||
/// Assets for assetsIcons3GangSwitch
|
||||
/// assets/icons/3GangSwitch.svg
|
||||
@@ -19,82 +20,98 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsAutomatedClock
|
||||
/// assets/icons/automated_clock.svg
|
||||
static const String assetsIconsAutomatedClock = "assets/icons/automated_clock.svg";
|
||||
static const String assetsIconsAutomatedClock =
|
||||
"assets/icons/automated_clock.svg";
|
||||
static const String acSwitchIcon = "assets/icons/ac_switch_ic.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff =
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOnstlowpmdmOff
|
||||
@@ -104,37 +121,44 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOnstlowpmdmOn
|
||||
@@ -144,37 +168,44 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn =
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOnstlowpmdmOn
|
||||
@@ -226,7 +257,8 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsDashboardFill
|
||||
/// assets/icons/dashboard-fill.svg
|
||||
static const String assetsIconsDashboardFill = "assets/icons/dashboard-fill.svg";
|
||||
static const String assetsIconsDashboardFill =
|
||||
"assets/icons/dashboard-fill.svg";
|
||||
|
||||
/// Assets for assetsIconsDevices
|
||||
/// assets/icons/Devices.svg
|
||||
@@ -242,7 +274,8 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsDoorLockLinkage
|
||||
/// assets/icons/DoorLockLinkage.svg
|
||||
static const String assetsIconsDoorLockLinkage = "assets/icons/DoorLockLinkage.svg";
|
||||
static const String assetsIconsDoorLockLinkage =
|
||||
"assets/icons/DoorLockLinkage.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorLockLock
|
||||
/// assets/icons/DoorLockLock.svg
|
||||
@@ -250,15 +283,18 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsDoorLockMembers
|
||||
/// assets/icons/DoorLockMembers.svg
|
||||
static const String assetsIconsDoorLockMembers = "assets/icons/DoorLockMembers.svg";
|
||||
static const String assetsIconsDoorLockMembers =
|
||||
"assets/icons/DoorLockMembers.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorLockPassword
|
||||
/// assets/icons/DoorLockPassword.svg
|
||||
static const String assetsIconsDoorLockPassword = "assets/icons/DoorLockPassword.svg";
|
||||
static const String assetsIconsDoorLockPassword =
|
||||
"assets/icons/DoorLockPassword.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorLockRecords
|
||||
/// assets/icons/DoorLockRecords.svg
|
||||
static const String assetsIconsDoorLockRecords = "assets/icons/DoorLockRecords.svg";
|
||||
static const String assetsIconsDoorLockRecords =
|
||||
"assets/icons/DoorLockRecords.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorlockAssetsBatteryIndicator
|
||||
/// assets/icons/doorlock-assets/BatteryIndicator.svg
|
||||
@@ -279,7 +315,8 @@ class Assets {
|
||||
/// assets/icons/doorlock-assets/lockIcon.svg
|
||||
static const String assetsIconsDoorlockAssetsLockIcon =
|
||||
"assets/icons/doorlock-assets/lockIcon.svg";
|
||||
static const String doorUnlockIcon = "assets/icons/doorlock-assets/door_un_look_ic.svg";
|
||||
static const String doorUnlockIcon =
|
||||
"assets/icons/doorlock-assets/door_un_look_ic.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorlockAssetsMembersManagement
|
||||
/// assets/icons/doorlock-assets/members-management.svg
|
||||
@@ -367,11 +404,13 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsLightSwitchOff
|
||||
/// assets/icons/lightSwitchOff.svg
|
||||
static const String assetsIconsLightSwitchOff = "assets/icons/lightSwitchOff.svg";
|
||||
static const String assetsIconsLightSwitchOff =
|
||||
"assets/icons/lightSwitchOff.svg";
|
||||
|
||||
/// Assets for assetsIconsLightSwitchOn
|
||||
/// assets/icons/lightSwitchOn.svg
|
||||
static const String assetsIconsLightSwitchOn = "assets/icons/lightSwitchOn.svg";
|
||||
static const String assetsIconsLightSwitchOn =
|
||||
"assets/icons/lightSwitchOn.svg";
|
||||
|
||||
/// Assets for assetsIconsLinkageIconsDoorLockAlarm
|
||||
/// assets/icons/linkageIcons/doorLockAlarm.svg
|
||||
@@ -380,7 +419,8 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsLinkTimeLimitedPasswordIcon
|
||||
/// assets/icons/timeLimitedPasswordIcon.svg
|
||||
static const String timeLimitedPasswordIcon = "assets/icons/timeLimitedPasswordIcon.svg";
|
||||
static const String timeLimitedPasswordIcon =
|
||||
"assets/icons/timeLimitedPasswordIcon.svg";
|
||||
|
||||
/// Assets for assetsIconsoneTimePassword
|
||||
/// assets/icons/oneTimePassword.svg
|
||||
@@ -388,7 +428,8 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsTimeLimitedPassword
|
||||
/// assets/icons/timeLimitedPassword.svg
|
||||
static const String timeLimitedPassword = "assets/icons/timeLimitedPassword.svg";
|
||||
static const String timeLimitedPassword =
|
||||
"assets/icons/timeLimitedPassword.svg";
|
||||
|
||||
/// Assets for assetsIconsNoValidPasswords
|
||||
/// assets/icons/noValidPasswords.svg
|
||||
@@ -557,11 +598,13 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
|
||||
/// assets/icons/presence-sensor-assets/space_type_icon.svg
|
||||
static const String spaceTypeIcon = "assets/icons/presence-sensor-assets/space_type_icon.svg";
|
||||
static const String spaceTypeIcon =
|
||||
"assets/icons/presence-sensor-assets/space_type_icon.svg";
|
||||
|
||||
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
|
||||
/// assets/icons/presence-sensor-assets/space_type_icon.svg
|
||||
static const String sensitivityIcon = "assets/icons/presence-sensor-assets/Sensitivity.svg";
|
||||
static const String sensitivityIcon =
|
||||
"assets/icons/presence-sensor-assets/Sensitivity.svg";
|
||||
|
||||
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
|
||||
/// assets/icons/presence-sensor-assets/maximum_distance.svg
|
||||
@@ -594,7 +637,8 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsRoutinesFill
|
||||
/// assets/icons/Routines-fill.svg
|
||||
static const String assetsIconsRoutinesFill = "assets/icons/Routines-fill.svg";
|
||||
static const String assetsIconsRoutinesFill =
|
||||
"assets/icons/Routines-fill.svg";
|
||||
|
||||
/// Assets for assetsIconsScan
|
||||
/// assets/icons/Scan.svg
|
||||
@@ -626,7 +670,8 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsSustainability
|
||||
/// assets/icons/sustainability.svg
|
||||
static const String assetsIconsSustainability = "assets/icons/sustainability.svg";
|
||||
static const String assetsIconsSustainability =
|
||||
"assets/icons/sustainability.svg";
|
||||
|
||||
/// Assets for assetsIconsUnlockingMethodsIconsFace
|
||||
/// assets/icons/unlockingMethodsIcons/face.svg
|
||||
@@ -718,7 +763,8 @@ class Assets {
|
||||
|
||||
/// Assets for assetsImagesHorizintalBlade
|
||||
/// assets/images/HorizintalBlade.png
|
||||
static const String assetsImagesHorizintalBlade = "assets/images/HorizintalBlade.png";
|
||||
static const String assetsImagesHorizintalBlade =
|
||||
"assets/images/HorizintalBlade.png";
|
||||
|
||||
/// Assets for assetsImagesLogo
|
||||
/// assets/images/Logo.svg
|
||||
@@ -726,7 +772,8 @@ class Assets {
|
||||
|
||||
/// Assets for assetsImagesLogoHorizontal
|
||||
/// assets/images/logo_horizontal.png
|
||||
static const String assetsImagesLogoHorizontal = "assets/images/logo_horizontal.png";
|
||||
static const String assetsImagesLogoHorizontal =
|
||||
"assets/images/logo_horizontal.png";
|
||||
|
||||
/// Assets for assetsImagesPause
|
||||
/// assets/images/Pause.png
|
||||
@@ -756,7 +803,8 @@ class Assets {
|
||||
/// assets/images/Window.png
|
||||
static const String assetsImagesWindow = "assets/images/Window.png";
|
||||
|
||||
static const String assetsSensitivityFunction = "assets/icons/functions_icons/sensitivity.svg";
|
||||
static const String assetsSensitivityFunction =
|
||||
"assets/icons/functions_icons/sensitivity.svg";
|
||||
|
||||
//assets/icons/functions_icons/sesitivity_operation_icon.svg
|
||||
static const String assetsSensitivityOperationIcon =
|
||||
@@ -764,59 +812,73 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/ac_power.svg
|
||||
|
||||
static const String assetsAcPower = "assets/icons/functions_icons/ac_power.svg";
|
||||
static const String assetsAcPower =
|
||||
"assets/icons/functions_icons/ac_power.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_power_off.svg
|
||||
|
||||
static const String assetsAcPowerOFF = "assets/icons/functions_icons/ac_power_off.svg";
|
||||
static const String assetsAcPowerOFF =
|
||||
"assets/icons/functions_icons/ac_power_off.svg";
|
||||
|
||||
//assets/icons/functions_icons/child_lock.svg
|
||||
|
||||
static const String assetsChildLock = "assets/icons/functions_icons/child_lock.svg";
|
||||
static const String assetsChildLock =
|
||||
"assets/icons/functions_icons/child_lock.svg";
|
||||
|
||||
//assets/icons/functions_icons/cooling.svg
|
||||
|
||||
static const String assetsFreezing = "assets/icons/functions_icons/freezing.svg";
|
||||
static const String assetsFreezing =
|
||||
"assets/icons/functions_icons/freezing.svg";
|
||||
|
||||
//assets/icons/functions_icons/fan_speed.svg
|
||||
|
||||
static const String assetsFanSpeed = "assets/icons/functions_icons/fan_speed.svg";
|
||||
static const String assetsFanSpeed =
|
||||
"assets/icons/functions_icons/fan_speed.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_cooling.svg
|
||||
|
||||
static const String assetsAcCooling = "assets/icons/functions_icons/ac_cooling.svg";
|
||||
static const String assetsAcCooling =
|
||||
"assets/icons/functions_icons/ac_cooling.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_heating.svg
|
||||
|
||||
static const String assetsAcHeating = "assets/icons/functions_icons/ac_heating.svg";
|
||||
static const String assetsAcHeating =
|
||||
"assets/icons/functions_icons/ac_heating.svg";
|
||||
|
||||
//assets/icons/functions_icons/celsius_degrees.svg
|
||||
|
||||
static const String assetsCelsiusDegrees = "assets/icons/functions_icons/celsius_degrees.svg";
|
||||
static const String assetsCelsiusDegrees =
|
||||
"assets/icons/functions_icons/celsius_degrees.svg";
|
||||
|
||||
//assets/icons/functions_icons/tempreture.svg
|
||||
|
||||
static const String assetsTempreture = "assets/icons/functions_icons/tempreture.svg";
|
||||
static const String assetsTempreture =
|
||||
"assets/icons/functions_icons/tempreture.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_fan_low.svg
|
||||
|
||||
static const String assetsAcFanLow = "assets/icons/functions_icons/ac_fan_low.svg";
|
||||
static const String assetsAcFanLow =
|
||||
"assets/icons/functions_icons/ac_fan_low.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_fan_middle.svg
|
||||
|
||||
static const String assetsAcFanMiddle = "assets/icons/functions_icons/ac_fan_middle.svg";
|
||||
static const String assetsAcFanMiddle =
|
||||
"assets/icons/functions_icons/ac_fan_middle.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_fan_high.svg
|
||||
|
||||
static const String assetsAcFanHigh = "assets/icons/functions_icons/ac_fan_high.svg";
|
||||
static const String assetsAcFanHigh =
|
||||
"assets/icons/functions_icons/ac_fan_high.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_fan_auto.svg
|
||||
|
||||
static const String assetsAcFanAuto = "assets/icons/functions_icons/ac_fan_auto.svg";
|
||||
static const String assetsAcFanAuto =
|
||||
"assets/icons/functions_icons/ac_fan_auto.svg";
|
||||
|
||||
//assets/icons/functions_icons/scene_child_lock.svg
|
||||
|
||||
static const String assetsSceneChildLock = "assets/icons/functions_icons/scene_child_lock.svg";
|
||||
static const String assetsSceneChildLock =
|
||||
"assets/icons/functions_icons/scene_child_lock.svg";
|
||||
|
||||
//assets/icons/functions_icons/scene_child_unlock.svg
|
||||
|
||||
@@ -825,15 +887,18 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/scene_refresh.svg
|
||||
|
||||
static const String assetsSceneRefresh = "assets/icons/functions_icons/scene_refresh.svg";
|
||||
static const String assetsSceneRefresh =
|
||||
"assets/icons/functions_icons/scene_refresh.svg";
|
||||
|
||||
//assets/icons/functions_icons/light_countdown.svg
|
||||
|
||||
static const String assetsLightCountdown = "assets/icons/functions_icons/light_countdown.svg";
|
||||
static const String assetsLightCountdown =
|
||||
"assets/icons/functions_icons/light_countdown.svg";
|
||||
|
||||
//assets/icons/functions_icons/far_detection.svg
|
||||
|
||||
static const String assetsFarDetection = "assets/icons/functions_icons/far_detection.svg";
|
||||
static const String assetsFarDetection =
|
||||
"assets/icons/functions_icons/far_detection.svg";
|
||||
|
||||
//assets/icons/functions_icons/far_detection_function.svg
|
||||
|
||||
@@ -842,11 +907,13 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/indicator.svg
|
||||
|
||||
static const String assetsIndicator = "assets/icons/functions_icons/indicator.svg";
|
||||
static const String assetsIndicator =
|
||||
"assets/icons/functions_icons/indicator.svg";
|
||||
|
||||
//assets/icons/functions_icons/motion_detection.svg
|
||||
|
||||
static const String assetsMotionDetection = "assets/icons/functions_icons/motion_detection.svg";
|
||||
static const String assetsMotionDetection =
|
||||
"assets/icons/functions_icons/motion_detection.svg";
|
||||
|
||||
//assets/icons/functions_icons/motionless_detection.svg
|
||||
|
||||
@@ -855,15 +922,18 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/nobody_time.svg
|
||||
|
||||
static const String assetsNobodyTime = "assets/icons/functions_icons/nobody_time.svg";
|
||||
static const String assetsNobodyTime =
|
||||
"assets/icons/functions_icons/nobody_time.svg";
|
||||
|
||||
//assets/icons/functions_icons/factory_reset.svg
|
||||
|
||||
static const String assetsFactoryReset = "assets/icons/functions_icons/factory_reset.svg";
|
||||
static const String assetsFactoryReset =
|
||||
"assets/icons/functions_icons/factory_reset.svg";
|
||||
|
||||
//assets/icons/functions_icons/master_state.svg
|
||||
|
||||
static const String assetsMasterState = "assets/icons/functions_icons/master_state.svg";
|
||||
static const String assetsMasterState =
|
||||
"assets/icons/functions_icons/master_state.svg";
|
||||
|
||||
//assets/icons/functions_icons/switch_alarm_sound.svg
|
||||
|
||||
@@ -872,5 +942,91 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/reset_off.svg
|
||||
|
||||
static const String assetsResetOff = "assets/icons/functions_icons/reset_off.svg";
|
||||
static const String assetsResetOff =
|
||||
"assets/icons/functions_icons/reset_off.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/card_unlock.svg
|
||||
|
||||
static const String assetsCardUnlock =
|
||||
"assets/icons/functions_icons/automation_functions/card_unlock.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/doorbell.svg
|
||||
|
||||
static const String assetsDoorbell =
|
||||
"assets/icons/functions_icons/automation_functions/doorbell.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg
|
||||
|
||||
static const String assetsDoorlockNormalOpen =
|
||||
"assets/icons/functions_icons/automation_functions/doorlock_normal_open.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/double_lock.svg
|
||||
|
||||
static const String assetsDoubleLock =
|
||||
"assets/icons/functions_icons/automation_functions/double_lock.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg
|
||||
|
||||
static const String assetsFingerprintUnlock =
|
||||
"assets/icons/functions_icons/automation_functions/fingerprint_unlock.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/hijack_alarm.svg
|
||||
|
||||
static const String assetsHijackAlarm =
|
||||
"assets/icons/functions_icons/automation_functions/hijack_alarm.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/lock_alarm.svg
|
||||
|
||||
static const String assetsLockAlarm =
|
||||
"assets/icons/functions_icons/automation_functions/lock_alarm.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/password_unlock.svg
|
||||
|
||||
static const String assetsPasswordUnlock =
|
||||
"assets/icons/functions_icons/automation_functions/password_unlock.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/remote_unlock_req.svg
|
||||
|
||||
static const String assetsRemoteUnlockReq =
|
||||
"assets/icons/functions_icons/automation_functions/remote_unlock_req.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg
|
||||
|
||||
static const String assetsRemoteUnlockViaApp =
|
||||
"assets/icons/functions_icons/automation_functions/remote_unlock_via_app.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/residual_electricity.svg
|
||||
|
||||
static const String assetsResidualElectricity =
|
||||
"assets/icons/functions_icons/automation_functions/residual_electricity.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/temp_password_unlock.svg
|
||||
|
||||
static const String assetsTempPasswordUnlock =
|
||||
"assets/icons/functions_icons/automation_functions/temp_password_unlock.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/self_test_result.svg
|
||||
|
||||
static const String assetsSelfTestResult =
|
||||
"assets/icons/functions_icons/automation_functions/self_test_result.svg";
|
||||
|
||||
///assets/icons/functions_icons/automation_functions/presence.svg
|
||||
|
||||
static const String assetsPresence =
|
||||
"assets/icons/functions_icons/automation_functions/presence.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/motion.svg
|
||||
|
||||
static const String assetsMotion =
|
||||
"assets/icons/functions_icons/automation_functions/motion.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/current_temp.svg
|
||||
|
||||
static const String assetsCurrentTemp =
|
||||
"assets/icons/functions_icons/automation_functions/current_temp.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/presence_state.svg
|
||||
|
||||
static const String assetsPresenceState =
|
||||
"assets/icons/functions_icons/automation_functions/presence_state.svg";
|
||||
}
|
||||
|
||||
+6
-1
@@ -3,6 +3,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
|
||||
import 'package:syncrow_app/navigation/navigation_service.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
@@ -28,7 +30,10 @@ class MyApp extends StatelessWidget {
|
||||
BlocProvider(create: (context) => CreateSceneBloc()),
|
||||
BlocProvider(create: (context) => SceneBloc()),
|
||||
BlocProvider(create: (context) => ProfileBloc()),
|
||||
|
||||
BlocProvider(create: (context) => SmartSceneSelectBloc()),
|
||||
BlocProvider(
|
||||
create: (context) => EffectPeriodBloc(),
|
||||
),
|
||||
],
|
||||
child: MaterialApp(
|
||||
navigatorKey: NavigationService.navigatorKey,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
+43
-17
@@ -14,9 +14,11 @@ import 'package:syncrow_app/features/menu/view/widgets/profile/profile_view.dart
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart';
|
||||
import 'package:syncrow_app/features/scene/view/device_functions_view.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_auto_settings.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_rooms_tabbar.dart';
|
||||
import 'package:syncrow_app/features/scene/view/scene_view.dart';
|
||||
import 'package:syncrow_app/features/scene/view/smart_automation_select_route.dart';
|
||||
import 'package:syncrow_app/features/splash/view/splash_view.dart';
|
||||
import 'routing_constants.dart';
|
||||
|
||||
@@ -24,54 +26,67 @@ class Router {
|
||||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||
switch (settings.name) {
|
||||
case Routes.splash:
|
||||
return MaterialPageRoute(builder: (_) => const SplashView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const SplashView(), settings: settings);
|
||||
|
||||
// case Routes.devicesRoute:
|
||||
// return MaterialPageRoute(
|
||||
// builder: (_) => const DevicesView(), settings: settings);
|
||||
|
||||
case Routes.profileRoute:
|
||||
return MaterialPageRoute(builder: (_) => const ProfileView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const ProfileView(), settings: settings);
|
||||
|
||||
case Routes.sceneRoute:
|
||||
return MaterialPageRoute(builder: (_) => const SceneView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const SceneView(), settings: settings);
|
||||
|
||||
case Routes.layoutRoute:
|
||||
return MaterialPageRoute(builder: (_) => const LayoutPage(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const LayoutPage(), settings: settings);
|
||||
|
||||
case Routes.authLogin:
|
||||
return MaterialPageRoute(builder: (_) => const LoginView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const LoginView(), settings: settings);
|
||||
|
||||
case Routes.otpRoute:
|
||||
return MaterialPageRoute(builder: (_) => const OtpView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const OtpView(), settings: settings);
|
||||
|
||||
case Routes.authSignUp:
|
||||
return MaterialPageRoute(builder: (_) => const SignUpView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const SignUpView(), settings: settings);
|
||||
|
||||
case Routes.dashboardRoute:
|
||||
return MaterialPageRoute(builder: (_) => const DashboardView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const DashboardView(), settings: settings);
|
||||
|
||||
case Routes.homeRoute:
|
||||
return MaterialPageRoute(builder: (_) => const AppLayout(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const AppLayout(), settings: settings);
|
||||
|
||||
case Routes.menuRoute:
|
||||
return MaterialPageRoute(builder: (_) => const MenuView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const MenuView(), settings: settings);
|
||||
|
||||
case Routes.createUnit:
|
||||
return MaterialPageRoute(builder: (_) => const CreateUnitView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const CreateUnitView(), settings: settings);
|
||||
case Routes.sceneTasksRoute:
|
||||
return MaterialPageRoute(builder: (_) => const SceneTasksView(), settings: settings);
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const SceneTasksView(), settings: settings);
|
||||
case Routes.sceneControlDevicesRoute:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider(
|
||||
create: (BuildContext context) => DeviceManagerBloc()..add(FetchAllDevices()),
|
||||
create: (BuildContext context) =>
|
||||
DeviceManagerBloc()..add(FetchAllDevices()),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (BuildContext context) =>
|
||||
TabBarBloc(context.read<DeviceManagerBloc>())
|
||||
..add(const TabChanged(selectedIndex: 0, roomId: '-1')),
|
||||
create: (BuildContext context) => TabBarBloc(
|
||||
context.read<DeviceManagerBloc>())
|
||||
..add(const TabChanged(selectedIndex: 0, roomId: '-1')),
|
||||
),
|
||||
],
|
||||
child: const SceneRoomsTabBarDevicesView(),
|
||||
@@ -79,7 +94,18 @@ class Router {
|
||||
settings: settings);
|
||||
case Routes.deviceFunctionsRoute:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const DeviceFunctionsView(),
|
||||
builder: (_) => DeviceFunctionsView(),
|
||||
settings: settings,
|
||||
);
|
||||
case Routes.sceneAutoSettingsRoute:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const SceneAutoSettings(),
|
||||
settings: settings,
|
||||
);
|
||||
|
||||
case Routes.smartAutomationSelectRoute:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const SmartAutomationSelectView(),
|
||||
settings: settings,
|
||||
);
|
||||
default:
|
||||
|
||||
@@ -19,6 +19,7 @@ class Routes {
|
||||
static const String createUnit = '/create-unit';
|
||||
static const String sceneTasksRoute = '/scene-tasks';
|
||||
static const String sceneControlDevicesRoute = '/scene-control-devices';
|
||||
static const String deviceFunctionsRoute = '/device-functions';
|
||||
|
||||
static const String deviceFunctionsRoute = '/device-functions';
|
||||
static const String sceneAutoSettingsRoute = '/scene-automation-settings';
|
||||
static const String smartAutomationSelectRoute = '/smart-automation-select';
|
||||
}
|
||||
|
||||
@@ -81,7 +81,8 @@ abstract class ApiEndpoints {
|
||||
static const String controlGroup = '/group/control';
|
||||
//GET
|
||||
static const String groupBySpace = '/group/{unitUuid}';
|
||||
static const String devicesByGroupName = '/group/{unitUuid}/devices/{groupName}';
|
||||
static const String devicesByGroupName =
|
||||
'/group/{unitUuid}/devices/{groupName}';
|
||||
|
||||
static const String groupByUuid = '/group/{groupUuid}';
|
||||
//DELETE
|
||||
@@ -93,7 +94,8 @@ abstract class ApiEndpoints {
|
||||
static const String addDeviceToRoom = '/device/room';
|
||||
static const String addDeviceToGroup = '/device/group';
|
||||
static const String controlDevice = '/device/{deviceUuid}/control';
|
||||
static const String firmwareDevice = '/device/{deviceUuid}/firmware/{firmwareVersion}';
|
||||
static const String firmwareDevice =
|
||||
'/device/{deviceUuid}/firmware/{firmwareVersion}';
|
||||
static const String getDevicesByUserId = '/device/user/{userId}';
|
||||
static const String getDevicesByUnitId = '/device/unit/{unitUuid}';
|
||||
|
||||
@@ -102,7 +104,8 @@ abstract class ApiEndpoints {
|
||||
static const String deviceByUuid = '/device/{deviceUuid}';
|
||||
static const String deviceFunctions = '/device/{deviceUuid}/functions';
|
||||
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices';
|
||||
static const String deviceFunctionsStatus = '/device/{deviceUuid}/functions/status';
|
||||
static const String deviceFunctionsStatus =
|
||||
'/device/{deviceUuid}/functions/status';
|
||||
|
||||
///Device Permission Module
|
||||
//POST
|
||||
@@ -114,26 +117,42 @@ abstract class ApiEndpoints {
|
||||
|
||||
static const String assignDeviceToRoom = '/device/room';
|
||||
|
||||
/// Scene API ////////////////////
|
||||
/// Scene & Automation API ////////////////////
|
||||
/// POST
|
||||
static const String createScene = '/scene/tap-to-run';
|
||||
static const String triggerScene = '/scene/tap-to-run/trigger/{sceneId}';
|
||||
static const String createAutomation = '/automation';
|
||||
|
||||
/// GET
|
||||
static const String getUnitScenes = '/scene/tap-to-run/{unitUuid}';
|
||||
|
||||
static const String getScene = '/scene/tap-to-run/details/{sceneId}';
|
||||
|
||||
static const String getUnitAutomation = '/automation/{unitUuid}';
|
||||
|
||||
static const String getAutomationDetails =
|
||||
'/automation/details/{automationId}';
|
||||
|
||||
/// PUT
|
||||
static const String updateScene = '/scene/tap-to-run/{sceneId}';
|
||||
|
||||
static const String updateAutomation = '/automation/{automationId}';
|
||||
|
||||
static const String updateAutomationStatus =
|
||||
'/automation/status/{automationId}';
|
||||
|
||||
/// DELETE
|
||||
static const String deleteScene = '/scene/tap-to-run/{unitUuid}/{sceneId}';
|
||||
|
||||
static const String deleteAutomation =
|
||||
'/automation/{unitUuid}/{automationId}';
|
||||
|
||||
//////////////////////Door Lock //////////////////////
|
||||
//online
|
||||
static const String addTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
|
||||
static const String getTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
|
||||
static const String addTemporaryPassword =
|
||||
'/door-lock/temporary-password/online/{doorLockUuid}';
|
||||
static const String getTemporaryPassword =
|
||||
'/door-lock/temporary-password/online/{doorLockUuid}';
|
||||
|
||||
//one-time offline
|
||||
static const String addOneTimeTemporaryPassword =
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scene_details_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/update_automation.dart';
|
||||
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
|
||||
import 'package:syncrow_app/services/api/http_service.dart';
|
||||
|
||||
class SceneApi {
|
||||
static final HTTPService _httpService = HTTPService();
|
||||
|
||||
//create scene
|
||||
static Future<Map<String, dynamic>> createScene(
|
||||
CreateSceneModel createSceneModel) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.createScene,
|
||||
body: createSceneModel.toJson(),
|
||||
body: createSceneModel.toMap(),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@@ -24,6 +27,26 @@ class SceneApi {
|
||||
}
|
||||
}
|
||||
|
||||
// create automation
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//get scene by unit id
|
||||
|
||||
static Future<List<ScenesModel>> getScenesByUnitId(String unitId) async {
|
||||
try {
|
||||
final response = await _httpService.get(
|
||||
@@ -43,6 +66,27 @@ class SceneApi {
|
||||
}
|
||||
}
|
||||
|
||||
//getAutomation
|
||||
|
||||
static Future<List<ScenesModel>> getAutomationByUnitId(String unitId) async {
|
||||
try {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getUnitAutomation.replaceAll('{unitUuid}', unitId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
List<ScenesModel> scenes = [];
|
||||
for (var scene in json) {
|
||||
scenes.add(ScenesModel.fromJson(scene));
|
||||
}
|
||||
return scenes;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool> triggerScene(String sceneId) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
@@ -56,6 +100,38 @@ class SceneApi {
|
||||
}
|
||||
}
|
||||
|
||||
//automation details
|
||||
static Future<SceneDetailsModel> getAutomationDetails(
|
||||
String automationId) async {
|
||||
try {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getAutomationDetails
|
||||
.replaceAll('{automationId}', automationId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => SceneDetailsModel.fromJson(json),
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
//updateAutomationStatus
|
||||
static Future<bool> updateAutomationStatus(String automationId,
|
||||
AutomationStatusUpdate createAutomationEnable) async {
|
||||
try {
|
||||
final response = await _httpService.put(
|
||||
path: ApiEndpoints.updateAutomationStatus
|
||||
.replaceAll('{automationId}', automationId),
|
||||
body: createAutomationEnable.toMap(),
|
||||
expectedResponseModel: (json) => json['success'],
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
//getScene
|
||||
|
||||
static Future<SceneDetailsModel> getSceneDetails(String sceneId) async {
|
||||
@@ -71,7 +147,7 @@ class SceneApi {
|
||||
}
|
||||
}
|
||||
|
||||
//updateScene
|
||||
//update Scene
|
||||
static updateScene(CreateSceneModel createSceneModel, String sceneId) async {
|
||||
try {
|
||||
final response = await _httpService.put(
|
||||
@@ -88,7 +164,26 @@ class SceneApi {
|
||||
}
|
||||
}
|
||||
|
||||
//deleteScene
|
||||
//update automation
|
||||
static updateAutomation(
|
||||
CreateAutomationModel createAutomationModel, String automationId) async {
|
||||
try {
|
||||
final response = await _httpService.put(
|
||||
path: ApiEndpoints.updateAutomation
|
||||
.replaceAll('{automationId}', automationId),
|
||||
body: createAutomationModel
|
||||
.toJson(automationId.isNotEmpty == true ? automationId : null),
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
//delete Scene
|
||||
|
||||
static Future<bool> deleteScene(
|
||||
{required String unitUuid, required String sceneId}) async {
|
||||
@@ -105,4 +200,21 @@ class SceneApi {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// delete automation
|
||||
static Future<bool> deleteAutomation(
|
||||
{required String unitUuid, required String automationId}) async {
|
||||
try {
|
||||
final response = await _httpService.delete(
|
||||
path: ApiEndpoints.deleteAutomation
|
||||
.replaceAll('{automationId}', automationId)
|
||||
.replaceAll('{unitUuid}', unitUuid),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => json['statusCode'] == 200,
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ extension ContextExtension on BuildContext {
|
||||
required String title,
|
||||
required VoidCallback onConfirm,
|
||||
VoidCallback? onDismiss,
|
||||
bool? hideConfirmButton,
|
||||
}) {
|
||||
showDialog(
|
||||
context: this,
|
||||
@@ -110,39 +111,57 @@ extension ContextExtension on BuildContext {
|
||||
width: double.infinity,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: onDismiss ??
|
||||
() {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium
|
||||
.copyWith(color: ColorsManager.greyColor),
|
||||
hideConfirmButton != true
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: onDismiss ??
|
||||
() {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium
|
||||
.copyWith(color: ColorsManager.greyColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 50,
|
||||
width: 1,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: onConfirm,
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Confirm',
|
||||
style: context.bodyMedium.copyWith(
|
||||
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),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 50,
|
||||
width: 1,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: onConfirm,
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Confirm',
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -40,4 +40,5 @@ class StringsManager {
|
||||
static const String functions = "Functions";
|
||||
static const String firstLaunch = "firstLaunch";
|
||||
static const String deleteScene = 'Delete Scene';
|
||||
static const String deleteAutomation = 'Delete Automation';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user