Compare commits

..

6 Commits

15 changed files with 245 additions and 224 deletions

View File

@ -1,6 +1,4 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
@ -31,7 +29,7 @@ class SixSceneScreen extends StatelessWidget {
..add(const SexSceneSwitchInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final _bloc = BlocProvider.of<SixSceneBloc>(context);
final bloc = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
scene_1: '',
scene_2: '',
@ -48,7 +46,7 @@ class SixSceneScreen extends StatelessWidget {
model = state.device;
}
return DefaultScaffold(
title: _bloc.deviceInfo.name,
title: device?.name ?? '6 Scene Switch',
actions: [
InkWell(
onTap: () async {
@ -58,9 +56,9 @@ class SixSceneScreen extends StatelessWidget {
),
);
if (val == null) {
_bloc.add(const SixSceneInitialInfo());
_bloc.add(const SixSceneInitial());
_bloc.add(const SexSceneSwitchInitial());
bloc.add(const SixSceneInitialInfo());
bloc.add(const SixSceneInitial());
bloc.add(const SexSceneSwitchInitial());
}
},
child: SvgPicture.asset(Assets.assetsIconsSettings),
@ -77,7 +75,7 @@ class SixSceneScreen extends StatelessWidget {
)
: RefreshIndicator(
onRefresh: () async {
_bloc.add(const SixSceneInitial());
bloc.add(const SixSceneInitial());
},
child: ListView(
children: [
@ -92,22 +90,22 @@ class SixSceneScreen extends StatelessWidget {
switch4Title: model.scene_4,
switch5Title: model.scene_5,
switch6Title: model.scene_6,
switch1Down: _bloc.deviceStatus.switch_backlight
switch1Down: bloc.deviceStatus.switch_backlight
? Assets.switchOn
: Assets.switchOff,
switch1Up: _bloc.deviceStatus.switch_backlight
switch1Up: bloc.deviceStatus.switch_backlight
? Assets.switchOn
: Assets.switchOff,
switch2Down: _bloc.deviceStatus.switch_backlight
switch2Down: bloc.deviceStatus.switch_backlight
? Assets.switchOn
: Assets.switchOff,
switch2Up: _bloc.deviceStatus.switch_backlight
switch2Up: bloc.deviceStatus.switch_backlight
? Assets.switchOn
: Assets.switchOff,
switch3Up: _bloc.deviceStatus.switch_backlight
switch3Up: bloc.deviceStatus.switch_backlight
? Assets.switchOn
: Assets.switchOff,
switch3Down: _bloc.deviceStatus.switch_backlight
switch3Down: bloc.deviceStatus.switch_backlight
? Assets.switchOn
: Assets.switchOff,
onSwitch3DownTap: () {
@ -135,7 +133,7 @@ class SixSceneScreen extends StatelessWidget {
Expanded(
child: DefaultContainer(
onTap: () {
_bloc.add(ChangeSwitchStatusEvent());
bloc.add(ChangeSwitchStatusEvent());
},
child: Column(
crossAxisAlignment:
@ -197,9 +195,9 @@ class SixSceneScreen extends StatelessWidget {
);
if (value == true) {
Future.delayed(
const Duration(
milliseconds: 200), () {
_bloc.add(
const Duration(milliseconds: 200),
() {
bloc.add(
const SexSceneSwitchInitial());
});
}

View File

@ -22,14 +22,15 @@ class DoorSensorScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Door Sensor',
title: device?.name,
child: BlocProvider(
create: (context) =>
DoorSensorBloc(DSId: device?.uuid ?? '')..add(const DoorSensorInitial()),
child: BlocBuilder<DoorSensorBloc, DoorSensorState>(
builder: (context, state) {
final doorSensorBloc = BlocProvider.of<DoorSensorBloc>(context);
DoorSensorModel model = DoorSensorModel(batteryPercentage: 0, doorContactState: false);
DoorSensorModel model =
DoorSensorModel(batteryPercentage: 0, doorContactState: false);
if (state is LoadingNewSate) {
model = state.doorSensor;
} else if (state is UpdateState) {
@ -37,8 +38,8 @@ class DoorSensorScreen extends StatelessWidget {
}
return state is DoorSensorLoadingState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
child: DefaultContainer(
width: 50, height: 50, child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
@ -56,7 +57,8 @@ class DoorSensorScreen extends StatelessWidget {
Expanded(
flex: 4,
child: InkWell(
overlayColor: WidgetStateProperty.all(Colors.transparent),
overlayColor:
WidgetStateProperty.all(Colors.transparent),
onTap: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
@ -107,17 +109,21 @@ class DoorSensorScreen extends StatelessWidget {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
DoorRecordsScreen(DSId: device!.uuid!)),
DoorRecordsScreen(
DSId: device!.uuid!)),
);
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
ConstrainedBox(
constraints:
const BoxConstraints(maxHeight: 46, maxWidth: 50),
child: SvgPicture.asset(Assets.doorRecordsIcon),
constraints: const BoxConstraints(
maxHeight: 46, maxWidth: 50),
child: SvgPicture.asset(
Assets.doorRecordsIcon),
),
const SizedBox(
height: 15,
@ -143,18 +149,21 @@ class DoorSensorScreen extends StatelessWidget {
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => NotificationSettingsPage()),
builder: (context) =>
NotificationSettingsPage()),
);
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
ConstrainedBox(
constraints:
const BoxConstraints(maxHeight: 46, maxWidth: 50),
child:
SvgPicture.asset(Assets.doorNotificationSetting),
constraints: const BoxConstraints(
maxHeight: 46, maxWidth: 50),
child: SvgPicture.asset(
Assets.doorNotificationSetting),
),
const SizedBox(
height: 15,

View File

@ -47,7 +47,7 @@ class FourSceneScreen extends StatelessWidget {
}
return DefaultScaffold(
title: _bloc.deviceInfo.name,
title: device?.name ?? '4 Scene',
actions: [
InkWell(
onTap: () async {
@ -165,7 +165,7 @@ class FourSceneScreen extends StatelessWidget {
Navigator.of(context).pop();
},
confirmTab:
(switchSelected) async {
(switchSelected) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>

View File

@ -21,7 +21,8 @@ class GateWayView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => GatewayBloc()..add(GatewayInitial(gatewayId: gatewayObj.uuid ?? '')),
create: (context) =>
GatewayBloc()..add(GatewayInitial(gatewayId: gatewayObj.uuid ?? '')),
child: BlocBuilder<GatewayBloc, GatewayState>(builder: (context, state) {
List<DeviceModel> devicesList = [];
if (state is UpdateGatewayState) {
@ -37,7 +38,7 @@ class GateWayView extends StatelessWidget {
extendBodyBehindAppBar: true,
extendBody: true,
appBar: DeviceAppbar(
deviceName: 'Gateway',
deviceName: gatewayObj.name ?? 'Gateway',
deviceUuid: gatewayObj.uuid!,
),
body: Container(
@ -60,7 +61,7 @@ class GateWayView extends StatelessWidget {
},
child: ListView(
children: [
Container(
SizedBox(
height: MediaQuery.of(context).size.height,
child: SafeArea(
child: Column(
@ -90,7 +91,8 @@ class GateWayView extends StatelessWidget {
),
]),
),
if (devicesList.isEmpty && state is UpdateGatewayState)
if (devicesList.isEmpty &&
state is UpdateGatewayState)
Container(
width: MediaQuery.sizeOf(context).width,
alignment: AlignmentDirectional.center,
@ -115,7 +117,8 @@ class GateWayView extends StatelessWidget {
margin: const EdgeInsets.only(top: 20),
height: 50,
width: 50,
child: const RefreshProgressIndicator()),
child:
const RefreshProgressIndicator()),
)
: Expanded(
child: GridView.builder(
@ -130,7 +133,8 @@ class GateWayView extends StatelessWidget {
shrinkWrap: true,
itemCount: devicesList.length,
itemBuilder: (context, index) {
return RoomPageSwitch(device: devicesList[index]);
return RoomPageSwitch(
device: devicesList[index]);
},
),
)

View File

@ -51,7 +51,7 @@ class _PowerClampPageState extends State<PowerClampPage> {
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Power Clamp',
title: widget.device?.name ?? 'Power Clamp',
child: BlocProvider(
create: (context) => PowerClampBloc(PCId: widget.device?.uuid ?? '')
..add(const PowerClampInitial()),
@ -153,41 +153,6 @@ class _PowerClampPageState extends State<PowerClampPage> {
];
}
List<Widget> _buildPowerClampCards(PowerClampModel model,
List<EnergyData> chartData, PowerClampBloc blocProvider) {
return [
_buildPowerClampCard(
phaseType: '',
title: 'Total Energy \nConsumption',
phase: model.status.general,
isGeneral: true,
chartData: chartData,
blocProvider: blocProvider,
),
_buildPowerClampCard(
phaseType: 'Phase A consumption',
title: 'Phase A Energy \nConsumption',
phase: model.status.phaseA,
chartData: chartData,
blocProvider: blocProvider,
),
_buildPowerClampCard(
phaseType: 'Phase B consumption',
title: 'Phase B Energy \nConsumption',
phase: model.status.phaseB,
chartData: chartData,
blocProvider: blocProvider,
),
_buildPowerClampCard(
phaseType: 'Phase C consumption',
title: 'Phase C Energy \nConsumption',
phase: model.status.phaseC,
chartData: chartData,
blocProvider: blocProvider,
),
];
}
Widget _buildPowerClampCard({
required String title,
required String phaseType,
@ -209,10 +174,8 @@ class _PowerClampPageState extends State<PowerClampPage> {
blocProvider.add(SelectDateEvent(context: context));
},
totalActiveGeneral: isGeneral ? _getValueOrNA(phase.dataPoints, 2) : null,
totalCurrentGeneral:
isGeneral ? _getValueOrNA(phase.dataPoints, 1) : null,
totalFrequencyGeneral:
isGeneral ? _getValueOrNA(phase.dataPoints, 4) : null,
totalCurrentGeneral: isGeneral ? _getValueOrNA(phase.dataPoints, 1) : null,
totalFrequencyGeneral: isGeneral ? _getValueOrNA(phase.dataPoints, 4) : null,
totalFactor: !isGeneral ? _getValueOrNA(phase.dataPoints, 3) : null,
totalActive: !isGeneral ? _getValueOrNA(phase.dataPoints, 2) : null,
totalCurrent: !isGeneral ? _getValueOrNA(phase.dataPoints, 1) : null,
@ -223,9 +186,7 @@ class _PowerClampPageState extends State<PowerClampPage> {
}
String _getValueOrNA(List<DataPoint> dataPoints, int index) {
return dataPoints.length > index
? dataPoints[index].value.toString()
: 'N/A';
return dataPoints.length > index ? dataPoints[index].value.toString() : 'N/A';
}
Widget _buildPageIndicator() {
@ -240,8 +201,7 @@ class _PowerClampPageState extends State<PowerClampPage> {
height: 10.0,
width: _currentPage == index ? 10.0 : 10.0,
decoration: BoxDecoration(
color:
_currentPage == index ? Colors.grey : ColorsManager.greyColor,
color: _currentPage == index ? Colors.grey : ColorsManager.greyColor,
borderRadius: BorderRadius.circular(5.0),
),
);

View File

@ -10,6 +10,7 @@ import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/six_scene_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/ceiling_sensor_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/door_sensor/door_sensor_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_screen.dart';
@ -19,14 +20,13 @@ import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_Interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_clamp_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/sos/sos_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_Interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_Interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/ceiling_sensor_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/water_heater/water_heater_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/water_leak/water_leak_screen.dart';
import 'package:syncrow_app/features/shared_widgets/custom_switch.dart';
@ -73,48 +73,31 @@ class RoomPageSwitch extends StatelessWidget {
? CustomSwitch(
device: device,
)
: const SizedBox(),
: const SizedBox.shrink(),
],
),
LayoutBuilder(
builder: (context, constraints) {
final text = device.name ?? "";
final textPainter = TextPainter(
text: TextSpan(
text: text,
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.grey,
),
),
maxLines: 1,
textDirection: TextDirection.ltr,
);
textPainter.layout(maxWidth: constraints.maxWidth);
final exceeded = textPainter.didExceedMaxLines;
return Text(
exceeded ? '${text.substring(0, 10)}...' : text,
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.grey,
),
overflow: TextOverflow.clip,
maxLines: 1,
);
},
),
Text(
device.subspace!.subspaceName ?? '',
overflow: TextOverflow.ellipsis,
style: context.bodySmall.copyWith(
fontWeight: FontWeight.w400,
fontSize: 10,
device.name ?? '',
textScaler: TextScaler.linear(1),
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
color: Colors.grey,
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
FittedBox(
fit: BoxFit.scaleDown,
child: Text(
device.subspace!.subspaceName ?? '',
overflow: TextOverflow.ellipsis,
textScaler: TextScaler.linear(1),
style: context.bodySmall.copyWith(
fontWeight: FontWeight.w400,
fontSize: 9,
color: Colors.grey,
),
),
),
],
@ -132,7 +115,6 @@ Future<void> showDeviceInterface(
required BuildContext context,
required isAllDevices,
List<DeviceModel>? allDevices}) async {
final devicesCubit = context.read<DevicesCubit>();
switch (device.productType) {

View File

@ -5,7 +5,6 @@ import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_event.dart';
import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/sos_model.dart';
import 'package:syncrow_app/features/devices/view/device_settings/settings_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/sos/sos_alarm_management_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/sos/sos_records_screen.dart';
@ -29,17 +28,8 @@ class SosScreen extends StatelessWidget {
child: BlocBuilder<SosBloc, SosState>(
builder: (context, state) {
final sensor = BlocProvider.of<SosBloc>(context);
SosModel model = SosModel(
batteryPercentage: 0,
sosContactState: '',
);
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return DefaultScaffold(
title: sensor.deviceInfo.name,
title: device?.name,
actions: [
InkWell(
onTap: () async {
@ -82,38 +72,33 @@ class SosScreen extends StatelessWidget {
Expanded(
flex: 4,
child: InkWell(
overlayColor: MaterialStateProperty.all(
Colors.transparent),
overlayColor:
WidgetStateProperty.all(Colors.transparent),
onTap: () {
// Add functionality for the main SOS button here
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(890),
borderRadius: BorderRadius.circular(890),
boxShadow: [
BoxShadow(
color:
Colors.white.withOpacity(0.1),
color: Colors.white.withOpacity(0.1),
blurRadius: 24,
offset: const Offset(-5, -5),
blurStyle: BlurStyle.outer,
),
BoxShadow(
color: Colors.black
.withOpacity(0.11),
color: Colors.black.withOpacity(0.11),
blurRadius: 25,
offset: const Offset(5, 5),
blurStyle: BlurStyle.outer,
),
BoxShadow(
color: Colors.black
.withOpacity(0.13),
color: Colors.black.withOpacity(0.13),
blurRadius: 30,
offset: const Offset(5, 5),
blurStyle: BlurStyle.inner,
@ -140,9 +125,8 @@ class SosScreen extends StatelessWidget {
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
SosRecordsScreen(
sosId: device!.uuid!),
builder: (context) => SosRecordsScreen(
sosId: device!.uuid!),
),
);
},
@ -197,8 +181,8 @@ class SosScreen extends StatelessWidget {
maxHeight: 46,
maxWidth: 50,
),
child: SvgPicture.asset(Assets
.doorNotificationSetting),
child: SvgPicture.asset(
Assets.doorNotificationSetting),
),
const SizedBox(height: 15),
const Flexible(

View File

@ -9,7 +9,10 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class GangSwitch extends StatelessWidget {
const GangSwitch(
{super.key, required this.threeGangSwitch, required this.value, required this.action});
{super.key,
required this.threeGangSwitch,
required this.value,
required this.action});
final DeviceModel threeGangSwitch;
final bool value;

View File

@ -21,7 +21,7 @@ class WaterHeaterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Water heater',
title: device?.name?? 'Water heater',
child: BlocProvider(
create: (context) => WaterHeaterBloc(switchCode: 'switch_1', whId: device?.uuid ?? '')
..add(const WaterHeaterInitial()),

View File

@ -22,7 +22,7 @@ class WaterLeakScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Water Leak Sensor',
title: device?.name ?? 'Water Leak',
child: BlocProvider(
create: (context) => WaterLeakBloc(WLId: device?.uuid ?? '')
..add(const WaterLeakInitial()),

View File

@ -259,6 +259,7 @@ mixin SceneOperationsDataHelper {
for (var condition in conditions) {
// Create a dummy Action from Condition to reuse _mapExecutorPropertyToSceneFunction
Action dummyAction = Action(
deviceName: condition.deviceName,
productType: condition.productType,
actionExecutor: 'device_report',
entityId: condition.entityId,
@ -369,7 +370,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Sensitivity',
isAutomation
@ -386,7 +387,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Set Door lock Normal Open',
OperationDialogType.onOff,
@ -440,7 +441,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Fingerprint Unlock',
OperationDialogType.integerSteps,
@ -455,7 +456,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Password Unlock',
OperationDialogType.integerSteps,
@ -470,7 +471,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Card Unlock',
OperationDialogType.integerSteps,
@ -485,7 +486,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Lock Alarm',
OperationDialogType.listOfOptions,
@ -500,7 +501,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Remote Unlock Request',
OperationDialogType.integerSteps,
@ -515,7 +516,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Residual Electricity',
OperationDialogType.integerSteps,
@ -530,7 +531,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Double Lock',
OperationDialogType.onOff,
@ -545,7 +546,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Remote Unlock Via App',
OperationDialogType.integerSteps,
@ -560,7 +561,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Hijack Alarm',
OperationDialogType.onOff,
@ -575,7 +576,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Doorbell',
OperationDialogType.onOff,
@ -590,7 +591,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Temporary Password Unlock',
OperationDialogType.integerSteps,
@ -605,7 +606,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Far Detection',
OperationDialogType.listOfOptions,
@ -620,7 +621,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Motion Detection Sensitivity',
OperationDialogType.listOfOptions,
@ -635,7 +636,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Motionless Detection Sensitivity',
OperationDialogType.listOfOptions,
@ -650,7 +651,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Indicator',
OperationDialogType.onOff,
@ -665,7 +666,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Nobody Time',
OperationDialogType.countdown,
@ -680,7 +681,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Presence State',
OperationDialogType.listOfOptions,
@ -695,7 +696,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Current Distance',
isAutomation
@ -712,7 +713,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Illuminance Value',
OperationDialogType.integerSteps,
@ -727,7 +728,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Self-Test Result',
OperationDialogType.listOfOptions,
@ -742,7 +743,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Power',
OperationDialogType.onOff,
@ -757,7 +758,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Set Temperature',
isAutomation
@ -776,7 +777,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Current Temperature',
OperationDialogType.integerSteps,
@ -791,7 +792,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Mode',
OperationDialogType.listOfOptions,
@ -806,7 +807,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Fan Speed',
OperationDialogType.listOfOptions,
@ -821,7 +822,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Child Lock',
OperationDialogType.onOff,
@ -838,7 +839,7 @@ mixin SceneOperationsDataHelper {
case "3G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 1 Switch',
OperationDialogType.onOff,
@ -850,7 +851,7 @@ mixin SceneOperationsDataHelper {
case "2G":
return _createSceneFunction(
action,
'2 Gang Button Switch L-L',
action.deviceName,
Assets.twoGang,
'Light 1 Switch',
OperationDialogType.onOff,
@ -862,7 +863,7 @@ mixin SceneOperationsDataHelper {
case "1G":
return _createSceneFunction(
action,
'1 Gang Button Switch L-L',
action.deviceName,
Assets.oneGang,
'Light 1 Switch',
OperationDialogType.onOff,
@ -892,7 +893,7 @@ mixin SceneOperationsDataHelper {
case "3G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 2 Switch',
OperationDialogType.onOff,
@ -904,7 +905,7 @@ mixin SceneOperationsDataHelper {
case "2G":
return _createSceneFunction(
action,
'2 Gang Button Switch L-L',
action.deviceName,
Assets.twoGang,
'Light 2 Switch',
OperationDialogType.onOff,
@ -916,7 +917,7 @@ mixin SceneOperationsDataHelper {
default:
return _createSceneFunction(
action,
'1 Gang Button Switch L-L',
action.deviceName,
Assets.oneGang,
'Light Switch',
OperationDialogType.onOff,
@ -932,7 +933,7 @@ mixin SceneOperationsDataHelper {
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 3 Switch',
OperationDialogType.onOff,
@ -949,7 +950,7 @@ mixin SceneOperationsDataHelper {
case "3G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 1 CountDown',
isAutomation
@ -965,7 +966,7 @@ mixin SceneOperationsDataHelper {
case "2G":
return _createSceneFunction(
action,
'2 Gang Button Switch L-L',
action.deviceName,
Assets.twoGang,
'Light 1 CountDown',
isAutomation
@ -981,7 +982,7 @@ mixin SceneOperationsDataHelper {
default:
return _createSceneFunction(
action,
'1 Gang Button Switch L-L',
action.deviceName,
Assets.oneGang,
'Light CountDown',
isAutomation
@ -1003,7 +1004,7 @@ mixin SceneOperationsDataHelper {
case "3G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 2 CountDown',
isAutomation
@ -1019,7 +1020,7 @@ mixin SceneOperationsDataHelper {
case "2G":
return _createSceneFunction(
action,
'2 Gang Button Switch L-L',
action.deviceName,
Assets.twoGang,
'Light 2 CountDown',
isAutomation
@ -1035,7 +1036,7 @@ mixin SceneOperationsDataHelper {
default:
return _createSceneFunction(
action,
'1 Gang Button Switch L-L',
action.deviceName,
Assets.oneGang,
'Light CountDown',
isAutomation
@ -1055,7 +1056,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 3 CountDown',
isAutomation
@ -1074,7 +1075,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Gateway',
action.deviceName,
Assets.assetsIconsGateway,
'Switch Alarm Sound',
OperationDialogType.onOff,
@ -1089,7 +1090,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Gateway',
action.deviceName,
Assets.assetsIconsGateway,
'Master State',
OperationDialogType.listOfOptions,
@ -1104,7 +1105,7 @@ mixin SceneOperationsDataHelper {
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Gateway',
action.deviceName,
Assets.assetsIconsGateway,
'Factory Reset',
OperationDialogType.onOff,
@ -1447,6 +1448,7 @@ mixin SceneOperationsDataHelper {
return [
_mapExecutorPropertyToSceneFunction(
Action(
deviceName: taskItem.deviceName,
productType: '',
entityId: deviceId,
executorProperty: ExecutorProperty(

View File

@ -76,6 +76,8 @@ class Action {
String? type;
final String productType;
final String deviceName;
Action({
required this.actionExecutor,
required this.entityId,
@ -83,6 +85,7 @@ class Action {
this.name,
this.type,
required this.productType,
required this.deviceName,
});
String toRawJson() => json.encode(toJson());
@ -95,6 +98,7 @@ class Action {
name: json['name'] as String?,
type: json['type'] as String?,
productType: json['productType'] as String,
deviceName: json['deviceName'] as String,
);
}
if (json["executorProperty"] == null) {
@ -106,6 +110,7 @@ class Action {
entityId: json["entityId"] as String,
executorProperty: ExecutorProperty.fromJson(json["executorProperty"]),
productType: json['productType'] as String,
deviceName: json['deviceName'] as String,
);
}
@ -147,6 +152,7 @@ class Condition {
final String entityType;
final Expr expr;
final String productType;
final String deviceName;
Condition({
required this.code,
@ -154,6 +160,7 @@ class Condition {
required this.entityType,
required this.expr,
required this.productType,
required this.deviceName,
});
factory Condition.fromRawJson(String str) =>
@ -167,6 +174,7 @@ class Condition {
entityType: json["entityType"],
expr: Expr.fromJson(json["expr"]),
productType: json['productType'] as String,
deviceName: json['deviceName'] as String,
);
Map<String, dynamic> toJson() => {

View File

@ -12,12 +12,10 @@ import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/light_divider.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigate_to_route.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class DeviceFunctionsView extends StatelessWidget
@ -69,14 +67,13 @@ class DeviceFunctionsView extends StatelessWidget
itemCount: functions.length,
padding: const EdgeInsets.only(top: 24.0),
itemBuilder: (context, index) {
final bool isFirstInPair = index % 2 == 0;
final bool isLastInPair =
index % 2 == 1 || index == functions.length - 1;
final bool isLastItem = index == functions.length - 1;
return Column(
mainAxisSize: MainAxisSize.min,
children: [
if (device.productType!.name.toString() == 'ThreeGang' ||
device.productType!.name.toString() == 'TwoGang') {
final bool isFirstInPair = index % 2 == 0;
final bool isLastInPair =
index % 2 == 1 || index == functions.length - 1;
final bool isLastItem = index == functions.length - 1;
return Column(mainAxisSize: MainAxisSize.min, children: [
if (isFirstInPair && index != 0) const SizedBox(height: 16),
DefaultContainer(
padding: EdgeInsets.only(
@ -124,9 +121,73 @@ class DeviceFunctionsView extends StatelessWidget
),
],
),
),
],
);
)
]);
} else {
return DefaultContainer(
padding: index == 0
? const EdgeInsets.only(top: 8)
: index == functions.length - 1
? const EdgeInsets.only(bottom: 8)
: EdgeInsets.zero,
margin: EdgeInsets.zero,
borderRadius: index == 0 && index == functions.length - 1
? const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
)
: index == 0
? const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
)
: index == functions.length - 1
? const BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
)
: BorderRadius.zero,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
BlocBuilder<CreateSceneBloc, CreateSceneState>(
builder: (context, state) {
return SceneListTile(
iconsSize: 22,
minLeadingWidth: 20,
assetPath: functions[index].icon,
titleString: functions[index].operationName,
trailingWidget: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.arrow_forward_ios_rounded,
color: ColorsManager.greyColor,
size: 16,
),
],
),
onPressed: () {
if (isAutomation) {
_showAutomationDialog(
context, functions[index], device);
} else {
_showTabToRunDialog(
context, functions[index], device);
}
},
);
}),
index != functions.length - 1
? SizedBox(
width: context.width * 0.8,
child: const LightDivider())
: const SizedBox(),
],
));
}
},
),
);

View File

@ -1,5 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
@ -7,6 +8,8 @@ import 'package:syncrow_app/features/devices/model/device_report_model.dart';
import 'package:syncrow_app/features/devices/model/function_model.dart';
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
import 'package:syncrow_app/services/api/http_service.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import '../../features/devices/model/create_temporary_password_model.dart';
class DevicesAPI {
@ -580,7 +583,7 @@ class DevicesAPI {
path: path,
showServerMessage: false,
expectedResponseModel: (json) {
final data = json['data'];
final data = json['data'] as List<dynamic>?;
if (data == null || data.isEmpty) {
return <DeviceModel>[];
@ -588,9 +591,14 @@ class DevicesAPI {
if (json == null || json.isEmpty || json == []) {
return <DeviceModel>[];
}
return data
.map<DeviceModel>((device) => DeviceModel.fromJson(device))
.toList();
final result = <DeviceModel>[];
for (final device in data) {
final mappedDevice = DeviceModel.fromJson(device);
if (mappedDevice.productType?.name != DeviceType.FlushMountedSensor.name) {
result.add(mappedDevice);
}
}
return result;
},
);

View File

@ -62,6 +62,7 @@ enum DeviceType {
SixScene,
SOS,
Other,
FlushMountedSensor,
}
enum FunctionType { Boolean, Enum, Integer, Raw, String }
@ -96,6 +97,7 @@ Map<String, DeviceType> devicesTypesMap = {
"4S": DeviceType.FourScene,
"6S": DeviceType.SixScene,
"SOS": DeviceType.SOS,
"NCPS": DeviceType.FlushMountedSensor,
};
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {