Refactor color management and UI components for consistency

- Updated color references in various widgets to use the new `opaquePrimary` color for better visual consistency.
- Refactored `ColorsManager` to improve color definitions and removed redundant color declarations.
- Enhanced UI elements across multiple dialogs and widgets to ensure a cohesive design language.

This change promotes maintainability and aligns with the updated color scheme.
This commit is contained in:
Faris Armoush
2025-07-24 10:27:17 +03:00
parent 04d1c37308
commit 99924c1e62
164 changed files with 911 additions and 997 deletions

View File

@ -12,11 +12,7 @@ class ConditionToggle extends StatelessWidget {
});
static const _conditions = ["<", "==", ">"];
static const _icons = [
Icons.chevron_left,
Icons.drag_handle,
Icons.chevron_right
];
static const _icons = [Icons.chevron_left, Icons.drag_handle, Icons.chevron_right];
@override
Widget build(BuildContext context) {
@ -41,16 +37,14 @@ class ConditionToggle extends StatelessWidget {
duration: const Duration(milliseconds: 180),
curve: Curves.ease,
decoration: BoxDecoration(
color:
isSelected ? ColorsManager.vividBlue : Colors.transparent,
color: isSelected ? ColorsManager.vividBlue : Colors.transparent,
),
child: Center(
child: Icon(
_icons[index],
size: 20,
color: isSelected
? ColorsManager.whiteColors
: ColorsManager.blackColor,
color:
isSelected ? ColorsManager.white : ColorsManager.blackColor,
weight: isSelected ? 700 : 500,
),
),

View File

@ -39,7 +39,8 @@ class DeleteSceneWidget extends StatelessWidget {
),
),
),
Container(width: 1, height: 50, color: ColorsManager.greyColor),
Container(
width: 1, height: 50, color: ColorsManager.greyColor),
InkWell(
onTap: () {
context.read<RoutineBloc>().add(const DeleteScene());
@ -51,7 +52,7 @@ class DeleteSceneWidget extends StatelessWidget {
child: Text(
'Confirm',
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.opaquePrimary,
),
),
),

View File

@ -37,9 +37,7 @@ class DialogFooter extends StatelessWidget {
DialogFooterButton(
text: 'Confirm',
onTap: onConfirm,
textColor: isConfirmEnabled
? ColorsManager.primaryColorWithOpacity
: Colors.red,
textColor: isConfirmEnabled ? ColorsManager.opaquePrimary : Colors.red,
),
],
],
@ -65,7 +63,7 @@ class DialogFooterButton extends StatelessWidget {
return Expanded(
child: TextButton(
style: TextButton.styleFrom(
foregroundColor: ColorsManager.primaryColorWithOpacity,
foregroundColor: ColorsManager.opaquePrimary,
disabledForegroundColor: ColorsManager.primaryColor,
),
onPressed: onTap,

View File

@ -18,7 +18,7 @@ class DialogHeader extends StatelessWidget {
title,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.opaquePrimary,
fontWeight: FontWeight.bold,
),
),

View File

@ -33,17 +33,18 @@ class DraggableCard extends StatelessWidget {
Widget build(BuildContext context) {
return BlocBuilder<RoutineBloc, RoutineState>(
builder: (context, state) {
final deviceFunctions = state.selectedFunctions[deviceData['uniqueCustomId']] ?? [];
final deviceFunctions =
state.selectedFunctions[deviceData['uniqueCustomId']] ?? [];
int index = state.thenItems
.indexWhere((item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']);
int index = state.thenItems.indexWhere(
(item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']);
if (index != -1) {
return _buildCardContent(context, deviceFunctions, padding: padding);
}
int ifIndex = state.ifItems
.indexWhere((item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']);
int ifIndex = state.ifItems.indexWhere(
(item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']);
if (ifIndex != -1) {
return _buildCardContent(context, deviceFunctions, padding: padding);
@ -62,12 +63,13 @@ class DraggableCard extends StatelessWidget {
);
}
Widget _buildCardContent(BuildContext context, List<DeviceFunctionData> deviceFunctions,
Widget _buildCardContent(
BuildContext context, List<DeviceFunctionData> deviceFunctions,
{EdgeInsetsGeometry? padding}) {
return Stack(
children: [
Card(
color: ColorsManager.whiteColors,
color: ColorsManager.white,
child: Container(
padding: const EdgeInsets.all(16),
width: 110,
@ -92,7 +94,8 @@ class DraggableCard extends StatelessWidget {
),
),
padding: const EdgeInsets.all(8),
child: deviceData['type'] == 'tap_to_run' || deviceData['type'] == 'scene'
child: deviceData['type'] == 'tap_to_run' ||
deviceData['type'] == 'scene'
? Image.memory(
base64Decode(deviceData['icon']),
)
@ -123,7 +126,9 @@ class DraggableCard extends StatelessWidget {
spacing: 2,
children: [
SizedBox(
width: 8, height: 8, child: SvgPicture.asset(Assets.deviceTagIcon)),
width: 8,
height: 8,
child: SvgPicture.asset(Assets.deviceTagIcon)),
Flexible(
child: Text(
deviceData['tag'] ?? '',
@ -141,13 +146,15 @@ class DraggableCard extends StatelessWidget {
),
),
Visibility(
visible: deviceData['subSpace'] != null && deviceData['subSpace'] != '',
visible: deviceData['subSpace'] != null &&
deviceData['subSpace'] != '',
child: const SizedBox(
height: 4,
),
),
Visibility(
visible: deviceData['subSpace'] != null && deviceData['subSpace'] != '',
visible: deviceData['subSpace'] != null &&
deviceData['subSpace'] != '',
child: Row(
spacing: 2,
children: [
@ -222,7 +229,8 @@ class DraggableCard extends StatelessWidget {
}
String _formatFunctionValue(DeviceFunctionData function) {
if (function.functionCode == 'temp_set' || function.functionCode == 'temp_current') {
if (function.functionCode == 'temp_set' ||
function.functionCode == 'temp_current') {
return '${(function.value / 10).toStringAsFixed(0)}°C';
} else if (function.functionCode.contains('countdown')) {
final seconds = function.value?.toInt() ?? 0;

View File

@ -32,8 +32,7 @@ class IfContainer extends StatelessWidget {
fontSize: 18, fontWeight: FontWeight.bold)),
if (state.isAutomation && state.ifItems.isNotEmpty)
AutomationOperatorSelector(
selectedOperator:
state.selectedAutomationOperator),
selectedOperator: state.selectedAutomationOperator),
],
),
const SizedBox(height: 16),
@ -57,8 +56,8 @@ class IfContainer extends StatelessWidget {
(index) => GestureDetector(
onTap: () async {
if (!state.isTabToRun) {
final result = await DeviceDialogHelper
.showDeviceDialog(
final result =
await DeviceDialogHelper.showDeviceDialog(
context: context,
data: state.ifItems[index],
removeComparetors: false,
@ -79,8 +78,8 @@ class IfContainer extends StatelessWidget {
'NCPS',
'WH',
'PC',
].contains(state.ifItems[index]
['productType'])) {
].contains(
state.ifItems[index]['productType'])) {
context.read<RoutineBloc>().add(
AddToIfContainer(
state.ifItems[index], false));
@ -97,12 +96,11 @@ class IfContainer extends StatelessWidget {
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']));
},
),
)),
@ -123,9 +121,7 @@ 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',
@ -184,7 +180,7 @@ class AutomationOperatorSelector extends StatelessWidget {
style: TextButton.styleFrom(
backgroundColor: selectedOperator.toLowerCase() == 'or'
? ColorsManager.dialogBlueTitle
: ColorsManager.whiteColors,
: ColorsManager.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
@ -193,7 +189,7 @@ class AutomationOperatorSelector extends StatelessWidget {
'Any condition is met',
style: context.textTheme.bodyMedium?.copyWith(
color: selectedOperator.toLowerCase() == 'or'
? ColorsManager.whiteColors
? ColorsManager.white
: ColorsManager.blackColor,
),
),
@ -212,7 +208,7 @@ class AutomationOperatorSelector extends StatelessWidget {
style: TextButton.styleFrom(
backgroundColor: selectedOperator.toLowerCase() == 'and'
? ColorsManager.dialogBlueTitle
: ColorsManager.whiteColors,
: ColorsManager.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
@ -221,7 +217,7 @@ class AutomationOperatorSelector extends StatelessWidget {
'All condition is met',
style: context.textTheme.bodyMedium?.copyWith(
color: selectedOperator.toLowerCase() == 'and'
? ColorsManager.whiteColors
? ColorsManager.white
: ColorsManager.blackColor,
),
),

View File

@ -91,7 +91,7 @@ class _RoutineViewCardState extends State<RoutineViewCard> {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: ColorsManager.whiteColors,
color: ColorsManager.white,
child: InkWell(
borderRadius: BorderRadius.circular(10),
child: Padding(
@ -121,8 +121,7 @@ class _RoutineViewCardState extends State<RoutineViewCard> {
child: SizedBox(
width: 16,
height: 16,
child:
CircularProgressIndicator(strokeWidth: 2),
child: CircularProgressIndicator(strokeWidth: 2),
),
),
)
@ -160,9 +159,8 @@ class _RoutineViewCardState extends State<RoutineViewCard> {
height: iconSize,
width: iconSize,
fit: BoxFit.contain,
errorBuilder:
(context, error, stackTrace) =>
Image.asset(
errorBuilder: (context, error, stackTrace) =>
Image.asset(
Assets.logo,
height: iconSize,
width: iconSize,
@ -205,8 +203,7 @@ class _RoutineViewCardState extends State<RoutineViewCard> {
maxLines: 1,
style: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.blackColor,
fontSize:
widget.isSmallScreenSize(context) ? 10 : 12,
fontSize: widget.isSmallScreenSize(context) ? 10 : 12,
),
),
if (widget.spaceName != '')
@ -225,9 +222,8 @@ class _RoutineViewCardState extends State<RoutineViewCard> {
maxLines: 1,
style: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.blackColor,
fontSize: widget.isSmallScreenSize(context)
? 10
: 12,
fontSize:
widget.isSmallScreenSize(context) ? 10 : 12,
),
),
],

View File

@ -37,9 +37,7 @@ class RoutineDialogSelectionListTile extends StatelessWidget {
trailing: Icon(
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
size: 24,
color: isSelected
? ColorsManager.primaryColorWithOpacity
: ColorsManager.textGray,
color: isSelected ? ColorsManager.opaquePrimary : ColorsManager.textGray,
),
onTap: onTap,
);

View File

@ -65,9 +65,8 @@ class ACHelper {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
DialogHeader(dialogType == 'THEN'
? 'AC Functions'
: 'AC Conditions'),
DialogHeader(
dialogType == 'THEN' ? 'AC Functions' : 'AC Conditions'),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
@ -78,15 +77,12 @@ class ACHelper {
child: _buildFunctionsList(
context: context,
acFunctions: acFunctions,
onFunctionSelected:
(functionCode, operationName) {
RoutineTapFunctionHelper.onTapFunction(
context,
onFunctionSelected: (functionCode, operationName) {
RoutineTapFunctionHelper.onTapFunction(context,
functionCode: functionCode,
functionOperationName: operationName,
functionValueDescription:
selectedFunctionData
.valueDescription,
selectedFunctionData.valueDescription,
deviceUuid: device?.uuid,
codesToAddIntoFunctionsWithDefaultValue: [
'temp_set',
@ -119,8 +115,7 @@ class ACHelper {
? () {
final selectedFunctionData =
state.addedFunctions.firstWhere(
(f) =>
f.functionCode == state.selectedFunction,
(f) => f.functionCode == state.selectedFunction,
orElse: () => DeviceFunctionData(
entityId: '',
functionCode: state.selectedFunction ?? '',
@ -214,12 +209,10 @@ class ACHelper {
required String operationName,
bool? removeComparators,
}) {
final selectedFn =
acFunctions.firstWhere((f) => f.code == selectedFunction);
final selectedFn = acFunctions.firstWhere((f) => f.code == selectedFunction);
if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') {
final displayValue =
(selectedFunctionData?.value ?? selectedFn.min!) / 10;
final displayValue = (selectedFunctionData?.value ?? selectedFn.min!) / 10;
final minValue = selectedFn.min! / 10;
final maxValue = selectedFn.max! / 10;
@ -462,13 +455,9 @@ class ACHelper {
style: context.textTheme.bodyMedium,
),
trailing: Icon(
isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
size: 24,
color: isSelected
? ColorsManager.primaryColorWithOpacity
: ColorsManager.textGray,
color: isSelected ? ColorsManager.opaquePrimary : ColorsManager.textGray,
),
onTap: () {
if (!isSelected) {
@ -480,8 +469,7 @@ class ACHelper {
operationName: operationName,
value: value.value,
condition: selectedFunctionData?.condition,
valueDescription:
selectedFunctionData?.valueDescription,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);

View File

@ -71,10 +71,8 @@ class CurtainHelper {
child: _buildFunctionsList(
context: context,
curtainFunctions: curtainFunctions,
onFunctionSelected:
(functionCode, operationName) {
RoutineTapFunctionHelper.onTapFunction(
context,
onFunctionSelected: (functionCode, operationName) {
RoutineTapFunctionHelper.onTapFunction(context,
functionCode: functionCode,
functionOperationName: operationName,
functionValueDescription:
@ -240,13 +238,9 @@ class CurtainHelper {
style: context.textTheme.bodyMedium,
),
trailing: Icon(
isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
size: 24,
color: isSelected
? ColorsManager.primaryColorWithOpacity
: ColorsManager.textGray,
color: isSelected ? ColorsManager.opaquePrimary : ColorsManager.textGray,
),
onTap: () {
if (!isSelected) {
@ -258,8 +252,7 @@ class CurtainHelper {
operationName: operationName,
value: value.value,
condition: selectedFunctionData?.condition,
valueDescription:
selectedFunctionData?.valueDescription,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);

View File

@ -89,15 +89,14 @@ class OneGangSwitchHelper {
size: 16,
color: ColorsManager.textGray,
),
onTap: () => RoutineTapFunctionHelper
.onTapFunction(
onTap: () =>
RoutineTapFunctionHelper.onTapFunction(
context,
functionCode: function.code,
functionOperationName:
function.operationName,
functionValueDescription:
selectedFunctionData
.valueDescription,
selectedFunctionData.valueDescription,
deviceUuid: device?.uuid,
codesToAddIntoFunctionsWithDefaultValue: [
'countdown_1',
@ -113,12 +112,10 @@ class OneGangSwitchHelper {
child: _buildValueSelector(
context: context,
selectedFunction: selectedFunction,
selectedFunctionData:
selectedFunctionData,
selectedFunctionData: selectedFunctionData,
acFunctions: oneGangFunctions,
device: device,
operationName:
selectedOperationName ?? '',
operationName: selectedOperationName ?? '',
removeComparetors: removeComparetors,
dialogType: dialogType),
),
@ -318,13 +315,9 @@ class OneGangSwitchHelper {
style: context.textTheme.bodyMedium,
),
trailing: Icon(
isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
size: 24,
color: isSelected
? ColorsManager.primaryColorWithOpacity
: ColorsManager.textGray,
color: isSelected ? ColorsManager.opaquePrimary : ColorsManager.textGray,
),
onTap: () {
if (!isSelected) {
@ -336,8 +329,7 @@ class OneGangSwitchHelper {
operationName: operationName,
value: value.value,
condition: selectedFunctionData?.condition,
valueDescription:
selectedFunctionData?.valueDescription,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);

View File

@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_bloc.dart';
@ -13,7 +14,6 @@ import 'package:syncrow_web/pages/routines/view/effective_period_view.dart';
import 'package:syncrow_web/pages/routines/widgets/delete_scene.dart';
import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:flutter/cupertino.dart';
class SettingHelper {
static Future<String?> showSettingDialog({
@ -30,14 +30,16 @@ class SettingHelper {
providers: [
if (effectiveTime != null)
BlocProvider(
create: (_) => EffectPeriodBloc()..add(InitialEffectPeriodEvent(effectiveTime)),
create: (_) =>
EffectPeriodBloc()..add(InitialEffectPeriodEvent(effectiveTime)),
),
if (effectiveTime == null)
BlocProvider(
create: (_) => EffectPeriodBloc(),
),
BlocProvider(
create: (_) => SettingBloc()..add(InitialEvent(selectedIcon: iconId ?? ''))),
create: (_) =>
SettingBloc()..add(InitialEvent(selectedIcon: iconId ?? ''))),
],
child: AlertDialog(
contentPadding: EdgeInsets.zero,
@ -53,7 +55,9 @@ class SettingHelper {
}
return Container(
width: context.read<SettingBloc>().isExpanded ? 800 : 400,
height: context.read<SettingBloc>().isExpanded && isAutomation ? 500 : 350,
height: context.read<SettingBloc>().isExpanded && isAutomation
? 500
: 350,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
@ -76,14 +80,18 @@ class SettingHelper {
children: [
Container(
padding: const EdgeInsets.only(
top: 10, left: 10, right: 10, bottom: 10),
top: 10,
left: 10,
right: 10,
bottom: 10),
child: Column(
children: [
InkWell(
onTap: () {},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
MainAxisAlignment
.spaceBetween,
children: [
Text(
'Validity',
@ -91,14 +99,17 @@ class SettingHelper {
.textTheme
.bodyMedium!
.copyWith(
color:
ColorsManager.textPrimaryColor,
fontWeight: FontWeight.w400,
color: ColorsManager
.textPrimaryColor,
fontWeight:
FontWeight.w400,
fontSize: 14),
),
const Icon(
Icons.arrow_forward_ios_outlined,
color: ColorsManager.textGray,
Icons
.arrow_forward_ios_outlined,
color:
ColorsManager.textGray,
size: 15,
)
],
@ -115,15 +126,17 @@ class SettingHelper {
),
InkWell(
onTap: () {
BlocProvider.of<SettingBloc>(context).add(
FetchIcons(
BlocProvider.of<SettingBloc>(
context)
.add(FetchIcons(
expanded: !context
.read<SettingBloc>()
.isExpanded));
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
MainAxisAlignment
.spaceBetween,
children: [
Text(
'Effective Period',
@ -131,14 +144,17 @@ class SettingHelper {
.textTheme
.bodyMedium!
.copyWith(
color:
ColorsManager.textPrimaryColor,
fontWeight: FontWeight.w400,
color: ColorsManager
.textPrimaryColor,
fontWeight:
FontWeight.w400,
fontSize: 14),
),
const Icon(
Icons.arrow_forward_ios_outlined,
color: ColorsManager.textGray,
Icons
.arrow_forward_ios_outlined,
color:
ColorsManager.textGray,
size: 15,
)
],
@ -154,7 +170,8 @@ class SettingHelper {
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'Executed by',
@ -162,8 +179,10 @@ class SettingHelper {
.textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.textPrimaryColor,
fontWeight: FontWeight.w400,
color: ColorsManager
.textPrimaryColor,
fontWeight:
FontWeight.w400,
fontSize: 14),
),
Text('Cloud',
@ -171,12 +190,17 @@ class SettingHelper {
.textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.textGray,
fontWeight: FontWeight.w400,
color: ColorsManager
.textGray,
fontWeight:
FontWeight.w400,
fontSize: 14)),
],
),
if (context.read<RoutineBloc>().state.isUpdate ??
if (context
.read<RoutineBloc>()
.state
.isUpdate ??
false)
const DeleteSceneWidget()
],
@ -188,20 +212,25 @@ class SettingHelper {
children: [
Container(
padding: const EdgeInsets.only(
top: 10, left: 10, right: 10, bottom: 10),
top: 10,
left: 10,
right: 10,
bottom: 10),
child: Column(
children: [
InkWell(
onTap: () {
BlocProvider.of<SettingBloc>(context).add(
FetchIcons(
BlocProvider.of<SettingBloc>(
context)
.add(FetchIcons(
expanded: !context
.read<SettingBloc>()
.isExpanded));
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
MainAxisAlignment
.spaceBetween,
children: [
Text(
'Icons',
@ -209,14 +238,17 @@ class SettingHelper {
.textTheme
.bodyMedium!
.copyWith(
color:
ColorsManager.textPrimaryColor,
fontWeight: FontWeight.w400,
color: ColorsManager
.textPrimaryColor,
fontWeight:
FontWeight.w400,
fontSize: 14),
),
const Icon(
Icons.arrow_forward_ios_outlined,
color: ColorsManager.textGray,
Icons
.arrow_forward_ios_outlined,
color:
ColorsManager.textGray,
size: 15,
)
],
@ -232,7 +264,8 @@ class SettingHelper {
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'Show on devices page',
@ -240,17 +273,21 @@ class SettingHelper {
.textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.textPrimaryColor,
fontWeight: FontWeight.w400,
color: ColorsManager
.textPrimaryColor,
fontWeight:
FontWeight.w400,
fontSize: 14),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Container(
height: 30,
width: 1,
color: ColorsManager.graysColor,
color: ColorsManager
.graysColor,
),
Transform.scale(
scale: .8,
@ -274,7 +311,8 @@ class SettingHelper {
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'Executed by',
@ -282,8 +320,10 @@ class SettingHelper {
.textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.textPrimaryColor,
fontWeight: FontWeight.w400,
color: ColorsManager
.textPrimaryColor,
fontWeight:
FontWeight.w400,
fontSize: 14),
),
Text('Cloud',
@ -291,12 +331,17 @@ class SettingHelper {
.textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.textGray,
fontWeight: FontWeight.w400,
color: ColorsManager
.textGray,
fontWeight:
FontWeight.w400,
fontSize: 14)),
],
),
if (context.read<RoutineBloc>().state.isUpdate ??
if (context
.read<RoutineBloc>()
.state
.isUpdate ??
false)
const DeleteSceneWidget()
],
@ -304,12 +349,14 @@ class SettingHelper {
],
),
),
if (context.read<SettingBloc>().isExpanded && !isAutomation)
if (context.read<SettingBloc>().isExpanded &&
!isAutomation)
SizedBox(
width: 400,
height: 150,
child: settingState is LoadingState
? const Center(child: CircularProgressIndicator())
? const Center(
child: CircularProgressIndicator())
: GridView.builder(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
@ -326,7 +373,8 @@ class SettingHelper {
height: 35,
child: InkWell(
onTap: () {
BlocProvider.of<SettingBloc>(context)
BlocProvider.of<SettingBloc>(
context)
.add(SelectIcon(
iconId: iconModel.uuid,
));
@ -335,12 +383,14 @@ class SettingHelper {
child: SizedBox(
child: ClipOval(
child: Container(
padding: const EdgeInsets.all(1),
padding:
const EdgeInsets.all(1),
decoration: BoxDecoration(
border: Border.all(
color: selectedIcon == iconModel.uuid
color: selectedIcon ==
iconModel.uuid
? ColorsManager
.primaryColorWithOpacity
.opaquePrimary
: Colors.transparent,
width: 2,
),
@ -356,8 +406,12 @@ class SettingHelper {
);
},
)),
if (context.read<SettingBloc>().isExpanded && isAutomation)
const SizedBox(height: 350, width: 400, child: EffectivePeriodView())
if (context.read<SettingBloc>().isExpanded &&
isAutomation)
const SizedBox(
height: 350,
width: 400,
child: EffectivePeriodView())
],
),
Container(
@ -381,23 +435,31 @@ class SettingHelper {
alignment: AlignmentDirectional.center,
child: Text(
'Cancel',
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.textGray,
),
),
),
),
),
Container(width: 1, height: 50, color: ColorsManager.greyColor),
Container(
width: 1,
height: 50,
color: ColorsManager.greyColor),
Expanded(
child: InkWell(
onTap: () {
if (isAutomation) {
BlocProvider.of<RoutineBloc>(context).add(
EffectiveTimePeriodEvent(EffectiveTime(
start: effectPeriodState.customStartTime!,
start:
effectPeriodState.customStartTime!,
end: effectPeriodState.customEndTime!,
loops: effectPeriodState.selectedDaysBinary)));
loops: effectPeriodState
.selectedDaysBinary)));
Navigator.of(context).pop();
} else {
Navigator.of(context).pop(selectedIcon);
@ -407,8 +469,11 @@ class SettingHelper {
alignment: AlignmentDirectional.center,
child: Text(
'Confirm',
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity,
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.opaquePrimary,
),
),
),

View File

@ -88,19 +88,17 @@ class ThreeGangSwitchHelper {
size: 16,
color: ColorsManager.textGray,
),
onTap: () => RoutineTapFunctionHelper
.onTapFunction(
onTap: () =>
RoutineTapFunctionHelper.onTapFunction(
context,
functionCode: function.code,
functionOperationName:
function.operationName,
functionValueDescription:
selectedFunctionData
.valueDescription,
selectedFunctionData.valueDescription,
deviceUuid: device?.uuid,
codesToAddIntoFunctionsWithDefaultValue:
function.code
.startsWith('countdown')
function.code.startsWith('countdown')
? [function.code]
: [],
),
@ -114,12 +112,10 @@ class ThreeGangSwitchHelper {
child: _buildValueSelector(
context: context,
selectedFunction: selectedFunction,
selectedFunctionData:
selectedFunctionData,
selectedFunctionData: selectedFunctionData,
switchFunctions: switchFunctions,
device: device,
operationName:
selectedOperationName ?? '',
operationName: selectedOperationName ?? '',
removeComparetors: removeComparetors,
dialogType: dialogType),
),
@ -188,8 +184,7 @@ class ThreeGangSwitchHelper {
dialogType: dialogType);
}
final selectedFn =
switchFunctions.firstWhere((f) => f.code == selectedFunction);
final selectedFn = switchFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues();
return _buildOperationalValuesList(
@ -307,13 +302,9 @@ class ThreeGangSwitchHelper {
style: context.textTheme.bodyMedium,
),
trailing: Icon(
isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
size: 24,
color: isSelected
? ColorsManager.primaryColorWithOpacity
: ColorsManager.textGray,
color: isSelected ? ColorsManager.opaquePrimary : ColorsManager.textGray,
),
onTap: () {
if (!isSelected) {
@ -325,8 +316,7 @@ class ThreeGangSwitchHelper {
operationName: operationName,
value: value.value,
condition: selectedFunctionData?.condition,
valueDescription:
selectedFunctionData?.valueDescription,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);

View File

@ -89,15 +89,14 @@ class TwoGangSwitchHelper {
size: 16,
color: ColorsManager.textGray,
),
onTap: () => RoutineTapFunctionHelper
.onTapFunction(
onTap: () =>
RoutineTapFunctionHelper.onTapFunction(
context,
functionCode: function.code,
functionOperationName:
function.operationName,
functionValueDescription:
selectedFunctionData
.valueDescription,
selectedFunctionData.valueDescription,
deviceUuid: device?.uuid,
codesToAddIntoFunctionsWithDefaultValue: [
'countdown_1',
@ -147,13 +146,10 @@ class TwoGangSwitchHelper {
// }
final selectedFunctionData =
state.addedFunctions.firstWhere(
(f) =>
f.functionCode ==
state.selectedFunction,
(f) => f.functionCode == state.selectedFunction,
orElse: () => DeviceFunctionData(
entityId: '',
functionCode:
state.selectedFunction ?? '',
functionCode: state.selectedFunction ?? '',
operationName: '',
value: null,
),
@ -192,8 +188,7 @@ class TwoGangSwitchHelper {
required bool removeComparetors,
required String dialogType,
}) {
if (selectedFunction == 'countdown_1' ||
selectedFunction == 'countdown_2') {
if (selectedFunction == 'countdown_1' || selectedFunction == 'countdown_2') {
final initialValue = selectedFunctionData?.value ?? 0;
return _buildTemperatureSelector(
context: context,
@ -207,8 +202,7 @@ class TwoGangSwitchHelper {
dialogType: dialogType);
}
final selectedFn =
switchFunctions.firstWhere((f) => f.code == selectedFunction);
final selectedFn = switchFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues();
return _buildOperationalValuesList(
@ -270,16 +264,15 @@ class TwoGangSwitchHelper {
);
},
borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: ColorsManager.primaryColorWithOpacity,
selectedBorderColor: ColorsManager.opaquePrimary,
selectedColor: Colors.white,
fillColor: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity,
fillColor: ColorsManager.opaquePrimary,
color: ColorsManager.opaquePrimary,
constraints: const BoxConstraints(
minHeight: 40.0,
minWidth: 40.0,
),
isSelected:
conditions.map((c) => c == (currentCondition ?? "==")).toList(),
isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(),
children: conditions.map((c) => Text(c)).toList(),
);
}
@ -295,13 +288,13 @@ class TwoGangSwitchHelper {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
color: ColorsManager.opaquePrimary.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Text(
DurationFormatMixin.formatDuration(initialValue?.toInt() ?? 0),
style: context.textTheme.headlineMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.opaquePrimary,
),
),
);
@ -338,8 +331,7 @@ class TwoGangSwitchHelper {
);
},
onTextChanged: (value) {
final roundedValue =
value.round(); // Round to nearest integer (stepSize 1)
final roundedValue = value.round(); // Round to nearest integer (stepSize 1)
context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
@ -391,13 +383,9 @@ class TwoGangSwitchHelper {
style: context.textTheme.bodyMedium,
),
trailing: Icon(
isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
size: 24,
color: isSelected
? ColorsManager.primaryColorWithOpacity
: ColorsManager.textGray,
color: isSelected ? ColorsManager.opaquePrimary : ColorsManager.textGray,
),
onTap: () {
if (!isSelected) {
@ -409,8 +397,7 @@ class TwoGangSwitchHelper {
operationName: operationName,
value: value.value,
condition: selectedFunctionData?.condition,
valueDescription:
selectedFunctionData?.valueDescription,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);

View File

@ -61,8 +61,9 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
children: [
ConstrainedBox(
constraints: BoxConstraints(
maxWidth:
constraints.maxWidth > 700 ? 450 : constraints.maxWidth - 32),
maxWidth: constraints.maxWidth > 700
? 450
: constraints.maxWidth - 32),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
@ -71,7 +72,9 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
children: [
Text('* ',
style: context.textTheme.bodyMedium!
.copyWith(color: ColorsManager.red, fontSize: 13)),
.copyWith(
color: ColorsManager.red,
fontSize: 13)),
Text(
'Routine Name',
style: context.textTheme.bodyMedium!.copyWith(
@ -93,9 +96,11 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
decoration: InputDecoration(
hintText: 'Please enter the name',
hintStyle: context.textTheme.bodyMedium!
.copyWith(fontSize: 12, color: ColorsManager.grayColor),
contentPadding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
.copyWith(
fontSize: 12,
color: ColorsManager.grayColor),
contentPadding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 10),
border: InputBorder.none,
),
onTapOutside: (_) {
@ -121,9 +126,11 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
width: 200,
child: Center(
child: DefaultButton(
onPressed: state.isAutomation || state.isTabToRun
onPressed: state.isAutomation ||
state.isTabToRun
? () async {
final result = await SettingHelper.showSettingDialog(
final result = await SettingHelper
.showSettingDialog(
context: context,
iconId: state.selectedIcon ?? '',
);
@ -186,10 +193,12 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
child: Center(
child: DefaultButton(
onPressed: () async {
if (state.routineName == null || state.routineName!.isEmpty) {
if (state.routineName == null ||
state.routineName!.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Please enter the routine name'),
content: const Text(
'Please enter the routine name'),
duration: const Duration(seconds: 2),
backgroundColor: ColorsManager.red,
action: SnackBarAction(
@ -203,10 +212,12 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
return;
}
if (state.ifItems.isEmpty || state.thenItems.isEmpty) {
if (state.ifItems.isEmpty ||
state.thenItems.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Please add if and then condition'),
content: const Text(
'Please add if and then condition'),
duration: const Duration(seconds: 2),
backgroundColor: ColorsManager.red,
action: SnackBarAction(
@ -221,7 +232,8 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
}
// final result =
// await
BlocProvider.of<RoutineBloc>(context).add(ResetErrorMessage());
BlocProvider.of<RoutineBloc>(context)
.add(ResetErrorMessage());
SaveRoutineHelper.showSaveRoutineDialog(context);
// if (result != null && result) {
// BlocProvider.of<RoutineBloc>(context).add(
@ -240,7 +252,7 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
color: ColorsManager.whiteColors,
color: ColorsManager.white,
),
),
),
@ -261,10 +273,14 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
child: DefaultButton(
onPressed: state.isAutomation || state.isTabToRun
? () async {
final result = await SettingHelper.showSettingDialog(
context: context, iconId: state.selectedIcon ?? '');
final result =
await SettingHelper.showSettingDialog(
context: context,
iconId: state.selectedIcon ?? '');
if (result != null) {
context.read<RoutineBloc>().add(AddSelectedIcon(result));
context
.read<RoutineBloc>()
.add(AddSelectedIcon(result));
}
}
: null,
@ -314,10 +330,12 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
child: Center(
child: DefaultButton(
onPressed: () async {
if (state.routineName == null || state.routineName!.isEmpty) {
if (state.routineName == null ||
state.routineName!.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Please enter the routine name'),
content:
const Text('Please enter the routine name'),
duration: const Duration(seconds: 2),
backgroundColor: ColorsManager.red,
action: SnackBarAction(
@ -334,7 +352,8 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
if (state.ifItems.isEmpty || state.thenItems.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Please add if and then condition'),
content: const Text(
'Please add if and then condition'),
duration: const Duration(seconds: 2),
backgroundColor: ColorsManager.red,
action: SnackBarAction(
@ -349,7 +368,8 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
}
// final result =
// await
BlocProvider.of<RoutineBloc>(context).add(ResetErrorMessage());
BlocProvider.of<RoutineBloc>(context)
.add(ResetErrorMessage());
SaveRoutineHelper.showSaveRoutineDialog(context);
// if (result != null && result) {
// BlocProvider.of<RoutineBloc>(context).add(
@ -368,7 +388,7 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
color: ColorsManager.whiteColors,
color: ColorsManager.white,
),
),
),

View File

@ -19,13 +19,13 @@ class ValueDisplay extends StatelessWidget {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
color: ColorsManager.opaquePrimary.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Text(
'$label $unit ',
style: context.textTheme.headlineMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.opaquePrimary,
),
),
);