mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
@ -11,8 +11,8 @@ class ConditionToggle extends StatelessWidget {
|
||||
super.key,
|
||||
});
|
||||
|
||||
static const _conditions = ['<', '==', '>'];
|
||||
static const List<IconData> _icons = [
|
||||
static const _conditions = ["<", "==", ">"];
|
||||
static const _icons = [
|
||||
Icons.chevron_left,
|
||||
Icons.drag_handle,
|
||||
Icons.chevron_right
|
||||
@ -20,13 +20,13 @@ class ConditionToggle extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final selectedIndex = _conditions.indexOf(currentCondition ?? '==');
|
||||
final selectedIndex = _conditions.indexOf(currentCondition ?? "==");
|
||||
|
||||
return Container(
|
||||
height: 30,
|
||||
width: MediaQuery.of(context).size.width * 0.1,
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.softGray.withValues(alpha: 0.5),
|
||||
color: ColorsManager.softGray.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/condition_toggle.dart';
|
||||
@ -46,10 +45,10 @@ class _CustomRoutinesTextboxState extends State<CustomRoutinesTextbox> {
|
||||
String? errorMessage;
|
||||
|
||||
int getDecimalPlaces(double step) {
|
||||
final stepStr = step.toString();
|
||||
String stepStr = step.toString();
|
||||
if (stepStr.contains('.')) {
|
||||
final parts = stepStr.split('.');
|
||||
var decimalPart = parts[1];
|
||||
List<String> parts = stepStr.split('.');
|
||||
String decimalPart = parts[1];
|
||||
decimalPart = decimalPart.replaceAll(RegExp(r'0+$'), '');
|
||||
return decimalPart.isEmpty ? 0 : decimalPart.length;
|
||||
} else {
|
||||
@ -112,11 +111,13 @@ class _CustomRoutinesTextboxState extends State<CustomRoutinesTextbox> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _validateInput(String value) {
|
||||
final doubleValue = double.tryParse(value);
|
||||
if (doubleValue == null) {
|
||||
setState(() {
|
||||
errorMessage = 'Invalid number';
|
||||
errorMessage = "Invalid number";
|
||||
hasError = true;
|
||||
});
|
||||
return;
|
||||
@ -127,23 +128,23 @@ class _CustomRoutinesTextboxState extends State<CustomRoutinesTextbox> {
|
||||
|
||||
if (doubleValue < min) {
|
||||
setState(() {
|
||||
errorMessage = 'Value must be at least $min';
|
||||
errorMessage = "Value must be at least $min";
|
||||
hasError = true;
|
||||
});
|
||||
} else if (doubleValue > max) {
|
||||
setState(() {
|
||||
errorMessage = 'Value must be at most $max';
|
||||
errorMessage = "Value must be at most $max";
|
||||
hasError = true;
|
||||
});
|
||||
} else {
|
||||
final decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
|
||||
final factor = pow(10, decimalPlaces).toInt();
|
||||
final scaledStep = (widget.stepIncreaseAmount * factor).round();
|
||||
final scaledValue = (doubleValue * factor).round();
|
||||
int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
|
||||
int factor = pow(10, decimalPlaces).toInt();
|
||||
int scaledStep = (widget.stepIncreaseAmount * factor).round();
|
||||
int scaledValue = (doubleValue * factor).round();
|
||||
|
||||
if (scaledValue % scaledStep != 0) {
|
||||
setState(() {
|
||||
errorMessage = 'must be a multiple of ${widget.stepIncreaseAmount}';
|
||||
errorMessage = "must be a multiple of ${widget.stepIncreaseAmount}";
|
||||
hasError = true;
|
||||
});
|
||||
} else {
|
||||
@ -155,10 +156,11 @@ class _CustomRoutinesTextboxState extends State<CustomRoutinesTextbox> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _correctAndUpdateValue(String value) {
|
||||
final doubleValue = double.tryParse(value) ?? 0.0;
|
||||
final decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
|
||||
var rounded = (doubleValue / widget.stepIncreaseAmount).round() *
|
||||
int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
|
||||
double rounded = (doubleValue / widget.stepIncreaseAmount).round() *
|
||||
widget.stepIncreaseAmount;
|
||||
rounded = rounded.clamp(widget.sliderRange.$1, widget.sliderRange.$2);
|
||||
rounded = double.parse(rounded.toStringAsFixed(decimalPlaces));
|
||||
@ -177,9 +179,9 @@ class _CustomRoutinesTextboxState extends State<CustomRoutinesTextbox> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
|
||||
int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
|
||||
|
||||
final formatters = <TextInputFormatter>[];
|
||||
List<TextInputFormatter> formatters = [];
|
||||
if (decimalPlaces == 0) {
|
||||
formatters.add(FilteringTextInputFormatter.digitsOnly);
|
||||
} else {
|
||||
@ -231,7 +233,7 @@ class _CustomRoutinesTextboxState extends State<CustomRoutinesTextbox> {
|
||||
color: ColorsManager.lightGrayBorderColor, width: 1),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: ColorsManager.blackColor.withValues(alpha: 0.05),
|
||||
color: ColorsManager.blackColor.withOpacity(0.05),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
|
@ -33,17 +33,13 @@ class DeleteSceneWidget extends StatelessWidget {
|
||||
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),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
context.read<RoutineBloc>().add(const DeleteScene());
|
||||
@ -54,10 +50,7 @@ class DeleteSceneWidget extends StatelessWidget {
|
||||
alignment: AlignmentDirectional.center,
|
||||
child: Text(
|
||||
'Confirm',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
),
|
||||
),
|
||||
|
@ -33,18 +33,17 @@ 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']] ?? [];
|
||||
|
||||
final 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);
|
||||
}
|
||||
|
||||
final 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);
|
||||
@ -54,8 +53,7 @@ class DraggableCard extends StatelessWidget {
|
||||
data: deviceData,
|
||||
feedback: Transform.rotate(
|
||||
angle: -0.1,
|
||||
child:
|
||||
_buildCardContent(context, deviceFunctions, padding: padding),
|
||||
child: _buildCardContent(context, deviceFunctions, padding: padding),
|
||||
),
|
||||
childWhenDragging: _buildGreyContainer(),
|
||||
child: _buildCardContent(context, deviceFunctions, padding: padding),
|
||||
@ -64,8 +62,7 @@ class DraggableCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCardContent(
|
||||
BuildContext context, List<DeviceFunctionData> deviceFunctions,
|
||||
Widget _buildCardContent(BuildContext context, List<DeviceFunctionData> deviceFunctions,
|
||||
{EdgeInsetsGeometry? padding}) {
|
||||
return Stack(
|
||||
children: [
|
||||
@ -95,8 +92,7 @@ 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']),
|
||||
)
|
||||
@ -122,15 +118,12 @@ class DraggableCard extends StatelessWidget {
|
||||
height: 4,
|
||||
),
|
||||
Visibility(
|
||||
visible:
|
||||
deviceData['tag'] != null && deviceData['tag'] != '',
|
||||
visible: deviceData['tag'] != null && deviceData['tag'] != '',
|
||||
child: Row(
|
||||
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'] ?? '',
|
||||
@ -148,23 +141,20 @@ 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: [
|
||||
SizedBox(
|
||||
width: 8,
|
||||
height: 8,
|
||||
child:
|
||||
SvgPicture.asset(Assets.spaceLocationIcon)),
|
||||
child: SvgPicture.asset(Assets.spaceLocationIcon)),
|
||||
Flexible(
|
||||
child: Text(
|
||||
deviceData['subSpace'] ?? '',
|
||||
@ -232,8 +222,7 @@ 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;
|
||||
|
@ -17,13 +17,12 @@ class FunctionSlider extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final (min, max) = range;
|
||||
final isValidRange = max > min;
|
||||
final value = initialValue is int
|
||||
final bool isValidRange = max > min;
|
||||
final double value = initialValue is int
|
||||
? (initialValue as int).toDouble()
|
||||
: (initialValue as double);
|
||||
|
||||
final divisions =
|
||||
isValidRange ? ((max - min) / dividendOfRange).round() : null;
|
||||
final int? divisions = isValidRange ? ((max - min) / dividendOfRange).round() : null;
|
||||
|
||||
return Slider(
|
||||
value: value.clamp(min, max),
|
||||
|
@ -62,7 +62,7 @@ class IfContainer extends StatelessWidget {
|
||||
context: context,
|
||||
data: state.ifItems[index],
|
||||
removeComparetors: false,
|
||||
dialogType: 'IF');
|
||||
dialogType: "IF");
|
||||
|
||||
if (result != null) {
|
||||
context.read<RoutineBloc>().add(
|
||||
|
@ -16,9 +16,8 @@ class FetchRoutineScenesAutomation extends StatelessWidget
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||
builder: (context, state) {
|
||||
if (state.isLoading) {
|
||||
if (state.isLoading)
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
@ -27,23 +26,23 @@ class FetchRoutineScenesAutomation extends StatelessWidget
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildListTitle(context, 'Scenes (Tap to Run)'),
|
||||
_buildListTitle(context, "Scenes (Tap to Run)"),
|
||||
const SizedBox(height: 10),
|
||||
Visibility(
|
||||
visible: state.scenes.isNotEmpty,
|
||||
replacement: _buildEmptyState(context, 'No scenes found'),
|
||||
replacement: _buildEmptyState(context, "No scenes found"),
|
||||
child: SizedBox(
|
||||
height: 200,
|
||||
child: _buildScenes(state),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
_buildListTitle(context, 'Automations'),
|
||||
_buildListTitle(context, "Automations"),
|
||||
const SizedBox(height: 3),
|
||||
Visibility(
|
||||
visible: state.automations.isNotEmpty,
|
||||
replacement:
|
||||
_buildEmptyState(context, 'No automations found'),
|
||||
_buildEmptyState(context, "No automations found"),
|
||||
child: SizedBox(
|
||||
height: 200,
|
||||
child: _buildAutomations(state),
|
||||
|
@ -67,15 +67,15 @@ class _RoutineViewCardState extends State<RoutineViewCard> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final cardWidth = widget.isSmallScreenSize(context)
|
||||
final double cardWidth = widget.isSmallScreenSize(context)
|
||||
? 120
|
||||
: widget.isMediumScreenSize(context)
|
||||
? 135
|
||||
: 150;
|
||||
|
||||
final cardHeight = widget.isSmallScreenSize(context) ? 190 : 200;
|
||||
final double cardHeight = widget.isSmallScreenSize(context) ? 190 : 200;
|
||||
|
||||
final iconSize = widget.isSmallScreenSize(context)
|
||||
final double iconSize = widget.isSmallScreenSize(context)
|
||||
? 70
|
||||
: widget.isMediumScreenSize(context)
|
||||
? 80
|
||||
@ -99,42 +99,41 @@ class _RoutineViewCardState extends State<RoutineViewCard> {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
if (widget.cardType != '')
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
if (widget.isFromScenes ?? false)
|
||||
InkWell(
|
||||
onTap: _handleSceneTap,
|
||||
child: Image.asset(
|
||||
_showTemporaryCheck
|
||||
? Assets.scenesPlayIcon
|
||||
: Assets.scenesPlayIconCheck,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
)
|
||||
else if (widget.isLoading)
|
||||
const SizedBox(
|
||||
width: 49,
|
||||
height: 20,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
CupertinoSwitch(
|
||||
activeTrackColor: ColorsManager.primaryColor,
|
||||
value: widget.status == 'enable',
|
||||
onChanged: widget.onChanged,
|
||||
)
|
||||
],
|
||||
)
|
||||
else
|
||||
const SizedBox(),
|
||||
widget.cardType != ''
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
if (widget.isFromScenes ?? false)
|
||||
InkWell(
|
||||
onTap: _handleSceneTap,
|
||||
child: Image.asset(
|
||||
_showTemporaryCheck
|
||||
? Assets.scenesPlayIcon
|
||||
: Assets.scenesPlayIconCheck,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
)
|
||||
else if (widget.isLoading)
|
||||
const SizedBox(
|
||||
width: 49,
|
||||
height: 20,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
CupertinoSwitch(
|
||||
activeTrackColor: ColorsManager.primaryColor,
|
||||
value: widget.status == 'enable',
|
||||
onChanged: widget.onChanged,
|
||||
)
|
||||
],
|
||||
)
|
||||
: const SizedBox(),
|
||||
Column(
|
||||
children: [
|
||||
Center(
|
||||
@ -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,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -21,12 +21,9 @@ class PeriodOptions extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
children: [
|
||||
_buildRadioOption(
|
||||
context, EnumEffectivePeriodOptions.allDay, '24 Hours'),
|
||||
_buildRadioOption(context, EnumEffectivePeriodOptions.daytime,
|
||||
'Sunrise to Sunset'),
|
||||
_buildRadioOption(
|
||||
context, EnumEffectivePeriodOptions.night, 'Sunset to Sunrise'),
|
||||
_buildRadioOption(context, EnumEffectivePeriodOptions.allDay, '24 Hours'),
|
||||
_buildRadioOption(context, EnumEffectivePeriodOptions.daytime, 'Sunrise to Sunset'),
|
||||
_buildRadioOption(context, EnumEffectivePeriodOptions.night, 'Sunset to Sunrise'),
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
onTap: () => showCustomTimePicker(context),
|
||||
@ -37,8 +34,7 @@ class PeriodOptions extends StatelessWidget {
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14),
|
||||
),
|
||||
subtitle: state.customStartTime != null &&
|
||||
state.customEndTime != null
|
||||
subtitle: state.customStartTime != null && state.customEndTime != null
|
||||
? Text(
|
||||
'${"${state.customStartTime}"} - ${"${state.customEndTime}"}',
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
@ -82,16 +78,12 @@ class PeriodOptions extends StatelessWidget {
|
||||
title: Text(
|
||||
EffectPeriodHelper.formatEnumValue(value),
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 12),
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 12),
|
||||
),
|
||||
subtitle: Text(
|
||||
subtitle,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 10),
|
||||
color: ColorsManager.textPrimaryColor, fontWeight: FontWeight.w400, fontSize: 10),
|
||||
),
|
||||
trailing: Radio<EnumEffectivePeriodOptions>(
|
||||
value: value,
|
||||
|
@ -16,9 +16,7 @@ class RepeatDays extends StatelessWidget {
|
||||
children: [
|
||||
Text('Repeat',
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14)),
|
||||
color: ColorsManager.textPrimaryColor, fontWeight: FontWeight.w400, fontSize: 14)),
|
||||
const SizedBox(width: 8),
|
||||
BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
||||
builder: (context, state) {
|
||||
@ -33,8 +31,7 @@ class RepeatDays extends StatelessWidget {
|
||||
final day = entry.key;
|
||||
final abbreviation = entry.value;
|
||||
final dayIndex = effectiveBloc.getDayIndex(day);
|
||||
final isSelected =
|
||||
state.selectedDaysBinary[dayIndex] == '1';
|
||||
final isSelected = state.selectedDaysBinary[dayIndex] == '1';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
||||
child: GestureDetector(
|
||||
@ -45,9 +42,7 @@ class RepeatDays extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? Colors.grey
|
||||
: Colors.grey.shade300,
|
||||
color: isSelected ? Colors.grey : Colors.grey.shade300,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
@ -58,9 +53,7 @@ class RepeatDays extends StatelessWidget {
|
||||
abbreviation,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: isSelected
|
||||
? Colors.grey
|
||||
: Colors.grey.shade300,
|
||||
color: isSelected ? Colors.grey : Colors.grey.shade300,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -74,15 +74,15 @@ class _RoutineDevicesState extends State<RoutineDevices> {
|
||||
.toLowerCase()
|
||||
.contains(state.searchText!.toLowerCase())
|
||||
? DraggableCard(
|
||||
imagePath: deviceData['imagePath']! as String,
|
||||
title: deviceData['title']! as String,
|
||||
imagePath: deviceData['imagePath'] as String,
|
||||
title: deviceData['title'] as String,
|
||||
deviceData: deviceData,
|
||||
)
|
||||
: const SizedBox.shrink();
|
||||
} else {
|
||||
return DraggableCard(
|
||||
imagePath: deviceData['imagePath']! as String,
|
||||
title: deviceData['title']! as String,
|
||||
imagePath: deviceData['imagePath'] as String,
|
||||
title: deviceData['title'] as String,
|
||||
deviceData: deviceData,
|
||||
);
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ class ACHelper {
|
||||
required bool? removeComparetors,
|
||||
required String dialogType,
|
||||
}) async {
|
||||
final acFunctions = functions.whereType<ACFunction>().where((function) {
|
||||
List<ACFunction> acFunctions =
|
||||
functions.whereType<ACFunction>().where((function) {
|
||||
if (dialogType == 'THEN') {
|
||||
return function.type == 'THEN' || function.type == 'BOTH';
|
||||
}
|
||||
@ -370,7 +371,7 @@ class ACHelper {
|
||||
// return Container(
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
// decoration: BoxDecoration(
|
||||
// color: ColorsManager.primaryColorWithOpacity.withValues(alpha:0.1),
|
||||
// color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
|
||||
// borderRadius: BorderRadius.circular(10),
|
||||
// ),
|
||||
// child: Text(
|
||||
|
@ -3,8 +3,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.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/widgets/dialog_footer.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
|
||||
import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class AutomationDialog extends StatefulWidget {
|
||||
@ -31,11 +31,9 @@ class _AutomationDialogState extends State<AutomationDialog> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final functions = context
|
||||
.read<RoutineBloc>()
|
||||
.state
|
||||
.selectedFunctions[widget.uniqueCustomId];
|
||||
for (final data in functions ?? []) {
|
||||
List<DeviceFunctionData>? functions =
|
||||
context.read<RoutineBloc>().state.selectedFunctions[widget.uniqueCustomId];
|
||||
for (DeviceFunctionData data in functions ?? []) {
|
||||
if (data.entityId == widget.automationId) {
|
||||
selectedAutomationActionExecutor = data.value;
|
||||
}
|
||||
@ -67,8 +65,7 @@ class _AutomationDialogState extends State<AutomationDialog> {
|
||||
}),
|
||||
),
|
||||
ListTile(
|
||||
leading:
|
||||
SvgPicture.asset(Assets.acPowerOff, width: 24, height: 24),
|
||||
leading: SvgPicture.asset(Assets.acPowerOff, width: 24, height: 24),
|
||||
title: const Text('Disable'),
|
||||
trailing: Radio<String?>(
|
||||
value: 'rule_disable',
|
||||
|
@ -45,8 +45,7 @@ class CpsDialogValueSelector extends StatelessWidget {
|
||||
operationName: operationName,
|
||||
value: operation.value,
|
||||
condition: selectedFunctionData?.condition,
|
||||
valueDescription:
|
||||
selectedFunctionData?.valueDescription,
|
||||
valueDescription: selectedFunctionData?.valueDescription,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -57,7 +57,7 @@ class CpsFunctionsList extends StatelessWidget {
|
||||
'moving_max_dis',
|
||||
'moving_range',
|
||||
'presence_range',
|
||||
if (dialogType == 'IF') 'sensitivity',
|
||||
if (dialogType == "IF") 'sensitivity',
|
||||
],
|
||||
);
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
abstract final class CpsSliderHelpers {
|
||||
static (double min, double max, double step) mappedRange(
|
||||
String functionCode) {
|
||||
static (double min, double max, double step) mappedRange(String functionCode) {
|
||||
final (defaultMin, defaultMax) = sliderRange(functionCode);
|
||||
final defaultDivdidend = dividendOfRange(functionCode);
|
||||
return switch (functionCode) {
|
||||
@ -63,10 +62,7 @@ abstract final class CpsSliderHelpers {
|
||||
'perceptual_boundary' ||
|
||||
'moving_boundary' =>
|
||||
'M',
|
||||
'moving_rigger_time' ||
|
||||
'moving_static_time' ||
|
||||
'none_body_time' =>
|
||||
'sec',
|
||||
'moving_rigger_time' || 'moving_static_time' || 'none_body_time' => 'sec',
|
||||
_ => '',
|
||||
};
|
||||
|
||||
|
@ -9,14 +9,14 @@ import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
|
||||
class DelayHelper {
|
||||
static Future<Map<String, dynamic>?> showDelayPickerDialog(
|
||||
BuildContext context, Map<String, dynamic> data) async {
|
||||
var hours = 0;
|
||||
var minutes = 0;
|
||||
int hours = 0;
|
||||
int minutes = 0;
|
||||
|
||||
return showDialog<Map<String, dynamic>?>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
final routineBloc = context.read<RoutineBloc>();
|
||||
var totalSec = 0;
|
||||
int totalSec = 0;
|
||||
|
||||
final selectedFunctionData =
|
||||
routineBloc.state.selectedFunctions[data['uniqueCustomId']] ?? [];
|
||||
@ -43,8 +43,7 @@ class DelayHelper {
|
||||
Expanded(
|
||||
child: CupertinoTimerPicker(
|
||||
mode: CupertinoTimerPickerMode.hm,
|
||||
initialTimerDuration:
|
||||
Duration(hours: hours, minutes: minutes),
|
||||
initialTimerDuration: Duration(hours: hours, minutes: minutes),
|
||||
onTimerDurationChanged: (Duration newDuration) {
|
||||
hours = newDuration.inHours;
|
||||
minutes = newDuration.inMinutes % 60;
|
||||
@ -56,7 +55,7 @@ class DelayHelper {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
onConfirm: () {
|
||||
final totalSeconds = (hours * 3600) + (minutes * 60);
|
||||
int totalSeconds = (hours * 3600) + (minutes * 60);
|
||||
context.read<RoutineBloc>().add(AddFunctionToRoutine(
|
||||
[
|
||||
DeviceFunctionData(
|
||||
|
@ -38,10 +38,10 @@ class DiscardDialog {
|
||||
color: ColorsManager.red,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
onDismissText: 'Don’t Close',
|
||||
onConfirmText: 'Close',
|
||||
onDismissText: "Don’t Close",
|
||||
onConfirmText: "Close",
|
||||
onDismissColor: ColorsManager.grayColor,
|
||||
onConfirmColor: ColorsManager.red.withValues(alpha: 0.8),
|
||||
onConfirmColor: ColorsManager.red.withOpacity(0.8),
|
||||
onDismiss: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
|
@ -8,14 +8,13 @@ import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
import 'package:time_picker_spinner/time_picker_spinner.dart';
|
||||
|
||||
class EffectPeriodHelper {
|
||||
static Future<List<String>?> showCustomTimePicker(
|
||||
BuildContext context) async {
|
||||
var selectedStartTime = '00:00';
|
||||
var selectedEndTime = '23:59';
|
||||
final pageController = PageController(initialPage: 0);
|
||||
static Future<List<String>?> showCustomTimePicker(BuildContext context) async {
|
||||
String selectedStartTime = "00:00";
|
||||
String selectedEndTime = "23:59";
|
||||
PageController pageController = PageController(initialPage: 0);
|
||||
|
||||
final startDateTime = DateTime(2022, 1, 1, 0, 0);
|
||||
final endDateTime = DateTime(2022, 1, 1, 23, 59);
|
||||
DateTime startDateTime = DateTime(2022, 1, 1, 0, 0);
|
||||
DateTime endDateTime = DateTime(2022, 1, 1, 23, 59);
|
||||
|
||||
context.customAlertDialog(
|
||||
alertBody: SizedBox(
|
||||
@ -47,7 +46,7 @@ class EffectPeriodHelper {
|
||||
],
|
||||
),
|
||||
),
|
||||
title: 'Custom',
|
||||
title: "Custom",
|
||||
onConfirm: () {
|
||||
context.read<EffectPeriodBloc>().add(
|
||||
SetCustomTime(selectedStartTime, selectedEndTime),
|
||||
@ -89,7 +88,7 @@ class EffectPeriodHelper {
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
child: Text(isStartTime ? 'Start' : 'End',
|
||||
child: Text(isStartTime ? "Start" : "End",
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -136,17 +135,17 @@ class EffectPeriodHelper {
|
||||
static String formatEnumValue(EnumEffectivePeriodOptions value) {
|
||||
switch (value) {
|
||||
case EnumEffectivePeriodOptions.allDay:
|
||||
return 'All Day';
|
||||
return "All Day";
|
||||
case EnumEffectivePeriodOptions.daytime:
|
||||
return 'Daytime';
|
||||
return "Daytime";
|
||||
case EnumEffectivePeriodOptions.night:
|
||||
return 'Night';
|
||||
return "Night";
|
||||
case EnumEffectivePeriodOptions.custom:
|
||||
return 'Custom';
|
||||
return "Custom";
|
||||
case EnumEffectivePeriodOptions.none:
|
||||
return 'None';
|
||||
return "None";
|
||||
default:
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ 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/custom_routines_textbox.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;
|
||||
@ -61,7 +62,7 @@ class FlushValueSelectorWidget extends StatelessWidget {
|
||||
selectedFunction == FlushMountedPresenceSensorModel.codeFarDetection;
|
||||
|
||||
final isDistanceDetection = isNearDetection || isFarDetection;
|
||||
var initialValue = (functionData.value as num?)?.toDouble() ?? 0.0;
|
||||
double initialValue = (functionData.value as num?)?.toDouble() ?? 0.0;
|
||||
|
||||
if (isDistanceDetection) {
|
||||
initialValue = initialValue / 100;
|
||||
@ -156,7 +157,7 @@ class FlushValueSelectorWidget extends StatelessWidget {
|
||||
|
||||
String get getDisplayText {
|
||||
final num? value = functionData.value;
|
||||
var displayValue = value?.toDouble() ?? 0.0;
|
||||
double displayValue = value?.toDouble() ?? 0.0;
|
||||
|
||||
if (functionData.functionCode ==
|
||||
FlushMountedPresenceSensorModel.codeNearDetection ||
|
||||
|
@ -49,6 +49,8 @@ class _TimeWheelPickerState extends State<TimeWheelPicker> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_hoursController.dispose();
|
||||
@ -101,7 +103,7 @@ class _TimeWheelPickerState extends State<TimeWheelPicker> {
|
||||
}
|
||||
|
||||
void _handleTimeChange(int hours, int minutes, int seconds) {
|
||||
var total = hours * 3600 + minutes * 60 + seconds;
|
||||
int total = hours * 3600 + minutes * 60 + seconds;
|
||||
if (total > 10000) {
|
||||
hours = 2;
|
||||
minutes = 46;
|
||||
|
@ -45,8 +45,7 @@ class GatewayDialogValueSelector extends StatelessWidget {
|
||||
operationName: operationName,
|
||||
value: operation.value,
|
||||
condition: selectedFunctionData?.condition,
|
||||
valueDescription:
|
||||
selectedFunctionData?.valueDescription,
|
||||
valueDescription: selectedFunctionData?.valueDescription,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -25,7 +25,8 @@ class OneGangSwitchHelper {
|
||||
required String uniqueCustomId,
|
||||
required bool removeComparetors,
|
||||
}) async {
|
||||
final oneGangFunctions = functions.whereType<BaseSwitchFunction>().toList();
|
||||
List<BaseSwitchFunction> oneGangFunctions =
|
||||
functions.whereType<BaseSwitchFunction>().toList();
|
||||
|
||||
return showDialog<Map<String, dynamic>?>(
|
||||
context: context,
|
||||
@ -245,9 +246,9 @@ class OneGangSwitchHelper {
|
||||
withSpecialChar: false,
|
||||
currentCondition: selectedFunctionData?.condition,
|
||||
dialogType: dialogType,
|
||||
sliderRange: (0, 43200),
|
||||
sliderRange: (0, 43200),
|
||||
displayedValue: (initialValue ?? 0).toString(),
|
||||
initialValue: (initialValue ?? 0).toString(),
|
||||
initialValue: (initialValue ?? 0).toString(),
|
||||
onConditionChanged: (condition) {
|
||||
context.read<FunctionBloc>().add(
|
||||
AddFunction(
|
||||
|
@ -81,4 +81,6 @@ class EnergyOperationalValuesList extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -27,11 +27,13 @@ class EnergyValueSelectorWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final selectedFn = functions.firstWhere((f) => f.code == selectedFunction);
|
||||
final selectedFn =
|
||||
functions.firstWhere((f) => f.code == selectedFunction);
|
||||
final values = selectedFn.getOperationalValues();
|
||||
final step = selectedFn.step ?? 1.0;
|
||||
final unit = selectedFn.unit ?? '';
|
||||
final sliderRange = (selectedFn.min ?? 0.0, selectedFn.max ?? 100.0);
|
||||
final step = selectedFn.step ?? 1.0;
|
||||
final _unit = selectedFn.unit ?? '';
|
||||
final (double, double) sliderRange =
|
||||
(selectedFn.min ?? 0.0, selectedFn.max ?? 100.0);
|
||||
|
||||
if (_isSliderFunction(selectedFunction)) {
|
||||
return CustomRoutinesTextbox(
|
||||
@ -63,7 +65,7 @@ class EnergyValueSelectorWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
unit: unit,
|
||||
unit: _unit,
|
||||
dividendOfRange: 1,
|
||||
stepIncreaseAmount: step,
|
||||
);
|
||||
|
@ -1,4 +1,3 @@
|
||||
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';
|
||||
@ -14,6 +13,7 @@ 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,16 +30,14 @@ 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,
|
||||
@ -47,18 +45,15 @@ class SettingHelper {
|
||||
builder: (context, effectPeriodState) {
|
||||
return BlocBuilder<SettingBloc, SettingState>(
|
||||
builder: (context, settingState) {
|
||||
var selectedIcon = '';
|
||||
var list = <IconModel>[];
|
||||
String selectedIcon = '';
|
||||
List<IconModel> list = [];
|
||||
if (settingState is TabToRunSettingLoaded) {
|
||||
selectedIcon = settingState.selectedIcon;
|
||||
list = settingState.iconList;
|
||||
}
|
||||
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),
|
||||
@ -81,18 +76,14 @@ 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',
|
||||
@ -100,18 +91,14 @@ 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,
|
||||
)
|
||||
],
|
||||
@ -121,27 +108,22 @@ class SettingHelper {
|
||||
height: 5,
|
||||
),
|
||||
const Divider(
|
||||
color:
|
||||
ColorsManager.graysColor,
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
BlocProvider.of<
|
||||
SettingBloc>(
|
||||
context)
|
||||
.add(FetchIcons(
|
||||
BlocProvider.of<SettingBloc>(context).add(
|
||||
FetchIcons(
|
||||
expanded: !context
|
||||
.read<
|
||||
SettingBloc>()
|
||||
.read<SettingBloc>()
|
||||
.isExpanded));
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Effective Period',
|
||||
@ -149,18 +131,14 @@ 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,
|
||||
)
|
||||
],
|
||||
@ -170,16 +148,13 @@ class SettingHelper {
|
||||
height: 5,
|
||||
),
|
||||
const Divider(
|
||||
color:
|
||||
ColorsManager.graysColor,
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Executed by',
|
||||
@ -187,11 +162,8 @@ class SettingHelper {
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(
|
||||
color: ColorsManager
|
||||
.textPrimaryColor,
|
||||
fontWeight:
|
||||
FontWeight
|
||||
.w400,
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14),
|
||||
),
|
||||
Text('Cloud',
|
||||
@ -199,19 +171,12 @@ 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()
|
||||
],
|
||||
@ -223,27 +188,20 @@ 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>()
|
||||
.read<SettingBloc>()
|
||||
.isExpanded));
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Icons',
|
||||
@ -251,18 +209,14 @@ 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,
|
||||
)
|
||||
],
|
||||
@ -272,16 +226,13 @@ class SettingHelper {
|
||||
height: 5,
|
||||
),
|
||||
const Divider(
|
||||
color:
|
||||
ColorsManager.graysColor,
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Show on devices page',
|
||||
@ -289,30 +240,23 @@ 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,
|
||||
child:
|
||||
CupertinoSwitch(
|
||||
child: CupertinoSwitch(
|
||||
value: true,
|
||||
onChanged:
|
||||
(value) {},
|
||||
onChanged: (value) {},
|
||||
applyTheme: true,
|
||||
),
|
||||
),
|
||||
@ -324,16 +268,13 @@ class SettingHelper {
|
||||
height: 5,
|
||||
),
|
||||
const Divider(
|
||||
color:
|
||||
ColorsManager.graysColor,
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Executed by',
|
||||
@ -341,11 +282,8 @@ class SettingHelper {
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(
|
||||
color: ColorsManager
|
||||
.textPrimaryColor,
|
||||
fontWeight:
|
||||
FontWeight
|
||||
.w400,
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14),
|
||||
),
|
||||
Text('Cloud',
|
||||
@ -353,19 +291,12 @@ 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()
|
||||
],
|
||||
@ -373,14 +304,12 @@ 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(
|
||||
@ -397,8 +326,7 @@ class SettingHelper {
|
||||
height: 35,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
BlocProvider.of<SettingBloc>(
|
||||
context)
|
||||
BlocProvider.of<SettingBloc>(context)
|
||||
.add(SelectIcon(
|
||||
iconId: iconModel.uuid,
|
||||
));
|
||||
@ -407,17 +335,13 @@ 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
|
||||
: Colors
|
||||
.transparent,
|
||||
: Colors.transparent,
|
||||
width: 2,
|
||||
),
|
||||
shape: BoxShape.circle,
|
||||
@ -432,12 +356,8 @@ 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(
|
||||
@ -461,33 +381,23 @@ 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!,
|
||||
end: effectPeriodState
|
||||
.customEndTime!,
|
||||
loops: effectPeriodState
|
||||
.selectedDaysBinary)));
|
||||
EffectiveTimePeriodEvent(EffectiveTime(
|
||||
start: effectPeriodState.customStartTime!,
|
||||
end: effectPeriodState.customEndTime!,
|
||||
loops: effectPeriodState.selectedDaysBinary)));
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
Navigator.of(context).pop(selectedIcon);
|
||||
@ -497,12 +407,8 @@ 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.primaryColorWithOpacity,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -24,7 +24,8 @@ class ThreeGangSwitchHelper {
|
||||
required String dialogType,
|
||||
required bool removeComparetors,
|
||||
}) async {
|
||||
final switchFunctions = functions.whereType<BaseSwitchFunction>().toList();
|
||||
List<BaseSwitchFunction> switchFunctions =
|
||||
functions.whereType<BaseSwitchFunction>().toList();
|
||||
|
||||
return showDialog<Map<String, dynamic>?>(
|
||||
context: context,
|
||||
|
@ -25,7 +25,8 @@ class TwoGangSwitchHelper {
|
||||
required bool removeComparetors,
|
||||
required String dialogType,
|
||||
}) async {
|
||||
final switchFunctions = functions.whereType<BaseSwitchFunction>().toList();
|
||||
List<BaseSwitchFunction> switchFunctions =
|
||||
functions.whereType<BaseSwitchFunction>().toList();
|
||||
|
||||
return showDialog<Map<String, dynamic>?>(
|
||||
context: context,
|
||||
@ -236,7 +237,7 @@ class TwoGangSwitchHelper {
|
||||
DeviceFunctionData? selectedFunctionData,
|
||||
// Function(String) onConditionChanged,
|
||||
) {
|
||||
final conditions = ['<', '==', '>'];
|
||||
final conditions = ["<", "==", ">"];
|
||||
|
||||
return ToggleButtons(
|
||||
onPressed: (int index) {
|
||||
@ -263,8 +264,8 @@ class TwoGangSwitchHelper {
|
||||
minWidth: 40.0,
|
||||
),
|
||||
isSelected:
|
||||
conditions.map((c) => c == (currentCondition ?? '==')).toList(),
|
||||
children: conditions.map(Text.new).toList(),
|
||||
conditions.map((c) => c == (currentCondition ?? "==")).toList(),
|
||||
children: conditions.map((c) => Text(c)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -279,7 +280,7 @@ class TwoGangSwitchHelper {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.primaryColorWithOpacity.withValues(alpha: 0.1),
|
||||
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Text(
|
||||
|
@ -49,6 +49,8 @@ class _TimeWheelPickerState extends State<TimeWheelPicker> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_hoursController.dispose();
|
||||
@ -101,7 +103,7 @@ class _TimeWheelPickerState extends State<TimeWheelPicker> {
|
||||
}
|
||||
|
||||
void _handleTimeChange(int hours, int minutes, int seconds) {
|
||||
var total = hours * 3600 + minutes * 60 + seconds;
|
||||
int total = hours * 3600 + minutes * 60 + seconds;
|
||||
if (total > 10000) {
|
||||
hours = 2;
|
||||
minutes = 46;
|
||||
|
@ -63,8 +63,7 @@ class _WallPresenceSensorState extends State<WallPresenceSensor> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_wpsFunctions =
|
||||
widget.functions.whereType<WpsFunctions>().where((function) {
|
||||
_wpsFunctions = widget.functions.whereType<WpsFunctions>().where((function) {
|
||||
if (widget.dialogType == 'THEN') {
|
||||
return function.type == 'THEN' || function.type == 'BOTH';
|
||||
}
|
||||
|
@ -30,8 +30,7 @@ class WpsOperationalValuesList extends StatelessWidget {
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.all(20),
|
||||
itemCount: values.length,
|
||||
itemBuilder: (context, index) =>
|
||||
_buildValueItem(context, values[index]),
|
||||
itemBuilder: (context, index) => _buildValueItem(context, values[index]),
|
||||
);
|
||||
}
|
||||
|
||||
@ -62,8 +61,7 @@ class WpsOperationalValuesList extends StatelessWidget {
|
||||
Widget _buildValueIcon(context, WpsOperationalValue value) {
|
||||
return Column(
|
||||
children: [
|
||||
if (_shouldShowTextDescription)
|
||||
Text(value.description.replaceAll('cm', '')),
|
||||
if (_shouldShowTextDescription) Text(value.description.replaceAll("cm", '')),
|
||||
SvgPicture.asset(value.icon, width: 25, height: 25),
|
||||
],
|
||||
);
|
||||
|
@ -61,4 +61,5 @@ class WaterHeaterOperationalValuesList extends StatelessWidget {
|
||||
groupValue: selectedValue,
|
||||
onChanged: (_) => onSelect(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ class WaterHeaterValueSelectorWidget extends StatelessWidget {
|
||||
final DeviceFunctionData functionData;
|
||||
final List<WaterHeaterFunctions> whFunctions;
|
||||
final AllDevicesModel? device;
|
||||
final String dialogType;
|
||||
final String dialogType;
|
||||
|
||||
const WaterHeaterValueSelectorWidget({
|
||||
required this.selectedFunction,
|
||||
@ -39,13 +39,14 @@ class WaterHeaterValueSelectorWidget extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildCountDownSlider(
|
||||
context,
|
||||
functionData.value,
|
||||
device,
|
||||
selectedFn.operationName,
|
||||
functionData,
|
||||
selectedFunction,
|
||||
dialogType),
|
||||
context,
|
||||
functionData.value,
|
||||
device,
|
||||
selectedFn.operationName,
|
||||
functionData,
|
||||
selectedFunction,
|
||||
dialogType
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
);
|
||||
|
@ -15,8 +15,7 @@ class RoutineSearchAndButtons extends StatefulWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
State<RoutineSearchAndButtons> createState() =>
|
||||
_RoutineSearchAndButtonsState();
|
||||
State<RoutineSearchAndButtons> createState() => _RoutineSearchAndButtonsState();
|
||||
}
|
||||
|
||||
class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
|
||||
@ -62,9 +61,8 @@ 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,
|
||||
@ -73,13 +71,10 @@ 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(
|
||||
style: context.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: ColorsManager.blackColor,
|
||||
@ -93,23 +88,20 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
|
||||
decoration: containerWhiteDecoration,
|
||||
child: TextFormField(
|
||||
style: context.textTheme.bodyMedium!
|
||||
.copyWith(
|
||||
color: ColorsManager.blackColor),
|
||||
.copyWith(color: ColorsManager.blackColor),
|
||||
controller: _nameController,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Please enter the name',
|
||||
hintStyle: context.textTheme.bodyMedium!
|
||||
.copyWith(
|
||||
fontSize: 12,
|
||||
color: ColorsManager.grayColor),
|
||||
.copyWith(fontSize: 12, color: ColorsManager.grayColor),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 12, vertical: 10),
|
||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
onTapOutside: (_) {
|
||||
context.read<RoutineBloc>().add(
|
||||
SetRoutineName(_nameController.text));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(SetRoutineName(_nameController.text));
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
@ -122,44 +114,41 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
|
||||
],
|
||||
),
|
||||
),
|
||||
if (constraints.maxWidth <= 1000)
|
||||
const SizedBox()
|
||||
else
|
||||
SizedBox(
|
||||
height: 40,
|
||||
width: 200,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
onPressed: state.isAutomation ||
|
||||
state.isTabToRun
|
||||
? () async {
|
||||
final result = await SettingHelper
|
||||
.showSettingDialog(
|
||||
context: context,
|
||||
iconId: state.selectedIcon ?? '',
|
||||
);
|
||||
if (result != null) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddSelectedIcon(result));
|
||||
}
|
||||
}
|
||||
: null,
|
||||
borderRadius: 15,
|
||||
elevation: 0,
|
||||
borderColor: ColorsManager.greyColor,
|
||||
backgroundColor: ColorsManager.boxColor,
|
||||
child: const Text(
|
||||
'Settings',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: ColorsManager.primaryColor,
|
||||
(constraints.maxWidth <= 1000)
|
||||
? const SizedBox()
|
||||
: SizedBox(
|
||||
height: 40,
|
||||
width: 200,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
onPressed: state.isAutomation || state.isTabToRun
|
||||
? () async {
|
||||
final result = await SettingHelper.showSettingDialog(
|
||||
context: context,
|
||||
iconId: state.selectedIcon ?? '',
|
||||
);
|
||||
if (result != null) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddSelectedIcon(result));
|
||||
}
|
||||
}
|
||||
: null,
|
||||
borderRadius: 15,
|
||||
elevation: 0,
|
||||
borderColor: ColorsManager.greyColor,
|
||||
backgroundColor: ColorsManager.boxColor,
|
||||
child: const Text(
|
||||
'Settings',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: ColorsManager.primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -197,12 +186,10 @@ 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(
|
||||
@ -216,12 +203,10 @@ 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(
|
||||
@ -236,10 +221,8 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
|
||||
}
|
||||
// final result =
|
||||
// await
|
||||
BlocProvider.of<RoutineBloc>(context)
|
||||
.add(ResetErrorMessage());
|
||||
SaveRoutineHelper.showSaveRoutineDialog(
|
||||
context);
|
||||
BlocProvider.of<RoutineBloc>(context).add(ResetErrorMessage());
|
||||
SaveRoutineHelper.showSaveRoutineDialog(context);
|
||||
// if (result != null && result) {
|
||||
// BlocProvider.of<RoutineBloc>(context).add(
|
||||
// const CreateNewRoutineViewEvent(createRoutineView: false),
|
||||
@ -278,14 +261,10 @@ 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,
|
||||
@ -335,12 +314,10 @@ 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(
|
||||
@ -354,12 +331,10 @@ 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(
|
||||
@ -374,8 +349,7 @@ 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(
|
||||
|
@ -27,16 +27,14 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
|
||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||
builder: (context, state) {
|
||||
if (!state.isLoading) {
|
||||
final scenes = [...state.scenes, ...state.automations];
|
||||
var scenes = [...state.scenes, ...state.automations];
|
||||
return Wrap(
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: scenes.asMap().entries.map((entry) {
|
||||
final scene = entry.value;
|
||||
if (state.searchText != null && state.searchText!.isNotEmpty) {
|
||||
return scene.name
|
||||
.toLowerCase()
|
||||
.contains(state.searchText!.toLowerCase())
|
||||
return scene.name.toLowerCase().contains(state.searchText!.toLowerCase())
|
||||
? DraggableCard(
|
||||
imagePath: scene.icon ?? Assets.loginLogo,
|
||||
title: scene.name,
|
||||
|
@ -6,8 +6,7 @@ import 'package:syncrow_web/pages/routines/widgets/routines_title_widget.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class ConditionTitleAndSearchBar extends StatelessWidget
|
||||
with HelperResponsiveLayout {
|
||||
class ConditionTitleAndSearchBar extends StatelessWidget with HelperResponsiveLayout {
|
||||
const ConditionTitleAndSearchBar({
|
||||
super.key,
|
||||
});
|
||||
|
@ -30,118 +30,123 @@ class ThenContainer extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
if (state.isLoading && state.isUpdate == true)
|
||||
const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
else
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: List.generate(
|
||||
state.thenItems.length,
|
||||
(index) => GestureDetector(
|
||||
onTap: () async {
|
||||
if (state.thenItems[index]['deviceId'] ==
|
||||
'delay') {
|
||||
final result = await DelayHelper
|
||||
.showDelayPickerDialog(context,
|
||||
state.thenItems[index]);
|
||||
state.isLoading && state.isUpdate == true
|
||||
? const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: List.generate(
|
||||
state.thenItems.length,
|
||||
(index) => GestureDetector(
|
||||
onTap: () async {
|
||||
if (state.thenItems[index]
|
||||
['deviceId'] ==
|
||||
'delay') {
|
||||
final result = await DelayHelper
|
||||
.showDelayPickerDialog(context,
|
||||
state.thenItems[index]);
|
||||
|
||||
if (result != null) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToThenContainer({
|
||||
...state.thenItems[index],
|
||||
'imagePath': Assets.delay,
|
||||
'title': 'Delay',
|
||||
}));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.thenItems[index]['type'] ==
|
||||
'automation') {
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
AutomationDialog(
|
||||
automationName:
|
||||
state.thenItems[index]
|
||||
['name'] ??
|
||||
'Automation',
|
||||
automationId:
|
||||
state.thenItems[index]
|
||||
['deviceId'] ??
|
||||
'',
|
||||
uniqueCustomId:
|
||||
state.thenItems[index]
|
||||
['uniqueCustomId'],
|
||||
),
|
||||
);
|
||||
|
||||
if (result != null) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToThenContainer({
|
||||
...state.thenItems[index],
|
||||
'imagePath':
|
||||
Assets.automation,
|
||||
'title':
|
||||
state.thenItems[index]
|
||||
['name'] ??
|
||||
state.thenItems[index]
|
||||
['title'],
|
||||
}));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final result = await DeviceDialogHelper
|
||||
.showDeviceDialog(
|
||||
context: context,
|
||||
data: state.thenItems[index],
|
||||
removeComparetors: true,
|
||||
dialogType: "THEN");
|
||||
|
||||
if (result != null) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToThenContainer({
|
||||
...state.thenItems[index],
|
||||
'imagePath': Assets.delay,
|
||||
'title': 'Delay',
|
||||
}));
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToThenContainer(
|
||||
state.thenItems[index]));
|
||||
} else if (![
|
||||
'AC',
|
||||
'1G',
|
||||
'2G',
|
||||
'3G',
|
||||
'WPS',
|
||||
'CPS',
|
||||
"GW",
|
||||
"NCPS",
|
||||
'WH',
|
||||
].contains(state.thenItems[index]
|
||||
['productType'])) {
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToThenContainer(
|
||||
state.thenItems[index]));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.thenItems[index]['type'] ==
|
||||
'automation') {
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
AutomationDialog(
|
||||
automationName: state
|
||||
.thenItems[index]['name'] ??
|
||||
'Automation',
|
||||
automationId: state.thenItems[index]
|
||||
['deviceId'] ??
|
||||
'',
|
||||
uniqueCustomId:
|
||||
state.thenItems[index]
|
||||
['uniqueCustomId'],
|
||||
),
|
||||
);
|
||||
|
||||
if (result != null) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToThenContainer({
|
||||
...state.thenItems[index],
|
||||
'imagePath': Assets.automation,
|
||||
'title': state.thenItems[index]
|
||||
['name'] ??
|
||||
state.thenItems[index]
|
||||
['title'],
|
||||
}));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final result = await DeviceDialogHelper
|
||||
.showDeviceDialog(
|
||||
context: context,
|
||||
data: state.thenItems[index],
|
||||
removeComparetors: true,
|
||||
dialogType: 'THEN');
|
||||
|
||||
if (result != null) {
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToThenContainer(
|
||||
state.thenItems[index]));
|
||||
} else if (![
|
||||
'AC',
|
||||
'1G',
|
||||
'2G',
|
||||
'3G',
|
||||
'WPS',
|
||||
'CPS',
|
||||
'GW',
|
||||
'NCPS',
|
||||
'WH',
|
||||
].contains(state.thenItems[index]
|
||||
['productType'])) {
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToThenContainer(
|
||||
state.thenItems[index]));
|
||||
}
|
||||
},
|
||||
child: DraggableCard(
|
||||
imagePath: state.thenItems[index]
|
||||
['imagePath'] ??
|
||||
'',
|
||||
title:
|
||||
state.thenItems[index]['title'] ?? '',
|
||||
deviceData: state.thenItems[index],
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 4, vertical: 8),
|
||||
isFromThen: true,
|
||||
isFromIf: false,
|
||||
onRemove: () {
|
||||
context.read<RoutineBloc>().add(
|
||||
RemoveDragCard(
|
||||
index: index,
|
||||
isFromThen: true,
|
||||
key: state.thenItems[index]
|
||||
['uniqueCustomId']));
|
||||
},
|
||||
),
|
||||
))),
|
||||
child: DraggableCard(
|
||||
imagePath: state.thenItems[index]
|
||||
['imagePath'] ??
|
||||
'',
|
||||
title: state.thenItems[index]
|
||||
['title'] ??
|
||||
'',
|
||||
deviceData: state.thenItems[index],
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 4, vertical: 8),
|
||||
isFromThen: true,
|
||||
isFromIf: false,
|
||||
onRemove: () {
|
||||
context.read<RoutineBloc>().add(
|
||||
RemoveDragCard(
|
||||
index: index,
|
||||
isFromThen: true,
|
||||
key: state.thenItems[index]
|
||||
['uniqueCustomId']));
|
||||
},
|
||||
),
|
||||
))),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -163,7 +168,7 @@ class ThenContainer extends StatelessWidget {
|
||||
}
|
||||
|
||||
if (mutableData['type'] == 'automation') {
|
||||
final index = state.thenItems.indexWhere(
|
||||
int index = state.thenItems.indexWhere(
|
||||
(item) => item['deviceId'] == mutableData['deviceId']);
|
||||
if (index != -1) {
|
||||
return;
|
||||
@ -189,7 +194,7 @@ class ThenContainer extends StatelessWidget {
|
||||
}
|
||||
|
||||
if (mutableData['type'] == 'tap_to_run' && state.isAutomation) {
|
||||
final index = state.thenItems.indexWhere(
|
||||
int index = state.thenItems.indexWhere(
|
||||
(item) => item['deviceId'] == mutableData['deviceId']);
|
||||
if (index != -1) {
|
||||
return;
|
||||
@ -225,7 +230,7 @@ class ThenContainer extends StatelessWidget {
|
||||
context: context,
|
||||
data: mutableData,
|
||||
removeComparetors: true,
|
||||
dialogType: 'THEN');
|
||||
dialogType: "THEN");
|
||||
if (result != null) {
|
||||
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
||||
} else if (![
|
||||
@ -236,8 +241,8 @@ class ThenContainer extends StatelessWidget {
|
||||
'WPS',
|
||||
'GW',
|
||||
'CPS',
|
||||
'NCPS',
|
||||
'WH',
|
||||
"NCPS",
|
||||
"WH",
|
||||
'PC',
|
||||
].contains(mutableData['productType'])) {
|
||||
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
||||
|
@ -19,7 +19,7 @@ class ValueDisplay extends StatelessWidget {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.primaryColorWithOpacity.withValues(alpha: 0.1),
|
||||
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Text(
|
||||
|
Reference in New Issue
Block a user