push switch autoaomtion status update

This commit is contained in:
ashrafzarkanisala
2024-07-28 06:57:33 +03:00
parent 50b455b4ae
commit eb8ad90dcb
12 changed files with 280 additions and 104 deletions

View File

@ -362,6 +362,7 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
tasksList = List<SceneStaticFunction>.from(
getTaskListFunctionsFromApi(
actions: response.actions, isAutomation: false));
emit(AddSceneTask(
automationTasksList: automationTasksList,
tasksList: tasksList,

View File

@ -13,6 +13,7 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
on<LoadScenes>(_onLoadScenes);
on<LoadAutomation>(_onLoadAutomation);
on<SceneTrigger>(_onSceneTrigger);
on<UpdateAutomationStatus>(_onUpdateAutomationStatus);
}
List<ScenesModel> scenes = [];
@ -26,7 +27,7 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
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'));
@ -53,8 +54,11 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
SceneTrigger event, Emitter<SceneState> emit) async {
final currentState = state;
if (currentState is SceneLoaded) {
emit(SceneLoaded(currentState.scenes, currentState.automationList,
loadingSceneId: event.sceneId));
emit(SceneLoaded(
currentState.scenes,
currentState.automationList,
loadingSceneId: event.sceneId,
));
try {
final success = await SceneApi.triggerScene(event.sceneId);
@ -69,4 +73,39 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
}
}
}
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'));
}
} catch (e) {
emit(const SceneError(message: 'Something went wrong'));
}
}
}
}

View File

@ -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();
@ -34,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];
}

View File

@ -15,11 +15,14 @@ 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.automationList, {this.loadingSceneId});
const SceneLoaded(this.scenes, this.automationList,
{this.loadingSceneId, this.loadingStates = const {}});
@override
List<Object?> get props => [scenes, loadingSceneId, automationList];
List<Object?> get props =>
[scenes, loadingSceneId, automationList, loadingStates];
}
class SceneError extends SceneState {
@ -39,3 +42,7 @@ class SceneTriggerSuccess extends SceneState {
@override
List<Object> get props => [sceneName];
}
class UpdateAutomationStatusLoading extends SceneState {
const UpdateAutomationStatusLoading();
}

View File

@ -66,36 +66,40 @@ mixin SceneLogicHelper {
);
},
),
actions: List.generate(
actions.length,
(index) {
final task = actions[index];
if (task.deviceId == 'delay') {
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: actions[index].deviceId,
actionExecutor: 'delay',
entityId: task.deviceId,
actionExecutor: 'device_issue',
executorProperty: CreateSceneExecutorProperty(
functionCode: '',
functionValue: '',
delaySeconds: task.functionValue,
functionCode: task.code,
functionValue: task.functionValue,
delaySeconds: 0,
),
);
}
return CreateSceneAction(
entityId: task.deviceId,
actionExecutor: 'device_issue',
executorProperty: CreateSceneExecutorProperty(
functionCode: task.code,
functionValue: task.functionValue,
delaySeconds: 0,
),
);
},
)..add(CreateSceneAction(
entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '',
actionExecutor:
smartSceneBloc.smartSceneEnable?.actionExecutor ?? '',
executorProperty: null)),
},
),
if (smartSceneBloc.smartSceneEnable != null)
CreateSceneAction(
entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '',
actionExecutor:
smartSceneBloc.smartSceneEnable?.actionExecutor ?? '',
executorProperty: null)
],
);
sceneBloc.add(CreateSceneWithTasksEvent(
createSceneModel: null,
@ -121,36 +125,40 @@ mixin SceneLogicHelper {
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
sceneName: sceneName.text,
decisionExpr: 'and',
actions: List.generate(
actions.length,
(index) {
final task = actions[index];
if (task.deviceId == 'delay') {
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: actions[index].deviceId,
actionExecutor: 'delay',
entityId: task.deviceId,
actionExecutor: 'device_issue',
executorProperty: CreateSceneExecutorProperty(
functionCode: '',
functionValue: '',
delaySeconds: task.functionValue,
functionCode: task.code,
functionValue: task.functionValue,
delaySeconds: 0,
),
);
}
return CreateSceneAction(
entityId: task.deviceId,
actionExecutor: 'device_issue',
executorProperty: CreateSceneExecutorProperty(
functionCode: task.code,
functionValue: task.functionValue,
delaySeconds: 0,
),
);
},
)..add(CreateSceneAction(
entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '',
actionExecutor:
smartSceneBloc.smartSceneEnable?.actionExecutor ?? '',
executorProperty: null)),
},
),
if (smartSceneBloc.smartSceneEnable != null)
CreateSceneAction(
entityId: smartSceneBloc.smartSceneEnable?.entityId ?? '',
actionExecutor:
smartSceneBloc.smartSceneEnable?.actionExecutor ?? '',
executorProperty: null)
],
);
sceneBloc.add(CreateSceneWithTasksEvent(
createSceneModel: createSceneModel,

View File

@ -32,11 +32,15 @@ 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
? List<Condition>.from(
json["conditions"].map((x) => Condition.fromJson(x)))
? (json["conditions"] as List)
.map((x) => Condition.fromJson(x))
.toList()
: null,
decisionExpr: json["decisionExpr"],
effectiveTime: json["effectiveTime"] != null
@ -69,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,

View File

@ -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,
};
}

