mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
Bug fixes
This commit is contained in:
@ -13,6 +13,7 @@ import 'package:syncrow_web/pages/routiens/models/routine_model.dart';
|
|||||||
import 'package:syncrow_web/services/devices_mang_api.dart';
|
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||||
import 'package:syncrow_web/services/routines_api.dart';
|
import 'package:syncrow_web/services/routines_api.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
part 'routine_event.dart';
|
part 'routine_event.dart';
|
||||||
@ -47,14 +48,14 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
on<SetAutomationActionExecutor>(_onSetAutomationActionExecutor);
|
on<SetAutomationActionExecutor>(_onSetAutomationActionExecutor);
|
||||||
on<TriggerSwitchTabsEvent>(_triggerSwitchTabsEvent);
|
on<TriggerSwitchTabsEvent>(_triggerSwitchTabsEvent);
|
||||||
on<CreateNewRoutineViewEvent>(_createNewRoutineViewEvent);
|
on<CreateNewRoutineViewEvent>(_createNewRoutineViewEvent);
|
||||||
|
on<ResetErrorMessage>(_resetErrorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _triggerSwitchTabsEvent(
|
FutureOr<void> _triggerSwitchTabsEvent(
|
||||||
TriggerSwitchTabsEvent event,
|
TriggerSwitchTabsEvent event,
|
||||||
Emitter<RoutineState> emit,
|
Emitter<RoutineState> emit,
|
||||||
) {
|
) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(routineTab: event.isRoutineTab, createRoutineView: false));
|
||||||
routineTab: event.isRoutineTab, createRoutineView: false));
|
|
||||||
add(ResetRoutineState());
|
add(ResetRoutineState());
|
||||||
if (event.isRoutineTab) {
|
if (event.isRoutineTab) {
|
||||||
add(const LoadScenes(spaceId, communityId));
|
add(const LoadScenes(spaceId, communityId));
|
||||||
@ -62,6 +63,13 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_resetErrorMessage(
|
||||||
|
ResetErrorMessage event,
|
||||||
|
Emitter<RoutineState> emit,
|
||||||
|
) {
|
||||||
|
emit(state.copyWith(errorMessage: ''));
|
||||||
|
}
|
||||||
|
|
||||||
FutureOr<void> _createNewRoutineViewEvent(
|
FutureOr<void> _createNewRoutineViewEvent(
|
||||||
CreateNewRoutineViewEvent event,
|
CreateNewRoutineViewEvent event,
|
||||||
Emitter<RoutineState> emit,
|
Emitter<RoutineState> emit,
|
||||||
@ -73,8 +81,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems);
|
final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems);
|
||||||
|
|
||||||
// Find the index of the item in teh current itemsList
|
// Find the index of the item in teh current itemsList
|
||||||
int index = updatedIfItems.indexWhere(
|
int index =
|
||||||
(map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
||||||
// Replace the map if the index is valid
|
// Replace the map if the index is valid
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
updatedIfItems[index] = event.item;
|
updatedIfItems[index] = event.item;
|
||||||
@ -83,21 +91,18 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event.isTabToRun) {
|
if (event.isTabToRun) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
|
||||||
ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
|
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: false, isAutomation: true));
|
||||||
ifItems: updatedIfItems, isTabToRun: false, isAutomation: true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onAddToThenContainer(
|
void _onAddToThenContainer(AddToThenContainer event, Emitter<RoutineState> emit) {
|
||||||
AddToThenContainer event, Emitter<RoutineState> emit) {
|
|
||||||
final currentItems = List<Map<String, dynamic>>.from(state.thenItems);
|
final currentItems = List<Map<String, dynamic>>.from(state.thenItems);
|
||||||
|
|
||||||
// Find the index of the item in teh current itemsList
|
// Find the index of the item in teh current itemsList
|
||||||
int index = currentItems.indexWhere(
|
int index =
|
||||||
(map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
||||||
// Replace the map if the index is valid
|
// Replace the map if the index is valid
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
currentItems[index] = event.item;
|
currentItems[index] = event.item;
|
||||||
@ -108,26 +113,22 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
emit(state.copyWith(thenItems: currentItems));
|
emit(state.copyWith(thenItems: currentItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onAddFunctionsToRoutine(
|
void _onAddFunctionsToRoutine(AddFunctionToRoutine event, Emitter<RoutineState> emit) {
|
||||||
AddFunctionToRoutine event, Emitter<RoutineState> emit) {
|
|
||||||
try {
|
try {
|
||||||
if (event.functions.isEmpty) return;
|
if (event.functions.isEmpty) return;
|
||||||
|
|
||||||
List<DeviceFunctionData> selectedFunction =
|
List<DeviceFunctionData> selectedFunction = List<DeviceFunctionData>.from(event.functions);
|
||||||
List<DeviceFunctionData>.from(event.functions);
|
|
||||||
|
|
||||||
Map<String, List<DeviceFunctionData>> currentSelectedFunctions =
|
Map<String, List<DeviceFunctionData>> currentSelectedFunctions =
|
||||||
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
||||||
if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
|
if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
|
||||||
List<DeviceFunctionData> currentFunctions =
|
List<DeviceFunctionData> currentFunctions =
|
||||||
List<DeviceFunctionData>.from(
|
List<DeviceFunctionData>.from(currentSelectedFunctions[event.uniqueCustomId] ?? []);
|
||||||
currentSelectedFunctions[event.uniqueCustomId] ?? []);
|
|
||||||
|
|
||||||
List<String> functionCode = [];
|
List<String> functionCode = [];
|
||||||
for (int i = 0; i < selectedFunction.length; i++) {
|
for (int i = 0; i < selectedFunction.length; i++) {
|
||||||
for (int j = 0; j < currentFunctions.length; j++) {
|
for (int j = 0; j < currentFunctions.length; j++) {
|
||||||
if (selectedFunction[i].functionCode ==
|
if (selectedFunction[i].functionCode == currentFunctions[j].functionCode) {
|
||||||
currentFunctions[j].functionCode) {
|
|
||||||
currentFunctions[j] = selectedFunction[i];
|
currentFunctions[j] = selectedFunction[i];
|
||||||
if (!functionCode.contains(currentFunctions[j].functionCode)) {
|
if (!functionCode.contains(currentFunctions[j].functionCode)) {
|
||||||
functionCode.add(currentFunctions[j].functionCode);
|
functionCode.add(currentFunctions[j].functionCode);
|
||||||
@ -137,15 +138,13 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < functionCode.length; i++) {
|
for (int i = 0; i < functionCode.length; i++) {
|
||||||
selectedFunction
|
selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]);
|
||||||
.removeWhere((code) => code.functionCode == functionCode[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSelectedFunctions[event.uniqueCustomId] =
|
currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions)
|
||||||
List.from(currentFunctions)..addAll(selectedFunction);
|
..addAll(selectedFunction);
|
||||||
} else {
|
} else {
|
||||||
currentSelectedFunctions[event.uniqueCustomId] =
|
currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions);
|
||||||
List.from(event.functions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(state.copyWith(selectedFunctions: currentSelectedFunctions));
|
emit(state.copyWith(selectedFunctions: currentSelectedFunctions));
|
||||||
@ -154,13 +153,11 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onLoadScenes(
|
Future<void> _onLoadScenes(LoadScenes event, Emitter<RoutineState> emit) async {
|
||||||
LoadScenes event, Emitter<RoutineState> emit) async {
|
|
||||||
emit(state.copyWith(isLoading: true, errorMessage: null));
|
emit(state.copyWith(isLoading: true, errorMessage: null));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final scenes =
|
final scenes = await SceneApi.getScenesByUnitId(event.unitId, event.communityId);
|
||||||
await SceneApi.getScenesByUnitId(event.unitId, event.communityId);
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
scenes: scenes,
|
scenes: scenes,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -175,8 +172,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onLoadAutomation(
|
Future<void> _onLoadAutomation(LoadAutomation event, Emitter<RoutineState> emit) async {
|
||||||
LoadAutomation event, Emitter<RoutineState> emit) async {
|
|
||||||
emit(state.copyWith(isLoading: true, errorMessage: null));
|
emit(state.copyWith(isLoading: true, errorMessage: null));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -204,44 +200,41 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onSearchRoutines(
|
FutureOr<void> _onSearchRoutines(SearchRoutines event, Emitter<RoutineState> emit) async {
|
||||||
SearchRoutines event, Emitter<RoutineState> emit) async {
|
|
||||||
emit(state.copyWith(isLoading: true, errorMessage: null));
|
emit(state.copyWith(isLoading: true, errorMessage: null));
|
||||||
await Future.delayed(const Duration(seconds: 1));
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
emit(state.copyWith(isLoading: false, errorMessage: null));
|
emit(state.copyWith(isLoading: false, errorMessage: null));
|
||||||
emit(state.copyWith(searchText: event.query));
|
emit(state.copyWith(searchText: event.query));
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onAddSelectedIcon(
|
FutureOr<void> _onAddSelectedIcon(AddSelectedIcon event, Emitter<RoutineState> emit) {
|
||||||
AddSelectedIcon event, Emitter<RoutineState> emit) {
|
|
||||||
emit(state.copyWith(selectedIcon: event.icon));
|
emit(state.copyWith(selectedIcon: event.icon));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isFirstActionDelay(List<Map<String, dynamic>> actions) {
|
// bool _isFirstActionDelay(List<Map<String, dynamic>> actions) {
|
||||||
if (actions.isEmpty) return false;
|
// if (actions.isEmpty) return false;
|
||||||
return actions.first['deviceId'] == 'delay';
|
// return actions.first['deviceId'] == 'delay';
|
||||||
}
|
// }
|
||||||
|
|
||||||
bool _isLastActionDelay(List<Map<String, dynamic>> actions) {
|
bool _isLastActionDelay(List<Map<String, dynamic>> actions) {
|
||||||
if (actions.isEmpty) return false;
|
if (actions.isEmpty) return false;
|
||||||
return actions.last['deviceId'] == 'delay';
|
return actions.last['deviceId'] == 'delay';
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onCreateScene(
|
Future<void> _onCreateScene(CreateSceneEvent event, Emitter<RoutineState> emit) async {
|
||||||
CreateSceneEvent event, Emitter<RoutineState> emit) async {
|
|
||||||
try {
|
try {
|
||||||
// Check if first action is delay
|
// Check if first action is delay
|
||||||
if (_isFirstActionDelay(state.thenItems)) {
|
// if (_isFirstActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
// emit(state.copyWith(
|
||||||
errorMessage: 'Cannot have delay as the first action',
|
// errorMessage: 'Cannot have delay as the first action',
|
||||||
isLoading: false,
|
// isLoading: false,
|
||||||
));
|
// ));
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (_isLastActionDelay(state.thenItems)) {
|
if (_isLastActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
errorMessage: 'Cannot have delay as the last action',
|
errorMessage: 'A delay condition cannot be the only or the last action',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
@ -314,28 +307,31 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onCreateAutomation(
|
Future<void> _onCreateAutomation(CreateAutomationEvent event, Emitter<RoutineState> emit) async {
|
||||||
CreateAutomationEvent event, Emitter<RoutineState> emit) async {
|
|
||||||
try {
|
try {
|
||||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
if (state.routineName == null || state.routineName!.isEmpty) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
errorMessage: 'Automation name is required',
|
errorMessage: 'Automation name is required',
|
||||||
));
|
));
|
||||||
|
CustomSnackBar.redSnackBar('Automation name is required');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_isFirstActionDelay(state.thenItems)) {
|
// if (_isFirstActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
// emit(state.copyWith(
|
||||||
errorMessage: 'Cannot have delay as the first action',
|
// errorMessage: 'Cannot have delay as the first action',
|
||||||
isLoading: false,
|
// isLoading: false,
|
||||||
));
|
// ));
|
||||||
return;
|
// CustomSnackBar.redSnackBar('Cannot have delay as the first action');
|
||||||
}
|
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
if (_isLastActionDelay(state.thenItems)) {
|
if (_isLastActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
errorMessage: 'Cannot have delay as the last action',
|
errorMessage: 'A delay condition cannot be the only or the last action',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
));
|
));
|
||||||
|
CustomSnackBar.redSnackBar('Cannot have delay as the last action');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit(state.copyWith(isLoading: true, errorMessage: null));
|
emit(state.copyWith(isLoading: true, errorMessage: null));
|
||||||
@ -430,30 +426,28 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
isLoading: false,
|
isLoading: false,
|
||||||
errorMessage: result['message'],
|
errorMessage: result['message'],
|
||||||
));
|
));
|
||||||
|
CustomSnackBar.redSnackBar('Something went wrong');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
errorMessage: 'Something went wrong',
|
errorMessage: 'Something went wrong',
|
||||||
));
|
));
|
||||||
|
CustomSnackBar.redSnackBar('Something went wrong');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onRemoveDragCard(
|
FutureOr<void> _onRemoveDragCard(RemoveDragCard event, Emitter<RoutineState> emit) {
|
||||||
RemoveDragCard event, Emitter<RoutineState> emit) {
|
|
||||||
if (event.isFromThen) {
|
if (event.isFromThen) {
|
||||||
final thenItems = List<Map<String, dynamic>>.from(state.thenItems);
|
final thenItems = List<Map<String, dynamic>>.from(state.thenItems);
|
||||||
final selectedFunctions =
|
final selectedFunctions = Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
||||||
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
|
||||||
|
|
||||||
thenItems.removeAt(event.index);
|
thenItems.removeAt(event.index);
|
||||||
selectedFunctions.remove(event.key);
|
selectedFunctions.remove(event.key);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(thenItems: thenItems, selectedFunctions: selectedFunctions));
|
||||||
thenItems: thenItems, selectedFunctions: selectedFunctions));
|
|
||||||
} else {
|
} else {
|
||||||
final ifItems = List<Map<String, dynamic>>.from(state.ifItems);
|
final ifItems = List<Map<String, dynamic>>.from(state.ifItems);
|
||||||
final selectedFunctions =
|
final selectedFunctions = Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
||||||
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
|
||||||
|
|
||||||
ifItems.removeAt(event.index);
|
ifItems.removeAt(event.index);
|
||||||
selectedFunctions.remove(event.key);
|
selectedFunctions.remove(event.key);
|
||||||
@ -464,8 +458,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
isAutomation: false,
|
isAutomation: false,
|
||||||
isTabToRun: false));
|
isTabToRun: false));
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(ifItems: ifItems, selectedFunctions: selectedFunctions));
|
||||||
ifItems: ifItems, selectedFunctions: selectedFunctions));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -477,23 +470,18 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onEffectiveTimeEvent(
|
FutureOr<void> _onEffectiveTimeEvent(EffectiveTimePeriodEvent event, Emitter<RoutineState> emit) {
|
||||||
EffectiveTimePeriodEvent event, Emitter<RoutineState> emit) {
|
|
||||||
emit(state.copyWith(effectiveTime: event.effectiveTime));
|
emit(state.copyWith(effectiveTime: event.effectiveTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onSetRoutineName(
|
FutureOr<void> _onSetRoutineName(SetRoutineName event, Emitter<RoutineState> emit) {
|
||||||
SetRoutineName event, Emitter<RoutineState> emit) {
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
routineName: event.name,
|
routineName: event.name,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(List<Map<String, dynamic>>, List<Map<String, dynamic>>, Map<String, List<DeviceFunctionData>>)
|
||||||
List<Map<String, dynamic>>,
|
_createCardData(
|
||||||
List<Map<String, dynamic>>,
|
|
||||||
Map<String, List<DeviceFunctionData>>
|
|
||||||
) _createCardData(
|
|
||||||
List<RoutineAction> actions,
|
List<RoutineAction> actions,
|
||||||
List<RoutineCondition>? conditions,
|
List<RoutineCondition>? conditions,
|
||||||
Map<String, List<DeviceFunctionData>> currentFunctions,
|
Map<String, List<DeviceFunctionData>> currentFunctions,
|
||||||
@ -526,8 +514,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
'deviceId': condition.entityId,
|
'deviceId': condition.entityId,
|
||||||
'title': matchingDevice.name ?? condition.entityId,
|
'title': matchingDevice.name ?? condition.entityId,
|
||||||
'productType': condition.entityType,
|
'productType': condition.entityType,
|
||||||
'imagePath':
|
'imagePath': matchingDevice.getDefaultIcon(condition.entityType),
|
||||||
matchingDevice.getDefaultIcon(condition.entityType),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
final functions = matchingDevice.functions;
|
final functions = matchingDevice.functions;
|
||||||
@ -563,11 +550,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final cardData = {
|
final cardData = {
|
||||||
'entityId': action.entityId,
|
'entityId': action.entityId,
|
||||||
'uniqueCustomId': const Uuid().v4(),
|
'uniqueCustomId': const Uuid().v4(),
|
||||||
'deviceId':
|
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||||
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
'title': action.actionExecutor == 'delay' ? 'Delay' : (matchingDevice.name ?? 'Device'),
|
||||||
'title': action.actionExecutor == 'delay'
|
|
||||||
? 'Delay'
|
|
||||||
: (matchingDevice.name ?? 'Device'),
|
|
||||||
'productType': action.productType,
|
'productType': action.productType,
|
||||||
'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
||||||
};
|
};
|
||||||
@ -610,8 +594,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
return (thenItems, ifItems, currentFunctions);
|
return (thenItems, ifItems, currentFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onGetSceneDetails(
|
Future<void> _onGetSceneDetails(GetSceneDetails event, Emitter<RoutineState> emit) async {
|
||||||
GetSceneDetails event, Emitter<RoutineState> emit) async {
|
|
||||||
try {
|
try {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
@ -659,10 +642,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
if (!deviceCards.containsKey(deviceId)) {
|
if (!deviceCards.containsKey(deviceId)) {
|
||||||
deviceCards[deviceId] = {
|
deviceCards[deviceId] = {
|
||||||
'entityId': action.entityId,
|
'entityId': action.entityId,
|
||||||
'deviceId':
|
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||||
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
'uniqueCustomId': action.type == 'automation' || action.actionExecutor == 'delay'
|
||||||
'uniqueCustomId':
|
|
||||||
action.type == 'automation' || action.actionExecutor == 'delay'
|
|
||||||
? const Uuid().v4()
|
? const Uuid().v4()
|
||||||
: action.entityId,
|
: action.entityId,
|
||||||
'title': action.actionExecutor == 'delay'
|
'title': action.actionExecutor == 'delay'
|
||||||
@ -699,8 +680,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
emit(state.copyWith(automationActionExecutor: action.actionExecutor));
|
emit(state.copyWith(automationActionExecutor: action.actionExecutor));
|
||||||
} else if (action.executorProperty != null &&
|
} else if (action.executorProperty != null && action.actionExecutor != 'delay') {
|
||||||
action.actionExecutor != 'delay') {
|
|
||||||
if (!updatedFunctions.containsKey(uniqueCustomId)) {
|
if (!updatedFunctions.containsKey(uniqueCustomId)) {
|
||||||
updatedFunctions[uniqueCustomId] = [];
|
updatedFunctions[uniqueCustomId] = [];
|
||||||
}
|
}
|
||||||
@ -785,8 +765,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
thenItems: [],
|
thenItems: [],
|
||||||
));
|
));
|
||||||
|
|
||||||
final automationDetails =
|
final automationDetails = await SceneApi.getAutomationDetails(event.automationId);
|
||||||
await SceneApi.getAutomationDetails(event.automationId);
|
|
||||||
|
|
||||||
final List<Map<String, dynamic>> thenItems;
|
final List<Map<String, dynamic>> thenItems;
|
||||||
final List<Map<String, dynamic>> ifItems;
|
final List<Map<String, dynamic>> ifItems;
|
||||||
@ -805,16 +784,13 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final cardData = {
|
final cardData = {
|
||||||
'entityId': condition.entityId,
|
'entityId': condition.entityId,
|
||||||
'uniqueCustomId': const Uuid().v4(),
|
'uniqueCustomId': const Uuid().v4(),
|
||||||
'deviceId': condition.expr.statusCode == 'delay'
|
'deviceId': condition.expr.statusCode == 'delay' ? 'delay' : condition.entityId,
|
||||||
? 'delay'
|
|
||||||
: condition.entityId,
|
|
||||||
'title': condition.expr.statusCode == 'delay'
|
'title': condition.expr.statusCode == 'delay'
|
||||||
? 'Delay'
|
? 'Delay'
|
||||||
: (matchingDevice?.name ?? 'Device'),
|
: (matchingDevice?.name ?? 'Device'),
|
||||||
'productType': condition.productType,
|
'productType': condition.productType,
|
||||||
'functions': matchingDevice?.functions ?? [],
|
'functions': matchingDevice?.functions ?? [],
|
||||||
'imagePath':
|
'imagePath': matchingDevice?.getDefaultIcon(condition.productType) ?? '',
|
||||||
matchingDevice?.getDefaultIcon(condition.productType) ?? '',
|
|
||||||
'device': matchingDevice,
|
'device': matchingDevice,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -851,19 +827,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final cardData = {
|
final cardData = {
|
||||||
'entityId': action.entityId,
|
'entityId': action.entityId,
|
||||||
'uniqueCustomId': const Uuid().v4(),
|
'uniqueCustomId': const Uuid().v4(),
|
||||||
'deviceId':
|
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||||
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
'title': action.actionExecutor == 'delay' ? 'Delay' : (matchingDevice.name ?? 'Device'),
|
||||||
'title': action.actionExecutor == 'delay'
|
|
||||||
? 'Delay'
|
|
||||||
: (matchingDevice.name ?? 'Device'),
|
|
||||||
'productType': action.productType,
|
'productType': action.productType,
|
||||||
'functions': matchingDevice.functions,
|
'functions': matchingDevice.functions,
|
||||||
'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
||||||
'device': matchingDevice,
|
'device': matchingDevice,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (action.executorProperty != null &&
|
if (action.executorProperty != null && action.actionExecutor != 'delay') {
|
||||||
action.actionExecutor != 'delay') {
|
|
||||||
final functions = matchingDevice.functions;
|
final functions = matchingDevice.functions;
|
||||||
final functionCode = action.executorProperty!.functionCode;
|
final functionCode = action.executorProperty!.functionCode;
|
||||||
for (var function in functions) {
|
for (var function in functions) {
|
||||||
@ -926,8 +898,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onResetRoutineState(
|
FutureOr<void> _onResetRoutineState(ResetRoutineState event, Emitter<RoutineState> emit) {
|
||||||
ResetRoutineState event, Emitter<RoutineState> emit) {
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
ifItems: [],
|
ifItems: [],
|
||||||
thenItems: [],
|
thenItems: [],
|
||||||
@ -955,8 +926,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
if (state.isTabToRun) {
|
if (state.isTabToRun) {
|
||||||
SceneApi.deleteScene(unitUuid: spaceId, sceneId: state.sceneId ?? '');
|
SceneApi.deleteScene(unitUuid: spaceId, sceneId: state.sceneId ?? '');
|
||||||
} else {
|
} else {
|
||||||
SceneApi.deleteAutomation(
|
SceneApi.deleteAutomation(unitUuid: spaceId, automationId: state.automationId ?? '');
|
||||||
unitUuid: spaceId, automationId: state.automationId ?? '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add(const LoadScenes(spaceId, communityId));
|
add(const LoadScenes(spaceId, communityId));
|
||||||
@ -985,8 +955,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
FutureOr<void> _fetchDevices(
|
FutureOr<void> _fetchDevices(FetchDevicesInRoutine event, Emitter<RoutineState> emit) async {
|
||||||
FetchDevicesInRoutine event, Emitter<RoutineState> emit) async {
|
|
||||||
emit(state.copyWith(isLoading: true));
|
emit(state.copyWith(isLoading: true));
|
||||||
try {
|
try {
|
||||||
final devices = await DevicesManagementApi().fetchDevices();
|
final devices = await DevicesManagementApi().fetchDevices();
|
||||||
@ -997,22 +966,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onUpdateScene(
|
FutureOr<void> _onUpdateScene(UpdateScene event, Emitter<RoutineState> emit) async {
|
||||||
UpdateScene event, Emitter<RoutineState> emit) async {
|
|
||||||
try {
|
try {
|
||||||
// Check if first action is delay
|
// Check if first action is delay
|
||||||
if (_isFirstActionDelay(state.thenItems)) {
|
// if (_isFirstActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
// emit(state.copyWith(
|
||||||
errorMessage: 'Cannot have delay as the first action',
|
// errorMessage: 'Cannot have delay as the first action',
|
||||||
isLoading: false,
|
// isLoading: false,
|
||||||
));
|
// ));
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (_isLastActionDelay(state.thenItems)) {
|
if (_isLastActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
errorMessage: 'Cannot have delay as the last action',
|
errorMessage: 'A delay condition cannot be the only or the last action',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
@ -1065,8 +1033,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
actions: actions,
|
actions: actions,
|
||||||
);
|
);
|
||||||
|
|
||||||
final result =
|
final result = await SceneApi.updateScene(createSceneModel, state.sceneId ?? '');
|
||||||
await SceneApi.updateScene(createSceneModel, state.sceneId ?? '');
|
|
||||||
if (result['success']) {
|
if (result['success']) {
|
||||||
add(ResetRoutineState());
|
add(ResetRoutineState());
|
||||||
add(const LoadScenes(spaceId, communityId));
|
add(const LoadScenes(spaceId, communityId));
|
||||||
@ -1085,21 +1052,19 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onUpdateAutomation(
|
FutureOr<void> _onUpdateAutomation(UpdateAutomation event, Emitter<RoutineState> emit) async {
|
||||||
UpdateAutomation event, Emitter<RoutineState> emit) async {
|
// if (_isFirstActionDelay(state.thenItems)) {
|
||||||
if (_isFirstActionDelay(state.thenItems)) {
|
// emit(state.copyWith(
|
||||||
emit(state.copyWith(
|
// errorMessage: 'Cannot have delay as the first action',
|
||||||
errorMessage: 'Cannot have delay as the first action',
|
// isLoading: false,
|
||||||
isLoading: false,
|
// ));
|
||||||
));
|
// return;
|
||||||
return;
|
// }
|
||||||
}
|
|
||||||
emit(state.copyWith(isLoading: true));
|
emit(state.copyWith(isLoading: true));
|
||||||
try {
|
try {
|
||||||
final conditions = state.ifItems
|
final conditions = state.ifItems
|
||||||
.map((item) {
|
.map((item) {
|
||||||
final functions =
|
final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
||||||
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
|
||||||
if (functions.isEmpty) return null;
|
if (functions.isEmpty) return null;
|
||||||
|
|
||||||
final function = functions.first;
|
final function = functions.first;
|
||||||
@ -1119,8 +1084,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
|
|
||||||
final actions = state.thenItems
|
final actions = state.thenItems
|
||||||
.map((item) {
|
.map((item) {
|
||||||
final functions =
|
final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
||||||
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
|
||||||
if (functions.isEmpty) return null;
|
if (functions.isEmpty) return null;
|
||||||
|
|
||||||
final function = functions.first;
|
final function = functions.first;
|
||||||
@ -1131,9 +1095,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
executorProperty: ExecutorProperty(
|
executorProperty: ExecutorProperty(
|
||||||
functionCode: function.functionCode,
|
functionCode: function.functionCode,
|
||||||
functionValue: function.value,
|
functionValue: function.value,
|
||||||
delaySeconds: function.functionCode == 'delay'
|
delaySeconds:
|
||||||
? (function.value as num).toInt()
|
function.functionCode == 'delay' ? (function.value as num).toInt() : null,
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -1144,14 +1107,13 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
spaceUuid: spaceId,
|
spaceUuid: spaceId,
|
||||||
automationName: state.routineName ?? '',
|
automationName: state.routineName ?? '',
|
||||||
decisionExpr: state.selectedAutomationOperator,
|
decisionExpr: state.selectedAutomationOperator,
|
||||||
effectiveTime:
|
effectiveTime: state.effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
|
||||||
state.effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
|
|
||||||
conditions: conditions,
|
conditions: conditions,
|
||||||
actions: actions,
|
actions: actions,
|
||||||
);
|
);
|
||||||
|
|
||||||
final result = await SceneApi.updateAutomation(
|
final result =
|
||||||
createAutomationModel, state.automationId ?? '');
|
await SceneApi.updateAutomation(createAutomationModel, state.automationId ?? '');
|
||||||
|
|
||||||
if (result['success']) {
|
if (result['success']) {
|
||||||
add(ResetRoutineState());
|
add(ResetRoutineState());
|
||||||
@ -1173,7 +1135,6 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
|
|
||||||
FutureOr<void> _onSetAutomationActionExecutor(
|
FutureOr<void> _onSetAutomationActionExecutor(
|
||||||
SetAutomationActionExecutor event, Emitter<RoutineState> emit) {
|
SetAutomationActionExecutor event, Emitter<RoutineState> emit) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(automationActionExecutor: event.automationActionExecutor));
|
||||||
automationActionExecutor: event.automationActionExecutor));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,3 +206,5 @@ class FetchDevicesInRoutine extends RoutineEvent {}
|
|||||||
class ResetRoutineState extends RoutineEvent {}
|
class ResetRoutineState extends RoutineEvent {}
|
||||||
|
|
||||||
class ClearFunctions extends RoutineEvent {}
|
class ClearFunctions extends RoutineEvent {}
|
||||||
|
|
||||||
|
class ResetErrorMessage extends RoutineEvent {}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
@ -6,6 +8,7 @@ import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart';
|
|||||||
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
class SaveRoutineHelper {
|
class SaveRoutineHelper {
|
||||||
static Future<void> showSaveRoutineDialog(BuildContext context) async {
|
static Future<void> showSaveRoutineDialog(BuildContext context) async {
|
||||||
@ -98,18 +101,29 @@ class SaveRoutineHelper {
|
|||||||
final functions =
|
final functions =
|
||||||
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: SvgPicture.asset(
|
leading: item['type'] == 'tap_to_run'
|
||||||
|
? Image.memory(
|
||||||
|
base64Decode(item['icon']),
|
||||||
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
)
|
||||||
|
: SvgPicture.asset(
|
||||||
item['imagePath'],
|
item['imagePath'],
|
||||||
width: 22,
|
width: 22,
|
||||||
height: 22,
|
height: 22,
|
||||||
),
|
),
|
||||||
title:
|
title: Text(
|
||||||
Text(item['title'], style: const TextStyle(fontSize: 14)),
|
item['title'],
|
||||||
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
subtitle: Wrap(
|
subtitle: Wrap(
|
||||||
children: functions
|
children: functions
|
||||||
.map((f) => Text(
|
.map((f) => Text(
|
||||||
'${f.operationName}: ${f.value}, ',
|
'${f.operationName}: ${f.value}, ',
|
||||||
style: const TextStyle(
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
color: ColorsManager.grayColor, fontSize: 8),
|
color: ColorsManager.grayColor, fontSize: 8),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
@ -124,17 +138,17 @@ class SaveRoutineHelper {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (state.errorMessage != null || state.errorMessage!.isNotEmpty)
|
// if (state.errorMessage != null || state.errorMessage!.isNotEmpty)
|
||||||
Padding(
|
// Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
// padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
// child: Text(
|
||||||
state.errorMessage!,
|
// state.errorMessage!,
|
||||||
style: const TextStyle(color: Colors.red),
|
// style: const TextStyle(color: Colors.red),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
DialogFooter(
|
DialogFooter(
|
||||||
onCancel: () => Navigator.pop(context),
|
onCancel: () => Navigator.pop(context),
|
||||||
onConfirm: () {
|
onConfirm: () async {
|
||||||
if (state.isAutomation) {
|
if (state.isAutomation) {
|
||||||
if (state.automationId != null) {
|
if (state.automationId != null) {
|
||||||
context.read<RoutineBloc>().add(const UpdateAutomation());
|
context.read<RoutineBloc>().add(const UpdateAutomation());
|
||||||
@ -148,10 +162,9 @@ class SaveRoutineHelper {
|
|||||||
context.read<RoutineBloc>().add(const CreateSceneEvent());
|
context.read<RoutineBloc>().add(const CreateSceneEvent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (context.read<RoutineBloc>().state.errorMessage == null ||
|
// if (state.errorMessage == null || state.errorMessage!.isEmpty) {
|
||||||
context.read<RoutineBloc>().state.errorMessage!.isEmpty) {
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
isConfirmEnabled: true,
|
isConfirmEnabled: true,
|
||||||
),
|
),
|
||||||
|
@ -32,15 +32,13 @@ class DraggableCard extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final deviceFunctions =
|
final deviceFunctions = state.selectedFunctions[deviceData['uniqueCustomId']] ?? [];
|
||||||
state.selectedFunctions[deviceData['uniqueCustomId']] ?? [];
|
|
||||||
|
|
||||||
return Draggable<Map<String, dynamic>>(
|
return Draggable<Map<String, dynamic>>(
|
||||||
data: deviceData,
|
data: deviceData,
|
||||||
feedback: Transform.rotate(
|
feedback: Transform.rotate(
|
||||||
angle: -0.1,
|
angle: -0.1,
|
||||||
child:
|
child: _buildCardContent(context, deviceFunctions, padding: padding),
|
||||||
_buildCardContent(context, deviceFunctions, padding: padding),
|
|
||||||
),
|
),
|
||||||
childWhenDragging: _buildGreyContainer(),
|
childWhenDragging: _buildGreyContainer(),
|
||||||
child: _buildCardContent(context, deviceFunctions, padding: padding),
|
child: _buildCardContent(context, deviceFunctions, padding: padding),
|
||||||
@ -49,8 +47,7 @@ class DraggableCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCardContent(
|
Widget _buildCardContent(BuildContext context, List<DeviceFunctionData> deviceFunctions,
|
||||||
BuildContext context, List<DeviceFunctionData> deviceFunctions,
|
|
||||||
{EdgeInsetsGeometry? padding}) {
|
{EdgeInsetsGeometry? padding}) {
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
@ -79,16 +76,12 @@ class DraggableCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
child: imagePath.contains('.svg')
|
child: deviceData['type'] == 'tap_to_run'
|
||||||
? SvgPicture.asset(
|
? Image.memory(
|
||||||
imagePath,
|
base64Decode(deviceData['icon']),
|
||||||
)
|
)
|
||||||
: imagePath.contains('.png')
|
: SvgPicture.asset(
|
||||||
? Image.asset(
|
|
||||||
imagePath,
|
imagePath,
|
||||||
)
|
|
||||||
: Image.memory(
|
|
||||||
base64Decode(imagePath),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@ -152,8 +145,7 @@ class DraggableCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _formatFunctionValue(DeviceFunctionData function) {
|
String _formatFunctionValue(DeviceFunctionData function) {
|
||||||
if (function.functionCode == 'temp_set' ||
|
if (function.functionCode == 'temp_set' || function.functionCode == 'temp_current') {
|
||||||
function.functionCode == 'temp_current') {
|
|
||||||
return '${(function.value / 10).toStringAsFixed(0)}°C';
|
return '${(function.value / 10).toStringAsFixed(0)}°C';
|
||||||
} else if (function.functionCode.contains('countdown')) {
|
} else if (function.functionCode.contains('countdown')) {
|
||||||
final seconds = function.value.toInt();
|
final seconds = function.value.toInt();
|
||||||
|
@ -43,6 +43,13 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
|
|||||||
return Wrap(
|
return Wrap(
|
||||||
runSpacing: 16,
|
runSpacing: 16,
|
||||||
children: [
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
state.errorMessage ?? '',
|
||||||
|
style: const TextStyle(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
@ -214,6 +221,7 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
|
|||||||
}
|
}
|
||||||
// final result =
|
// final result =
|
||||||
// await
|
// await
|
||||||
|
BlocProvider.of<RoutineBloc>(context).add(ResetErrorMessage());
|
||||||
SaveRoutineHelper.showSaveRoutineDialog(context);
|
SaveRoutineHelper.showSaveRoutineDialog(context);
|
||||||
// if (result != null && result) {
|
// if (result != null && result) {
|
||||||
// BlocProvider.of<RoutineBloc>(context).add(
|
// BlocProvider.of<RoutineBloc>(context).add(
|
||||||
@ -341,6 +349,7 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
|
|||||||
}
|
}
|
||||||
// final result =
|
// final result =
|
||||||
// await
|
// await
|
||||||
|
BlocProvider.of<RoutineBloc>(context).add(ResetErrorMessage());
|
||||||
SaveRoutineHelper.showSaveRoutineDialog(context);
|
SaveRoutineHelper.showSaveRoutineDialog(context);
|
||||||
// if (result != null && result) {
|
// if (result != null && result) {
|
||||||
// BlocProvider.of<RoutineBloc>(context).add(
|
// BlocProvider.of<RoutineBloc>(context).add(
|
||||||
|
@ -26,9 +26,7 @@ class ThenContainer extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('THEN',
|
const Text('THEN', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18, fontWeight: FontWeight.bold)),
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
state.isLoading && state.isUpdate == true
|
state.isLoading && state.isUpdate == true
|
||||||
? const Center(
|
? const Center(
|
||||||
@ -41,17 +39,12 @@ class ThenContainer extends StatelessWidget {
|
|||||||
state.thenItems.length,
|
state.thenItems.length,
|
||||||
(index) => GestureDetector(
|
(index) => GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (state.thenItems[index]
|
if (state.thenItems[index]['deviceId'] == 'delay') {
|
||||||
['deviceId'] ==
|
final result = await DelayHelper.showDelayPickerDialog(
|
||||||
'delay') {
|
context, state.thenItems[index]);
|
||||||
final result = await DelayHelper
|
|
||||||
.showDelayPickerDialog(context,
|
|
||||||
state.thenItems[index]);
|
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context
|
context.read<RoutineBloc>().add(AddToThenContainer({
|
||||||
.read<RoutineBloc>()
|
|
||||||
.add(AddToThenContainer({
|
|
||||||
...state.thenItems[index],
|
...state.thenItems[index],
|
||||||
'imagePath': Assets.delay,
|
'imagePath': Assets.delay,
|
||||||
'title': 'Delay',
|
'title': 'Delay',
|
||||||
@ -60,76 +53,57 @@ class ThenContainer extends StatelessWidget {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.thenItems[index]['type'] ==
|
if (state.thenItems[index]['type'] == 'automation') {
|
||||||
'automation') {
|
|
||||||
final result = await showDialog<bool>(
|
final result = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) =>
|
builder: (BuildContext context) => AutomationDialog(
|
||||||
AutomationDialog(
|
|
||||||
automationName:
|
automationName:
|
||||||
state.thenItems[index]
|
state.thenItems[index]['name'] ?? 'Automation',
|
||||||
['name'] ??
|
|
||||||
'Automation',
|
|
||||||
automationId:
|
automationId:
|
||||||
state.thenItems[index]
|
state.thenItems[index]['deviceId'] ?? '',
|
||||||
['deviceId'] ??
|
uniqueCustomId: state.thenItems[index]
|
||||||
'',
|
|
||||||
uniqueCustomId:
|
|
||||||
state.thenItems[index]
|
|
||||||
['uniqueCustomId'],
|
['uniqueCustomId'],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context
|
context.read<RoutineBloc>().add(AddToThenContainer({
|
||||||
.read<RoutineBloc>()
|
|
||||||
.add(AddToThenContainer({
|
|
||||||
...state.thenItems[index],
|
...state.thenItems[index],
|
||||||
'imagePath':
|
'imagePath': Assets.automation,
|
||||||
Assets.automation,
|
'title': state.thenItems[index]['name'],
|
||||||
'title': state
|
|
||||||
.thenItems[index]['name'],
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final result = await DeviceDialogHelper
|
final result = await DeviceDialogHelper.showDeviceDialog(
|
||||||
.showDeviceDialog(
|
|
||||||
context, state.thenItems[index],
|
context, state.thenItems[index],
|
||||||
removeComparetors: true);
|
removeComparetors: true);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(
|
context
|
||||||
AddToThenContainer(
|
.read<RoutineBloc>()
|
||||||
state.thenItems[index]));
|
.add(AddToThenContainer(state.thenItems[index]));
|
||||||
} else if (!['AC', '1G', '2G', '3G']
|
} else if (!['AC', '1G', '2G', '3G']
|
||||||
.contains(state.thenItems[index]
|
.contains(state.thenItems[index]['productType'])) {
|
||||||
['productType'])) {
|
context
|
||||||
context.read<RoutineBloc>().add(
|
.read<RoutineBloc>()
|
||||||
AddToThenContainer(
|
.add(AddToThenContainer(state.thenItems[index]));
|
||||||
state.thenItems[index]));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: DraggableCard(
|
child: DraggableCard(
|
||||||
imagePath: state.thenItems[index]
|
imagePath: state.thenItems[index]['imagePath'] ?? '',
|
||||||
['imagePath'] ??
|
title: state.thenItems[index]['title'] ?? '',
|
||||||
'',
|
|
||||||
title: state.thenItems[index]
|
|
||||||
['title'] ??
|
|
||||||
'',
|
|
||||||
deviceData: state.thenItems[index],
|
deviceData: state.thenItems[index],
|
||||||
padding: const EdgeInsets.symmetric(
|
padding:
|
||||||
horizontal: 4, vertical: 8),
|
const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
|
||||||
isFromThen: true,
|
isFromThen: true,
|
||||||
isFromIf: false,
|
isFromIf: false,
|
||||||
onRemove: () {
|
onRemove: () {
|
||||||
context.read<RoutineBloc>().add(
|
context.read<RoutineBloc>().add(RemoveDragCard(
|
||||||
RemoveDragCard(
|
|
||||||
index: index,
|
index: index,
|
||||||
isFromThen: true,
|
isFromThen: true,
|
||||||
key: state.thenItems[index]
|
key: state.thenItems[index]['uniqueCustomId']));
|
||||||
['uniqueCustomId']));
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
))),
|
))),
|
||||||
@ -149,6 +123,12 @@ class ThenContainer extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mutableData['type'] == 'automation') {
|
if (mutableData['type'] == 'automation') {
|
||||||
|
int index =
|
||||||
|
state.thenItems.indexWhere((item) => item['deviceId'] == mutableData['deviceId']);
|
||||||
|
if (index != -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final result = await showDialog<bool>(
|
final result = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) => AutomationDialog(
|
builder: (BuildContext context) => AutomationDialog(
|
||||||
@ -169,6 +149,11 @@ class ThenContainer extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mutableData['type'] == 'tap_to_run' && state.isAutomation) {
|
if (mutableData['type'] == 'tap_to_run' && state.isAutomation) {
|
||||||
|
int index =
|
||||||
|
state.thenItems.indexWhere((item) => item['deviceId'] == mutableData['deviceId']);
|
||||||
|
if (index != -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer({
|
context.read<RoutineBloc>().add(AddToThenContainer({
|
||||||
...mutableData,
|
...mutableData,
|
||||||
'imagePath': Assets.logo,
|
'imagePath': Assets.logo,
|
||||||
@ -183,8 +168,7 @@ class ThenContainer extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mutableData['deviceId'] == 'delay') {
|
if (mutableData['deviceId'] == 'delay') {
|
||||||
final result =
|
final result = await DelayHelper.showDelayPickerDialog(context, mutableData);
|
||||||
await DelayHelper.showDelayPickerDialog(context, mutableData);
|
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer({
|
context.read<RoutineBloc>().add(AddToThenContainer({
|
||||||
@ -196,13 +180,11 @@ class ThenContainer extends StatelessWidget {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final result = await DeviceDialogHelper.showDeviceDialog(
|
final result = await DeviceDialogHelper.showDeviceDialog(context, mutableData,
|
||||||
context, mutableData,
|
|
||||||
removeComparetors: true);
|
removeComparetors: true);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
||||||
} else if (!['AC', '1G', '2G', '3G']
|
} else if (!['AC', '1G', '2G', '3G'].contains(mutableData['productType'])) {
|
||||||
.contains(mutableData['productType'])) {
|
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/navigation_service.dart';
|
import 'package:syncrow_web/utils/navigation_service.dart';
|
||||||
|
|
||||||
class CustomSnackBar {
|
class CustomSnackBar {
|
||||||
@ -11,6 +12,35 @@ class CustomSnackBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static redSnackBar(String message) {
|
||||||
|
final key = NavigationService.snackbarKey;
|
||||||
|
BuildContext? currentContext = key?.currentContext;
|
||||||
|
if (key != null && currentContext != null) {
|
||||||
|
final snackBar = SnackBar(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
backgroundColor: ColorsManager.red,
|
||||||
|
content: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
|
const Icon(
|
||||||
|
Icons.check_circle,
|
||||||
|
color: ColorsManager.whiteColors,
|
||||||
|
size: 32,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
message,
|
||||||
|
style: Theme.of(currentContext)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.green),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
key.currentState?.showSnackBar(snackBar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static greenSnackBar(String message) {
|
static greenSnackBar(String message) {
|
||||||
final key = NavigationService.snackbarKey;
|
final key = NavigationService.snackbarKey;
|
||||||
BuildContext? currentContext = key?.currentContext;
|
BuildContext? currentContext = key?.currentContext;
|
||||||
@ -29,8 +59,10 @@ class CustomSnackBar {
|
|||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
message,
|
message,
|
||||||
style: Theme.of(currentContext).textTheme.bodySmall!.copyWith(
|
style: Theme.of(currentContext)
|
||||||
fontSize: 14, fontWeight: FontWeight.w500, color: Colors.green),
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.green),
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user