Merge pull request #32 from SyncrowIOT/scene_bug

Scene bug
This commit is contained in:
Abdullah
2024-07-02 13:54:57 +03:00
committed by GitHub
22 changed files with 254 additions and 201 deletions

View File

@ -5,7 +5,9 @@
<application
android:label="syncrow_app"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
>
<activity
android:name=".MainActivity"
android:exported="true"

View File

@ -274,35 +274,39 @@ class AuthCubit extends Cubit<AuthState> {
}
getTokenAndValidate() async {
emit(AuthTokenLoading());
const storage = FlutterSecureStorage();
final firstLaunch =
await SharedPreferencesHelper.readBoolFromSP(StringsManager.firstLaunch) ?? true;
try {
emit(AuthTokenLoading());
const storage = FlutterSecureStorage();
final firstLaunch =
await SharedPreferencesHelper.readBoolFromSP(StringsManager.firstLaunch) ?? true;
if (firstLaunch) {
storage.deleteAll();
}
await SharedPreferencesHelper.saveBoolToSP(StringsManager.firstLaunch, false);
final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
if (value.isEmpty) {
emit(AuthTokenError(message: "Token not found"));
return;
}
final tokenData = Token.decodeToken(value);
if (tokenData.containsKey('exp')) {
final exp = tokenData['exp'] ?? 0;
final currentTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;
if (currentTime < exp) {
emit(AuthTokenSuccess());
} else {
emit(AuthTokenError(message: "Token expired"));
if (firstLaunch) {
storage.deleteAll();
}
} else {
await SharedPreferencesHelper.saveBoolToSP(StringsManager.firstLaunch, false);
final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
if (value.isEmpty) {
emit(AuthTokenError(message: "Token not found"));
return;
}
final tokenData = Token.decodeToken(value);
if (tokenData.containsKey('exp')) {
final exp = tokenData['exp'] ?? 0;
final currentTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;
if (currentTime < exp) {
emit(AuthTokenSuccess());
} else {
emit(AuthTokenError(message: "Token expired"));
}
} else {
emit(AuthTokenError(message: "Something went wrong"));
}
} catch (_) {
emit(AuthTokenError(message: "Something went wrong"));
}
}

View File

@ -25,11 +25,10 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
static List<DevicesCategoryModel>? allCategories;
Future<void> _onFetchAllDevices(
FetchAllDevices event, Emitter<DeviceManagerState> emit) async {
Future<void> _onFetchAllDevices(FetchAllDevices event, Emitter<DeviceManagerState> emit) async {
emit(state.copyWith(loading: true));
try {
final allDevices = await HomeManagementAPI.fetchDevicesByUserId();
final allDevices = await HomeManagementAPI.fetchDevicesByUnitId();
emit(state.copyWith(devices: allDevices, loading: false));
} catch (e) {
emit(state.copyWith(error: e.toString(), loading: false));
@ -47,16 +46,14 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
}
}
void _onSelectCategory(
SelectCategory event, Emitter<DeviceManagerState> emit) {
void _onSelectCategory(SelectCategory event, Emitter<DeviceManagerState> emit) {
for (var i = 0; i < allCategories!.length; i++) {
allCategories![i].isSelected = i == event.index;
}
emit(state.copyWith(categoryChanged: true));
}
void _onUnselectAllCategories(
UnselectAllCategories event, Emitter<DeviceManagerState> emit) {
void _onUnselectAllCategories(UnselectAllCategories event, Emitter<DeviceManagerState> emit) {
for (var category in allCategories!) {
category.isSelected = false;
}
@ -100,8 +97,7 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
_updateDevicesStatus(category, emit);
}
void _onTurnOnOffDevice(
TurnOnOffDevice event, Emitter<DeviceManagerState> emit) {
void _onTurnOnOffDevice(TurnOnOffDevice event, Emitter<DeviceManagerState> emit) {
var device = event.device;
device.isOnline = !device.isOnline!;
DevicesCategoryModel category = allCategories!.firstWhere((category) {
@ -124,8 +120,7 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
emit(state.copyWith(categoryChanged: true)); // Set category changed state
}
void _updateDevicesStatus(
DevicesCategoryModel category, Emitter<DeviceManagerState> emit) {
void _updateDevicesStatus(DevicesCategoryModel category, Emitter<DeviceManagerState> emit) {
if (category.devices != null && category.devices!.isNotEmpty) {
bool? tempStatus = category.devices![0].isOnline;
for (var device in category.devices!) {
@ -145,8 +140,7 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
try {
final deviceFunctions = await DevicesAPI.deviceFunctions(event.deviceId);
emit(state.copyWith(
functionsLoading: false, deviceFunctions: deviceFunctions));
emit(state.copyWith(functionsLoading: false, deviceFunctions: deviceFunctions));
} catch (e) {
emit(state.copyWith(functionsLoading: false, error: e.toString()));
}

View File

@ -30,8 +30,7 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
List<SceneStaticFunction> tempTasksList = [];
final Map<String, dynamic> selectedValues = {};
FutureOr<void> _onAddSceneTask(
AddTaskEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _onAddSceneTask(AddTaskEvent event, Emitter<CreateSceneState> emit) {
final copyList = List<SceneStaticFunction>.from(tempTasksList);
tasksList.addAll(copyList);
tempTasksList.clear();
@ -87,16 +86,16 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
}
emit(TempHoldSceneTask(tempTasksList: tempTasksList));
emit(AddSceneTask(tasksList: tasksList));
}
FutureOr<void> _selectedValue(
SelectedValueEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _selectedValue(SelectedValueEvent event, Emitter<CreateSceneState> emit) {
selectedValues[event.code] = event.value;
emit(SelectedTaskValueState(value: event.value));
emit(AddSceneTask(tasksList: tasksList));
}
FutureOr<void> _removeTaskById(
RemoveTaskByIdEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _removeTaskById(RemoveTaskByIdEvent event, Emitter<CreateSceneState> emit) {
emit(CreateSceneLoading());
for (var element in tasksList) {
@ -116,6 +115,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
tempTasksList.remove(element);
emit(TempHoldSceneTask(tempTasksList: tempTasksList));
emit(AddSceneTask(tasksList: tasksList));
break;
}
}
@ -141,8 +142,7 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
}
}
FutureOr<void> _clearTaskList(
ClearTaskListEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _clearTaskList(ClearTaskListEvent event, Emitter<CreateSceneState> emit) {
tasksList.clear();
emit(AddSceneTask(tasksList: tasksList));
}
@ -154,8 +154,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
try {
final response = await SceneApi.getSceneDetails(event.sceneId);
if (response.id.isNotEmpty) {
tasksList = List<SceneStaticFunction>.from(getTaskListFunctionsFromApi(
actions: response.actions, deviceId: response.id));
tasksList =
List<SceneStaticFunction>.from(getTaskListFunctionsFromApi(actions: response.actions));
emit(AddSceneTask(
tasksList: tasksList,
));
@ -167,11 +167,11 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
}
}
FutureOr<void> _clearTempTaskList(
ClearTempTaskListEvent event, Emitter<CreateSceneState> emit) {
FutureOr<void> _clearTempTaskList(ClearTempTaskListEvent event, Emitter<CreateSceneState> emit) {
tempTasksList.clear();
selectedValues.clear();
emit(TempHoldSceneTask(tempTasksList: tempTasksList));
emit(AddSceneTask(tasksList: tempTasksList));
}
FutureOr<void> _removeFromSelectedValueById(
@ -179,16 +179,15 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
if (selectedValues.containsKey(event.code)) {
selectedValues.remove(event.code);
emit(const SelectedTaskValueState(value: null));
emit(AddSceneTask(tasksList: tasksList));
}
}
FutureOr<void> _deleteScene(
DeleteSceneEvent event, Emitter<CreateSceneState> emit) async {
FutureOr<void> _deleteScene(DeleteSceneEvent event, Emitter<CreateSceneState> emit) async {
emit(DeleteSceneLoading());
try {
final response = await SceneApi.deleteScene(
sceneId: event.sceneId, unitUuid: event.unitUuid);
final response = await SceneApi.deleteScene(sceneId: event.sceneId, unitUuid: event.unitUuid);
if (response == true) {
emit(const DeleteSceneSuccess(true));
} else {

View File

@ -8,8 +8,6 @@ sealed class CreateSceneEvent extends Equatable {
}
class AddTaskEvent extends CreateSceneEvent {
final bool updateTaskListFromTemp;
const AddTaskEvent({required this.updateTaskListFromTemp});
@override
List<Object> get props => [];
}

View File

@ -18,15 +18,18 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
emit(SceneLoading());
try {
final scenes = await SceneApi.getScenesByUnitId(event.unitId);
emit(SceneLoaded(scenes));
if (event.unitId.isNotEmpty) {
final scenes = await SceneApi.getScenesByUnitId(event.unitId);
emit(SceneLoaded(scenes));
} else {
const SceneError(message: '');
}
} catch (e) {
emit(const SceneError(message: 'Something went wrong'));
}
}
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(currentState.scenes, loadingSceneId: event.sceneId));

View File

@ -15,7 +15,8 @@ import 'package:syncrow_app/utils/context_extension.dart';
mixin SceneLogicHelper {
bool isOnlyDelayOrDelayLast(List<SceneStaticFunction> tasks) {
final lastTask = tasks.last;
return tasks.every((task) => task.code == 'delay') || lastTask.code == 'delay';
return tasks.every((task) => task.code == 'delay') ||
lastTask.code == 'delay';
}
void handleSaveButtonPress(
@ -44,14 +45,14 @@ mixin SceneLogicHelper {
tasks.length,
(index) {
final task = tasks[index];
if (task.code == 'delay') {
if (task.deviceId == 'delay') {
return CreateSceneAction(
entityId: tasks[index].deviceId,
actionExecutor: 'delay',
executorProperty: CreateSceneExecutorProperty(
functionCode: task.code,
functionValue: task.operationalValues.first.value,
delaySeconds: 0,
functionCode: '',
functionValue: '',
delaySeconds: task.functionValue,
),
);
}
@ -60,7 +61,7 @@ mixin SceneLogicHelper {
actionExecutor: 'device_issue',
executorProperty: CreateSceneExecutorProperty(
functionCode: task.code,
functionValue: task.operationalValues.first.value,
functionValue: task.functionValue,
delaySeconds: 0,
),
);
@ -121,7 +122,8 @@ mixin SceneLogicHelper {
);
} else {
return AlertDialogCountdown(
durationValue: listOfSceneStaticFunction[index].functionValue ?? taskItem.functionValue,
durationValue: listOfSceneStaticFunction[index].functionValue ??
taskItem.functionValue,
functionValue: taskItem.functionValue,
function: listOfSceneStaticFunction[index],
);

View File

@ -458,11 +458,6 @@ mixin SceneOperationsDataHelper {
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
SceneOperationalValue(
icon: Assets.assetsSceneRefresh,
description: "Reverse Switch",
value: null,
),
],
),
SceneStaticFunction(
@ -477,11 +472,6 @@ mixin SceneOperationsDataHelper {
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
SceneOperationalValue(
icon: Assets.assetsSceneRefresh,
description: "Reverse Switch",
value: null,
),
],
),
SceneStaticFunction(
@ -496,11 +486,6 @@ mixin SceneOperationsDataHelper {
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
SceneOperationalValue(
icon: Assets.assetsSceneRefresh,
description: "Reverse Switch",
value: null,
),
],
),
SceneStaticFunction(
@ -660,20 +645,42 @@ mixin SceneOperationsDataHelper {
];
}
///////&************ END of get function with icons for device *************&&////////
///
///
List<SceneStaticFunction> getTaskListFunctionsFromApi({
required List<Action> actions,
required String deviceId,
}) {
List<SceneStaticFunction> functions = [];
for (var action in actions) {
if (action.entityId == 'delay') {
functions.add(
SceneStaticFunction(
deviceId: action.entityId,
deviceName: 'delay',
deviceIcon: Assets.delay,
icon: Assets.delay,
operationName: 'delay',
functionValue: action.executorProperty.delaySeconds,
code: '',
operationalValues: [
SceneOperationalValue(
icon: '',
description: "",
value: action.executorProperty.delaySeconds,
),
],
),
);
}
ExecutorProperty executorProperty = action.executorProperty;
switch (executorProperty.functionCode) {
case 'sensitivity':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Presence Sensor',
deviceIcon: Assets.assetsIconsSensors,
icon: Assets.assetsSensitivityFunction,
@ -738,7 +745,7 @@ mixin SceneOperationsDataHelper {
case 'normal_open_switch':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'WIFI LOCK PRO',
deviceIcon: Assets.assetsIconsDoorLock,
icon: Assets.assetsIconsDoorLock,
@ -760,7 +767,7 @@ mixin SceneOperationsDataHelper {
case 'far_detection':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Human Presence Sensor',
deviceIcon: Assets.assetsIconsSensors,
icon: Assets.assetsFarDetection,
@ -823,7 +830,7 @@ mixin SceneOperationsDataHelper {
case 'motion_sensitivity_value':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Human Presence Sensor',
deviceIcon: Assets.assetsIconsSensors,
icon: Assets.assetsMotionDetection,
@ -863,7 +870,7 @@ mixin SceneOperationsDataHelper {
case 'motionless_sensitivity':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Human Presence Sensor',
deviceIcon: Assets.assetsIconsSensors,
icon: Assets.assetsMotionlessDetection,
@ -908,7 +915,7 @@ mixin SceneOperationsDataHelper {
case 'indicator':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Human Presence Sensor',
deviceIcon: Assets.assetsIconsSensors,
icon: Assets.assetsIndicator,
@ -930,7 +937,7 @@ mixin SceneOperationsDataHelper {
case 'presence_time':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Human Presence Sensor',
deviceIcon: Assets.assetsIconsSensors,
icon: Assets.assetsNobodyTime,
@ -946,7 +953,7 @@ mixin SceneOperationsDataHelper {
case 'switch_alarm_sound':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Multi-Mode Gateway Z-W-B',
deviceIcon: Assets.assetsIconsGateway,
icon: Assets.assetsSwitchAlarmSound,
@ -970,7 +977,7 @@ mixin SceneOperationsDataHelper {
case 'master_state':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Multi-Mode Gateway Z-W-B',
deviceIcon: Assets.assetsIconsGateway,
icon: Assets.assetsMasterState,
@ -995,7 +1002,7 @@ mixin SceneOperationsDataHelper {
case 'factory_reset':
functions.add(
SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Multi-Mode Gateway Z-W-B',
deviceIcon: Assets.assetsIconsGateway,
icon: Assets.assetsFactoryReset,
@ -1018,7 +1025,7 @@ mixin SceneOperationsDataHelper {
break;
case 'switch_1':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: '3 Gang Button Switch L-L',
deviceIcon: Assets.assetsIcons3GangSwitch,
icon: Assets.assetsAcPower,
@ -1045,7 +1052,7 @@ mixin SceneOperationsDataHelper {
break;
case 'switch_2':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: '3 Gang Button Switch L-L',
deviceIcon: Assets.assetsIcons3GangSwitch,
icon: Assets.assetsAcPower,
@ -1069,7 +1076,7 @@ mixin SceneOperationsDataHelper {
break;
case 'switch_3':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: '3 Gang Button Switch L-L',
deviceIcon: Assets.assetsIcons3GangSwitch,
icon: Assets.assetsAcPower,
@ -1093,7 +1100,7 @@ mixin SceneOperationsDataHelper {
break;
case 'countdown_1':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: '3 Gang Button Switch L-L',
deviceIcon: Assets.assetsIcons3GangSwitch,
icon: Assets.assetsLightCountdown,
@ -1107,7 +1114,7 @@ mixin SceneOperationsDataHelper {
break;
case 'countdown_2':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: '3 Gang Button Switch L-L',
deviceIcon: Assets.assetsIcons3GangSwitch,
icon: Assets.assetsLightCountdown,
@ -1121,7 +1128,7 @@ mixin SceneOperationsDataHelper {
break;
case 'countdown_3':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: '3 Gang Button Switch L-L',
deviceIcon: Assets.assetsIcons3GangSwitch,
icon: Assets.assetsLightCountdown,
@ -1135,7 +1142,7 @@ mixin SceneOperationsDataHelper {
break;
case 'switch':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Smart AC Thermostat - Grey - Model A',
deviceIcon: Assets.assetsIconsAC,
icon: Assets.assetsAcPower,
@ -1158,14 +1165,14 @@ mixin SceneOperationsDataHelper {
break;
case 'temp_set':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Smart AC Thermostat - Grey - Model A',
deviceIcon: Assets.assetsIconsAC,
icon: Assets.assetsTempreture,
operationName: 'Set Temperature',
code: 'temp_set',
functionValue: executorProperty.functionValue != null
? ((executorProperty.functionValue / 10) as double).toInt()
? ((executorProperty.functionValue! / 10) as double).toInt()
: null,
operationalValues: [
SceneOperationalValue(
@ -1178,7 +1185,7 @@ mixin SceneOperationsDataHelper {
break;
case 'mode':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Smart AC Thermostat - Grey - Model A',
deviceIcon: Assets.assetsIconsAC,
icon: Assets.assetsFreezing,
@ -1206,7 +1213,7 @@ mixin SceneOperationsDataHelper {
break;
case 'level':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Smart AC Thermostat - Grey - Model A',
deviceIcon: Assets.assetsIconsAC,
icon: Assets.assetsFanSpeed,
@ -1239,7 +1246,7 @@ mixin SceneOperationsDataHelper {
break;
case 'child_lock':
functions.add(SceneStaticFunction(
deviceId: deviceId,
deviceId: action.entityId,
deviceName: 'Smart AC Thermostat - Grey - Model A',
deviceIcon: Assets.assetsIconsAC,
icon: Assets.assetsChildLock,
@ -1267,6 +1274,11 @@ mixin SceneOperationsDataHelper {
return functions;
}
///// END of get fucntion for once device based on the CODE ***** ///////
///
///
///
List<SceneStaticFunction> getOperationsForOneFunction({
required String deviceId,
required SceneStaticFunction taskItem,

View File

@ -183,9 +183,9 @@ class CreateSceneExecutorProperty {
Map<String, dynamic> toMap() {
return {
'functionCode': functionCode,
'functionValue': functionValue,
'delaySeconds': delaySeconds,
if (functionCode.isNotEmpty == true) 'functionCode': functionCode,
if (functionValue != '') 'functionValue': functionValue,
if (delaySeconds > 0) 'delaySeconds': delaySeconds,
};
}

View File

@ -81,8 +81,8 @@ class ExecutorProperty {
factory ExecutorProperty.fromJson(Map<String, dynamic> json) =>
ExecutorProperty(
functionCode: json["functionCode"] ?? '',
functionValue: json["functionValue"],
delaySeconds: json["delaySeconds"],
functionValue: json["functionValue"] ?? '',
delaySeconds: json["delaySeconds"] ?? 0,
);
Map<String, dynamic> toJson() => {

View File

@ -46,9 +46,7 @@ class DeviceFunctionsView extends StatelessWidget
actions: [
TextButton(
onPressed: () {
context
.read<CreateSceneBloc>()
.add(const AddTaskEvent(updateTaskListFromTemp: true));
context.read<CreateSceneBloc>().add(AddTaskEvent());
Navigator.popUntil(context, (route) {
return route.settings.name == Routes.sceneTasksRoute;
});
@ -62,7 +60,19 @@ class DeviceFunctionsView extends StatelessWidget
],
leading: TextButton(
onPressed: () {
context.read<CreateSceneBloc>().add(const ClearTaskListEvent());
final selectedValue =
context.read<CreateSceneBloc>().selectedValues;
for (var element in device.functions) {
if (selectedValue.containsKey(element.code)) {
context
.read<CreateSceneBloc>()
.add(RemoveTempTaskByIdEvent(code: element.code!));
context
.read<CreateSceneBloc>()
.add(RemoveFromSelectedValueById(code: element.code!));
}
}
Navigator.pop(context);
},
child: BodyMedium(
@ -123,6 +133,7 @@ class DeviceFunctionsView extends StatelessWidget
final functionValues = context
.read<CreateSceneBloc>()
.selectedValues[functions[index].code];
context.customAlertDialog(
alertBody: functions[index].code == 'temp_set'
? AlertDialogTemperatureBody(
@ -154,6 +165,9 @@ class DeviceFunctionsView extends StatelessWidget
final selectedValue = context
.read<CreateSceneBloc>()
.selectedValues[functions[index].code];
if (selectedValue == null) {
return;
}
context
.read<CreateSceneBloc>()
.add(TempHoldSceneTasksEvent(
@ -174,22 +188,22 @@ class DeviceFunctionsView extends StatelessWidget
final tempTaskList = context
.read<CreateSceneBloc>()
.tempTasksList;
if (tempTaskList.isEmpty) {
context
.read<CreateSceneBloc>()
.add(const ClearTempTaskListEvent());
} else {
for (var element in tempTaskList) {
if (element.code == functions[index].code) {
context.read<CreateSceneBloc>().add(
RemoveTempTaskByIdEvent(
code: functions[index].code));
context.read<CreateSceneBloc>().add(
RemoveFromSelectedValueById(
code: functions[index].code));
}
// if (tempTaskList.isEmpty) {
// context
// .read<CreateSceneBloc>()
// .add(const ClearTempTaskListEvent());
// } else {
for (var element in tempTaskList) {
if (element.code == functions[index].code) {
context.read<CreateSceneBloc>().add(
RemoveTempTaskByIdEvent(
code: functions[index].code));
context.read<CreateSceneBloc>().add(
RemoveFromSelectedValueById(
code: functions[index].code));
}
}
//}
Navigator.pop(context);
},
);

View File

@ -33,11 +33,14 @@ class SceneTasksView extends StatelessWidget {
SizedBox(
width: 40,
child: GestureDetector(
onTap: () {
context.customBottomSheet(
child: DeleteBottomSheetContent(sceneId: sceneSettings.sceneId),
);
},
onTap: sceneSettings.sceneName.isEmpty
? null
: () {
context.customBottomSheet(
child: DeleteBottomSheetContent(
sceneId: sceneSettings.sceneId),
);
},
child: SvgPicture.asset(
Assets.assetsIconsSettings,
colorFilter: const ColorFilter.mode(

View File

@ -7,6 +7,7 @@ import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_view.dart';
import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_header.dart';
import 'package:syncrow_app/features/shared_widgets/create_unit.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/context_extension.dart';
@ -16,8 +17,8 @@ class SceneView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => SceneBloc()
..add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)),
create: (BuildContext context) =>
SceneBloc()..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '')),
child: BlocBuilder<CreateSceneBloc, CreateSceneState>(
builder: (context, state) {
if (state is DeleteSceneSuccess) {
@ -26,12 +27,17 @@ class SceneView extends StatelessWidget {
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
}
}
if (state is CreateSceneWithTasks) {
if (state.success == true) {
BlocProvider.of<SceneBloc>(context)
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
}
}
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
@ -55,12 +61,22 @@ class SceneView extends StatelessWidget {
);
}
if (state is SceneLoaded) {
return Expanded(
child: SceneGrid(
scenes: state.scenes,
loadingSceneId: state.loadingSceneId,
),
);
if (state.scenes.isNotEmpty) {
return Expanded(
child: SceneGrid(
scenes: state.scenes,
loadingSceneId: state.loadingSceneId,
),
);
} else {
return const Expanded(
child: Center(
child: BodyMedium(
text: 'No scenes have been added yet',
),
),
);
}
}
return const SizedBox();

View File

@ -61,7 +61,10 @@ class _AlertDialogCountdownState extends State<AlertDialogCountdown> {
durationInSeconds = newDuration.inSeconds;
});
context.read<CreateSceneBloc>().add(SelectedValueEvent(
value: newDuration.inSeconds, code: widget.function.code));
value: newDuration.inSeconds,
code: widget.function.deviceId == 'delay'
? 'delay'
: widget.function.code));
},
),
);

View File

@ -29,9 +29,10 @@ class _AlertDialogFunctionsOperationsBodyState
didChangeDependencies() {
super.didChangeDependencies();
final tempTaskList = context.read<CreateSceneBloc>().tempTasksList;
if (tempTaskList.isEmpty) {
context.read<CreateSceneBloc>().add(const ClearTempTaskListEvent());
} else if (tempTaskList.isNotEmpty) {
if (tempTaskList.isNotEmpty) {
for (var element in tempTaskList) {
if (element.code == widget.functions[widget.index].code) {
groupValue = element.functionValue;

View File

@ -95,7 +95,7 @@ class CustomBottomSheetWidget extends StatelessWidget {
deviceName: 'Delay The Action',
icon: '',
operationName: 'Delay The Action',
code: 'delay',
code: '',
functionValue: 0,
operationalValues: [
SceneOperationalValue(icon: '', value: 0),
@ -111,11 +111,11 @@ class CustomBottomSheetWidget extends StatelessWidget {
title: functions[0].operationName,
onConfirm: () {
final selectedValue =
context.read<CreateSceneBloc>().selectedValues[functions[0].code];
context.read<CreateSceneBloc>().selectedValues['delay'];
context.read<CreateSceneBloc>().add(TempHoldSceneTasksEvent(
deviceControlModel: DeviceControlModel(
deviceId: 'delay',
code: functions[0].code,
deviceId: '',
code: '',
value: selectedValue,
),
deviceId: 'delay',
@ -124,27 +124,26 @@ class CustomBottomSheetWidget extends StatelessWidget {
deviceName: 'Delay The Action',
uniqueId: functions[0].uniqueCustomId,
));
context
.read<CreateSceneBloc>()
.add(const AddTaskEvent(updateTaskListFromTemp: true));
context.read<CreateSceneBloc>().add(AddTaskEvent());
Navigator.pop(context);
Navigator.pop(context);
},
onDismiss: () {
final tempTaskList = context.read<CreateSceneBloc>().tempTasksList;
if (tempTaskList.isEmpty) {
context.read<CreateSceneBloc>().add(const ClearTempTaskListEvent());
} else {
for (var element in tempTaskList) {
if (element.code == functions[0].code) {
context
.read<CreateSceneBloc>()
.add(RemoveTempTaskByIdEvent(code: functions[0].code));
context
.read<CreateSceneBloc>()
.add(RemoveFromSelectedValueById(code: functions[0].code));
}
// if (tempTaskList.isNotEmpty) {
// context.read<CreateSceneBloc>().add(const ClearTempTaskListEvent());
// } else {
for (var element in tempTaskList) {
if (element.code == functions[0].code) {
context
.read<CreateSceneBloc>()
.add(RemoveTempTaskByIdEvent(code: functions[0].code));
context
.read<CreateSceneBloc>()
.add(RemoveFromSelectedValueById(code: functions[0].code));
}
}
// }
Navigator.pop(context);
},
);

View File

@ -45,7 +45,6 @@ class _CreateSceneSaveButtonState extends State<CreateSceneSaveButton>
if (state.success == true) {
Navigator.pop(context);
Navigator.pop(context);
context.showCustomSnackbar(
message: 'Scene created successfully',
icon: const Icon(
@ -123,7 +122,7 @@ class _CreateSceneSaveButtonState extends State<CreateSceneSaveButton>
),
isLoading: state is CreateSceneLoading,
child: BodyLarge(
text: 'Save',
text: widget.sceneName.isNotEmpty ? 'Update' : 'Save',
style: context.bodyLarge.copyWith(color: Colors.white),
),
);

View File

@ -33,7 +33,8 @@ class ThenAddedTasksContainer extends StatelessWidget
@override
Widget build(BuildContext context) {
String operationValue = '';
if (taskItem.code.contains('countdown')) {
if (taskItem.code.contains('countdown') ||
taskItem.deviceId.contains('delay')) {
final functionValue =
taskItem.functionValue ?? taskItem.operationalValues.first.value;
final duration =

View File

@ -55,6 +55,7 @@ class ThenDefaultContainer extends StatelessWidget {
if (state is CreateSceneLoading) {
return const Center(child: LinearProgressIndicator());
}
if (state is AddSceneTask) {
final taskLists = state.tasksList;
if (taskLists.isNotEmpty) {

View File

@ -9,8 +9,7 @@ abstract class ApiEndpoints {
static const String deleteUser = '$baseUrl/authentication/user/delete/{id}';
static const String sendOtp = '$baseUrl/authentication/user/send-otp';
static const String verifyOtp = '$baseUrl/authentication/user/verify-otp';
static const String forgetPassword =
'$baseUrl/authentication/user/forget-password';
static const String forgetPassword = '$baseUrl/authentication/user/forget-password';
////////////////////////////////////// Spaces ///////////////////////////////////////
@ -20,12 +19,10 @@ abstract class ApiEndpoints {
static const String addCommunityToUser = '$baseUrl/community/user';
//GET
static const String communityByUuid = '$baseUrl/community/{communityUuid}';
static const String communityChild =
'$baseUrl/community/child/{communityUuid}';
static const String communityChild = '$baseUrl/community/child/{communityUuid}';
static const String communityUser = '$baseUrl/community/user/{userUuid}';
//PUT
static const String renameCommunity =
'$baseUrl/community/rename/{communityUuid}';
static const String renameCommunity = '$baseUrl/community/rename/{communityUuid}';
///Building Module
//POST
@ -34,12 +31,10 @@ abstract class ApiEndpoints {
//GET
static const String buildingByUuid = '$baseUrl/building/{buildingUuid}';
static const String buildingChild = '$baseUrl/building/child/{buildingUuid}';
static const String buildingParent =
'$baseUrl/building/parent/{buildingUuid}';
static const String buildingParent = '$baseUrl/building/parent/{buildingUuid}';
static const String buildingUser = '$baseUrl/building/user/{userUuid}';
//PUT
static const String renameBuilding =
'$baseUrl/building/rename/{buildingUuid}';
static const String renameBuilding = '$baseUrl/building/rename/{buildingUuid}';
///Floor Module
//POST
@ -62,8 +57,7 @@ abstract class ApiEndpoints {
static const String unitChild = '$baseUrl/unit/child/';
static const String unitParent = '$baseUrl/unit/parent/{unitUuid}';
static const String unitUser = '$baseUrl/unit/user/';
static const String invitationCode =
'$baseUrl/unit/{unitUuid}/invitation-code';
static const String invitationCode = '$baseUrl/unit/{unitUuid}/invitation-code';
static const String verifyInvitationCode = '$baseUrl/unit/user/verify-code';
//PUT
@ -86,8 +80,7 @@ abstract class ApiEndpoints {
static const String controlGroup = '$baseUrl/group/control';
//GET
static const String groupBySpace = '$baseUrl/group/{unitUuid}';
static const String devicesByGroupName =
'$baseUrl/group/{unitUuid}/devices/{groupName}';
static const String devicesByGroupName = '$baseUrl/group/{unitUuid}/devices/{groupName}';
static const String groupByUuid = '$baseUrl/group/{groupUuid}';
//DELETE
@ -99,19 +92,16 @@ abstract class ApiEndpoints {
static const String addDeviceToRoom = '$baseUrl/device/room';
static const String addDeviceToGroup = '$baseUrl/device/group';
static const String controlDevice = '$baseUrl/device/{deviceUuid}/control';
static const String firmwareDevice =
'$baseUrl/device/{deviceUuid}/firmware/{firmwareVersion}';
static const String firmwareDevice = '$baseUrl/device/{deviceUuid}/firmware/{firmwareVersion}';
static const String getDevicesByUserId = '$baseUrl/device/user/{userId}';
static const String getDevicesByUnitId = '$baseUrl/device/unit/{unitUuid}';
//GET
static const String deviceByRoom = '$baseUrl/device/room';
static const String deviceByUuid = '$baseUrl/device/{deviceUuid}';
static const String deviceFunctions =
'$baseUrl/device/{deviceUuid}/functions';
static const String gatewayApi =
'$baseUrl/device/gateway/{gatewayUuid}/devices';
static const String deviceFunctionsStatus =
'$baseUrl/device/{deviceUuid}/functions/status';
static const String deviceFunctions = '$baseUrl/device/{deviceUuid}/functions';
static const String gatewayApi = '$baseUrl/device/gateway/{gatewayUuid}/devices';
static const String deviceFunctionsStatus = '$baseUrl/device/{deviceUuid}/functions/status';
///Device Permission Module
//POST
@ -119,16 +109,14 @@ abstract class ApiEndpoints {
//GET
static const String devicePermissionList = '$baseUrl/device-permission/list';
//PUT
static const String editDevicePermission =
'$baseUrl/device-permission/edit/{userId}';
static const String editDevicePermission = '$baseUrl/device-permission/edit/{userId}';
static const String assignDeviceToRoom = '$baseUrl/device/room';
/// Scene API ////////////////////
/// POST
static const String createScene = '$baseUrl/scene/tap-to-run';
static const String triggerScene =
'$baseUrl/scene/tap-to-run/trigger/{sceneId}';
static const String triggerScene = '$baseUrl/scene/tap-to-run/trigger/{sceneId}';
/// GET
static const String getUnitScenes = '$baseUrl/scene/tap-to-run/{unitUuid}';
@ -139,8 +127,7 @@ abstract class ApiEndpoints {
static const String updateScene = '$baseUrl/scene/tap-to-run/{sceneId}';
/// DELETE
static const String deleteScene =
'$baseUrl/scene/tap-to-run/{unitUuid}/{sceneId}';
static const String deleteScene = '$baseUrl/scene/tap-to-run/{unitUuid}/{sceneId}';
//////////////////////Door Lock //////////////////////
//online

View File

@ -1,4 +1,5 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/user_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
@ -23,6 +24,20 @@ class HomeManagementAPI {
return list;
}
static Future<List<DeviceModel>> fetchDevicesByUnitId() async {
List<DeviceModel> list = [];
await _httpService.get(
path: ApiEndpoints.getDevicesByUnitId
.replaceAll("{unitUuid}", HomeCubit.getInstance().selectedSpace?.id ?? ''),
showServerMessage: false,
expectedResponseModel: (json) {
json.forEach((value) {
list.add(DeviceModel.fromJson(value));
});
});
return list;
}
static Future<Map<String, dynamic>> assignDeviceToRoom(Map<String, String> body) async {
try {
final response = await _httpService.put(

View File

@ -5,7 +5,7 @@ description: This is the mobile application project, developed with Flutter for
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.8+9
version: 1.0.0+10
environment:
sdk: ">=3.0.6 <4.0.0"