View File

@ -98,7 +98,9 @@ class SceneView extends StatelessWidget {
scenes: scenes,
loadingSceneId:
state.loadingSceneId,
disablePLayButton: false,
disablePlayButton: false,
loadingStates: state
.loadingStates, // Add this line
)
: const Center(
child: BodyMedium(
@ -129,7 +131,9 @@ class SceneView extends StatelessWidget {
scenes: automationList,
loadingSceneId:
state.loadingSceneId,
disablePLayButton: true,
disablePlayButton: true,
loadingStates: state
.loadingStates, // Add this line
)
: const Center(
child: BodyMedium(

View File

@ -4,12 +4,15 @@ import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_item.
class SceneGrid extends StatelessWidget {
final List<dynamic> scenes;
final String? loadingSceneId;
final bool disablePLayButton;
final bool disablePlayButton;
final Map<String, bool> loadingStates;
const SceneGrid({
required this.scenes,
required this.loadingSceneId,
required this.disablePlayButton,
required this.loadingStates,
super.key,
required this.disablePLayButton,
});
@override
@ -27,10 +30,14 @@ class SceneGrid extends StatelessWidget {
itemBuilder: (context, index) {
final scene = scenes[index];
final isLoading = loadingSceneId == scene.id;
final isSwitchLoading = loadingStates[scene.id] ?? false;
return SceneItem(
scene: scene,
isLoading: isLoading,
disablePLayButton: disablePLayButton);
scene: scene,
isLoading: isLoading,
disablePlayButton: disablePlayButton,
isSwitchLoading: isSwitchLoading,
);
},
);
}

View File

@ -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,13 +19,15 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SceneItem extends StatelessWidget {
final ScenesModel scene;
final bool isLoading;
final bool disablePLayButton;
final bool isSwitchLoading;
final bool disablePlayButton;
const SceneItem({
required this.scene,
required this.isLoading,
super.key,
required this.disablePLayButton,
required this.disablePlayButton,
required this.isSwitchLoading,
});
@override
@ -33,14 +38,14 @@ class SceneItem extends StatelessWidget {
context,
Routes.sceneTasksRoute,
arguments: SceneSettingsRouteArguments(
sceneType: disablePLayButton == false
sceneType: disablePlayButton == false
? CreateSceneEnum.tabToRun.name
: CreateSceneEnum.deviceStatusChanges.name,
sceneId: scene.id,
sceneName: scene.name,
),
);
if (disablePLayButton == false) {
if (disablePlayButton == false) {
BlocProvider.of<CreateSceneBloc>(context)
.add(const SceneTypeEvent(CreateSceneEnum.tabToRun));
BlocProvider.of<CreateSceneBloc>(context).add(
@ -66,26 +71,45 @@ class SceneItem extends StatelessWidget {
Assets.assetsIconsLogo,
fit: BoxFit.fill,
),
Visibility(
visible: disablePLayButton == false,
child: IconButton(
padding: EdgeInsets.zero,
onPressed: () {
context
.read<SceneBloc>()
.add(SceneTrigger(scene.id, scene.name));
},
icon: isLoading
? const Center(
child: CircularProgressIndicator(),
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,
),
)
: const Icon(
Icons.play_circle,
size: 40,
color: ColorsManager.greyColor,
: 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),