mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
push ac functions and gang switches functions
This commit is contained in:
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"automations"
|
||||||
|
]
|
||||||
|
}
|
@ -4,6 +4,9 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/room.dart'
|
|||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/models/ac/ac_function.dart';
|
import 'package:syncrow_web/pages/routiens/models/ac/ac_function.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/one_gang_switch/one_gang_switch.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/three_gang_switch/three_gang_switch.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/two_gang_switch/two_gang_switch.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/enum/device_types.dart';
|
import 'package:syncrow_web/utils/enum/device_types.dart';
|
||||||
|
|
||||||
@ -71,7 +74,6 @@ class AllDevicesModel {
|
|||||||
int? batteryLevel;
|
int? batteryLevel;
|
||||||
String? productName;
|
String? productName;
|
||||||
List<DeviceSpaceModel>? spaces;
|
List<DeviceSpaceModel>? spaces;
|
||||||
List<DeviceFunction>? _deviceFunctions;
|
|
||||||
|
|
||||||
AllDevicesModel({
|
AllDevicesModel({
|
||||||
this.room,
|
this.room,
|
||||||
@ -104,8 +106,12 @@ class AllDevicesModel {
|
|||||||
this.spaces,
|
this.spaces,
|
||||||
});
|
});
|
||||||
AllDevicesModel.fromJson(Map<String, dynamic> json) {
|
AllDevicesModel.fromJson(Map<String, dynamic> json) {
|
||||||
room = (json['room'] != null && (json['room'] is Map)) ? DevicesModelRoom.fromJson(json['room']) : null;
|
room = (json['room'] != null && (json['room'] is Map))
|
||||||
unit = (json['unit'] != null && (json['unit'] is Map)) ? DevicesModelUnit.fromJson(json['unit']) : null;
|
? DevicesModelRoom.fromJson(json['room'])
|
||||||
|
: null;
|
||||||
|
unit = (json['unit'] != null && (json['unit'] is Map))
|
||||||
|
? DevicesModelUnit.fromJson(json['unit'])
|
||||||
|
: null;
|
||||||
community = (json['community'] != null && (json['community'] is Map))
|
community = (json['community'] != null && (json['community'] is Map))
|
||||||
? DeviceCommunityModel.fromJson(json['community'])
|
? DeviceCommunityModel.fromJson(json['community'])
|
||||||
: null;
|
: null;
|
||||||
@ -134,7 +140,9 @@ class AllDevicesModel {
|
|||||||
batteryLevel = int.tryParse(json['battery']?.toString() ?? '');
|
batteryLevel = int.tryParse(json['battery']?.toString() ?? '');
|
||||||
productName = json['productName']?.toString();
|
productName = json['productName']?.toString();
|
||||||
if (json['spaces'] != null && json['spaces'] is List) {
|
if (json['spaces'] != null && json['spaces'] is List) {
|
||||||
spaces = (json['spaces'] as List).map((space) => DeviceSpaceModel.fromJson(space)).toList();
|
spaces = (json['spaces'] as List)
|
||||||
|
.map((space) => DeviceSpaceModel.fromJson(space))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +190,8 @@ SOS
|
|||||||
String tempIcon = '';
|
String tempIcon = '';
|
||||||
if (type == DeviceType.LightBulb) {
|
if (type == DeviceType.LightBulb) {
|
||||||
tempIcon = Assets.lightBulb;
|
tempIcon = Assets.lightBulb;
|
||||||
} else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
|
} else if (type == DeviceType.CeilingSensor ||
|
||||||
|
type == DeviceType.WallSensor) {
|
||||||
tempIcon = Assets.sensors;
|
tempIcon = Assets.sensors;
|
||||||
} else if (type == DeviceType.AC) {
|
} else if (type == DeviceType.AC) {
|
||||||
tempIcon = Assets.ac;
|
tempIcon = Assets.ac;
|
||||||
@ -218,11 +227,11 @@ SOS
|
|||||||
return tempIcon;
|
return tempIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DeviceFunction> get deviceFunctions {
|
List<DeviceFunction> get functions {
|
||||||
_deviceFunctions ??= _getDeviceFunctions();
|
return _getDeviceFunctions();
|
||||||
return _deviceFunctions!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Functions for Devices Types
|
||||||
List<DeviceFunction> _getDeviceFunctions() {
|
List<DeviceFunction> _getDeviceFunctions() {
|
||||||
switch (productType) {
|
switch (productType) {
|
||||||
case 'AC':
|
case 'AC':
|
||||||
@ -234,7 +243,38 @@ SOS
|
|||||||
ChildLockFunction(deviceId: uuid ?? '', deviceName: name ?? ''),
|
ChildLockFunction(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
];
|
];
|
||||||
|
|
||||||
// other product types
|
case '1G':
|
||||||
|
return [
|
||||||
|
OneGangSwitchFunction(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
OneGangCountdownFunction(
|
||||||
|
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
];
|
||||||
|
|
||||||
|
case '2G':
|
||||||
|
return [
|
||||||
|
TwoGangSwitch1Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
TwoGangSwitch2Function(deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
TwoGangCountdown1Function(
|
||||||
|
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
TwoGangCountdown2Function(
|
||||||
|
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
];
|
||||||
|
|
||||||
|
case '3G':
|
||||||
|
return [
|
||||||
|
ThreeGangSwitch1Function(
|
||||||
|
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
ThreeGangSwitch2Function(
|
||||||
|
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
ThreeGangSwitch3Function(
|
||||||
|
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
ThreeGangCountdown1Function(
|
||||||
|
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
ThreeGangCountdown2Function(
|
||||||
|
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
ThreeGangCountdown3Function(
|
||||||
|
deviceId: uuid ?? '', deviceName: name ?? ''),
|
||||||
|
];
|
||||||
default:
|
default:
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -1,154 +1,39 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc.dart';
|
|
||||||
import 'package:syncrow_web/pages/routiens/models/ac/ac_function.dart';
|
import 'package:syncrow_web/pages/routiens/models/ac/ac_function.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
mixin ACHelper {
|
class ACHelper {
|
||||||
Future<Map<String, dynamic>?> showACFunctionsDialog(BuildContext context, List<DeviceFunction<dynamic>> functions) {
|
static Future<Map<String, dynamic>?> showACFunctionsDialog(
|
||||||
|
BuildContext context,
|
||||||
|
List<DeviceFunction<dynamic>> functions,
|
||||||
|
) async {
|
||||||
List<ACFunction> acFunctions = functions.whereType<ACFunction>().toList();
|
List<ACFunction> acFunctions = functions.whereType<ACFunction>().toList();
|
||||||
String? selectedFunction;
|
String? selectedFunction;
|
||||||
dynamic selectedValue;
|
dynamic selectedValue = 20;
|
||||||
|
String? selectedCondition = "==";
|
||||||
|
List<bool> _selectedConditions = [false, true, false];
|
||||||
|
|
||||||
return showDialog(
|
return showDialog<Map<String, dynamic>?>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return StatefulBuilder(
|
return StatefulBuilder(
|
||||||
builder: (context, setState) {
|
builder: (context, setState) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
content: Container(
|
content: _buildDialogContent(
|
||||||
width: selectedFunction != null ? 600 : 360,
|
context,
|
||||||
decoration: BoxDecoration(
|
setState,
|
||||||
color: Colors.white,
|
acFunctions,
|
||||||
borderRadius: BorderRadius.circular(20),
|
selectedFunction,
|
||||||
),
|
selectedValue,
|
||||||
padding: const EdgeInsets.only(top: 20),
|
selectedCondition,
|
||||||
child: Column(
|
_selectedConditions,
|
||||||
mainAxisSize: MainAxisSize.min,
|
(fn) => selectedFunction = fn,
|
||||||
children: [
|
(val) => selectedValue = val,
|
||||||
Text(
|
(cond) => selectedCondition = cond,
|
||||||
'AC Functions',
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
|
||||||
color: ColorsManager.primaryColorWithOpacity,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 50),
|
|
||||||
child: Container(
|
|
||||||
height: 1,
|
|
||||||
width: double.infinity,
|
|
||||||
color: ColorsManager.greyColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: ListView.separated(
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemCount: acFunctions.length,
|
|
||||||
separatorBuilder: (context, index) => Divider(),
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final function = acFunctions[index];
|
|
||||||
return ListTile(
|
|
||||||
leading: Image.asset(function.icon, width: 24, height: 24),
|
|
||||||
title: Text(function.operationName),
|
|
||||||
trailing: Icon(Icons.arrow_forward_ios),
|
|
||||||
onTap: () {
|
|
||||||
setState(() {
|
|
||||||
selectedFunction = function.code;
|
|
||||||
selectedValue = null;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (selectedFunction != null)
|
|
||||||
Container(
|
|
||||||
width: 1,
|
|
||||||
color: ColorsManager.greyColor,
|
|
||||||
),
|
|
||||||
if (selectedFunction != null)
|
|
||||||
Expanded(
|
|
||||||
child: ListView.separated(
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemCount: acFunctions
|
|
||||||
.firstWhere((f) => f.code == selectedFunction)
|
|
||||||
.getOperationalValues()
|
|
||||||
.length,
|
|
||||||
separatorBuilder: (context, index) => Divider(),
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final operationalValue = acFunctions.firstWhere((f) => f.code == selectedFunction)
|
|
||||||
..getOperationalValues()[index];
|
|
||||||
return ListTile(
|
|
||||||
leading: Image.asset(operationalValue.icon, width: 24, height: 24),
|
|
||||||
title: Text(operationalValue.getOperationalValues()[index].description),
|
|
||||||
trailing: Radio<dynamic>(
|
|
||||||
value: operationalValue.getOperationalValues()[index].value,
|
|
||||||
groupValue: selectedValue,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
selectedValue = value;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
height: 1,
|
|
||||||
width: double.infinity,
|
|
||||||
color: ColorsManager.greyColor,
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
'Cancel',
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: ColorsManager.greyColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
height: 50,
|
|
||||||
width: 1,
|
|
||||||
color: ColorsManager.greyColor,
|
|
||||||
),
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
// Handle the confirmation action here
|
|
||||||
Navigator.pop(context, {
|
|
||||||
'function': selectedFunction,
|
|
||||||
'value': selectedValue,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
'Confirm',
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
|
||||||
color: ColorsManager.primaryColorWithOpacity,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -157,34 +42,370 @@ mixin ACHelper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleACDeviceDrop(BuildContext context, Map<String, dynamic> data) {
|
/// Build dialog content for AC functions dialog
|
||||||
final device = data['device'] as AllDevicesModel;
|
static Widget _buildDialogContent(
|
||||||
final acFunctions = device.deviceFunctions;
|
BuildContext context,
|
||||||
|
StateSetter setState,
|
||||||
showACFunctionsDialog(context, acFunctions).then((result) {
|
List<ACFunction> acFunctions,
|
||||||
if (result != null) {
|
String? selectedFunction,
|
||||||
_addACDeviceToRoutine(context, data, result);
|
dynamic selectedValue,
|
||||||
}
|
String? selectedCondition,
|
||||||
});
|
List<bool> selectedConditions,
|
||||||
|
Function(String?) onFunctionSelected,
|
||||||
|
Function(dynamic) onValueSelected,
|
||||||
|
Function(String?) onConditionSelected,
|
||||||
|
) {
|
||||||
|
return Container(
|
||||||
|
width: selectedFunction != null ? 600 : 360,
|
||||||
|
height: 450,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.only(top: 20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
_buildDialogHeader(context),
|
||||||
|
Flexible(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
_buildFunctionsList(
|
||||||
|
context,
|
||||||
|
setState,
|
||||||
|
acFunctions,
|
||||||
|
selectedFunction,
|
||||||
|
onFunctionSelected,
|
||||||
|
),
|
||||||
|
if (selectedFunction != null)
|
||||||
|
_buildValueSelector(
|
||||||
|
context,
|
||||||
|
setState,
|
||||||
|
selectedFunction,
|
||||||
|
selectedValue,
|
||||||
|
selectedCondition,
|
||||||
|
selectedConditions,
|
||||||
|
onValueSelected,
|
||||||
|
onConditionSelected,
|
||||||
|
acFunctions,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_buildDialogFooter(
|
||||||
|
context,
|
||||||
|
selectedFunction,
|
||||||
|
selectedValue,
|
||||||
|
selectedCondition,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleNonACDeviceDrop(BuildContext context, Map<String, dynamic> data) {
|
/// Build header for AC functions dialog
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer(data));
|
static Widget _buildDialogHeader(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'AC Condition',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 50),
|
||||||
|
child: Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addACDeviceToRoutine(BuildContext context, Map<String, dynamic> deviceData, Map<String, dynamic> functionData) {
|
/// Build functions list for AC functions dialog
|
||||||
final updatedData = {
|
static Widget _buildFunctionsList(
|
||||||
...deviceData,
|
BuildContext context,
|
||||||
'function': functionData['function'],
|
StateSetter setState,
|
||||||
'value': functionData['value'],
|
List<ACFunction> acFunctions,
|
||||||
};
|
String? selectedFunction,
|
||||||
|
Function(String?) onFunctionSelected,
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer(updatedData));
|
) {
|
||||||
|
return Expanded(
|
||||||
_logACFunctionSelection(functionData);
|
child: ListView.separated(
|
||||||
|
shrinkWrap: false,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemCount: acFunctions.length,
|
||||||
|
separatorBuilder: (context, index) => const Divider(
|
||||||
|
color: ColorsManager.dividerColor,
|
||||||
|
),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final function = acFunctions[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
function.icon,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
function.operationName,
|
||||||
|
style: context.textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
trailing: const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
size: 16,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
onTap: () => setState(() => onFunctionSelected(function.code)),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _logACFunctionSelection(Map<String, dynamic> functionData) {
|
/// Build value selector for AC functions dialog
|
||||||
print('Selected AC function: ${functionData['function']}, Value: ${functionData['value']}');
|
static Widget _buildValueSelector(
|
||||||
|
BuildContext context,
|
||||||
|
StateSetter setState,
|
||||||
|
String selectedFunction,
|
||||||
|
dynamic selectedValue,
|
||||||
|
String? selectedCondition,
|
||||||
|
List<bool> selectedConditions,
|
||||||
|
Function(dynamic) onValueSelected,
|
||||||
|
Function(String?) onConditionSelected,
|
||||||
|
List<ACFunction> acFunctions,
|
||||||
|
) {
|
||||||
|
if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') {
|
||||||
|
return Expanded(
|
||||||
|
child: _buildTemperatureSelector(
|
||||||
|
context,
|
||||||
|
setState,
|
||||||
|
selectedValue,
|
||||||
|
selectedCondition,
|
||||||
|
selectedConditions,
|
||||||
|
onValueSelected,
|
||||||
|
onConditionSelected,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final selectedFn =
|
||||||
|
acFunctions.firstWhere((f) => f.code == selectedFunction);
|
||||||
|
final values = selectedFn.getOperationalValues();
|
||||||
|
return Expanded(
|
||||||
|
child: _buildOperationalValuesList(
|
||||||
|
context,
|
||||||
|
setState,
|
||||||
|
values,
|
||||||
|
selectedValue,
|
||||||
|
onValueSelected,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build temperature selector for AC functions dialog
|
||||||
|
static Widget _buildTemperatureSelector(
|
||||||
|
BuildContext context,
|
||||||
|
StateSetter setState,
|
||||||
|
dynamic selectedValue,
|
||||||
|
String? selectedCondition,
|
||||||
|
List<bool> selectedConditions,
|
||||||
|
Function(dynamic) onValueSelected,
|
||||||
|
Function(String?) onConditionSelected,
|
||||||
|
) {
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
_buildConditionToggle(
|
||||||
|
context,
|
||||||
|
setState,
|
||||||
|
selectedConditions,
|
||||||
|
onConditionSelected,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
_buildTemperatureDisplay(context, selectedValue),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
_buildTemperatureSlider(
|
||||||
|
context,
|
||||||
|
setState,
|
||||||
|
selectedValue,
|
||||||
|
onValueSelected,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build condition toggle for AC functions dialog
|
||||||
|
static Widget _buildConditionToggle(
|
||||||
|
BuildContext context,
|
||||||
|
StateSetter setState,
|
||||||
|
List<bool> selectedConditions,
|
||||||
|
Function(String?) onConditionSelected,
|
||||||
|
) {
|
||||||
|
return ToggleButtons(
|
||||||
|
onPressed: (int index) {
|
||||||
|
setState(() {
|
||||||
|
for (int i = 0; i < selectedConditions.length; i++) {
|
||||||
|
selectedConditions[i] = i == index;
|
||||||
|
}
|
||||||
|
onConditionSelected(index == 0
|
||||||
|
? "<"
|
||||||
|
: index == 1
|
||||||
|
? "=="
|
||||||
|
: ">");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
selectedBorderColor: ColorsManager.primaryColorWithOpacity,
|
||||||
|
selectedColor: Colors.white,
|
||||||
|
fillColor: ColorsManager.primaryColorWithOpacity,
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
minHeight: 40.0,
|
||||||
|
minWidth: 40.0,
|
||||||
|
),
|
||||||
|
isSelected: selectedConditions,
|
||||||
|
children: const [Text("<"), Text("="), Text(">")],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build temperature display for AC functions dialog
|
||||||
|
static Widget _buildTemperatureDisplay(
|
||||||
|
BuildContext context, dynamic selectedValue) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'${selectedValue ?? 20}°C',
|
||||||
|
style: context.textTheme.headlineMedium!.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Widget _buildTemperatureSlider(
|
||||||
|
BuildContext context,
|
||||||
|
StateSetter setState,
|
||||||
|
dynamic selectedValue,
|
||||||
|
Function(dynamic) onValueSelected,
|
||||||
|
) {
|
||||||
|
final currentValue = selectedValue is int ? selectedValue.toDouble() : 20.0;
|
||||||
|
return Slider(
|
||||||
|
value: currentValue,
|
||||||
|
min: 16,
|
||||||
|
max: 30,
|
||||||
|
divisions: 14,
|
||||||
|
label: '${currentValue.toInt()}°C',
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() => onValueSelected(value.toInt()));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Widget _buildOperationalValuesList(
|
||||||
|
BuildContext context,
|
||||||
|
StateSetter setState,
|
||||||
|
List<dynamic> values,
|
||||||
|
dynamic selectedValue,
|
||||||
|
Function(dynamic) onValueSelected,
|
||||||
|
) {
|
||||||
|
return ListView.builder(
|
||||||
|
shrinkWrap: false,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemCount: values.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final value = values[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
value.icon,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
value.description,
|
||||||
|
style: context.textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
trailing: Radio<dynamic>(
|
||||||
|
value: value.value,
|
||||||
|
groupValue: selectedValue,
|
||||||
|
onChanged: (newValue) {
|
||||||
|
setState(() => onValueSelected(newValue));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Widget _buildDialogFooter(
|
||||||
|
BuildContext context,
|
||||||
|
String? selectedFunction,
|
||||||
|
dynamic selectedValue,
|
||||||
|
String? selectedCondition,
|
||||||
|
) {
|
||||||
|
return Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
_buildFooterButton(
|
||||||
|
context,
|
||||||
|
'Cancel',
|
||||||
|
selectedFunction != null ? 299 : 179,
|
||||||
|
() => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
_buildFooterButton(
|
||||||
|
context,
|
||||||
|
'Confirm',
|
||||||
|
selectedFunction != null ? 299 : 179,
|
||||||
|
selectedFunction != null && selectedValue != null
|
||||||
|
? () => Navigator.pop(context, {
|
||||||
|
'function': selectedFunction,
|
||||||
|
'value': selectedValue,
|
||||||
|
'condition': selectedCondition ?? "==",
|
||||||
|
})
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Widget _buildFooterButton(
|
||||||
|
BuildContext context,
|
||||||
|
String text,
|
||||||
|
double width,
|
||||||
|
VoidCallback? onTap,
|
||||||
|
) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 50,
|
||||||
|
width: width,
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: context.textTheme.bodyMedium!.copyWith(
|
||||||
|
color: onTap != null
|
||||||
|
? ColorsManager.primaryColorWithOpacity
|
||||||
|
: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/helper/ac_helper.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/helper/one_gang_switch_helper.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/helper/three_gang_switch_helper.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/helper/two_gang_switch_helper.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||||
|
|
||||||
|
class DeviceDialogHelper {
|
||||||
|
static Future<Map<String, dynamic>?> showDeviceDialog(
|
||||||
|
BuildContext context,
|
||||||
|
Map<String, dynamic> data,
|
||||||
|
) async {
|
||||||
|
final functions = data['functions'] as List<DeviceFunction>;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = await _getDialogForDeviceType(
|
||||||
|
context,
|
||||||
|
data['productType'],
|
||||||
|
functions,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return {...data, ...result};
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Error: $e');
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<Map<String, dynamic>?> _getDialogForDeviceType(
|
||||||
|
BuildContext context,
|
||||||
|
String productType,
|
||||||
|
List<DeviceFunction> functions,
|
||||||
|
) async {
|
||||||
|
switch (productType) {
|
||||||
|
case 'AC':
|
||||||
|
return ACHelper.showACFunctionsDialog(context, functions);
|
||||||
|
case '1G':
|
||||||
|
return OneGangSwitchHelper.showSwitchFunctionsDialog(
|
||||||
|
context, functions);
|
||||||
|
case '2G':
|
||||||
|
return TwoGangSwitchHelper.showSwitchFunctionsDialog(
|
||||||
|
context, functions);
|
||||||
|
case '3G':
|
||||||
|
return ThreeGangSwitchHelper.showSwitchFunctionsDialog(
|
||||||
|
context, functions);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
206
lib/pages/routiens/helper/one_gang_switch_helper.dart
Normal file
206
lib/pages/routiens/helper/one_gang_switch_helper.dart
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/one_gang_switch/one_gang_switch.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
|
class OneGangSwitchHelper {
|
||||||
|
static Future<Map<String, dynamic>?> showSwitchFunctionsDialog(
|
||||||
|
BuildContext context, List<DeviceFunction<dynamic>> functions) async {
|
||||||
|
List<DeviceFunction<dynamic>> switchFunctions = functions
|
||||||
|
.where(
|
||||||
|
(f) => f is OneGangSwitchFunction || f is OneGangCountdownFunction)
|
||||||
|
.toList();
|
||||||
|
String? selectedFunction;
|
||||||
|
dynamic selectedValue;
|
||||||
|
|
||||||
|
return showDialog<Map<String, dynamic>?>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (context, setState) {
|
||||||
|
return AlertDialog(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
content: Container(
|
||||||
|
width: selectedFunction != null ? 600 : 360,
|
||||||
|
height: 450,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.only(top: 20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'1 Gang Light Switch Condition',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 15, horizontal: 50),
|
||||||
|
child: Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ListView.separated(
|
||||||
|
shrinkWrap: false,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemCount: switchFunctions.length,
|
||||||
|
separatorBuilder: (context, index) =>
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.dividerColor,
|
||||||
|
),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final function = switchFunctions[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
function.icon,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
function.operationName,
|
||||||
|
style: context.textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
trailing: const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
size: 16,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
selectedFunction = function.code;
|
||||||
|
selectedValue = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (selectedFunction != null)
|
||||||
|
Expanded(
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final selectedFn = switchFunctions.firstWhere(
|
||||||
|
(f) => f.code == selectedFunction)
|
||||||
|
as BaseSwitchFunction;
|
||||||
|
final values =
|
||||||
|
selectedFn.getOperationalValues();
|
||||||
|
return ListView.builder(
|
||||||
|
shrinkWrap: false,
|
||||||
|
physics:
|
||||||
|
const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemCount: values.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final value = values[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
value.icon,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
value.description,
|
||||||
|
style: context.textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
trailing: Radio<dynamic>(
|
||||||
|
value: value.value,
|
||||||
|
groupValue: selectedValue,
|
||||||
|
onChanged: (newValue) {
|
||||||
|
setState(() {
|
||||||
|
selectedValue = newValue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 50,
|
||||||
|
width: selectedFunction != null ? 299 : 179,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
right:
|
||||||
|
BorderSide(color: ColorsManager.greyColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Cancel',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(color: ColorsManager.greyColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (selectedFunction != null &&
|
||||||
|
selectedValue != null) {
|
||||||
|
Navigator.pop(context, {
|
||||||
|
'function': selectedFunction,
|
||||||
|
'value': selectedValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
height: 50,
|
||||||
|
width: selectedFunction != null ? 299 : 179,
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Confirm',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(
|
||||||
|
color:
|
||||||
|
ColorsManager.primaryColorWithOpacity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
211
lib/pages/routiens/helper/three_gang_switch_helper.dart
Normal file
211
lib/pages/routiens/helper/three_gang_switch_helper.dart
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/three_gang_switch/three_gang_switch.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
|
class ThreeGangSwitchHelper {
|
||||||
|
static Future<Map<String, dynamic>?> showSwitchFunctionsDialog(
|
||||||
|
BuildContext context, List<DeviceFunction<dynamic>> functions) async {
|
||||||
|
List<DeviceFunction<dynamic>> switchFunctions = functions
|
||||||
|
.where((f) =>
|
||||||
|
f is ThreeGangSwitch1Function ||
|
||||||
|
f is ThreeGangSwitch2Function ||
|
||||||
|
f is ThreeGangSwitch3Function ||
|
||||||
|
f is ThreeGangCountdown1Function ||
|
||||||
|
f is ThreeGangCountdown2Function ||
|
||||||
|
f is ThreeGangCountdown3Function)
|
||||||
|
.toList();
|
||||||
|
String? selectedFunction;
|
||||||
|
dynamic selectedValue;
|
||||||
|
|
||||||
|
return showDialog<Map<String, dynamic>?>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (context, setState) {
|
||||||
|
return AlertDialog(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
content: Container(
|
||||||
|
width: selectedFunction != null ? 600 : 360,
|
||||||
|
height: 450,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.only(top: 20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'3 Gangs Light Switch Condition',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 15, horizontal: 50),
|
||||||
|
child: Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ListView.separated(
|
||||||
|
shrinkWrap: false,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemCount: switchFunctions.length,
|
||||||
|
separatorBuilder: (context, index) =>
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.dividerColor,
|
||||||
|
),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final function = switchFunctions[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
function.icon,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
function.operationName,
|
||||||
|
style: context.textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
trailing: const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
size: 16,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
selectedFunction = function.code;
|
||||||
|
selectedValue = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (selectedFunction != null)
|
||||||
|
Expanded(
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final selectedFn = switchFunctions.firstWhere(
|
||||||
|
(f) => f.code == selectedFunction)
|
||||||
|
as BaseSwitchFunction;
|
||||||
|
final values =
|
||||||
|
selectedFn.getOperationalValues();
|
||||||
|
return ListView.builder(
|
||||||
|
shrinkWrap: false,
|
||||||
|
physics:
|
||||||
|
const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemCount: values.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final value = values[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
value.icon,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
value.description,
|
||||||
|
style: context.textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
trailing: Radio<dynamic>(
|
||||||
|
value: value.value,
|
||||||
|
groupValue: selectedValue,
|
||||||
|
onChanged: (newValue) {
|
||||||
|
setState(() {
|
||||||
|
selectedValue = newValue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 50,
|
||||||
|
width: selectedFunction != null ? 299 : 179,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
right:
|
||||||
|
BorderSide(color: ColorsManager.greyColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Cancel',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(color: ColorsManager.greyColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (selectedFunction != null &&
|
||||||
|
selectedValue != null) {
|
||||||
|
Navigator.pop(context, {
|
||||||
|
'function': selectedFunction,
|
||||||
|
'value': selectedValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
height: 50,
|
||||||
|
width: selectedFunction != null ? 299 : 179,
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Confirm',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(
|
||||||
|
color:
|
||||||
|
ColorsManager.primaryColorWithOpacity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
209
lib/pages/routiens/helper/two_gang_switch_helper.dart
Normal file
209
lib/pages/routiens/helper/two_gang_switch_helper.dart
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/two_gang_switch/two_gang_switch.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
|
class TwoGangSwitchHelper {
|
||||||
|
static Future<Map<String, dynamic>?> showSwitchFunctionsDialog(
|
||||||
|
BuildContext context, List<DeviceFunction<dynamic>> functions) async {
|
||||||
|
List<DeviceFunction<dynamic>> switchFunctions = functions
|
||||||
|
.where((f) =>
|
||||||
|
f is TwoGangSwitch1Function ||
|
||||||
|
f is TwoGangSwitch2Function ||
|
||||||
|
f is TwoGangCountdown1Function ||
|
||||||
|
f is TwoGangCountdown2Function)
|
||||||
|
.toList();
|
||||||
|
String? selectedFunction;
|
||||||
|
dynamic selectedValue;
|
||||||
|
|
||||||
|
return showDialog<Map<String, dynamic>?>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (context, setState) {
|
||||||
|
return AlertDialog(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
content: Container(
|
||||||
|
width: selectedFunction != null ? 600 : 360,
|
||||||
|
height: 450,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.only(top: 20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'2 Gangs Light Switch Condition',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 15, horizontal: 50),
|
||||||
|
child: Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ListView.separated(
|
||||||
|
shrinkWrap: false,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemCount: switchFunctions.length,
|
||||||
|
separatorBuilder: (context, index) =>
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.dividerColor,
|
||||||
|
),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final function = switchFunctions[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
function.icon,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
function.operationName,
|
||||||
|
style: context.textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
trailing: const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
size: 16,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
selectedFunction = function.code;
|
||||||
|
selectedValue = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (selectedFunction != null)
|
||||||
|
Expanded(
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final selectedFn = switchFunctions.firstWhere(
|
||||||
|
(f) => f.code == selectedFunction)
|
||||||
|
as BaseSwitchFunction;
|
||||||
|
final values =
|
||||||
|
selectedFn.getOperationalValues();
|
||||||
|
return ListView.builder(
|
||||||
|
shrinkWrap: false,
|
||||||
|
physics:
|
||||||
|
const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemCount: values.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final value = values[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
value.icon,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
value.description,
|
||||||
|
style: context.textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
trailing: Radio<dynamic>(
|
||||||
|
value: value.value,
|
||||||
|
groupValue: selectedValue,
|
||||||
|
onChanged: (newValue) {
|
||||||
|
setState(() {
|
||||||
|
selectedValue = newValue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 50,
|
||||||
|
width: selectedFunction != null ? 299 : 179,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
right:
|
||||||
|
BorderSide(color: ColorsManager.greyColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Cancel',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(color: ColorsManager.greyColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (selectedFunction != null &&
|
||||||
|
selectedValue != null) {
|
||||||
|
Navigator.pop(context, {
|
||||||
|
'function': selectedFunction,
|
||||||
|
'value': selectedValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
height: 50,
|
||||||
|
width: selectedFunction != null ? 299 : 179,
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Confirm',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(
|
||||||
|
color:
|
||||||
|
ColorsManager.primaryColorWithOpacity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart';
|
||||||
|
|
||||||
|
abstract class BaseSwitchFunction extends DeviceFunction<bool> {
|
||||||
|
BaseSwitchFunction({
|
||||||
|
required super.deviceId,
|
||||||
|
required super.deviceName,
|
||||||
|
required super.code,
|
||||||
|
required super.operationName,
|
||||||
|
required super.icon,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue);
|
||||||
|
|
||||||
|
List<SwitchOperationalValue> getOperationalValues();
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
|
class OneGangSwitchFunction extends BaseSwitchFunction {
|
||||||
|
OneGangSwitchFunction({required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'switch_1',
|
||||||
|
operationName: 'Light Switch',
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
description: "ON",
|
||||||
|
value: true,
|
||||||
|
),
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPowerOFF,
|
||||||
|
description: "OFF",
|
||||||
|
value: false,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class OneGangCountdownFunction extends BaseSwitchFunction {
|
||||||
|
OneGangCountdownFunction({required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'countdown_1',
|
||||||
|
operationName: 'Light Countdown',
|
||||||
|
icon: Assets.assetsLightCountdown,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: '',
|
||||||
|
description: "sec",
|
||||||
|
value: 0.0,
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 43200,
|
||||||
|
stepValue: 1,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
class SwitchOperationalValue {
|
||||||
|
final String icon;
|
||||||
|
final String description;
|
||||||
|
final dynamic value;
|
||||||
|
final double? minValue;
|
||||||
|
final double? maxValue;
|
||||||
|
final double? stepValue;
|
||||||
|
|
||||||
|
SwitchOperationalValue({
|
||||||
|
required this.icon,
|
||||||
|
required this.value,
|
||||||
|
this.description = '',
|
||||||
|
this.minValue,
|
||||||
|
this.maxValue,
|
||||||
|
this.stepValue,
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
|
class ThreeGangSwitch1Function extends BaseSwitchFunction {
|
||||||
|
ThreeGangSwitch1Function({required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'switch_1',
|
||||||
|
operationName: 'Light 1 Switch',
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
description: "ON",
|
||||||
|
value: true,
|
||||||
|
),
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPowerOFF,
|
||||||
|
description: "OFF",
|
||||||
|
value: false,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThreeGangCountdown1Function extends BaseSwitchFunction {
|
||||||
|
ThreeGangCountdown1Function(
|
||||||
|
{required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'countdown_1',
|
||||||
|
operationName: 'Light 1 Countdown',
|
||||||
|
icon: Assets.assetsLightCountdown,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: '',
|
||||||
|
description: "sec",
|
||||||
|
value: 0.0,
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 43200,
|
||||||
|
stepValue: 1,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThreeGangSwitch2Function extends BaseSwitchFunction {
|
||||||
|
ThreeGangSwitch2Function({required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'switch_2',
|
||||||
|
operationName: 'Light 2 Switch',
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
description: "ON",
|
||||||
|
value: true,
|
||||||
|
),
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPowerOFF,
|
||||||
|
description: "OFF",
|
||||||
|
value: false,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThreeGangCountdown2Function extends BaseSwitchFunction {
|
||||||
|
ThreeGangCountdown2Function(
|
||||||
|
{required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'countdown_2',
|
||||||
|
operationName: 'Light 2 Countdown',
|
||||||
|
icon: Assets.assetsLightCountdown,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: '',
|
||||||
|
description: "sec",
|
||||||
|
value: 0.0,
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 43200,
|
||||||
|
stepValue: 1,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThreeGangSwitch3Function extends BaseSwitchFunction {
|
||||||
|
ThreeGangSwitch3Function({required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'switch_3',
|
||||||
|
operationName: 'Light 3 Switch',
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
description: "ON",
|
||||||
|
value: true,
|
||||||
|
),
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPowerOFF,
|
||||||
|
description: "OFF",
|
||||||
|
value: false,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThreeGangCountdown3Function extends BaseSwitchFunction {
|
||||||
|
ThreeGangCountdown3Function(
|
||||||
|
{required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'countdown_3',
|
||||||
|
operationName: 'Light 3 Countdown',
|
||||||
|
icon: Assets.assetsLightCountdown,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: '',
|
||||||
|
description: "sec",
|
||||||
|
value: 0.0,
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 43200,
|
||||||
|
stepValue: 1,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
|
class TwoGangSwitch1Function extends BaseSwitchFunction {
|
||||||
|
TwoGangSwitch1Function({required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'switch_1',
|
||||||
|
operationName: 'Light 1 Switch',
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
description: "ON",
|
||||||
|
value: true,
|
||||||
|
),
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPowerOFF,
|
||||||
|
description: "OFF",
|
||||||
|
value: false,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TwoGangSwitch2Function extends BaseSwitchFunction {
|
||||||
|
TwoGangSwitch2Function({required String deviceId, required String deviceName})
|
||||||
|
: super(
|
||||||
|
deviceId: deviceId,
|
||||||
|
deviceName: deviceName,
|
||||||
|
code: 'switch_2',
|
||||||
|
operationName: 'Light 2 Switch',
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPower,
|
||||||
|
description: "ON",
|
||||||
|
value: true,
|
||||||
|
),
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: Assets.assetsAcPowerOFF,
|
||||||
|
description: "OFF",
|
||||||
|
value: false,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TwoGangCountdown1Function extends BaseSwitchFunction {
|
||||||
|
TwoGangCountdown1Function(
|
||||||
|
{required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'countdown_1',
|
||||||
|
operationName: 'Light 1 Countdown',
|
||||||
|
icon: Assets.assetsLightCountdown,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: '',
|
||||||
|
description: "sec",
|
||||||
|
value: 0.0,
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 43200,
|
||||||
|
stepValue: 1,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TwoGangCountdown2Function extends BaseSwitchFunction {
|
||||||
|
TwoGangCountdown2Function(
|
||||||
|
{required super.deviceId, required super.deviceName})
|
||||||
|
: super(
|
||||||
|
code: 'countdown_2',
|
||||||
|
operationName: 'Light 2 Countdown',
|
||||||
|
icon: Assets.assetsLightCountdown,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool execute(bool currentStatus, dynamic newValue) {
|
||||||
|
return newValue as bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<SwitchOperationalValue> getOperationalValues() => [
|
||||||
|
SwitchOperationalValue(
|
||||||
|
icon: '',
|
||||||
|
description: "sec",
|
||||||
|
value: 0.0,
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 43200,
|
||||||
|
stepValue: 1,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
@ -11,6 +11,7 @@ class DraggableCard extends StatelessWidget {
|
|||||||
this.titleColor,
|
this.titleColor,
|
||||||
this.isDragged = false,
|
this.isDragged = false,
|
||||||
this.isDisabled = false,
|
this.isDisabled = false,
|
||||||
|
this.deviceData,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String imagePath;
|
final String imagePath;
|
||||||
@ -18,11 +19,17 @@ class DraggableCard extends StatelessWidget {
|
|||||||
final Color? titleColor;
|
final Color? titleColor;
|
||||||
final bool isDragged;
|
final bool isDragged;
|
||||||
final bool isDisabled;
|
final bool isDisabled;
|
||||||
|
final Map<String, dynamic>? deviceData;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Widget card = Draggable<Map<String, String>>(
|
Widget card = Draggable<Map<String, dynamic>>(
|
||||||
data: {'key': UniqueKey().toString(), 'imagePath': imagePath, 'title': title},
|
data: deviceData ??
|
||||||
|
{
|
||||||
|
'key': UniqueKey().toString(),
|
||||||
|
'imagePath': imagePath,
|
||||||
|
'title': title,
|
||||||
|
},
|
||||||
feedback: Transform.rotate(
|
feedback: Transform.rotate(
|
||||||
angle: -0.1,
|
angle: -0.1,
|
||||||
child: _buildCardContent(context),
|
child: _buildCardContent(context),
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
// lib/pages/routiens/widgets/if_container.dart
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/helper/dialog_helper/device_dialog_helper.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
|
||||||
|
|
||||||
class IfContainer extends StatelessWidget {
|
class IfContainer extends StatelessWidget {
|
||||||
const IfContainer({Key? key}) : super(key: key);
|
const IfContainer({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return DragTarget<Map<String, String>>(
|
return DragTarget<Map<String, dynamic>>(
|
||||||
builder: (context, candidateData, rejectedData) {
|
builder: (context, candidateData, rejectedData) {
|
||||||
return Container(
|
return Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@ -20,7 +19,9 @@ class IfContainer extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('IF', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
const Text('IF',
|
||||||
|
style:
|
||||||
|
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Wrap(
|
Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
@ -37,8 +38,16 @@ class IfContainer extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onAccept: (data) {
|
onWillAccept: (data) => data != null,
|
||||||
context.read<RoutineBloc>().add(AddToIfContainer(data));
|
onAccept: (data) async {
|
||||||
|
final result =
|
||||||
|
await DeviceDialogHelper.showDeviceDialog(context, data);
|
||||||
|
if (result != null) {
|
||||||
|
context.read<RoutineBloc>().add(AddToIfContainer(result));
|
||||||
|
} else if (!['AC', '1G', '2G', '3G']
|
||||||
|
.contains(data['productType'])) {
|
||||||
|
context.read<RoutineBloc>().add(AddToIfContainer(data));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -29,11 +29,18 @@ class RoutineDevices extends StatelessWidget {
|
|||||||
spacing: 10,
|
spacing: 10,
|
||||||
runSpacing: 10,
|
runSpacing: 10,
|
||||||
children: deviceList.asMap().entries.map((entry) {
|
children: deviceList.asMap().entries.map((entry) {
|
||||||
final index = entry.key;
|
|
||||||
final device = entry.value;
|
final device = entry.value;
|
||||||
return DraggableCard(
|
return DraggableCard(
|
||||||
imagePath: device.getDefaultIcon(device.productType),
|
imagePath: device.getDefaultIcon(device.productType),
|
||||||
title: device.name ?? '',
|
title: device.name ?? '',
|
||||||
|
deviceData: {
|
||||||
|
'key': UniqueKey().toString(),
|
||||||
|
'imagePath': device.getDefaultIcon(device.productType),
|
||||||
|
'title': device.name ?? '',
|
||||||
|
'deviceId': device.uuid,
|
||||||
|
'productType': device.productType,
|
||||||
|
'functions': device.functions,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
);
|
);
|
||||||
|
@ -14,10 +14,10 @@ class ScenesAndAutomations extends StatelessWidget {
|
|||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => RoutineBloc()
|
create: (context) => RoutineBloc()
|
||||||
..add(
|
..add(
|
||||||
LoadScenes(spaceId),
|
const LoadScenes(spaceId),
|
||||||
)
|
)
|
||||||
..add(
|
..add(
|
||||||
LoadAutomation(spaceId),
|
const LoadAutomation(spaceId),
|
||||||
),
|
),
|
||||||
child: BlocBuilder<RoutineBloc, RoutineState>(
|
child: BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -27,11 +27,10 @@ class ScenesAndAutomations extends StatelessWidget {
|
|||||||
spacing: 10,
|
spacing: 10,
|
||||||
runSpacing: 10,
|
runSpacing: 10,
|
||||||
children: scenes.asMap().entries.map((entry) {
|
children: scenes.asMap().entries.map((entry) {
|
||||||
final index = entry.key;
|
|
||||||
final scene = entry.value;
|
final scene = entry.value;
|
||||||
return DraggableCard(
|
return DraggableCard(
|
||||||
imagePath: Assets.logo,
|
imagePath: Assets.logo,
|
||||||
title: scene.name ?? '',
|
title: scene.name,
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
);
|
);
|
||||||
|
@ -3,16 +3,17 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/helper/dialog_helper/device_dialog_helper.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
|
||||||
|
|
||||||
class ThenContainer extends StatelessWidget {
|
class ThenContainer extends StatelessWidget {
|
||||||
const ThenContainer({Key? key}) : super(key: key);
|
const ThenContainer({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return DragTarget<Map<String, String>>(
|
return DragTarget<Map<String, dynamic>>(
|
||||||
builder: (context, candidateData, rejectedData) {
|
builder: (context, candidateData, rejectedData) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
@ -20,7 +21,9 @@ class ThenContainer extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('THEN', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
const Text('THEN',
|
||||||
|
style:
|
||||||
|
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Wrap(
|
Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
@ -37,8 +40,16 @@ class ThenContainer extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onAccept: (data) {
|
onWillAccept: (data) => data != null,
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer(data));
|
onAccept: (data) async {
|
||||||
|
final result =
|
||||||
|
await DeviceDialogHelper.showDeviceDialog(context, data);
|
||||||
|
if (result != null) {
|
||||||
|
context.read<RoutineBloc>().add(AddToThenContainer(result));
|
||||||
|
} else if (!['AC', '1G', '2G', '3G']
|
||||||
|
.contains(data['productType'])) {
|
||||||
|
context.read<RoutineBloc>().add(AddToThenContainer(data));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
95
macos/DerivedData/Runner/Logs/Build/.dat.nosync1585.W9c579
Normal file
95
macos/DerivedData/Runner/Logs/Build/.dat.nosync1585.W9c579
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>logFormatVersion</key>
|
||||||
|
<integer>11</integer>
|
||||||
|
<key>logs</key>
|
||||||
|
<dict>
|
||||||
|
<key>DEC061F9-9521-4D0C-959C-43A07F62CC12</key>
|
||||||
|
<dict>
|
||||||
|
<key>className</key>
|
||||||
|
<string>IDECommandLineBuildLog</string>
|
||||||
|
<key>documentTypeString</key>
|
||||||
|
<string><nil></string>
|
||||||
|
<key>domainType</key>
|
||||||
|
<string>Xcode.IDEActivityLogDomainType.BuildLog</string>
|
||||||
|
<key>fileName</key>
|
||||||
|
<string>DEC061F9-9521-4D0C-959C-43A07F62CC12.xcactivitylog</string>
|
||||||
|
<key>hasPrimaryLog</key>
|
||||||
|
<true/>
|
||||||
|
<key>primaryObservable</key>
|
||||||
|
<dict>
|
||||||
|
<key>highLevelStatus</key>
|
||||||
|
<string>S</string>
|
||||||
|
<key>totalNumberOfAnalyzerIssues</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>totalNumberOfErrors</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>totalNumberOfTestFailures</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>totalNumberOfWarnings</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<key>schemeIdentifier-containerName</key>
|
||||||
|
<string>Runner project</string>
|
||||||
|
<key>schemeIdentifier-schemeName</key>
|
||||||
|
<string>Flutter Assemble</string>
|
||||||
|
<key>schemeIdentifier-sharedScheme</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>signature</key>
|
||||||
|
<string>Cleaning workspace Runner with scheme Flutter Assemble</string>
|
||||||
|
<key>timeStartedRecording</key>
|
||||||
|
<real>752000674.27645695</real>
|
||||||
|
<key>timeStoppedRecording</key>
|
||||||
|
<real>752000674.42918503</real>
|
||||||
|
<key>title</key>
|
||||||
|
<string>Cleaning workspace Runner with scheme Flutter Assemble</string>
|
||||||
|
<key>uniqueIdentifier</key>
|
||||||
|
<string>DEC061F9-9521-4D0C-959C-43A07F62CC12</string>
|
||||||
|
</dict>
|
||||||
|
<key>FB42CDDD-C79D-4D4B-891A-12C476DFCB10</key>
|
||||||
|
<dict>
|
||||||
|
<key>className</key>
|
||||||
|
<string>IDECommandLineBuildLog</string>
|
||||||
|
<key>documentTypeString</key>
|
||||||
|
<string><nil></string>
|
||||||
|
<key>domainType</key>
|
||||||
|
<string>Xcode.IDEActivityLogDomainType.BuildLog</string>
|
||||||
|
<key>fileName</key>
|
||||||
|
<string>FB42CDDD-C79D-4D4B-891A-12C476DFCB10.xcactivitylog</string>
|
||||||
|
<key>hasPrimaryLog</key>
|
||||||
|
<true/>
|
||||||
|
<key>primaryObservable</key>
|
||||||
|
<dict>
|
||||||
|
<key>highLevelStatus</key>
|
||||||
|
<string>S</string>
|
||||||
|
<key>totalNumberOfAnalyzerIssues</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>totalNumberOfErrors</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>totalNumberOfTestFailures</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>totalNumberOfWarnings</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<key>schemeIdentifier-containerName</key>
|
||||||
|
<string>Runner project</string>
|
||||||
|
<key>schemeIdentifier-schemeName</key>
|
||||||
|
<string>Runner</string>
|
||||||
|
<key>schemeIdentifier-sharedScheme</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>signature</key>
|
||||||
|
<string>Cleaning workspace Runner with scheme Runner</string>
|
||||||
|
<key>timeStartedRecording</key>
|
||||||
|
<real>752000674.90370798</real>
|
||||||
|
<key>timeStoppedRecording</key>
|
||||||
|
<real>752000675.05962098</real>
|
||||||
|
<key>title</key>
|
||||||
|
<string>Cleaning workspace Runner with scheme Runner</string>
|
||||||
|
<key>uniqueIdentifier</key>
|
||||||
|
<string>FB42CDDD-C79D-4D4B-891A-12C476DFCB10</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
Binary file not shown.
53
macos/DerivedData/Runner/Logs/Build/LogStoreManifest.plist
Normal file
53
macos/DerivedData/Runner/Logs/Build/LogStoreManifest.plist
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>logFormatVersion</key>
|
||||||
|
<integer>11</integer>
|
||||||
|
<key>logs</key>
|
||||||
|
<dict>
|
||||||
|
<key>DEC061F9-9521-4D0C-959C-43A07F62CC12</key>
|
||||||
|
<dict>
|
||||||
|
<key>className</key>
|
||||||
|
<string>IDECommandLineBuildLog</string>
|
||||||
|
<key>documentTypeString</key>
|
||||||
|
<string><nil></string>
|
||||||
|
<key>domainType</key>
|
||||||
|
<string>Xcode.IDEActivityLogDomainType.BuildLog</string>
|
||||||
|
<key>fileName</key>
|
||||||
|
<string>DEC061F9-9521-4D0C-959C-43A07F62CC12.xcactivitylog</string>
|
||||||
|
<key>hasPrimaryLog</key>
|
||||||
|
<true/>
|
||||||
|
<key>primaryObservable</key>
|
||||||
|
<dict>
|
||||||
|
<key>highLevelStatus</key>
|
||||||
|
<string>S</string>
|
||||||
|
<key>totalNumberOfAnalyzerIssues</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>totalNumberOfErrors</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>totalNumberOfTestFailures</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>totalNumberOfWarnings</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<key>schemeIdentifier-containerName</key>
|
||||||
|
<string>Runner project</string>
|
||||||
|
<key>schemeIdentifier-schemeName</key>
|
||||||
|
<string>Flutter Assemble</string>
|
||||||
|
<key>schemeIdentifier-sharedScheme</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>signature</key>
|
||||||
|
<string>Cleaning workspace Runner with scheme Flutter Assemble</string>
|
||||||
|
<key>timeStartedRecording</key>
|
||||||
|
<real>752000674.27645695</real>
|
||||||
|
<key>timeStoppedRecording</key>
|
||||||
|
<real>752000674.42918503</real>
|
||||||
|
<key>title</key>
|
||||||
|
<string>Cleaning workspace Runner with scheme Flutter Assemble</string>
|
||||||
|
<key>uniqueIdentifier</key>
|
||||||
|
<string>DEC061F9-9521-4D0C-959C-43A07F62CC12</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
10
macos/DerivedData/Runner/Logs/Launch/LogStoreManifest.plist
Normal file
10
macos/DerivedData/Runner/Logs/Launch/LogStoreManifest.plist
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>logFormatVersion</key>
|
||||||
|
<integer>11</integer>
|
||||||
|
<key>logs</key>
|
||||||
|
<dict/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>logFormatVersion</key>
|
||||||
|
<integer>11</integer>
|
||||||
|
<key>logs</key>
|
||||||
|
<dict/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
10
macos/DerivedData/Runner/Logs/Package/LogStoreManifest.plist
Normal file
10
macos/DerivedData/Runner/Logs/Package/LogStoreManifest.plist
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>logFormatVersion</key>
|
||||||
|
<integer>11</integer>
|
||||||
|
<key>logs</key>
|
||||||
|
<dict/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
10
macos/DerivedData/Runner/Logs/Test/LogStoreManifest.plist
Normal file
10
macos/DerivedData/Runner/Logs/Test/LogStoreManifest.plist
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>logFormatVersion</key>
|
||||||
|
<integer>11</integer>
|
||||||
|
<key>logs</key>
|
||||||
|
<dict/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
10
macos/DerivedData/Runner/info.plist
Normal file
10
macos/DerivedData/Runner/info.plist
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>LastAccessedDate</key>
|
||||||
|
<date>2024-10-30T17:04:35Z</date>
|
||||||
|
<key>WorkspacePath</key>
|
||||||
|
<string>/Users/akmz/Developer/web/syncrow-web/web/macos/Runner.xcworkspace</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -76,6 +76,7 @@ flutter:
|
|||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
assets:
|
assets:
|
||||||
- assets/icons/automation_functions/
|
- assets/icons/automation_functions/
|
||||||
|
- assets/icons/functions_icons/
|
||||||
- assets/icons/routine/
|
- assets/icons/routine/
|
||||||
- assets/icons/
|
- assets/icons/
|
||||||
- assets/images/
|
- assets/images/
|
||||||
|
Reference in New Issue
Block a user