fixed automation

This commit is contained in:
hannathkadher
2024-11-02 23:10:24 +04:00
parent dcccc4db3a
commit 87a4a88417
13 changed files with 240 additions and 132 deletions

View File

@ -32,6 +32,7 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
final allDevices = await HomeManagementAPI.fetchDevicesByUnitId();
emit(state.copyWith(devices: allDevices, loading: false));
} catch (e) {
print(e);
emit(state.copyWith(error: e.toString(), loading: false));
}
}

View File

@ -60,7 +60,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
String selectedIcon = '';
bool showInDeviceScreen = false;
FutureOr<void> _onAddSceneTask(AddTaskEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _onAddSceneTask(
AddTaskEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
final copyList = List<SceneStaticFunction>.from(automationTempTasksList);
@ -95,7 +96,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
}
}
void addToTempTaskList(TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
void addToTempTaskList(
TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
bool updated = false;
@ -180,7 +182,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
));
}
void addToTempAutomationTaskList(TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
void addToTempAutomationTaskList(
TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
bool updated = false;
for (var element in automationTempTasksList) {
@ -202,8 +205,10 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
],
comparator: automationComparatorValues[element.code],
);
automationTempTasksList[automationTempTasksList.indexOf(element)] = updatedElement;
automationSelectedValues[updatedElement.code] = event.deviceControlModel.value;
automationTempTasksList[automationTempTasksList.indexOf(element)] =
updatedElement;
automationSelectedValues[updatedElement.code] =
event.deviceControlModel.value;
updated = true;
break;
}
@ -223,10 +228,12 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
icon: '',
),
],
comparator: automationComparatorValues[event.deviceControlModel.code] ?? '==',
comparator:
automationComparatorValues[event.deviceControlModel.code] ?? '==',
);
automationTempTasksList.add(newElement);
automationSelectedValues[newElement.code] = event.deviceControlModel.value;
automationSelectedValues[newElement.code] =
event.deviceControlModel.value;
}
emit(AddSceneTask(
tasksList: tasksList,
@ -235,7 +242,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
));
}
FutureOr<void> _selectedValue(SelectedValueEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _selectedValue(
SelectedValueEvent event, Emitter<CreateSceneState> emit) {
if (event.isAutomation == true) {
automationSelectedValues[event.code] = event.value;
automationComparatorValues[event.code] = event.comparator ?? '==';
@ -272,7 +280,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
));
}
FutureOr<void> _removeTaskById(RemoveTaskByIdEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _removeTaskById(
RemoveTaskByIdEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
for (var element in automationTasksList) {
@ -345,7 +354,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
: await SceneApi.createScene(event.createSceneModel!);
} else if (event.createAutomationModel != null) {
response = event.updateScene
? await SceneApi.updateAutomation(event.createAutomationModel!, event.sceneId)
? await SceneApi.updateAutomation(
event.createAutomationModel!, event.sceneId)
: await SceneApi.createAutomation(event.createAutomationModel!);
}
@ -359,12 +369,14 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
automationComparatorValues.clear();
selectedIcon = '';
showInDeviceScreen = false;
effectiveTime = EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
effectiveTime =
EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
sceneType = CreateSceneEnum.none;
conditionRule = 'or';
emit(const CreateSceneWithTasks(success: true));
CustomSnackBar.greenSnackBar(
event.updateScene ? 'Scene updated successfully' : 'Scene created successfully');
CustomSnackBar.greenSnackBar(event.updateScene
? 'Scene updated successfully'
: 'Scene created successfully');
} else {
emit(const CreateSceneError(message: 'Something went wrong'));
}
@ -378,7 +390,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
}
}
FutureOr<void> _clearTaskList(ClearTaskListEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _clearTaskList(
ClearTaskListEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
automationTasksList.clear();
tasksList.clear();
@ -389,7 +402,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
));
}
FutureOr<void> _clearTabToRunSetting(ClearTabToRunSetting event, Emitter<CreateSceneState> emit) {
FutureOr<void> _clearTabToRunSetting(
ClearTabToRunSetting event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
selectedIcon = '';
showInDeviceScreen = false;
@ -416,7 +430,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
automationComparatorValues.clear();
selectedIcon = '';
showInDeviceScreen = false;
effectiveTime = EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
effectiveTime =
EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
sceneType = CreateSceneEnum.none;
conditionRule = 'or';
@ -425,10 +440,14 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
: await SceneApi.getSceneDetails(event.sceneId);
if (response.id.isNotEmpty) {
if (event.isAutomation) {
automationTasksList = List<SceneStaticFunction>.from(getTaskListFunctionsFromApi(
actions: [], isAutomation: true, conditions: response.conditions));
automationTasksList = List<SceneStaticFunction>.from(
getTaskListFunctionsFromApi(
actions: [],
isAutomation: true,
conditions: response.conditions));
tasksList = List<SceneStaticFunction>.from(
getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false));
getTaskListFunctionsFromApi(
actions: response.actions, isAutomation: false));
conditionRule = response.decisionExpr ?? conditionRule;
@ -441,11 +460,13 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
: EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
// Set the days directly from the API response
BlocProvider.of<EffectPeriodBloc>(NavigationService.navigatorKey.currentContext!)
BlocProvider.of<EffectPeriodBloc>(
NavigationService.navigatorKey.currentContext!)
.add(SetDays(response.effectiveTime?.loops ?? '1111111'));
// Set Custom Time and reset days first
BlocProvider.of<EffectPeriodBloc>(NavigationService.navigatorKey.currentContext!)
BlocProvider.of<EffectPeriodBloc>(
NavigationService.navigatorKey.currentContext!)
.add(SetCustomTime(effectiveTime!.start, effectiveTime!.end));
emit(AddSceneTask(
@ -457,7 +478,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
showInDevice: showInDeviceScreen));
} else {
tasksList = List<SceneStaticFunction>.from(
getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false));
getTaskListFunctionsFromApi(
actions: response.actions, isAutomation: false));
selectedIcon = response.icon!;
showInDeviceScreen = response.showInDevice!;
emit(AddSceneTask(
@ -475,7 +497,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
}
}
FutureOr<void> _fetchIconScene(SceneIconEvent event, Emitter<CreateSceneState> emit) async {
FutureOr<void> _fetchIconScene(
SceneIconEvent event, Emitter<CreateSceneState> emit) async {
emit(CreateSceneLoading());
try {
iconModelList = await SceneApi.getIcon();
@ -491,7 +514,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
}
}
FutureOr<void> _iconSelected(IconSelected event, Emitter<CreateSceneState> emit) async {
FutureOr<void> _iconSelected(
IconSelected event, Emitter<CreateSceneState> emit) async {
try {
if (event.confirmSelection) {
selectedIcon = event.iconId;
@ -531,7 +555,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
return days[index];
}
FutureOr<void> _clearTempTaskList(ClearTempTaskListEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _clearTempTaskList(
ClearTempTaskListEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
automationTempTasksList.clear();
@ -575,13 +600,18 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
}
}
FutureOr<void> _deleteScene(DeleteSceneEvent event, Emitter<CreateSceneState> emit) async {
FutureOr<void> _deleteScene(
DeleteSceneEvent event, Emitter<CreateSceneState> emit) async {
emit(DeleteSceneLoading());
try {
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);
final response =
sceneType.name == CreateSceneEnum.deviceStatusChanges.name
? await SceneApi.deleteAutomation(
automationId: event.sceneId, unitUuid: event.unitUuid)
: await SceneApi.deleteScene(
sceneId: event.sceneId,
);
if (response == true) {
emit(const DeleteSceneSuccess(true));
} else {
@ -592,7 +622,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
}
}
FutureOr<void> _updateTaskValue(UpdateTaskEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _updateTaskValue(
UpdateTaskEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
if (event.isAutomation == true) {
for (var i = 0; i < automationTasksList.length; i++) {
@ -628,7 +659,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
));
}
FutureOr<void> _selectConditionRule(SelectConditionEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _selectConditionRule(
SelectConditionEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneInitial());
if (event.condition.contains('any')) {
conditionRule = 'or';
@ -643,7 +675,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
));
}
FutureOr<void> _sceneTypeEvent(SceneTypeEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _sceneTypeEvent(
SceneTypeEvent event, Emitter<CreateSceneState> emit) {
// emit(CreateSceneInitial());
if (event.type == CreateSceneEnum.tabToRun) {

View File

@ -24,7 +24,9 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
try {
if (event.unitId.isNotEmpty) {
scenes = await SceneApi.getScenesByUnitId(event.unitId, showInDevice: event.showInDevice);
scenes = await SceneApi.getScenesByUnitId(
event.unitId, event.unit.community.uuid,
showInDevice: event.showInDevice);
emit(SceneLoaded(scenes, automationList));
} else {
emit(const SceneError(message: 'Unit ID is empty'));
@ -34,7 +36,8 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
}
}
Future<void> _onLoadAutomation(LoadAutomation event, Emitter<SceneState> emit) async {
Future<void> _onLoadAutomation(
LoadAutomation event, Emitter<SceneState> emit) async {
emit(SceneLoading());
try {
@ -49,7 +52,8 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
}
}
Future<void> _onSceneTrigger(SceneTrigger event, Emitter<SceneState> emit) async {
Future<void> _onSceneTrigger(
SceneTrigger event, Emitter<SceneState> emit) async {
final currentState = state;
if (currentState is SceneLoaded) {
emit(SceneLoaded(
@ -76,8 +80,9 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
UpdateAutomationStatus event, Emitter<SceneState> emit) async {
final currentState = state;
if (currentState is SceneLoaded) {
final newLoadingStates = Map<String, bool>.from(currentState.loadingStates)
..[event.automationId] = true;
final newLoadingStates =
Map<String, bool>.from(currentState.loadingStates)
..[event.automationId] = true;
emit(SceneLoaded(
currentState.scenes,
@ -86,11 +91,11 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
));
try {
final success =
await SceneApi.updateAutomationStatus(event.automationId, event.automationStatusUpdate);
final success = await SceneApi.updateAutomationStatus(
event.automationId, event.automationStatusUpdate);
if (success) {
automationList =
await SceneApi.getAutomationByUnitId(event.automationStatusUpdate.unitUuid);
automationList = await SceneApi.getAutomationByUnitId(
event.automationStatusUpdate.unitUuid);
newLoadingStates[event.automationId] = false;
emit(SceneLoaded(
currentState.scenes,

View File

@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/scene/model/update_automation.dart';
abstract class SceneEvent extends Equatable {
@ -11,8 +12,9 @@ abstract class SceneEvent extends Equatable {
class LoadScenes extends SceneEvent {
final String unitId;
final bool showInDevice;
final SpaceModel unit;
const LoadScenes(this.unitId, {this.showInDevice = false});
const LoadScenes(this.unitId, this.unit, {this.showInDevice = false});
@override
List<Object> get props => [unitId, showInDevice];

View File

@ -39,7 +39,7 @@ class CreateAutomationModel {
Map<String, dynamic> toMap([String? automationId]) {
return {
if (automationId == null) 'unitUuid': unitUuid,
if (automationId == null) 'spaceUuid': unitUuid,
'automationName': automationName,
'decisionExpr': decisionExpr,
'effectiveTime': effectiveTime.toMap(),
@ -50,7 +50,7 @@ class CreateAutomationModel {
factory CreateAutomationModel.fromMap(Map<String, dynamic> map) {
return CreateAutomationModel(
unitUuid: map['unitUuid'] ?? '',
unitUuid: map['spaceUuid'] ?? '',
automationName: map['automationName'] ?? '',
decisionExpr: map['decisionExpr'] ?? '',
effectiveTime: EffectiveTime.fromMap(map['effectiveTime']),

View File

@ -25,28 +25,34 @@ class SceneDetailsModel {
this.effectiveTime,
});
factory SceneDetailsModel.fromRawJson(String str) => SceneDetailsModel.fromJson(json.decode(str));
factory SceneDetailsModel.fromRawJson(String str) =>
SceneDetailsModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory SceneDetailsModel.fromJson(Map<String, dynamic> json) => SceneDetailsModel(
id: json["id"],
name: json["name"],
status: json["status"],
type: json["type"],
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,
icon: json["iconUuid"] != null ? json["iconUuid"] ?? '' : '',
showInDevice: json['showInHome'] != null ? json['showInHome'] ?? false : false);
factory SceneDetailsModel.fromJson(Map<String, dynamic> json) =>
SceneDetailsModel(
id: json["uuid"],
name: json["name"],
status: json["status"],
type: json["type"],
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,
icon: json["iconUuid"] != null ? json["iconUuid"] ?? '' : '',
showInDevice:
json['showInHome'] != null ? json['showInHome'] ?? false : false);
Map<String, dynamic> toJson() => {
"id": id,
@ -54,8 +60,9 @@ 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,
"conditions": conditions != null
? List<dynamic>.from(conditions!.map((x) => x.toJson()))
: null,
"decisionExpr": decisionExpr,
"effectiveTime": effectiveTime?.toJson(),
};
@ -116,7 +123,8 @@ class ExecutorProperty {
this.delaySeconds,
});
factory ExecutorProperty.fromJson(Map<String, dynamic> json) => ExecutorProperty(
factory ExecutorProperty.fromJson(Map<String, dynamic> json) =>
ExecutorProperty(
functionCode: json["functionCode"] ?? '',
functionValue: json["functionValue"] ?? '',
delaySeconds: json["delaySeconds"] ?? 0,
@ -142,7 +150,8 @@ class Condition {
required this.expr,
});
factory Condition.fromRawJson(String str) => Condition.fromJson(json.decode(str));
factory Condition.fromRawJson(String str) =>
Condition.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
@ -200,7 +209,8 @@ class EffectiveTime {
required this.loops,
});
factory EffectiveTime.fromRawJson(String str) => EffectiveTime.fromJson(json.decode(str));
factory EffectiveTime.fromRawJson(String str) =>
EffectiveTime.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());

View File

@ -3,32 +3,40 @@ import 'dart:typed_data';
class ScenesModel {
final String id;
final String? sceneTuyaId;
final String name;
final String status;
final String type;
final String icon;
final String? icon;
ScenesModel(
{required this.id,
this.sceneTuyaId,
required this.name,
required this.status,
required this.type,
required this.icon});
this.icon});
factory ScenesModel.fromRawJson(String str) => ScenesModel.fromJson(json.decode(str));
factory ScenesModel.fromRawJson(String str) =>
ScenesModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
Uint8List get iconInBytes => base64Decode(icon);
factory ScenesModel.fromJson(Map<String, dynamic> json) => ScenesModel(
id: json["uuid"],
name: json["name"] ?? '',
status: json["status"] ?? '',
type: json["type"] ?? '',
icon: json["icon"] ?? '');
Uint8List get iconInBytes => base64Decode(icon ?? '');
factory ScenesModel.fromJson(Map<String, dynamic> json) {
return ScenesModel(
id: json["id"] ?? json["uuid"] ?? '', // Fallback to empty string if id is null
sceneTuyaId: json["sceneTuyaId"] as String?, // Nullable
name: json["name"] ?? '', // Fallback to empty string if name is null
status:
json["status"] ?? '', // Fallback to empty string if status is null
type: json["type"] ?? '', // Fallback to empty string if type is null
icon: json["icon"] as String?, // Nullable
);
}
Map<String, dynamic> toJson() => {
"id": id,
"sceneTuyaId": sceneTuyaId ?? '',
"name": name,
"status": status,
"type": type,

View File

@ -1,6 +1,8 @@
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/app_layout/model/community_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
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';
@ -21,32 +23,47 @@ class SceneView extends StatelessWidget {
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => SceneBloc()
..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '', showInDevice: pageType))
..add(LoadScenes(
HomeCubit.getInstance().selectedSpace?.id ?? '',
HomeCubit.getInstance().selectedSpace ??
SpaceModel(
id: '-1',
name: '',
community: Community(
uuid: '-1',
name: '',
)),
showInDevice: pageType))
..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!,HomeCubit.getInstance().selectedSpace!,
showInDevice: pageType));
BlocProvider.of<SceneBloc>(context).add(
LoadScenes(HomeCubit.getInstance().selectedSpace!.id!, showInDevice: pageType));
BlocProvider.of<SceneBloc>(context)
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
}
}
if (state is CreateSceneWithTasks) {
if (state.success == true) {
BlocProvider.of<SceneBloc>(context).add(LoadScenes(
HomeCubit.getInstance().selectedSpace!.id!,HomeCubit.getInstance().selectedSpace!,
showInDevice: pageType));
BlocProvider.of<SceneBloc>(context).add(
LoadScenes(HomeCubit.getInstance().selectedSpace!.id!, showInDevice: pageType));
BlocProvider.of<SceneBloc>(context)
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent());
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
context
.read<SmartSceneSelectBloc>()
.add(const SmartSceneClearEvent());
}
}
return BlocListener<SceneBloc, SceneState>(
listener: (context, state) {
if (state is SceneTriggerSuccess) {
context.showCustomSnackbar(
message: 'Scene ${state.sceneName} triggered successfully!');
message:
'Scene ${state.sceneName} triggered successfully!');
}
},
child: HomeCubit.getInstance().spaces?.isEmpty ?? true
@ -83,25 +100,30 @@ class SceneView extends StatelessWidget {
child: ListView(
children: [
Theme(
data: ThemeData()
.copyWith(dividerColor: Colors.transparent),
data: ThemeData().copyWith(
dividerColor: Colors.transparent),
child: ExpansionTile(
tilePadding: const EdgeInsets.symmetric(horizontal: 6),
tilePadding:
const EdgeInsets.symmetric(
horizontal: 6),
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
title: const BodyMedium(text: 'Tap to run routines'),
title: const BodyMedium(
text: 'Tap to run routines'),
children: [
scenes.isNotEmpty
? SceneGrid(
scenes: scenes,
loadingSceneId: state.loadingSceneId,
loadingSceneId:
state.loadingSceneId,
disablePlayButton: false,
loadingStates:
state.loadingStates, // Add this line
loadingStates: state
.loadingStates, // Add this line
)
: const Center(
child: BodyMedium(
text: 'No scenes have been added yet',
text:
'No scenes have been added yet',
),
),
const SizedBox(
@ -111,25 +133,30 @@ class SceneView extends StatelessWidget {
),
),
Theme(
data: ThemeData()
.copyWith(dividerColor: Colors.transparent),
data: ThemeData().copyWith(
dividerColor: Colors.transparent),
child: ExpansionTile(
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
tilePadding: const EdgeInsets.symmetric(horizontal: 6),
title: const BodyMedium(text: 'Automation'),
tilePadding:
const EdgeInsets.symmetric(
horizontal: 6),
title: const BodyMedium(
text: 'Automation'),
children: [
automationList.isNotEmpty
? SceneGrid(
scenes: automationList,
loadingSceneId: state.loadingSceneId,
loadingSceneId:
state.loadingSceneId,
disablePlayButton: true,
loadingStates:
state.loadingStates, // Add this line
loadingStates: state
.loadingStates, // Add this line
)
: const Center(
child: BodyMedium(
text: 'No automations have been added yet',
text:
'No automations have been added yet',
),
),
const SizedBox(

View File

@ -24,7 +24,7 @@ class DeleteRoutineButton extends StatelessWidget {
if (state.success) {
navigateToRoute(context, Routes.homeRoute);
BlocProvider.of<SceneBloc>(context)
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!,HomeCubit.getInstance().selectedSpace!));
BlocProvider.of<SceneBloc>(context).add(
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
}

View File

@ -17,7 +17,7 @@ class SmartEnableTabRun extends StatelessWidget {
width: double.infinity,
child: BlocBuilder<SceneBloc, SceneState>(
bloc: context.read<SceneBloc>()
..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '')),
..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '',HomeCubit.getInstance().selectedSpace!)),
builder: (context, state) {
if (state is SceneLoading) {
return const Align(

View File

@ -150,9 +150,9 @@ class DevicesAPI {
}) async {
try {
final String path = ApiEndpoints.deviceByRoom
.replaceAll(':communityUuid', communityUuid)
.replaceAll(':spaceUuid', spaceUuid)
.replaceAll(':subSpaceUuid', roomId);
.replaceAll('{communityUuid}', communityUuid)
.replaceAll('{spaceUuid}', spaceUuid)
.replaceAll('{subSpaceUuid}', roomId);
final response = await _httpService.get(
path: path,

View File

@ -37,15 +37,17 @@ class HomeManagementAPI {
// Ensure both placeholders are replaced
final path = ApiEndpoints.spaceDevices
.replaceAll("{communityUuid}", communityUuid)
.replaceAll("{spaceUuid}", spaceUuid);
.replaceAll('{communityUuid}', communityUuid)
.replaceAll('{spaceUuid}', spaceUuid);
await _httpService.get(
path: path,
showServerMessage: false,
expectedResponseModel: (json) {
json.forEach((value) {
list.add(DeviceModel.fromJson(value));
});
if (json['data'] != null) {
json['data'].forEach((value) {
list.add(DeviceModel.fromJson(value));
});
}
},
);

View File

@ -1,3 +1,5 @@
import 'dart:convert';
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/icon_model.dart';
@ -11,7 +13,8 @@ class SceneApi {
static final HTTPService _httpService = HTTPService();
//create scene
static Future<Map<String, dynamic>> createScene(CreateSceneModel createSceneModel) async {
static Future<Map<String, dynamic>> createScene(
CreateSceneModel createSceneModel) async {
try {
final response = await _httpService.post(
path: ApiEndpoints.createScene,
@ -47,15 +50,21 @@ class SceneApi {
//get scene by unit id
static Future<List<ScenesModel>> getScenesByUnitId(String unitId, {showInDevice = false}) async {
static Future<List<ScenesModel>> getScenesByUnitId(
String unitId, String communityId,
{showInDevice = false}) async {
try {
final response = await _httpService.get(
path: ApiEndpoints.getUnitScenes.replaceAll('{unitUuid}', unitId),
path: ApiEndpoints.getUnitScenes
.replaceAll('{spaceUuid}', unitId)
.replaceAll('{communityUuid}', communityId),
queryParameters: {'showInHomePage': showInDevice},
showServerMessage: false,
expectedResponseModel: (json) {
final scenesJson = json['data'] as List;
List<ScenesModel> scenes = [];
for (var scene in json) {
for (var scene in scenesJson) {
scenes.add(ScenesModel.fromJson(scene));
}
return scenes;
@ -102,10 +111,12 @@ class SceneApi {
}
//automation details
static Future<SceneDetailsModel> getAutomationDetails(String automationId) async {
static Future<SceneDetailsModel> getAutomationDetails(
String automationId) async {
try {
final response = await _httpService.get(
path: ApiEndpoints.getAutomationDetails.replaceAll('{automationId}', automationId),
path: ApiEndpoints.getAutomationDetails
.replaceAll('{automationId}', automationId),
showServerMessage: false,
expectedResponseModel: (json) => SceneDetailsModel.fromJson(json),
);
@ -116,11 +127,12 @@ class SceneApi {
}
//updateAutomationStatus
static Future<bool> updateAutomationStatus(
String automationId, AutomationStatusUpdate createAutomationEnable) async {
static Future<bool> updateAutomationStatus(String automationId,
AutomationStatusUpdate createAutomationEnable) async {
try {
final response = await _httpService.put(
path: ApiEndpoints.updateAutomationStatus.replaceAll('{automationId}', automationId),
path: ApiEndpoints.updateAutomationStatus
.replaceAll('{automationId}', automationId),
body: createAutomationEnable.toMap(),
expectedResponseModel: (json) => json['success'],
);
@ -135,7 +147,13 @@ class SceneApi {
final response = await _httpService.get(
path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId),
showServerMessage: false,
expectedResponseModel: (json) => SceneDetailsModel.fromJson(json),
expectedResponseModel: (json) {
if (json != null && json['data'] != null) {
return SceneDetailsModel.fromJson(json['data']);
} else {
throw Exception('Data field is null');
}
},
);
return response;
} catch (e) {
@ -163,7 +181,8 @@ class SceneApi {
try {
final response = await _httpService.put(
path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId),
body: createSceneModel.toJson(sceneId.isNotEmpty == true ? sceneId : null),
body: createSceneModel
.toJson(sceneId.isNotEmpty == true ? sceneId : null),
expectedResponseModel: (json) {
return json;
},
@ -175,11 +194,14 @@ class SceneApi {
}
//update automation
static updateAutomation(CreateAutomationModel createAutomationModel, String automationId) async {
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),
path: ApiEndpoints.updateAutomation
.replaceAll('{automationId}', automationId),
body: createAutomationModel
.toJson(automationId.isNotEmpty == true ? automationId : null),
expectedResponseModel: (json) {
return json;
},
@ -192,12 +214,10 @@ class SceneApi {
//delete Scene
static Future<bool> deleteScene({required String unitUuid, required String sceneId}) async {
static Future<bool> deleteScene({required String sceneId}) async {
try {
final response = await _httpService.delete(
path: ApiEndpoints.deleteScene
.replaceAll('{sceneId}', sceneId)
.replaceAll('{unitUuid}', unitUuid),
path: ApiEndpoints.deleteScene.replaceAll('{sceneId}', sceneId),
showServerMessage: false,
expectedResponseModel: (json) => json['statusCode'] == 200,
);