mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-16 01:56:19 +00:00
push switch autoaomtion status update
This commit is contained in:
@ -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,
|
||||
|
@ -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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
38
lib/features/scene/model/update_automation.dart
Normal file
38
lib/features/scene/model/update_automation.dart
Normal 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,
|
||||
};
|
||||
}
|
@ -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(
|
||||
|
@ -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,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -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),
|
||||
|
Reference in New Issue
Block a user