diff --git a/lib/features/scene/enum/operation_dialog_type.dart b/lib/features/scene/enum/operation_dialog_type.dart index b1829b1..815b701 100644 --- a/lib/features/scene/enum/operation_dialog_type.dart +++ b/lib/features/scene/enum/operation_dialog_type.dart @@ -4,6 +4,7 @@ enum OperationDialogType { temperature, onOff, integerSteps, + counterSteps, listOfOptions, none, } diff --git a/lib/features/scene/helper/functions_per_device/flush_functions_helper.dart b/lib/features/scene/helper/functions_per_device/flush_functions_helper.dart index 7ff88c0..c27c560 100644 --- a/lib/features/scene/helper/functions_per_device/flush_functions_helper.dart +++ b/lib/features/scene/helper/functions_per_device/flush_functions_helper.dart @@ -116,7 +116,7 @@ class FlushFunctionsHelper { operationName: 'Min Detection Distance', code: 'near_detection', functionValue: functionValue, - operationDialogType: OperationDialogType.integerSteps, + operationDialogType: OperationDialogType.counterSteps, operationalValues: [ SceneOperationalValue( icon: '', @@ -136,10 +136,10 @@ class FlushFunctionsHelper { operationName: 'Max Detection Distance', code: 'far_detection', functionValue: functionValue, - operationDialogType: OperationDialogType.integerSteps, + operationDialogType: OperationDialogType.counterSteps, operationalValues: [ SceneOperationalValue( - icon: '', + icon: Assets.assetsCelsiusDegrees, value: 0.0, description: "m", minValue: 0.0, @@ -156,23 +156,17 @@ class FlushFunctionsHelper { operationName: 'Trigger Level', code: 'sensi_reduce', functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, + operationDialogType: OperationDialogType.counterSteps, operationalValues: [ SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, + icon: Assets.assetsCelsiusDegrees, value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), + description: "", + minValue: 1, + maxValue: 3, + stepValue: 1, ), + ], ), SceneStaticFunction( @@ -183,23 +177,17 @@ class FlushFunctionsHelper { operationName: 'Indent Level', code: 'occur_dist_reduce', functionValue: functionValue, - operationDialogType: OperationDialogType.listOfOptions, + operationDialogType: OperationDialogType.counterSteps, operationalValues: [ SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, + icon: Assets.assetsCelsiusDegrees, value: 1, - description: 1.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 2, - description: 2.toString(), - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - value: 3, - description: 3.toString(), + description: "", + minValue: 1, + maxValue: 3, + stepValue: 1, ), + ], ), SceneStaticFunction( @@ -210,7 +198,7 @@ class FlushFunctionsHelper { operationName: 'Target Confirm Time', code: 'presence_delay', functionValue: functionValue, - operationDialogType: OperationDialogType.integerSteps, + operationDialogType: OperationDialogType.counterSteps, operationalValues: [ SceneOperationalValue( icon: '', @@ -235,7 +223,7 @@ class FlushFunctionsHelper { SceneOperationalValue( icon: '', value: 20.0, - description: "", + description: "sec", minValue: 20.0, maxValue: 300.0, stepValue: 1.0, diff --git a/lib/features/scene/helper/scene_logic_helper.dart b/lib/features/scene/helper/scene_logic_helper.dart index 1c1d270..d3deec7 100644 --- a/lib/features/scene/helper/scene_logic_helper.dart +++ b/lib/features/scene/helper/scene_logic_helper.dart @@ -8,6 +8,7 @@ import 'package:syncrow_app/features/scene/model/create_automation_model.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart'; +import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_counter.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart'; @@ -132,7 +133,7 @@ mixin SceneLogicHelper { 'presence_delay' || action.executorProperty!.functionCode == 'none_delay') { action.executorProperty!.functionValue = - action.executorProperty!.functionValue * 10; + (action.executorProperty!.functionValue * 10).round(); } } } @@ -193,12 +194,12 @@ mixin SceneLogicHelper { if (action.executorProperty!.functionCode == 'near_detection' || action.executorProperty!.functionCode == 'far_detection') { action.executorProperty!.functionValue = - action.executorProperty!.functionValue * 100; + (action.executorProperty!.functionValue * 100).round(); } else if (action.executorProperty!.functionCode == 'presence_delay' || action.executorProperty!.functionCode == 'none_delay') { action.executorProperty!.functionValue = - action.executorProperty!.functionValue * 10; + (action.executorProperty!.functionValue * 10).round(); } } } @@ -234,6 +235,13 @@ mixin SceneLogicHelper { functionValue: functionValue ?? taskItem.functionValue, isAutomation: isAutomation, ); + } else if (taskItem.operationDialogType == + OperationDialogType.counterSteps) { + return AlertDialogCounterSteps( + taskItem: taskItem, + functionValue: functionValue ?? taskItem.functionValue, + isAutomation: isAutomation, + ); } return AlertDialogFunctionsOperationsBody( diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index 415a59b..bec63dc 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -1748,7 +1748,7 @@ mixin SceneOperationsDataHelper { action.deviceName, Assets.flushIcon, 'Min Detection distance', - OperationDialogType.integerSteps, + OperationDialogType.counterSteps, _createMinDetection(), isAutomation, comparator, @@ -1763,7 +1763,7 @@ mixin SceneOperationsDataHelper { action.deviceName, Assets.flushIcon, 'Max Detection distance', - OperationDialogType.integerSteps, + OperationDialogType.counterSteps, _createFarDetection(), isAutomation, comparator, @@ -1778,7 +1778,7 @@ mixin SceneOperationsDataHelper { action.deviceName, Assets.flushIcon, "Trigger Level", - OperationDialogType.listOfOptions, + OperationDialogType.counterSteps, _createTriggerLevelFunction(), isAutomation, comparator, @@ -1789,19 +1789,12 @@ mixin SceneOperationsDataHelper { List _createTriggerLevelFunction() { return [ SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - description: "1", - value: 1, - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - description: "2", - value: 2, - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - description: "3", - value: 3, + icon: Assets.assetsCelsiusDegrees, + value: 0, + description: '', + minValue: 0, + maxValue: 3, + stepValue: 1, ), ]; } @@ -1813,7 +1806,7 @@ mixin SceneOperationsDataHelper { action.deviceName, Assets.flushIcon, 'Indent Level', - OperationDialogType.listOfOptions, + OperationDialogType.counterSteps, _createIndentLevelFunction(), isAutomation, comparator, @@ -1824,19 +1817,12 @@ mixin SceneOperationsDataHelper { List _createIndentLevelFunction() { return [ SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - description: "1", - value: 1, - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - description: "2", - value: 2, - ), - SceneOperationalValue( - icon: Assets.assetsSensitivityOperationIcon, - description: "3", - value: 3, + icon: Assets.assetsCelsiusDegrees, + value: 0, + description: '', + minValue: 0, + maxValue: 3, + stepValue: 1, ), ]; } @@ -1848,7 +1834,7 @@ mixin SceneOperationsDataHelper { action.deviceName, Assets.flushIcon, 'Target Confirm Time', - OperationDialogType.integerSteps, + OperationDialogType.counterSteps, _targetConfirmTimeFun(), isAutomation, comparator, @@ -1876,7 +1862,7 @@ mixin SceneOperationsDataHelper { SceneOperationalValue( icon: Assets.flushIcon, value: 0.0, - description: '', + description: 'sec', minValue: 20, maxValue: 300, stepValue: 1, @@ -1892,7 +1878,7 @@ mixin SceneOperationsDataHelper { value: 0.0, minValue: 0.0, maxValue: 9.5, - stepValue: 1, + stepValue: 0.10, ), ]; } @@ -1905,7 +1891,7 @@ mixin SceneOperationsDataHelper { value: 0.0, minValue: 0.0, maxValue: 9.5, - stepValue: 1, + stepValue: 0.10, ), ]; } @@ -1915,7 +1901,7 @@ mixin SceneOperationsDataHelper { SceneOperationalValue( icon: Assets.assetsCelsiusDegrees, value: 0.0, - description: '', + description: 'sec', minValue: 0.0, maxValue: 0.5, stepValue: 0.1, diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_counter.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_counter.dart new file mode 100644 index 0000000..2e13e16 --- /dev/null +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_counter.dart @@ -0,0 +1,243 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class AlertDialogCounterSteps extends StatefulWidget { + const AlertDialogCounterSteps({ + super.key, + this.functionValue, + required this.taskItem, + required this.isAutomation, + }); + + final dynamic functionValue; + final SceneStaticFunction taskItem; + final bool isAutomation; + + @override + State createState() => + _AlertDialogCounterStepsState(); +} + +class _AlertDialogCounterStepsState extends State { + double? groupValue; + int selectedToggleIndex = 1; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + final createSceneBloc = context.read(); + + if (widget.taskItem.comparator != null) { + selectedToggleIndex = _comparatorToIndex(widget.taskItem.comparator); + } + + if (widget.isAutomation) { + final automationTempTaskList = createSceneBloc.automationTempTasksList; + final automationComparatorValues = + createSceneBloc.automationComparatorValues; + + for (var element in automationTempTaskList) { + if (element.code == widget.taskItem.code) { + groupValue = element.functionValue; + selectedToggleIndex = + _comparatorToIndex(automationComparatorValues[element.code]); + } + } + } + + if (widget.taskItem.code == 'temp_current') { + groupValue = widget.functionValue != null + ? _normalizeValue( + double.tryParse(widget.functionValue.toString()) ?? + widget.taskItem.operationalValues[0].minValue, + ) + : widget.taskItem.operationalValues[0].minValue; + } else { + groupValue = widget.functionValue != null + ? _normalizeValue(widget.functionValue) + : _normalizeValue(widget.taskItem.operationalValues[0].minValue); + } + + setState(() {}); + + context.read().add( + SelectedValueEvent( + value: _deNormalizeValue(groupValue), + code: widget.taskItem.code, + isAutomation: widget.isAutomation, + comparator: _indexToComparator(selectedToggleIndex), + ), + ); + } + + int _comparatorToIndex(String? comparator) { + switch (comparator) { + case "<": + return 0; + case "==": + return 1; + case ">": + return 2; + default: + return 1; + } + } + + String _indexToComparator(int index) { + switch (index) { + case 0: + return "<"; + case 1: + return "=="; + case 2: + return ">"; + default: + return "=="; + } + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (widget.isAutomation) + ToggleButtons( + isSelected: [ + selectedToggleIndex == 0, + selectedToggleIndex == 1, + selectedToggleIndex == 2, + ], + onPressed: (index) { + setState(() { + selectedToggleIndex = index; + }); + context.read().add( + SelectedValueEvent( + value: _deNormalizeValue(groupValue), + code: widget.taskItem.code, + isAutomation: widget.isAutomation, + comparator: _indexToComparator(selectedToggleIndex), + ), + ); + }, + borderRadius: BorderRadius.circular(30), + selectedColor: Colors.white, + color: ColorsManager.blackColor, + fillColor: ColorsManager.primaryColorWithOpacity, + borderColor: ColorsManager.greyColor, + constraints: BoxConstraints.tight(Size(70, 30)), + children: const [ + SizedBox(width: 70, height: 30, child: Center(child: Text("<"))), + SizedBox(width: 70, height: 30, child: Center(child: Text("="))), + SizedBox(width: 70, height: 30, child: Center(child: Text(">"))), + ], + ), + const SizedBox(height: 12), + ...widget.taskItem.operationalValues.map( + (operation) => BlocBuilder( + builder: (context, state) { + final step = operation.stepValue?.toDouble() ?? 1.0; + final min = operation.minValue?.toDouble() ?? 0.0; + final max = operation.maxValue?.toDouble() ?? 100.0; + + return Column( + children: [ + const SizedBox(height: 12), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconButton( + icon: const Icon(Icons.remove), + onPressed: () { + setState(() { + groupValue = + ((groupValue ?? min) - step).clamp(min, max); + }); + context.read().add( + SelectedValueEvent( + value: _deNormalizeValue(groupValue), + code: widget.taskItem.code, + isAutomation: widget.isAutomation, + comparator: + _indexToComparator(selectedToggleIndex), + ), + ); + }, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TitleMedium( + text: groupValue != null + ? (groupValue! % 1 == 0 + ? groupValue!.toStringAsFixed(0) + : groupValue!.toStringAsFixed(1)) + : "0", + style: context.titleMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontSize: 30, + ), + ), + const SizedBox(width: 8), + TitleMedium( + text: operation.description.toString(), + style: context.titleMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontSize: 30, + ), + ), + ], + ), + IconButton( + icon: const Icon(Icons.add), + onPressed: () { + setState(() { + groupValue = + ((groupValue ?? 0) + step).clamp(min, max); + }); + context.read().add( + SelectedValueEvent( + value: _deNormalizeValue(groupValue), + code: widget.taskItem.code, + isAutomation: widget.isAutomation, + comparator: + _indexToComparator(selectedToggleIndex), + ), + ); + }, + ), + ], + ), + const SizedBox(height: 12), + ], + ); + }, + ), + ), + ], + ); + } + + double _normalizeValue(dynamic value) { + if ((widget.taskItem.code == "temp_set" && value > 199) || + (widget.taskItem.code == "temp_current" && value >= -99.0)) { + return (value) / 10; + } + return value.toDouble(); + } + + double _deNormalizeValue(double? value) { + if (widget.taskItem.code == "temp_set" || + widget.taskItem.code == "temp_current") { + return (value ?? 0) * 10; + } + return value ?? 0; + } +}