push design changes

This commit is contained in:
ashrafzarkanisala
2024-11-22 21:38:39 +03:00
parent a52604360f
commit 7e2f605466

View File

@ -13,210 +13,203 @@ class ACHelper {
List<DeviceFunction<dynamic>> functions, List<DeviceFunction<dynamic>> functions,
) async { ) async {
List<ACFunction> acFunctions = functions.whereType<ACFunction>().toList(); List<ACFunction> acFunctions = functions.whereType<ACFunction>().toList();
String? selectedFunction; final selectedFunctionNotifier = ValueNotifier<String?>(null);
dynamic selectedValue = 20; final selectedValueNotifier = ValueNotifier<dynamic>(null);
String? selectedCondition = "=="; final selectedConditionNotifier = ValueNotifier<String?>('==');
List<bool> _selectedConditions = [false, true, false]; final selectedConditionsNotifier =
ValueNotifier<List<bool>>([false, true, false]);
return showDialog<Map<String, dynamic>?>( return showDialog<Map<String, dynamic>?>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return StatefulBuilder( return ValueListenableBuilder<String?>(
builder: (context, setState) { valueListenable: selectedFunctionNotifier,
builder: (context, selectedFunction, _) {
return AlertDialog( return AlertDialog(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
content: _buildDialogContent( content: Container(
context, width: selectedFunction != null ? 600 : 360,
setState, height: 450,
acFunctions, decoration: BoxDecoration(
selectedFunction, color: Colors.white,
selectedValue, borderRadius: BorderRadius.circular(20),
selectedCondition, ),
_selectedConditions, padding: const EdgeInsets.only(top: 20),
(fn) => selectedFunction = fn, child: Column(
(val) => selectedValue = val, mainAxisSize: MainAxisSize.min,
(cond) => selectedCondition = cond, children: [
const DialogHeader('AC Functions'),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Function list
SizedBox(
width: selectedFunction != null ? 320 : 360,
child: _buildFunctionsList(
context,
acFunctions,
selectedFunctionNotifier,
),
),
// Value selector
if (selectedFunction != null)
Expanded(
child: _buildValueSelector(
context,
selectedFunction,
selectedValueNotifier,
selectedConditionNotifier,
selectedConditionsNotifier,
acFunctions,
),
),
],
),
),
DialogFooter(
onCancel: () {
selectedFunctionNotifier.dispose();
selectedValueNotifier.dispose();
selectedConditionNotifier.dispose();
selectedConditionsNotifier.dispose();
Navigator.pop(context);
},
onConfirm: selectedFunctionNotifier.value != null &&
selectedValueNotifier.value != null
? () {
selectedFunctionNotifier.dispose();
selectedValueNotifier.dispose();
selectedConditionNotifier.dispose();
selectedConditionsNotifier.dispose();
Navigator.pop(context, {
'function': selectedFunctionNotifier.value,
'value': selectedValueNotifier.value,
'condition':
selectedConditionNotifier.value ?? "==",
});
}
: null,
isConfirmEnabled: selectedFunction != null,
),
],
),
), ),
); );
}, },
); );
}, },
); ).then((value) {
} selectedFunctionNotifier.dispose();
selectedValueNotifier.dispose();
/// Build dialog content for AC functions dialog selectedConditionNotifier.dispose();
static Widget _buildDialogContent( selectedConditionsNotifier.dispose();
BuildContext context, return value;
StateSetter setState, });
List<ACFunction> acFunctions,
String? selectedFunction,
dynamic selectedValue,
String? selectedCondition,
List<bool> selectedConditions,
Function(String?) onFunctionSelected,
Function(dynamic) onValueSelected,
Function(String?) onConditionSelected,
) {
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('AC Functions'),
Flexible(
child: Row(
children: [
_buildFunctionsList(
context,
setState,
acFunctions,
selectedFunction,
onFunctionSelected,
),
if (selectedFunction != null)
_buildValueSelector(
context,
setState,
selectedFunction,
selectedValue,
selectedCondition,
selectedConditions,
onValueSelected,
onConditionSelected,
acFunctions,
),
],
),
),
DialogFooter(
onCancel: () => Navigator.pop(context),
onConfirm: selectedFunction != null && selectedValue != null
? () => Navigator.pop(context, {
'function': selectedFunction,
'value': selectedValue,
'condition': selectedCondition ?? "==",
})
: null,
isConfirmEnabled: selectedFunction != null && selectedValue != null,
),
],
),
);
} }
/// Build functions list for AC functions dialog /// Build functions list for AC functions dialog
static Widget _buildFunctionsList( static Widget _buildFunctionsList(
BuildContext context, BuildContext context,
StateSetter setState,
List<ACFunction> acFunctions, List<ACFunction> acFunctions,
String? selectedFunction, ValueNotifier<String?> selectedFunctionNotifier,
Function(String?) onFunctionSelected,
) { ) {
return Expanded( return ListView.separated(
child: ListView.separated( shrinkWrap: false,
shrinkWrap: false, physics: const AlwaysScrollableScrollPhysics(),
physics: const AlwaysScrollableScrollPhysics(), itemCount: acFunctions.length,
itemCount: acFunctions.length, separatorBuilder: (context, index) => const Padding(
separatorBuilder: (context, index) => const Divider( padding: EdgeInsets.symmetric(horizontal: 40.0),
child: Divider(
color: ColorsManager.dividerColor, color: ColorsManager.dividerColor,
), ),
itemBuilder: (context, index) { ),
final function = acFunctions[index]; itemBuilder: (context, index) {
return ListTile( final function = acFunctions[index];
leading: SvgPicture.asset( return ListTile(
function.icon, leading: SvgPicture.asset(
function.icon,
width: 24,
height: 24,
placeholderBuilder: (BuildContext context) => Container(
width: 24, width: 24,
height: 24, height: 24,
color: Colors.transparent,
), ),
title: Text( ),
function.operationName, title: Text(
style: context.textTheme.bodyMedium, function.operationName,
), style: context.textTheme.bodyMedium,
trailing: const Icon( ),
Icons.arrow_forward_ios, trailing: const Icon(
size: 16, Icons.arrow_forward_ios,
color: ColorsManager.textGray, size: 16,
), color: ColorsManager.textGray,
onTap: () => setState(() => onFunctionSelected(function.code)), ),
); onTap: () => selectedFunctionNotifier.value = function.code,
}, );
), },
); );
} }
/// Build value selector for AC functions dialog /// Build value selector for AC functions dialog
static Widget _buildValueSelector( static Widget _buildValueSelector(
BuildContext context, BuildContext context,
StateSetter setState,
String selectedFunction, String selectedFunction,
dynamic selectedValue, ValueNotifier<dynamic> selectedValueNotifier,
String? selectedCondition, ValueNotifier<String?> selectedConditionNotifier,
List<bool> selectedConditions, ValueNotifier<List<bool>> selectedConditionsNotifier,
Function(dynamic) onValueSelected,
Function(String?) onConditionSelected,
List<ACFunction> acFunctions, List<ACFunction> acFunctions,
) { ) {
// Handle temperature functions
if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') { if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') {
return Expanded( // Initialize with 20°C (200 in internal representation)
child: _buildTemperatureSelector( if (selectedValueNotifier.value == null ||
context, selectedValueNotifier.value is! int) {
setState, selectedValueNotifier.value = 200;
selectedValue, }
selectedCondition, return _buildTemperatureSelector(
selectedConditions, context,
onValueSelected, selectedValueNotifier,
onConditionSelected, selectedConditionNotifier,
), selectedConditionsNotifier,
); );
} }
// Handle other functions
final selectedFn = final selectedFn =
acFunctions.firstWhere((f) => f.code == selectedFunction); acFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues(); final values = selectedFn.getOperationalValues();
return Expanded(
child: _buildOperationalValuesList( // Don't set any default value for non-temperature functions
context, return _buildOperationalValuesList(
setState, context,
values, values,
selectedValue, selectedValueNotifier,
onValueSelected,
),
); );
} }
/// Build temperature selector for AC functions dialog /// Build temperature selector for AC functions dialog
static Widget _buildTemperatureSelector( static Widget _buildTemperatureSelector(
BuildContext context, BuildContext context,
StateSetter setState, ValueNotifier<dynamic> selectedValueNotifier,
dynamic selectedValue, ValueNotifier<String?> selectedConditionNotifier,
String? selectedCondition, ValueNotifier<List<bool>> selectedConditionsNotifier,
List<bool> selectedConditions,
Function(dynamic) onValueSelected,
Function(String?) onConditionSelected,
) { ) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
_buildConditionToggle( _buildConditionToggle(
context, context,
setState, selectedConditionNotifier,
selectedConditions, selectedConditionsNotifier,
onConditionSelected,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildTemperatureDisplay(context, selectedValue), _buildTemperatureDisplay(context, selectedValueNotifier),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildTemperatureSlider( _buildTemperatureSlider(
context, context,
setState, selectedValueNotifier,
selectedValue,
onValueSelected,
), ),
], ],
); );
@ -225,104 +218,121 @@ class ACHelper {
/// Build condition toggle for AC functions dialog /// Build condition toggle for AC functions dialog
static Widget _buildConditionToggle( static Widget _buildConditionToggle(
BuildContext context, BuildContext context,
StateSetter setState, ValueNotifier<String?> selectedConditionNotifier,
List<bool> selectedConditions, ValueNotifier<List<bool>> selectedConditionsNotifier,
Function(String?) onConditionSelected,
) { ) {
return ToggleButtons( return ValueListenableBuilder<List<bool>>(
onPressed: (int index) { valueListenable: selectedConditionsNotifier,
setState(() { builder: (context, selectedConditions, _) {
for (int i = 0; i < selectedConditions.length; i++) { return ToggleButtons(
selectedConditions[i] = i == index; onPressed: (int index) {
} final newConditions = [false, false, false];
onConditionSelected(index == 0 newConditions[index] = true;
? "<" selectedConditionsNotifier.value = newConditions;
: index == 1 selectedConditionNotifier.value = index == 0
? "==" ? "<"
: ">"); : index == 1
}); ? "=="
: ">";
},
borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: ColorsManager.primaryColorWithOpacity,
selectedColor: Colors.white,
fillColor: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity,
constraints: const BoxConstraints(
minHeight: 40.0,
minWidth: 40.0,
),
isSelected: selectedConditions,
children: const [Text("<"), Text("="), Text(">")],
);
}, },
borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: ColorsManager.primaryColorWithOpacity,
selectedColor: Colors.white,
fillColor: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity,
constraints: const BoxConstraints(
minHeight: 40.0,
minWidth: 40.0,
),
isSelected: selectedConditions,
children: const [Text("<"), Text("="), Text(">")],
); );
} }
/// Build temperature display for AC functions dialog /// Build temperature display for AC functions dialog
static Widget _buildTemperatureDisplay( static Widget _buildTemperatureDisplay(
BuildContext context, dynamic selectedValue) { BuildContext context, ValueNotifier<dynamic> selectedValueNotifier) {
return Container( return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1), color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: Text( child: ValueListenableBuilder(
'${selectedValue ?? 20}°C', valueListenable: selectedValueNotifier,
style: context.textTheme.headlineMedium!.copyWith( builder: (context, selectedValue, child) {
color: ColorsManager.primaryColorWithOpacity, return Text(
), '${(selectedValue ?? 200) / 10}°C',
style: context.textTheme.headlineMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity,
),
);
},
), ),
); );
} }
static Widget _buildTemperatureSlider( static Widget _buildTemperatureSlider(
BuildContext context, BuildContext context,
StateSetter setState, ValueNotifier<dynamic> selectedValueNotifier,
dynamic selectedValue,
Function(dynamic) onValueSelected,
) { ) {
final currentValue = selectedValue is int ? selectedValue.toDouble() : 20.0; return ValueListenableBuilder(
return Slider( valueListenable: selectedValueNotifier,
value: currentValue, builder: (context, selectedValue, child) {
min: 16, final currentValue =
max: 30, selectedValue is int ? selectedValue.toDouble() : 200.0;
divisions: 14, return Slider(
label: '${currentValue.toInt()}°C', value: currentValue,
onChanged: (value) { min: 160,
setState(() => onValueSelected(value.toInt())); max: 300,
divisions: 14,
label: '${(currentValue / 10).toInt()}°C',
onChanged: (value) => selectedValueNotifier.value = value.toInt(),
);
}, },
); );
} }
static Widget _buildOperationalValuesList( static Widget _buildOperationalValuesList(
BuildContext context, BuildContext context,
StateSetter setState,
List<dynamic> values, List<dynamic> values,
dynamic selectedValue, ValueNotifier<dynamic> selectedValueNotifier,
Function(dynamic) onValueSelected,
) { ) {
return ListView.builder( return ValueListenableBuilder<dynamic>(
shrinkWrap: false, valueListenable: selectedValueNotifier,
physics: const AlwaysScrollableScrollPhysics(), builder: (context, selectedValue, _) {
itemCount: values.length, return ListView.builder(
itemBuilder: (context, index) { shrinkWrap: false,
final value = values[index]; physics: const AlwaysScrollableScrollPhysics(),
return ListTile( itemCount: values.length,
leading: SvgPicture.asset( itemBuilder: (context, index) {
value.icon, final value = values[index];
width: 24, return ListTile(
height: 24, leading: SvgPicture.asset(
), value.icon,
title: Text( width: 24,
value.description, height: 24,
style: context.textTheme.bodyMedium, placeholderBuilder: (BuildContext context) => Container(
), width: 24,
trailing: Radio<dynamic>( height: 24,
value: value.value, color: Colors.transparent,
groupValue: selectedValue, ),
onChanged: (newValue) { ),
setState(() => onValueSelected(newValue)); title: Text(
}, value.description,
), style: context.textTheme.bodyMedium,
),
trailing: Radio<dynamic>(
value: value.value,
groupValue: selectedValue,
onChanged: (_) => selectedValueNotifier.value = value.value,
activeColor: ColorsManager.primaryColorWithOpacity,
),
onTap: () => selectedValueNotifier.value = value.value,
);
},
); );
}, },
); );