mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-16 01:56:24 +00:00
Merge branch 'dev' of https://github.com/SyncrowIOT/web into bugfix/fix-issue-in-save
This commit is contained in:
@ -7,6 +7,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/room.dart'
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/ac/ac_function.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/flush/flush_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/gang_switches/one_gang_switch/one_gang_switch.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/gang_switches/three_gang_switch/three_gang_switch.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/gang_switches/two_gang_switch/two_gang_switch.dart';
|
||||
@ -155,13 +156,17 @@ class AllDevicesModel {
|
||||
batteryLevel = int.tryParse(json['battery']?.toString() ?? '');
|
||||
productName = json['productName']?.toString();
|
||||
deviceTags = json['deviceTag'] != null && json['deviceTag'] is List
|
||||
? (json['deviceTag'] as List).map((tag) => DeviceTagModel.fromJson(tag)).toList()
|
||||
? (json['deviceTag'] as List)
|
||||
.map((tag) => DeviceTagModel.fromJson(tag))
|
||||
.toList()
|
||||
: [];
|
||||
deviceSubSpace = json['subspace'] != null
|
||||
? DeviceSubSpace.fromJson(json['subspace'])
|
||||
: DeviceSubSpace(subspaceName: '');
|
||||
if (json['spaces'] != null && json['spaces'] is List) {
|
||||
spaces = (json['spaces'] as List).map((space) => DeviceSpaceModel.fromJson(space)).toList();
|
||||
spaces = (json['spaces'] as List)
|
||||
.map((space) => DeviceSpaceModel.fromJson(space))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,7 +214,8 @@ SOS
|
||||
String tempIcon = '';
|
||||
if (type == DeviceType.LightBulb) {
|
||||
tempIcon = Assets.lightBulb;
|
||||
} else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
|
||||
} else if (type == DeviceType.CeilingSensor ||
|
||||
type == DeviceType.WallSensor) {
|
||||
tempIcon = Assets.sensors;
|
||||
} else if (type == DeviceType.AC) {
|
||||
tempIcon = Assets.ac;
|
||||
@ -239,6 +245,8 @@ SOS
|
||||
// tempIcon = Assets.gang3touch;
|
||||
} else if (type == DeviceType.WaterLeak) {
|
||||
tempIcon = Assets.waterLeakNormal;
|
||||
} else if (type == DeviceType.NCPS) {
|
||||
tempIcon = Assets.sensors;
|
||||
} else {
|
||||
tempIcon = Assets.logoHorizontal;
|
||||
}
|
||||
@ -254,51 +262,75 @@ SOS
|
||||
switch (productType) {
|
||||
case 'AC':
|
||||
return [
|
||||
SwitchFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ModeFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
TempSetFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
CurrentTempFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
LevelFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ChildLockFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
SwitchFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ModeFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
TempSetFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
CurrentTempFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
LevelFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ChildLockFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
];
|
||||
|
||||
case '1G':
|
||||
return [
|
||||
OneGangSwitchFunction(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
OneGangCountdownFunction(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
OneGangCountdownFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
];
|
||||
|
||||
case '2G':
|
||||
return [
|
||||
TwoGangSwitch1Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangSwitch2Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangCountdown1Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangCountdown2Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangCountdown1Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
TwoGangCountdown2Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||
];
|
||||
|
||||
case '3G':
|
||||
return [
|
||||
ThreeGangSwitch1Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch2Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch3Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown1Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown2Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown3Function(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch1Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch2Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangSwitch3Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown1Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown2Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
ThreeGangCountdown3Function(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
];
|
||||
case 'WPS':
|
||||
return [
|
||||
//IF Functions
|
||||
PresenceStateFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
CurrentDistanceFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
IlluminanceValueFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
PresenceTimeFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
PresenceStateFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
CurrentDistanceFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
IlluminanceValueFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
PresenceTimeFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
|
||||
//THEN Functions
|
||||
FarDetectionFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
MotionSensitivityFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
MotionLessSensitivityFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
IndicatorFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
NoOneTimeFunction(deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
FarDetectionFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
MotionSensitivityFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
MotionLessSensitivityFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
IndicatorFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'BOTH'),
|
||||
NoOneTimeFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
];
|
||||
case 'GW':
|
||||
return [
|
||||
@ -323,6 +355,30 @@ SOS
|
||||
uuid: uuid ?? '',
|
||||
name: name ?? '',
|
||||
);
|
||||
case 'NCPS':
|
||||
return [
|
||||
FlushPresenceDelayFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF',),
|
||||
|
||||
FlushIlluminanceFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
|
||||
//THEN Functions
|
||||
FlushSensitivityFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
FlushNearDetectionFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
FlushMaxDetectDistFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
FlushTargetConfirmTimeFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
FlushDisappeDelayFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
FlushIndentLevelFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
FlushTriggerLevelFunction(
|
||||
deviceId: uuid ?? '', deviceName: name ?? '', type: 'THEN'),
|
||||
];
|
||||
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
@ -454,5 +510,6 @@ SOS
|
||||
"3GT": DeviceType.ThreeTouch,
|
||||
"GD": DeviceType.GarageDoor,
|
||||
"WL": DeviceType.WaterLeak,
|
||||
"NCPS": DeviceType.NCPS,
|
||||
};
|
||||
}
|
||||
|
@ -97,3 +97,7 @@ class FlushMountedPresenceSensorModel {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -106,14 +106,14 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
ScheduleEntry newSchedule = ScheduleEntry(
|
||||
category: event.category,
|
||||
time: formatTimeOfDayToISO(event.time),
|
||||
function: Status(code: 'switch_1', value: event.functionOn),
|
||||
function: Status(code: 'doorcontact_state', value: event.functionOn),
|
||||
days: ScheduleModel.convertSelectedDaysToStrings(event.selectedDays),
|
||||
);
|
||||
bool success =
|
||||
await DevicesManagementApi().addScheduleRecord(newSchedule, deviceId);
|
||||
if (success) {
|
||||
add(FetchGarageDoorSchedulesEvent(
|
||||
deviceId: deviceId, category: 'switch_1'));
|
||||
deviceId: deviceId, category: 'doorcontact_state'));
|
||||
} else {
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
}
|
||||
@ -149,7 +149,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
final updatedSchedules = deviceStatus.schedules?.map((schedule) {
|
||||
if (schedule.scheduleId == event.scheduleId) {
|
||||
return schedule.copyWith(
|
||||
function: Status(code: 'switch_1', value: event.functionOn),
|
||||
function:
|
||||
Status(code: 'doorcontact_state', value: event.functionOn),
|
||||
enable: event.enable,
|
||||
);
|
||||
}
|
||||
@ -274,7 +275,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
|
||||
Future<void> _onBatchControl(
|
||||
GarageDoorBatchControlEvent event, Emitter<GarageDoorState> emit) async {
|
||||
final oldValue = event.code == 'switch_1' ? deviceStatus.switch1 : false;
|
||||
final oldValue =
|
||||
event.code == 'doorcontact_state' ? deviceStatus.switch1 : false;
|
||||
|
||||
_updateLocalValue(event.code, event.value);
|
||||
emit(GarageDoorBatchStatusLoaded(deviceStatus));
|
||||
@ -409,7 +411,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
void _revertValue(
|
||||
String code, dynamic oldValue, Emitter<GarageDoorState> emit) {
|
||||
switch (code) {
|
||||
case 'switch_1':
|
||||
case 'doorcontact_state':
|
||||
if (oldValue is bool) {
|
||||
deviceStatus = deviceStatus.copyWith(switch1: oldValue);
|
||||
}
|
||||
@ -468,10 +470,11 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
deviceStatus = deviceStatus.copyWith(voiceControl1: value);
|
||||
}
|
||||
break;
|
||||
case 'door_contact_state':
|
||||
case 'doorcontact_state':
|
||||
if (value is bool) {
|
||||
deviceStatus = deviceStatus.copyWith(doorContactState: value);
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -490,14 +493,14 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
scheduleId: event.scheduleId,
|
||||
category: event.category,
|
||||
time: formatTimeOfDayToISO(event.time),
|
||||
function: Status(code: 'switch_1', value: event.functionOn),
|
||||
function: Status(code: 'doorcontact_state', value: event.functionOn),
|
||||
days: ScheduleModel.convertSelectedDaysToStrings(event.selectedDays),
|
||||
);
|
||||
bool success = await DevicesManagementApi()
|
||||
.editScheduleRecord(deviceId, newSchedule);
|
||||
if (success) {
|
||||
add(FetchGarageDoorSchedulesEvent(
|
||||
deviceId: deviceId, category: 'switch_1'));
|
||||
deviceId: deviceId, category: 'doorcontact_state'));
|
||||
} else {
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
}
|
||||
|
@ -14,7 +14,8 @@ import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout {
|
||||
class GarageDoorControlView extends StatelessWidget
|
||||
with HelperResponsiveLayout {
|
||||
final String deviceId;
|
||||
|
||||
const GarageDoorControlView({required this.deviceId, super.key});
|
||||
@ -22,7 +23,8 @@ class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => GarageDoorBloc(deviceId: deviceId)..add(GarageDoorInitialEvent(deviceId)),
|
||||
create: (context) => GarageDoorBloc(deviceId: deviceId)
|
||||
..add(GarageDoorInitialEvent(deviceId)),
|
||||
child: BlocBuilder<GarageDoorBloc, GarageDoorState>(
|
||||
builder: (context, state) {
|
||||
if (state is GarageDoorLoadingState) {
|
||||
@ -34,7 +36,9 @@ class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout
|
||||
garageDoorSensor: true,
|
||||
onRowTap: (index) {},
|
||||
onClose: () {
|
||||
context.read<GarageDoorBloc>().add(BackToGarageDoorGridViewEvent());
|
||||
context
|
||||
.read<GarageDoorBloc>()
|
||||
.add(BackToGarageDoorGridViewEvent());
|
||||
},
|
||||
);
|
||||
} else if (state is GarageDoorLoadedState) {
|
||||
@ -71,11 +75,14 @@ class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout
|
||||
children: [
|
||||
IconNameStatusContainer(
|
||||
isFullIcon: false,
|
||||
name: status.switch1 ? 'Opened' : 'Closed',
|
||||
icon: status.switch1 ? Assets.openedDoor : Assets.closedDoor,
|
||||
name: status.doorContactState ? 'Opened' : 'Closed',
|
||||
icon: status.doorContactState ? Assets.openedDoor : Assets.closedDoor,
|
||||
onTap: () {
|
||||
context.read<GarageDoorBloc>().add(
|
||||
GarageDoorControlEvent(deviceId: status.uuid, value: !status.switch1, code: 'switch_1'),
|
||||
GarageDoorControlEvent(
|
||||
deviceId: status.uuid,
|
||||
value: !status.switch1,
|
||||
code: 'doorcontact_state'),
|
||||
);
|
||||
},
|
||||
status: status.switch1,
|
||||
@ -84,7 +91,8 @@ class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout
|
||||
IconNameStatusContainer(
|
||||
onTap: () {
|
||||
context.read<GarageDoorBloc>().add(
|
||||
FetchGarageDoorSchedulesEvent(deviceId: deviceId, category: 'switch_1'),
|
||||
FetchGarageDoorSchedulesEvent(
|
||||
deviceId: deviceId, category: 'doorcontact_state'),
|
||||
);
|
||||
showDialog(
|
||||
context: context,
|
||||
@ -107,7 +115,9 @@ class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
context.read<GarageDoorBloc>().add(DecreaseGarageDoorDelayEvent(deviceId: status.uuid));
|
||||
context
|
||||
.read<GarageDoorBloc>()
|
||||
.add(DecreaseGarageDoorDelayEvent(deviceId: status.uuid));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.remove,
|
||||
@ -125,7 +135,8 @@ class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout
|
||||
),
|
||||
Text(
|
||||
'h',
|
||||
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor),
|
||||
style: context.textTheme.bodySmall!
|
||||
.copyWith(color: ColorsManager.blackColor),
|
||||
),
|
||||
Text(
|
||||
(status.delay.inMinutes % 60).toString().padLeft(2, '0'),
|
||||
@ -136,11 +147,14 @@ class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout
|
||||
),
|
||||
Text(
|
||||
'm',
|
||||
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor),
|
||||
style: context.textTheme.bodySmall!
|
||||
.copyWith(color: ColorsManager.blackColor),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
context.read<GarageDoorBloc>().add(IncreaseGarageDoorDelayEvent(deviceId: status.uuid));
|
||||
context
|
||||
.read<GarageDoorBloc>()
|
||||
.add(IncreaseGarageDoorDelayEvent(deviceId: status.uuid));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.add,
|
||||
@ -158,7 +172,9 @@ class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout
|
||||
onChange: (value) {
|
||||
context.read<GarageDoorBloc>().add(
|
||||
GarageDoorControlEvent(
|
||||
deviceId: status.uuid, value: value ? status.delay.inSeconds : 0, code: 'countdown_1'),
|
||||
deviceId: status.uuid,
|
||||
value: value ? status.delay.inSeconds : 0,
|
||||
code: 'countdown_1'),
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -167,7 +183,8 @@ class GarageDoorControlView extends StatelessWidget with HelperResponsiveLayout
|
||||
name: 'Records',
|
||||
icon: Assets.records,
|
||||
onTap: () {
|
||||
context.read<GarageDoorBloc>().add(FetchGarageDoorRecordsEvent(code: 'switch_1', deviceId: status.uuid));
|
||||
context.read<GarageDoorBloc>().add(FetchGarageDoorRecordsEvent(
|
||||
code: 'doorcontact_state', deviceId: status.uuid));
|
||||
},
|
||||
status: false,
|
||||
textColor: ColorsManager.blackColor,
|
||||
|
@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ac_dialog.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/ceiling_sensor_helper.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/flush_presence_sensor/flush_presence_sensor.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/gateway/gateway_helper.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/one_gang_switch_dialog.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/three_gang_switch_dialog.dart';
|
||||
@ -116,6 +117,15 @@ class DeviceDialogHelper {
|
||||
deviceSelectedFunctions: deviceSelectedFunctions,
|
||||
device: data['device'],
|
||||
);
|
||||
case 'NCPS':
|
||||
return FlushPresenceSensor.showFlushFunctionsDialog(
|
||||
context: context,
|
||||
functions: functions,
|
||||
uniqueCustomId: data['uniqueCustomId'],
|
||||
deviceSelectedFunctions: deviceSelectedFunctions,
|
||||
dialogType: dialogType,
|
||||
device: data['device'],
|
||||
);
|
||||
|
||||
default:
|
||||
return null;
|
||||
|
407
lib/pages/routines/models/flush/flush_functions.dart
Normal file
407
lib/pages/routines/models/flush/flush_functions.dart
Normal file
@ -0,0 +1,407 @@
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/models/flush_mounted_presence_sensor_model.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/flush/flush_operational_value.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
abstract class FlushFunctions
|
||||
extends DeviceFunction<FlushMountedPresenceSensorModel> {
|
||||
final String type;
|
||||
|
||||
FlushFunctions({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.code,
|
||||
required super.operationName,
|
||||
required super.icon,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
List<FlushOperationalValue> getOperationalValues();
|
||||
}
|
||||
|
||||
class FlushPresenceDelayFunction extends FlushFunctions {
|
||||
final int min;
|
||||
FlushPresenceDelayFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 0,
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codePresenceState,
|
||||
operationName: 'Presence State',
|
||||
icon: Assets.presenceStateIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
return [
|
||||
FlushOperationalValue(
|
||||
icon: Assets.nobodyTime,
|
||||
description: 'None',
|
||||
value: "none",
|
||||
),
|
||||
FlushOperationalValue(
|
||||
icon: Assets.presenceStateIcon,
|
||||
description: 'Presence',
|
||||
value: 'presence',
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class FlushSensiReduceFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final int step;
|
||||
|
||||
FlushSensiReduceFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 1,
|
||||
max = 5,
|
||||
step = 1,
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeSensiReduce,
|
||||
operationName: 'Sensitivity Reduction',
|
||||
icon: Assets.motionlessDetectionSensitivityIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
return List.generate(
|
||||
(max - min) ~/ step + 1,
|
||||
(index) => FlushOperationalValue(
|
||||
icon: Assets.currentDistanceIcon,
|
||||
description: '${min + (index * step)}',
|
||||
value: min + (index * step),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class FlushNoneDelayFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final String unit;
|
||||
|
||||
FlushNoneDelayFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 10,
|
||||
max = 10000,
|
||||
unit = '秒',
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeNoneDelay,
|
||||
operationName: 'None Delay',
|
||||
icon: Assets.nobodyTime,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
return [
|
||||
FlushOperationalValue(
|
||||
icon: icon,
|
||||
description: 'Custom $unit',
|
||||
value: null,
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class FlushIlluminanceFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final int step;
|
||||
|
||||
FlushIlluminanceFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 0,
|
||||
max = 2000,
|
||||
step = 0,
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeIlluminance,
|
||||
operationName: 'Illuminance',
|
||||
icon: Assets.IlluminanceIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
List<FlushOperationalValue> values = [];
|
||||
for (int lux = min; lux <= max; lux += step) {
|
||||
values.add(FlushOperationalValue(
|
||||
icon: Assets.IlluminanceIcon,
|
||||
description: "$lux Lux",
|
||||
value: lux,
|
||||
));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
class FlushOccurDistReduceFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final int step;
|
||||
|
||||
FlushOccurDistReduceFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 0,
|
||||
max = 100,
|
||||
step = 1,
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeOccurDistReduce,
|
||||
operationName: 'Occurrence Distance Reduction',
|
||||
icon: Assets.assetsTempreture,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
return List.generate(
|
||||
(max - min) ~/ step + 1,
|
||||
(index) => FlushOperationalValue(
|
||||
icon: Assets.assetsTempreture,
|
||||
description: '${min + (index * step)}',
|
||||
value: min + (index * step),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// ==== then functions ====
|
||||
class FlushSensitivityFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final int step;
|
||||
|
||||
FlushSensitivityFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 1,
|
||||
max = 9,
|
||||
step = 1,
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeSensitivity,
|
||||
operationName: 'Sensitivity',
|
||||
icon: Assets.sensitivity,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
return List.generate(
|
||||
(max - min) ~/ step + 1,
|
||||
(index) => FlushOperationalValue(
|
||||
icon: Assets.motionDetectionSensitivityValueIcon,
|
||||
description: '${min + (index * step)}',
|
||||
value: min + (index * step),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class FlushNearDetectionFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final double max;
|
||||
final int step;
|
||||
final String unit;
|
||||
|
||||
FlushNearDetectionFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 0,
|
||||
max = 9.5,
|
||||
step = 1,
|
||||
unit = 'm',
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeNearDetection,
|
||||
operationName: 'Nearest Detect Dist',
|
||||
icon: Assets.currentDistanceIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
final values = <FlushOperationalValue>[];
|
||||
for (var value = min; value <= max; value += step) {
|
||||
values.add(FlushOperationalValue(
|
||||
icon: Assets.nobodyTime,
|
||||
description: '$value $unit',
|
||||
value: value * 10,
|
||||
));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
class FlushMaxDetectDistFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final int step;
|
||||
final String unit;
|
||||
|
||||
FlushMaxDetectDistFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 75,
|
||||
max = 600,
|
||||
step = 75,
|
||||
unit = 'cm',
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeFarDetection,
|
||||
operationName: 'Max Detect Dist',
|
||||
icon: Assets.currentDistanceIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
final values = <FlushOperationalValue>[];
|
||||
for (var value = min; value <= max; value += step) {
|
||||
values.add(FlushOperationalValue(
|
||||
icon: Assets.nobodyTime,
|
||||
description: '$value $unit',
|
||||
value: value,
|
||||
));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
class FlushTargetConfirmTimeFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final int step;
|
||||
final String unit;
|
||||
|
||||
FlushTargetConfirmTimeFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 75,
|
||||
max = 600,
|
||||
step = 75,
|
||||
unit = 'cm',
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codePresenceDelay,
|
||||
operationName: 'Target Confirm Time',
|
||||
icon: Assets.targetConfirmTimeIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
final values = <FlushOperationalValue>[];
|
||||
for (var value = min; value <= max; value += step) {
|
||||
values.add(FlushOperationalValue(
|
||||
icon: Assets.nobodyTime,
|
||||
description: '$value $unit',
|
||||
value: value,
|
||||
));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
class FlushDisappeDelayFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final int step;
|
||||
final String unit;
|
||||
|
||||
FlushDisappeDelayFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 75,
|
||||
max = 600,
|
||||
step = 75,
|
||||
unit = 'cm',
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeNoneDelay,
|
||||
operationName: 'Disappe Delay',
|
||||
icon: Assets.DisappeDelayIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
final values = <FlushOperationalValue>[];
|
||||
for (var value = min; value <= max; value += step) {
|
||||
values.add(FlushOperationalValue(
|
||||
icon: Assets.nobodyTime,
|
||||
description: '$value $unit',
|
||||
value: value,
|
||||
));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
class FlushIndentLevelFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final int step;
|
||||
final String unit;
|
||||
|
||||
FlushIndentLevelFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 75,
|
||||
max = 600,
|
||||
step = 75,
|
||||
unit = 'cm',
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeOccurDistReduce,
|
||||
operationName: 'Indent Level',
|
||||
icon: Assets.indentLevelIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
final values = <FlushOperationalValue>[];
|
||||
for (var value = min; value <= max; value += step) {
|
||||
values.add(FlushOperationalValue(
|
||||
icon: Assets.nobodyTime,
|
||||
description: '$value $unit',
|
||||
value: value,
|
||||
));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
class FlushTriggerLevelFunction extends FlushFunctions {
|
||||
final int min;
|
||||
final int max;
|
||||
final int step;
|
||||
final String unit;
|
||||
|
||||
FlushTriggerLevelFunction({
|
||||
required super.deviceId,
|
||||
required super.deviceName,
|
||||
required super.type,
|
||||
}) : min = 75,
|
||||
max = 600,
|
||||
step = 75,
|
||||
unit = 'cm',
|
||||
super(
|
||||
code: FlushMountedPresenceSensorModel.codeSensiReduce,
|
||||
operationName: 'Trigger Level',
|
||||
icon: Assets.triggerLevelIcon,
|
||||
);
|
||||
|
||||
@override
|
||||
List<FlushOperationalValue> getOperationalValues() {
|
||||
final values = <FlushOperationalValue>[];
|
||||
for (var value = min; value <= max; value += step) {
|
||||
values.add(FlushOperationalValue(
|
||||
icon: Assets.nobodyTime,
|
||||
description: '$value $unit',
|
||||
value: value,
|
||||
));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
11
lib/pages/routines/models/flush/flush_operational_value.dart
Normal file
11
lib/pages/routines/models/flush/flush_operational_value.dart
Normal file
@ -0,0 +1,11 @@
|
||||
class FlushOperationalValue {
|
||||
final String icon;
|
||||
final String description;
|
||||
final dynamic value;
|
||||
|
||||
FlushOperationalValue({
|
||||
required this.icon,
|
||||
required this.description,
|
||||
required this.value,
|
||||
});
|
||||
}
|
@ -28,10 +28,12 @@ class IfContainer extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('IF',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
style: TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
if (state.isAutomation && state.ifItems.isNotEmpty)
|
||||
AutomationOperatorSelector(
|
||||
selectedOperator: state.selectedAutomationOperator),
|
||||
selectedOperator:
|
||||
state.selectedAutomationOperator),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
@ -55,16 +57,17 @@ class IfContainer extends StatelessWidget {
|
||||
(index) => GestureDetector(
|
||||
onTap: () async {
|
||||
if (!state.isTabToRun) {
|
||||
final result = await DeviceDialogHelper.showDeviceDialog(
|
||||
context: context,
|
||||
data: state.ifItems[index],
|
||||
removeComparetors: false,
|
||||
dialogType: "IF");
|
||||
final result = await DeviceDialogHelper
|
||||
.showDeviceDialog(
|
||||
context: context,
|
||||
data: state.ifItems[index],
|
||||
removeComparetors: false,
|
||||
dialogType: "IF");
|
||||
|
||||
if (result != null) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(state.ifItems[index], false));
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToIfContainer(
|
||||
state.ifItems[index], false));
|
||||
} else if (![
|
||||
'AC',
|
||||
'1G',
|
||||
@ -73,25 +76,32 @@ class IfContainer extends StatelessWidget {
|
||||
'WPS',
|
||||
'GW',
|
||||
'CPS',
|
||||
].contains(state.ifItems[index]['productType'])) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(state.ifItems[index], false));
|
||||
'NCPS'
|
||||
].contains(state.ifItems[index]
|
||||
['productType'])) {
|
||||
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToIfContainer(
|
||||
state.ifItems[index], false));
|
||||
}
|
||||
}
|
||||
},
|
||||
child: DraggableCard(
|
||||
imagePath: state.ifItems[index]['imagePath'] ?? '',
|
||||
imagePath:
|
||||
state.ifItems[index]['imagePath'] ?? '',
|
||||
title: state.ifItems[index]['title'] ?? '',
|
||||
deviceData: state.ifItems[index],
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 4, vertical: 8),
|
||||
isFromThen: false,
|
||||
isFromIf: true,
|
||||
onRemove: () {
|
||||
context.read<RoutineBloc>().add(RemoveDragCard(
|
||||
index: index,
|
||||
isFromThen: false,
|
||||
key: state.ifItems[index]['uniqueCustomId']));
|
||||
context.read<RoutineBloc>().add(
|
||||
RemoveDragCard(
|
||||
index: index,
|
||||
isFromThen: false,
|
||||
key: state.ifItems[index]
|
||||
['uniqueCustomId']));
|
||||
},
|
||||
),
|
||||
)),
|
||||
@ -112,7 +122,9 @@ class IfContainer extends StatelessWidget {
|
||||
|
||||
if (!state.isTabToRun) {
|
||||
if (mutableData['deviceId'] == 'tab_to_run') {
|
||||
context.read<RoutineBloc>().add(AddToIfContainer(mutableData, true));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(mutableData, true));
|
||||
} else {
|
||||
final result = await DeviceDialogHelper.showDeviceDialog(
|
||||
dialogType: 'IF',
|
||||
@ -121,10 +133,14 @@ class IfContainer extends StatelessWidget {
|
||||
removeComparetors: false);
|
||||
|
||||
if (result != null) {
|
||||
context.read<RoutineBloc>().add(AddToIfContainer(mutableData, false));
|
||||
} else if (!['AC', '1G', '2G', '3G', 'WPS', 'GW', 'CPS']
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(mutableData, false));
|
||||
} else if (!['AC', '1G', '2G', '3G', 'WPS', 'GW', 'CPS', 'NCPS']
|
||||
.contains(mutableData['productType'])) {
|
||||
context.read<RoutineBloc>().add(AddToIfContainer(mutableData, false));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(mutableData, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -170,7 +186,9 @@ class AutomationOperatorSelector extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
context.read<RoutineBloc>().add(const ChangeAutomationOperator(operator: 'or'));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(const ChangeAutomationOperator(operator: 'or'));
|
||||
},
|
||||
),
|
||||
Container(
|
||||
@ -196,7 +214,9 @@ class AutomationOperatorSelector extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
context.read<RoutineBloc>().add(const ChangeAutomationOperator(operator: 'and'));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(const ChangeAutomationOperator(operator: 'and'));
|
||||
},
|
||||
),
|
||||
],
|
||||
|
@ -17,7 +17,16 @@ class _RoutineDevicesState extends State<RoutineDevices> {
|
||||
context.read<RoutineBloc>().add(FetchDevicesInRoutine());
|
||||
}
|
||||
|
||||
static const _allowedProductTypes = {'AC', '1G', '2G', '3G', 'WPS', 'GW', 'CPS'};
|
||||
static const _allowedProductTypes = {
|
||||
'AC',
|
||||
'1G',
|
||||
'2G',
|
||||
'3G',
|
||||
'WPS',
|
||||
'GW',
|
||||
'CPS',
|
||||
'NCPS'
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -34,7 +43,8 @@ class _RoutineDevicesState extends State<RoutineDevices> {
|
||||
});
|
||||
|
||||
final deviceList = state.devices
|
||||
.where((device) => _allowedProductTypes.contains(device.productType))
|
||||
.where(
|
||||
(device) => _allowedProductTypes.contains(device.productType))
|
||||
.toList();
|
||||
|
||||
return Wrap(
|
||||
@ -51,12 +61,16 @@ class _RoutineDevicesState extends State<RoutineDevices> {
|
||||
'productType': device.productType,
|
||||
'functions': device.functions,
|
||||
'uniqueCustomId': '',
|
||||
'tag': device.deviceTags!.isNotEmpty ? device.deviceTags![0].name : '',
|
||||
'tag': device.deviceTags!.isNotEmpty
|
||||
? device.deviceTags![0].name
|
||||
: '',
|
||||
'subSpace': device.deviceSubSpace?.subspaceName ?? '',
|
||||
};
|
||||
|
||||
if (state.searchText != null && state.searchText!.isNotEmpty) {
|
||||
return device.name!.toLowerCase().contains(state.searchText!.toLowerCase())
|
||||
return device.name!
|
||||
.toLowerCase()
|
||||
.contains(state.searchText!.toLowerCase())
|
||||
? DraggableCard(
|
||||
imagePath: deviceData['imagePath'] as String,
|
||||
title: deviceData['title'] as String,
|
||||
|
@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/flush/flush_operational_value.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/wall_sensor/time_wheel.dart';
|
||||
|
||||
class FlushOperationalValuesList extends StatelessWidget {
|
||||
final List<FlushOperationalValue> values;
|
||||
final dynamic selectedValue;
|
||||
final AllDevicesModel? device;
|
||||
final String operationName;
|
||||
final String selectCode;
|
||||
final ValueChanged<FlushOperationalValue> onSelect;
|
||||
const FlushOperationalValuesList({
|
||||
required this.values,
|
||||
required this.selectedValue,
|
||||
required this.device,
|
||||
required this.operationName,
|
||||
required this.selectCode,
|
||||
required this.onSelect,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(20),
|
||||
itemCount: values.length,
|
||||
itemBuilder: (context, index) =>
|
||||
_buildValueItem(context, values[index]),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Widget _buildValueItem(BuildContext context, FlushOperationalValue value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: _buildValueDescription(value)),
|
||||
_buildValueRadio(context, value),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Widget _buildValueDescription(FlushOperationalValue value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: Text(value.description),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildValueRadio(context, FlushOperationalValue value) {
|
||||
return Radio<dynamic>(
|
||||
value: value.value,
|
||||
groupValue: selectedValue,
|
||||
onChanged: (_) => onSelect(value));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/flush/flush_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/flush_presence_sensor/flush_value_selector_widget.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
||||
class FlushPresenceSensor extends StatefulWidget {
|
||||
final List<DeviceFunction> functions;
|
||||
final AllDevicesModel? device;
|
||||
final List<DeviceFunctionData>? deviceSelectedFunctions;
|
||||
final String? uniqueCustomId;
|
||||
final String dialogType;
|
||||
final bool removeComparetors;
|
||||
|
||||
const FlushPresenceSensor({
|
||||
super.key,
|
||||
required this.functions,
|
||||
this.device,
|
||||
this.deviceSelectedFunctions,
|
||||
this.uniqueCustomId,
|
||||
required this.dialogType,
|
||||
this.removeComparetors = false,
|
||||
});
|
||||
|
||||
static Future<Map<String, dynamic>?> showFlushFunctionsDialog({
|
||||
required BuildContext context,
|
||||
required List<DeviceFunction> functions,
|
||||
AllDevicesModel? device,
|
||||
List<DeviceFunctionData>? deviceSelectedFunctions,
|
||||
String? uniqueCustomId,
|
||||
required String dialogType,
|
||||
bool removeComparetors = false,
|
||||
}) async {
|
||||
return showDialog<Map<String, dynamic>?>(
|
||||
context: context,
|
||||
builder: (context) => FlushPresenceSensor(
|
||||
functions: functions,
|
||||
device: device,
|
||||
deviceSelectedFunctions: deviceSelectedFunctions,
|
||||
uniqueCustomId: uniqueCustomId,
|
||||
removeComparetors: removeComparetors,
|
||||
dialogType: dialogType,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
State<FlushPresenceSensor> createState() => _WallPresenceSensorState();
|
||||
}
|
||||
|
||||
class _WallPresenceSensorState extends State<FlushPresenceSensor> {
|
||||
late final List<FlushFunctions> _flushFunctions;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_flushFunctions =
|
||||
widget.functions.whereType<FlushFunctions>().where((function) {
|
||||
if (widget.dialogType == 'THEN') {
|
||||
return function.type == 'THEN' || function.type == 'BOTH';
|
||||
}
|
||||
return function.type == 'IF' || function.type == 'BOTH';
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (_) => FunctionBloc()
|
||||
..add(InitializeFunctions(widget.deviceSelectedFunctions ?? [])),
|
||||
child: _buildDialogContent(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDialogContent() {
|
||||
return AlertDialog(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: BlocBuilder<FunctionBloc, FunctionBlocState>(
|
||||
builder: (context, state) {
|
||||
final selectedFunction = state.selectedFunction;
|
||||
return Container(
|
||||
width: selectedFunction != null ? 600 : 360,
|
||||
height: 450,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const DialogHeader('Presence Sensor Condition'),
|
||||
Expanded(child: _buildMainContent(context, state)),
|
||||
_buildDialogFooter(context, state),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMainContent(BuildContext context, FunctionBlocState state) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_buildFunctionList(context),
|
||||
if (state.selectedFunction != null) _buildValueSelector(context, state),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFunctionList(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: 360,
|
||||
child: ListView.separated(
|
||||
shrinkWrap: false,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
itemCount: _flushFunctions.length,
|
||||
separatorBuilder: (context, index) => const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 40.0),
|
||||
child: Divider(color: ColorsManager.dividerColor),
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
final function = _flushFunctions[index];
|
||||
return ListTile(
|
||||
leading: SvgPicture.asset(
|
||||
function.icon,
|
||||
width: 24,
|
||||
height: 24,
|
||||
placeholderBuilder: (context) => const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
function.operationName,
|
||||
style: context.textTheme.bodyMedium,
|
||||
),
|
||||
trailing: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 16,
|
||||
color: ColorsManager.textGray,
|
||||
),
|
||||
onTap: () => context.read<FunctionBloc>().add(
|
||||
SelectFunction(
|
||||
functionCode: function.code,
|
||||
operationName: function.operationName,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildValueSelector(BuildContext context, FunctionBlocState state) {
|
||||
final selectedFunction = state.selectedFunction ?? '';
|
||||
final functionData = state.addedFunctions.firstWhere(
|
||||
(f) => f.functionCode == selectedFunction,
|
||||
orElse: () => DeviceFunctionData(
|
||||
entityId: '',
|
||||
functionCode: selectedFunction,
|
||||
operationName: state.selectedOperationName ?? '',
|
||||
value: null,
|
||||
),
|
||||
);
|
||||
|
||||
return Expanded(
|
||||
child: FlushValueSelectorWidget(
|
||||
selectedFunction: selectedFunction,
|
||||
functionData: functionData,
|
||||
flushFunctions: _flushFunctions,
|
||||
device: widget.device,
|
||||
dialogType: widget.dialogType,
|
||||
removeComparators: widget.removeComparetors,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDialogFooter(BuildContext context, FunctionBlocState state) {
|
||||
return DialogFooter(
|
||||
onCancel: () => Navigator.pop(context),
|
||||
onConfirm: state.addedFunctions.isNotEmpty
|
||||
? () {
|
||||
context.read<RoutineBloc>().add(
|
||||
AddFunctionToRoutine(
|
||||
state.addedFunctions,
|
||||
widget.uniqueCustomId!,
|
||||
),
|
||||
);
|
||||
Navigator.pop(
|
||||
context,
|
||||
{'deviceId': widget.functions.first.deviceId},
|
||||
);
|
||||
}
|
||||
: null,
|
||||
isConfirmEnabled: state.selectedFunction != null,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/models/flush_mounted_presence_sensor_model.dart';
|
||||
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/models/flush/flush_functions.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/flush_presence_sensor/flush_operational_values_list.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/slider_value_selector.dart';
|
||||
|
||||
class FlushValueSelectorWidget extends StatelessWidget {
|
||||
final String selectedFunction;
|
||||
final DeviceFunctionData functionData;
|
||||
final List<FlushFunctions> flushFunctions;
|
||||
final AllDevicesModel? device;
|
||||
final String dialogType;
|
||||
final bool removeComparators;
|
||||
|
||||
const FlushValueSelectorWidget({
|
||||
required this.selectedFunction,
|
||||
required this.functionData,
|
||||
required this.flushFunctions,
|
||||
required this.device,
|
||||
required this.dialogType,
|
||||
required this.removeComparators,
|
||||
super.key,
|
||||
});
|
||||
|
||||
(double, double) get sliderRange => switch (functionData.functionCode) {
|
||||
FlushMountedPresenceSensorModel.codeOccurDistReduce => (0, 3),
|
||||
FlushMountedPresenceSensorModel.codeNoneDelay => (200, 3000),
|
||||
FlushMountedPresenceSensorModel.codeSensiReduce => (0, 3),
|
||||
FlushMountedPresenceSensorModel.codePresenceDelay => (0, 5),
|
||||
FlushMountedPresenceSensorModel.codeIlluminance => (0.0, 2000.0),
|
||||
FlushMountedPresenceSensorModel.codeFarDetection => (0.0, 9.5),
|
||||
FlushMountedPresenceSensorModel.codeNearDetection => (0.0, 9.5),
|
||||
_ => (0.0, 100.0),
|
||||
};
|
||||
|
||||
double get stepSize => switch (functionData.functionCode) {
|
||||
FlushMountedPresenceSensorModel.codeNoneDelay => 10.0,
|
||||
FlushMountedPresenceSensorModel.codeFarDetection => 0.5,
|
||||
FlushMountedPresenceSensorModel.codeNearDetection => 0.5,
|
||||
FlushMountedPresenceSensorModel.codePresenceDelay => 1.0,
|
||||
FlushMountedPresenceSensorModel.codeOccurDistReduce => 1.0,
|
||||
FlushMountedPresenceSensorModel.codeSensiReduce => 1.0,
|
||||
_ => 1.0,
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final selectedFn = flushFunctions.firstWhere(
|
||||
(f) => f.code == selectedFunction,
|
||||
orElse: () => throw Exception('Function $selectedFunction not found'),
|
||||
);
|
||||
|
||||
if (_isSliderFunction(selectedFunction)) {
|
||||
final isNearDetection =
|
||||
selectedFunction == FlushMountedPresenceSensorModel.codeNearDetection;
|
||||
final isFarDetection =
|
||||
selectedFunction == FlushMountedPresenceSensorModel.codeFarDetection;
|
||||
|
||||
final isDistanceDetection = isNearDetection || isFarDetection;
|
||||
double initialValue = (functionData.value as num?)?.toDouble() ?? 0.0;
|
||||
|
||||
if (isDistanceDetection) {
|
||||
initialValue = initialValue / 100;
|
||||
}
|
||||
return SliderValueSelector(
|
||||
currentCondition: functionData.condition,
|
||||
dialogType: dialogType,
|
||||
sliderRange: sliderRange,
|
||||
displayedValue: getDisplayText,
|
||||
initialValue: initialValue,
|
||||
onConditionChanged: (condition) => context.read<FunctionBloc>().add(
|
||||
AddFunction(
|
||||
functionData: DeviceFunctionData(
|
||||
entityId: device?.uuid ?? '',
|
||||
functionCode: selectedFunction,
|
||||
operationName: functionData.operationName,
|
||||
condition: condition,
|
||||
value: functionData.value ?? 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
onSliderChanged: (value) {
|
||||
final roundedValue = _roundToStep(value, stepSize);
|
||||
final finalValue =
|
||||
isDistanceDetection ? (roundedValue * 100).toInt() : roundedValue;
|
||||
|
||||
context.read<FunctionBloc>().add(
|
||||
AddFunction(
|
||||
functionData: DeviceFunctionData(
|
||||
entityId: device?.uuid ?? '',
|
||||
functionCode: selectedFunction,
|
||||
operationName: functionData.operationName,
|
||||
value: finalValue,
|
||||
condition: functionData.condition,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
unit: _unit,
|
||||
dividendOfRange: stepSize,
|
||||
);
|
||||
}
|
||||
|
||||
return FlushOperationalValuesList(
|
||||
values: selectedFn.getOperationalValues(),
|
||||
selectedValue: functionData.value,
|
||||
device: device,
|
||||
operationName: selectedFn.operationName,
|
||||
selectCode: selectedFunction,
|
||||
onSelect: (selectedValue) async {
|
||||
context.read<FunctionBloc>().add(
|
||||
AddFunction(
|
||||
functionData: DeviceFunctionData(
|
||||
entityId: device?.uuid ?? '',
|
||||
functionCode: selectedFunction,
|
||||
operationName: functionData.operationName,
|
||||
value: selectedValue.value,
|
||||
condition: functionData.condition,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
double _roundToStep(double value, double step) {
|
||||
return (value / step).roundToDouble() * step;
|
||||
}
|
||||
|
||||
bool _isSliderFunction(String function) => [
|
||||
FlushMountedPresenceSensorModel.codeOccurDistReduce,
|
||||
FlushMountedPresenceSensorModel.codeSensiReduce,
|
||||
FlushMountedPresenceSensorModel.codeNoneDelay,
|
||||
FlushMountedPresenceSensorModel.codeIlluminance,
|
||||
FlushMountedPresenceSensorModel.codePresenceDelay,
|
||||
FlushMountedPresenceSensorModel.codeFarDetection,
|
||||
FlushMountedPresenceSensorModel.codeNearDetection,
|
||||
].contains(function);
|
||||
|
||||
String get _unit => switch (functionData.functionCode) {
|
||||
FlushMountedPresenceSensorModel.codeOccurDistReduce => 'Min',
|
||||
FlushMountedPresenceSensorModel.codeSensiReduce => 'Sec',
|
||||
FlushMountedPresenceSensorModel.codeNoneDelay => 'Sec',
|
||||
FlushMountedPresenceSensorModel.codePresenceDelay => 'Sec',
|
||||
FlushMountedPresenceSensorModel.codeIlluminance => 'Lux',
|
||||
FlushMountedPresenceSensorModel.codeFarDetection => 'm',
|
||||
FlushMountedPresenceSensorModel.codeNearDetection => 'm',
|
||||
_ => '',
|
||||
};
|
||||
|
||||
String get getDisplayText {
|
||||
final num? value = functionData.value;
|
||||
double displayValue = value?.toDouble() ?? 0.0;
|
||||
|
||||
if (functionData.functionCode ==
|
||||
FlushMountedPresenceSensorModel.codeNearDetection ||
|
||||
functionData.functionCode ==
|
||||
FlushMountedPresenceSensorModel.codeFarDetection) {
|
||||
displayValue = displayValue / 100;
|
||||
}
|
||||
|
||||
switch (functionData.functionCode) {
|
||||
case FlushMountedPresenceSensorModel.codeFarDetection:
|
||||
case FlushMountedPresenceSensorModel.codeNearDetection:
|
||||
return displayValue.toStringAsFixed(1);
|
||||
case FlushMountedPresenceSensorModel.codeOccurDistReduce:
|
||||
case FlushMountedPresenceSensorModel.codeSensiReduce:
|
||||
case FlushMountedPresenceSensorModel.codePresenceDelay:
|
||||
return displayValue.toStringAsFixed(0);
|
||||
default:
|
||||
return displayValue.toStringAsFixed(0);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,169 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class TimeWheelPicker extends StatefulWidget {
|
||||
final int initialHours;
|
||||
final int initialMinutes;
|
||||
final int initialSeconds;
|
||||
final Function(int, int, int) onTimeChanged;
|
||||
|
||||
const TimeWheelPicker({
|
||||
super.key,
|
||||
required this.initialHours,
|
||||
required this.initialMinutes,
|
||||
required this.initialSeconds,
|
||||
required this.onTimeChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
State<TimeWheelPicker> createState() => _TimeWheelPickerState();
|
||||
}
|
||||
|
||||
class _TimeWheelPickerState extends State<TimeWheelPicker> {
|
||||
late FixedExtentScrollController _hoursController;
|
||||
late FixedExtentScrollController _minutesController;
|
||||
late FixedExtentScrollController _secondsController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_hoursController =
|
||||
FixedExtentScrollController(initialItem: widget.initialHours);
|
||||
_minutesController =
|
||||
FixedExtentScrollController(initialItem: widget.initialMinutes);
|
||||
_secondsController =
|
||||
FixedExtentScrollController(initialItem: widget.initialSeconds);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(TimeWheelPicker oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.initialHours != widget.initialHours) {
|
||||
_hoursController.jumpToItem(widget.initialHours);
|
||||
}
|
||||
if (oldWidget.initialMinutes != widget.initialMinutes) {
|
||||
_minutesController.jumpToItem(widget.initialMinutes);
|
||||
}
|
||||
if (oldWidget.initialSeconds != widget.initialSeconds) {
|
||||
_secondsController.jumpToItem(widget.initialSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_hoursController.dispose();
|
||||
_minutesController.dispose();
|
||||
_secondsController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildPickerColumn(
|
||||
label: 'h',
|
||||
controller: _hoursController,
|
||||
itemCount: 3,
|
||||
onChanged: (value) {
|
||||
_handleTimeChange(
|
||||
value,
|
||||
_minutesController.selectedItem,
|
||||
_secondsController.selectedItem,
|
||||
);
|
||||
}),
|
||||
const SizedBox(width: 5),
|
||||
_buildPickerColumn(
|
||||
label: 'm',
|
||||
controller: _minutesController,
|
||||
itemCount: 60,
|
||||
onChanged: (value) {
|
||||
_handleTimeChange(
|
||||
_hoursController.selectedItem,
|
||||
value,
|
||||
_secondsController.selectedItem,
|
||||
);
|
||||
}),
|
||||
const SizedBox(width: 5),
|
||||
_buildPickerColumn(
|
||||
label: 's',
|
||||
controller: _secondsController,
|
||||
itemCount: 60,
|
||||
onChanged: (value) => _handleTimeChange(
|
||||
_hoursController.selectedItem,
|
||||
_minutesController.selectedItem,
|
||||
value,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _handleTimeChange(int hours, int minutes, int seconds) {
|
||||
int total = hours * 3600 + minutes * 60 + seconds;
|
||||
if (total > 10000) {
|
||||
hours = 2;
|
||||
minutes = 46;
|
||||
seconds = 40;
|
||||
total = 10000;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_hoursController.jumpToItem(hours);
|
||||
_minutesController.jumpToItem(minutes);
|
||||
_secondsController.jumpToItem(seconds);
|
||||
});
|
||||
}
|
||||
|
||||
widget.onTimeChanged(hours, minutes, seconds);
|
||||
}
|
||||
|
||||
Widget _buildPickerColumn({
|
||||
required String label,
|
||||
required FixedExtentScrollController controller,
|
||||
required int itemCount,
|
||||
required Function(int) onChanged,
|
||||
}) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.boxColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: ListWheelScrollView.useDelegate(
|
||||
controller: controller,
|
||||
itemExtent: 40.0,
|
||||
physics: const FixedExtentScrollPhysics(),
|
||||
onSelectedItemChanged: onChanged,
|
||||
childDelegate: ListWheelChildBuilderDelegate(
|
||||
builder: (context, index) => Center(
|
||||
child: Text(
|
||||
index.toString().padLeft(2),
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
color: ColorsManager.blue1,
|
||||
),
|
||||
),
|
||||
),
|
||||
childCount: itemCount,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -27,7 +27,8 @@ class ThenContainer extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('THEN',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
style: TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
state.isLoading && state.isUpdate == true
|
||||
? const Center(
|
||||
@ -40,11 +41,12 @@ class ThenContainer extends StatelessWidget {
|
||||
state.thenItems.length,
|
||||
(index) => GestureDetector(
|
||||
onTap: () async {
|
||||
if (state.thenItems[index]['deviceId'] ==
|
||||
if (state.thenItems[index]
|
||||
['deviceId'] ==
|
||||
'delay') {
|
||||
final result = await DelayHelper
|
||||
.showDelayPickerDialog(
|
||||
context, state.thenItems[index]);
|
||||
.showDelayPickerDialog(context,
|
||||
state.thenItems[index]);
|
||||
|
||||
if (result != null) {
|
||||
context
|
||||
@ -64,14 +66,17 @@ class ThenContainer extends StatelessWidget {
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
AutomationDialog(
|
||||
automationName: state.thenItems[index]
|
||||
['name'] ??
|
||||
'Automation',
|
||||
automationId: state.thenItems[index]
|
||||
['deviceId'] ??
|
||||
'',
|
||||
uniqueCustomId: state.thenItems[index]
|
||||
['uniqueCustomId'],
|
||||
automationName:
|
||||
state.thenItems[index]
|
||||
['name'] ??
|
||||
'Automation',
|
||||
automationId:
|
||||
state.thenItems[index]
|
||||
['deviceId'] ??
|
||||
'',
|
||||
uniqueCustomId:
|
||||
state.thenItems[index]
|
||||
['uniqueCustomId'],
|
||||
),
|
||||
);
|
||||
|
||||
@ -80,11 +85,13 @@ class ThenContainer extends StatelessWidget {
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToThenContainer({
|
||||
...state.thenItems[index],
|
||||
'imagePath': Assets.automation,
|
||||
'title': state.thenItems[index]
|
||||
['name'] ??
|
||||
'imagePath':
|
||||
Assets.automation,
|
||||
'title':
|
||||
state.thenItems[index]
|
||||
['title'],
|
||||
['name'] ??
|
||||
state.thenItems[index]
|
||||
['title'],
|
||||
}));
|
||||
}
|
||||
return;
|
||||
@ -109,8 +116,9 @@ class ThenContainer extends StatelessWidget {
|
||||
'WPS',
|
||||
'CPS',
|
||||
"GW",
|
||||
].contains(
|
||||
state.thenItems[index]['productType'])) {
|
||||
"NCPS"
|
||||
].contains(state.thenItems[index]
|
||||
['productType'])) {
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToThenContainer(
|
||||
state.thenItems[index]));
|
||||
@ -120,7 +128,9 @@ class ThenContainer extends StatelessWidget {
|
||||
imagePath: state.thenItems[index]
|
||||
['imagePath'] ??
|
||||
'',
|
||||
title: state.thenItems[index]['title'] ?? '',
|
||||
title: state.thenItems[index]
|
||||
['title'] ??
|
||||
'',
|
||||
deviceData: state.thenItems[index],
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 4, vertical: 8),
|
||||
@ -157,8 +167,8 @@ class ThenContainer extends StatelessWidget {
|
||||
}
|
||||
|
||||
if (mutableData['type'] == 'automation') {
|
||||
int index = state.thenItems
|
||||
.indexWhere((item) => item['deviceId'] == mutableData['deviceId']);
|
||||
int index = state.thenItems.indexWhere(
|
||||
(item) => item['deviceId'] == mutableData['deviceId']);
|
||||
if (index != -1) {
|
||||
return;
|
||||
}
|
||||
@ -183,8 +193,8 @@ class ThenContainer extends StatelessWidget {
|
||||
}
|
||||
|
||||
if (mutableData['type'] == 'tap_to_run' && state.isAutomation) {
|
||||
int index = state.thenItems
|
||||
.indexWhere((item) => item['deviceId'] == mutableData['deviceId']);
|
||||
int index = state.thenItems.indexWhere(
|
||||
(item) => item['deviceId'] == mutableData['deviceId']);
|
||||
if (index != -1) {
|
||||
return;
|
||||
}
|
||||
@ -222,7 +232,7 @@ class ThenContainer extends StatelessWidget {
|
||||
dialogType: "THEN");
|
||||
if (result != null) {
|
||||
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
||||
} else if (!['AC', '1G', '2G', '3G', 'WPS', 'GW', 'CPS']
|
||||
} else if (!['AC', '1G', '2G', '3G', 'WPS', 'GW', 'CPS', "NCPS"]
|
||||
.contains(mutableData['productType'])) {
|
||||
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
||||
}
|
||||
|
Reference in New Issue
Block a user