Compare commits

..

8 Commits

Author SHA1 Message Date
7a19291088 Refactor screen titles to use bloc device info 2025-05-19 11:04:59 +03:00
c76995fbb8 Merge pull request #103 from SyncrowIOT/SP-1586-FE-On-Device-settings-screen-after-editing
add PopScope to setting page
2025-05-15 14:23:50 +03:00
5d1b8e39b0 add PopScope to setting page 2025-05-15 12:35:47 +03:00
a04beb32f2 Merge pull request #102 from SyncrowIOT/Fix-Flush-Presence-Records
Refactor flush presence records widget to display the correct status
2025-05-14 11:16:45 +03:00
23c307338a Refactor flush presence records widget to display the correct status 2025-05-14 11:14:27 +03:00
4db16fd567 Merge pull request #101 from SyncrowIOT/change-New-PS-Functions-UI
Refactor operation dialog types and add counter steps
2025-05-13 15:58:28 +03:00
2c5ca67b10 Refactor operation dialog types and add counter steps 2025-05-13 14:46:27 +03:00
79c1205932 Merge pull request #100 from SyncrowIOT/fix-flush-bugs
fix flush bugs
2025-05-13 10:51:06 +03:00
11 changed files with 896 additions and 610 deletions

View File

@ -22,141 +22,155 @@ class SettingProfilePage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var spaces = HomeCubit.getInstance().spaces; var spaces = HomeCubit.getInstance().spaces;
return DefaultScaffold( return PopScope(
title: 'Device Settings', canPop: false,
leading: IconButton( onPopInvoked: (didPop) {
onPressed: () { if (didPop) {
Navigator.of(context).pop(true); return;
}, }
icon: const Icon(Icons.arrow_back_ios)), Navigator.of(context).pop(true);
child: BlocProvider( },
create: (context) => DeviceSettingBloc(deviceId: device?.uuid ?? '') child: DefaultScaffold(
..add(const DeviceSettingInitial()) title: 'Device Settings',
..add(const DeviceSettingInitialInfo()), leading: IconButton(
child: BlocBuilder<DeviceSettingBloc, DeviceSettingState>( onPressed: () {
builder: (context, state) { Navigator.of(context).pop(true);
final _bloc = BlocProvider.of<DeviceSettingBloc>(context); },
return state is DeviceSettingLoadingState icon: const Icon(Icons.arrow_back_ios)),
? const Center( child: BlocProvider(
child: DefaultContainer( create: (context) => DeviceSettingBloc(deviceId: device?.uuid ?? '')
width: 50, ..add(const DeviceSettingInitial())
height: 50, ..add(const DeviceSettingInitialInfo()),
child: CircularProgressIndicator()), child: BlocBuilder<DeviceSettingBloc, DeviceSettingState>(
) builder: (context, state) {
: RefreshIndicator( final _bloc = BlocProvider.of<DeviceSettingBloc>(context);
onRefresh: () async { return state is DeviceSettingLoadingState
_bloc.add(const DeviceSettingInitial()); ? const Center(
}, child: DefaultContainer(
child: ListView( width: 50,
children: [ height: 50,
buildDeviceAvatar(context, device!), child: CircularProgressIndicator()),
const SizedBox( )
height: 10, : RefreshIndicator(
), onRefresh: () async {
SizedBox( _bloc.add(const DeviceSettingInitial());
child: Row( },
mainAxisAlignment: MainAxisAlignment.center, child: ListView(
crossAxisAlignment: CrossAxisAlignment.center, children: [
children: [ buildDeviceAvatar(context, device!),
IntrinsicWidth( const SizedBox(
child: ConstrainedBox( height: 10,
constraints:
const BoxConstraints(maxWidth: 200),
child: TextFormField(
maxLength: 30,
style: const TextStyle(
color: Colors.black,
),
textAlign: TextAlign.center,
focusNode: _bloc.focusNode,
controller: _bloc.nameController,
enabled: _bloc.editName,
onEditingComplete: () {
_bloc.add(const SaveNameEvent());
},
decoration: const InputDecoration(
hintText: "Your Name",
border: InputBorder.none,
fillColor: Colors.white10,
counterText: '',
),
),
),
),
const SizedBox(width: 5),
InkWell(
onTap: () {
_bloc.add(const ChangeNameEvent(value: true));
},
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: SvgPicture.asset(
Assets.sosEditProfile,
color: Colors.grey,
fit: BoxFit.contain,
height: MediaQuery.of(context).size.height *
0.02,
),
),
),
],
), ),
), SizedBox(
const SizedBox(height: 20),
const BodyMedium(
text: 'Smart Device Information',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
const SizedBox(height: 7),
DefaultContainer(
padding: const EdgeInsets.all(20),
child: InkWell(
onTap: () async {
if (HomeCubit.visitorPasswordManagement) {
bool? val = await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => LocationSettingPage(
space: spaces!.first,
deviceId: device?.uuid ?? '',
)),
);
if (val != null && val == true) {
_bloc.add(const DeviceSettingInitialInfo());
}
}
},
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const SizedBox( IntrinsicWidth(
child: Text('Location'), child: ConstrainedBox(
), constraints:
Row( const BoxConstraints(maxWidth: 200),
children: [ child: TextFormField(
SizedBox( maxLength: 30,
child: BodyMedium( style: const TextStyle(
text: _bloc color: Colors.black,
.deviceInfo.subspace.subspaceName, ),
fontColor: ColorsManager.textGray, textAlign: TextAlign.center,
focusNode: _bloc.focusNode,
controller: _bloc.nameController,
enabled: _bloc.editName,
onEditingComplete: () {
_bloc.add(const SaveNameEvent());
},
decoration: const InputDecoration(
hintText: "Your Name",
border: InputBorder.none,
fillColor: Colors.white10,
counterText: '',
), ),
), ),
const Icon( ),
Icons.arrow_forward_ios, ),
size: 15, const SizedBox(width: 5),
color: ColorsManager.textGray, InkWell(
onTap: () {
_bloc.add(
const ChangeNameEvent(value: true));
},
child: Padding(
padding:
EdgeInsets.symmetric(horizontal: 10),
child: SvgPicture.asset(
Assets.sosEditProfile,
color: Colors.grey,
fit: BoxFit.contain,
height:
MediaQuery.of(context).size.height *
0.02,
), ),
], ),
) ),
], ],
), ),
), ),
) const SizedBox(height: 20),
], const BodyMedium(
), text: 'Smart Device Information',
); fontWeight: FontWeight.w700,
}, fontSize: 12,
fontColor: ColorsManager.grayColor,
),
const SizedBox(height: 7),
DefaultContainer(
padding: const EdgeInsets.all(20),
child: InkWell(
onTap: () async {
if (HomeCubit.visitorPasswordManagement) {
bool? val = await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
LocationSettingPage(
space: spaces!.first,
deviceId: device?.uuid ?? '',
)),
);
if (val != null && val == true) {
_bloc.add(const DeviceSettingInitialInfo());
}
}
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
const SizedBox(
child: Text('Location'),
),
Row(
children: [
SizedBox(
child: BodyMedium(
text: _bloc
.deviceInfo.subspace.subspaceName,
fontColor: ColorsManager.textGray,
),
),
const Icon(
Icons.arrow_forward_ios,
size: 15,
color: ColorsManager.textGray,
),
],
)
],
),
),
)
],
),
);
},
),
), ),
), ),
); );

View File

@ -28,406 +28,449 @@ class SettingsPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DefaultScaffold( return PopScope(
title: 'Device Settings', canPop: false,
child: BlocProvider( onPopInvoked: (didPop) {
create: (context) => DeviceSettingBloc(deviceId: device?.uuid ?? '') if (didPop) {
..add(const DeviceSettingInitial()) return;
..add(const DeviceSettingInitialInfo()), }
child: BlocBuilder<DeviceSettingBloc, DeviceSettingState>( Navigator.of(context).pop(true);
builder: (context, state) { },
final _bloc = BlocProvider.of<DeviceSettingBloc>(context); child: DefaultScaffold(
title: 'Device Settings',
child: BlocProvider(
create: (context) => DeviceSettingBloc(deviceId: device?.uuid ?? '')
..add(const DeviceSettingInitial())
..add(const DeviceSettingInitialInfo()),
child: BlocBuilder<DeviceSettingBloc, DeviceSettingState>(
builder: (context, state) {
final _bloc = BlocProvider.of<DeviceSettingBloc>(context);
return state is DeviceSettingLoadingState return state is DeviceSettingLoadingState
? const Center( ? const Center(
child: child: DefaultContainer(
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()), width: 50,
) height: 50,
: ListView( child: CircularProgressIndicator()),
children: [ )
Padding( : ListView(
padding: const EdgeInsets.symmetric( children: [
vertical: 10, Padding(
), padding: const EdgeInsets.symmetric(
child: InkWell( vertical: 10,
onTap: () async {
bool val = await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SettingProfilePage(
device: device,
),
),
);
if (val == true) {
_bloc.add(const DeviceSettingInitialInfo());
}
},
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 20),
DefaultContainer(
borderRadius: const BorderRadius.all(Radius.circular(30)),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Padding(
padding: const EdgeInsets.only(left: 90),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
child: Text(
_bloc.deviceInfo.name,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: ColorsManager.grayColor,
),
overflow: TextOverflow
.ellipsis, // Adds ellipsis (...) when the text overflows.
maxLines:
1, // Restricts the text to a single line.
)),
const SizedBox(
height: 5,
),
BodySmall(
text: _bloc.deviceInfo.subspace.subspaceName),
],
),
),
SvgPicture.asset(
Assets.editNameSetting,
fit: BoxFit.contain,
height: 30,
),
],
),
),
),
),
],
),
Positioned(
top: 0,
left: 20,
child: CircleAvatar(
radius: 43,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 40,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 40,
backgroundColor: ColorsManager.backgroundColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
device!.type == 'NCPS'
? SizedBox(
height: 80,
width: 50,
child: SvgPicture.asset(
Assets.flushIcon,
fit: BoxFit.contain,
),
):
device!.type == "SOS"
? ClipOval(
child: SvgPicture.asset(
Assets.sosHomeIcon,
fit: BoxFit.contain,
height: 70,
),
)
: Padding(
padding: device!.type == "4S"
? const EdgeInsets.only(top: 5)
: const EdgeInsets.only(top: 0),
child: SizedBox(
height: 70,
child: SvgPicture.asset(
device!.type == "4S"
? Assets.fourSceneIcon
: Assets.sixSceneIcon,
fit: BoxFit.contain,
),
),
),
],
),
),
)),
),
],
), ),
), child: InkWell(
), onTap: () async {
const SizedBox(height: 20), bool val = await Navigator.of(context).push(
const BodyMedium( MaterialPageRoute(
text: 'Device Management', builder: (context) => SettingProfilePage(
fontWeight: FontWeight.w700, device: device,
fontSize: 12, ),
fontColor: ColorsManager.grayColor, ),
), );
DefaultContainer( if (val == true) {
child: Column( _bloc.add(const DeviceSettingInitialInfo());
children: [ }
SettingWidget( },
onTap: () { child: Stack(
Navigator.of(context).push( children: [
MaterialPageRoute( Column(
builder: (context) => SettingInfoPage( crossAxisAlignment:
device: device!, CrossAxisAlignment.stretch,
)),
);
},
text: 'Device Information',
icon: Assets.infoIcon,
),
// const Divider(
// color: ColorsManager.dividerColor,
// ),
// SettingWidget(
// onTap: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// ShareFourScenePage(
// device: device!)),
// );
// },
// text: 'Tap-to Run and Automation',
// icon: Assets.tapRunIcon,
// ),
],
),
),
const SizedBox(height: 20),
// const BodyMedium(
// text: 'Device Offline Notification',
// fontWeight: FontWeight.w700,
// fontSize: 12,
// fontColor: ColorsManager.grayColor,
// ),
// DefaultContainer(
// child: Column(
// children: [
// SettingWidget(
// value: _bloc.enableAlarm,
// onChanged: (p0) {
// context
// .read<DeviceSettingBloc>()
// .add(ToggleEnableAlarmEvent(p0));
// },
// isNotification: true,
// onTap: () {},
// text: 'Offline Notification',
// icon: Assets.notificationIcon,
// ),
// ],
// ),
// ),
// const SizedBox(height: 20),
// const BodyMedium(
// text: 'Others',
// fontWeight: FontWeight.w700,
// fontSize: 12,
// fontColor: ColorsManager.grayColor,
// ),
// const SizedBox(height: 5),
// DefaultContainer(
// child: Column(
// children: [
// SettingWidget(
// onTap: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// ShareDevicePage(device: device!)),
// );
// },
// text: 'Share Device',
// icon: Assets.shareIcon,
// ),
// // const Divider(
// // color: ColorsManager.dividerColor,
// // ),
// // SettingWidget(
// // onTap: () {
// // Navigator.of(context).push(
// // MaterialPageRoute(
// // builder: (context) =>
// // FourSceneCreateGroup(
// // device: device!)),
// // );
// // },
// // text: 'Create Group',
// // icon: Assets.createGroupIcon,
// // ),
// const Divider(
// color: ColorsManager.dividerColor,
// ),
// SettingWidget(
// onTap: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// FaqSettingPage(device: device!)),
// );
// },
// text: 'Device FAQ',
// icon: Assets.faqIcon,
// ),
// const Divider(
// color: ColorsManager.dividerColor,
// ),
// SettingWidget(
// onTapUpdate: () {
// showDialog(
// context: context,
// builder: (context) {
// return UpdateInfoDialog(
// cancelTab: () {
// Navigator.of(context).pop();
// },
// confirmTab: () {
// Navigator.of(context).pop();
// },
// );
// },
// );
// },
// isUpdate: true,
// onTap: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// const UpdatePageSetting()),
// );
// },
// text: 'Device Update',
// icon: Assets.updateIcon,
// ),
// ],
// ),
// ),
const SizedBox(height: 20),
InkWell(
onTap: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [ children: [
const BodyMedium(
text: 'Remove Device',
fontWeight: FontWeight.w700,
fontSize: 16,
fontColor: ColorsManager.red,
),
const SizedBox(height: 10),
const SizedBox(
width: 250,
child: Divider(
color: ColorsManager.dividerColor,
),
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DisconnectDeviceDialog(
cancelTab: () {
Navigator.of(context).pop();
},
confirmTab: () {
Navigator.of(context).pop();
},
);
},
);
},
child: const BodyMedium(
text: 'Disconnect Device',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager.textPrimaryColor,
),
),
const Icon(
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
)
],
),
const SizedBox(height: 20), const SizedBox(height: 20),
Row( DefaultContainer(
mainAxisAlignment: MainAxisAlignment.spaceBetween, borderRadius: const BorderRadius.all(
children: [ Radius.circular(30)),
InkWell( child: Padding(
onTap: () { padding: const EdgeInsets.all(10.0),
showDialog( child: Padding(
context: context, padding:
builder: (context) { const EdgeInsets.only(left: 90),
return DisconnectWipeData( child: Row(
cancelTab: () { mainAxisAlignment:
Navigator.of(context).pop(); MainAxisAlignment.spaceBetween,
}, children: [
confirmTab: () { Expanded(
_bloc.add(DeleteDeviceEvent()); child: Column(
}, crossAxisAlignment:
); CrossAxisAlignment.start,
}, children: [
); SizedBox(
}, child: Text(
child: const BodyMedium( _bloc.deviceInfo.name,
text: 'Disconnect Device and Wipe Data', style: const TextStyle(
fontWeight: FontWeight.w400, fontSize: 16,
fontSize: 15, fontWeight:
fontColor: ColorsManager.textPrimaryColor, FontWeight.w700,
color: ColorsManager
.grayColor,
),
overflow: TextOverflow
.ellipsis, // Adds ellipsis (...) when the text overflows.
maxLines:
1, // Restricts the text to a single line.
)),
const SizedBox(
height: 5,
),
BodySmall(
text: _bloc
.deviceInfo
.subspace
.subspaceName),
],
),
),
SvgPicture.asset(
Assets.editNameSetting,
fit: BoxFit.contain,
height: 30,
),
],
), ),
), ),
const Icon( ),
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
)
],
), ),
], ],
), ),
); Positioned(
}, top: 0,
); left: 20,
}, child: CircleAvatar(
child: const Center( radius: 43,
child: BodyMedium( backgroundColor: Colors.white,
text: 'Remove Device', child: CircleAvatar(
fontWeight: FontWeight.w400, radius: 40,
fontSize: 15, backgroundColor: Colors.white,
fontColor: ColorsManager.red, child: CircleAvatar(
radius: 40,
backgroundColor:
ColorsManager.backgroundColor,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
device!.type == 'NCPS'
? SizedBox(
height: 80,
width: 50,
child: SvgPicture.asset(
Assets.flushIcon,
fit: BoxFit.contain,
),
)
: device!.type == "SOS"
? ClipOval(
child:
SvgPicture.asset(
Assets.sosHomeIcon,
fit: BoxFit.contain,
height: 70,
),
)
: Padding(
padding: device!
.type ==
"4S"
? const EdgeInsets
.only(top: 5)
: const EdgeInsets
.only(top: 0),
child: SizedBox(
height: 70,
child: SvgPicture
.asset(
device!.type ==
"4S"
? Assets
.fourSceneIcon
: Assets
.sixSceneIcon,
fit: BoxFit
.contain,
),
),
),
],
),
),
)),
),
],
),
), ),
), ),
), const SizedBox(height: 20),
], const BodyMedium(
); text: 'Device Management',
}, fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
child: Column(
children: [
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SettingInfoPage(
device: device!,
)),
);
},
text: 'Device Information',
icon: Assets.infoIcon,
),
// const Divider(
// color: ColorsManager.dividerColor,
// ),
// SettingWidget(
// onTap: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// ShareFourScenePage(
// device: device!)),
// );
// },
// text: 'Tap-to Run and Automation',
// icon: Assets.tapRunIcon,
// ),
],
),
),
const SizedBox(height: 20),
// const BodyMedium(
// text: 'Device Offline Notification',
// fontWeight: FontWeight.w700,
// fontSize: 12,
// fontColor: ColorsManager.grayColor,
// ),
// DefaultContainer(
// child: Column(
// children: [
// SettingWidget(
// value: _bloc.enableAlarm,
// onChanged: (p0) {
// context
// .read<DeviceSettingBloc>()
// .add(ToggleEnableAlarmEvent(p0));
// },
// isNotification: true,
// onTap: () {},
// text: 'Offline Notification',
// icon: Assets.notificationIcon,
// ),
// ],
// ),
// ),
// const SizedBox(height: 20),
// const BodyMedium(
// text: 'Others',
// fontWeight: FontWeight.w700,
// fontSize: 12,
// fontColor: ColorsManager.grayColor,
// ),
// const SizedBox(height: 5),
// DefaultContainer(
// child: Column(
// children: [
// SettingWidget(
// onTap: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// ShareDevicePage(device: device!)),
// );
// },
// text: 'Share Device',
// icon: Assets.shareIcon,
// ),
// // const Divider(
// // color: ColorsManager.dividerColor,
// // ),
// // SettingWidget(
// // onTap: () {
// // Navigator.of(context).push(
// // MaterialPageRoute(
// // builder: (context) =>
// // FourSceneCreateGroup(
// // device: device!)),
// // );
// // },
// // text: 'Create Group',
// // icon: Assets.createGroupIcon,
// // ),
// const Divider(
// color: ColorsManager.dividerColor,
// ),
// SettingWidget(
// onTap: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// FaqSettingPage(device: device!)),
// );
// },
// text: 'Device FAQ',
// icon: Assets.faqIcon,
// ),
// const Divider(
// color: ColorsManager.dividerColor,
// ),
// SettingWidget(
// onTapUpdate: () {
// showDialog(
// context: context,
// builder: (context) {
// return UpdateInfoDialog(
// cancelTab: () {
// Navigator.of(context).pop();
// },
// confirmTab: () {
// Navigator.of(context).pop();
// },
// );
// },
// );
// },
// isUpdate: true,
// onTap: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// const UpdatePageSetting()),
// );
// },
// text: 'Device Update',
// icon: Assets.updateIcon,
// ),
// ],
// ),
// ),
const SizedBox(height: 20),
InkWell(
onTap: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const BodyMedium(
text: 'Remove Device',
fontWeight: FontWeight.w700,
fontSize: 16,
fontColor: ColorsManager.red,
),
const SizedBox(height: 10),
const SizedBox(
width: 250,
child: Divider(
color: ColorsManager.dividerColor,
),
),
const SizedBox(height: 10),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DisconnectDeviceDialog(
cancelTab: () {
Navigator.of(context)
.pop();
},
confirmTab: () {
Navigator.of(context)
.pop();
},
);
},
);
},
child: const BodyMedium(
text: 'Disconnect Device',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager
.textPrimaryColor,
),
),
const Icon(
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
)
],
),
const SizedBox(height: 20),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DisconnectWipeData(
cancelTab: () {
Navigator.of(context)
.pop();
},
confirmTab: () {
_bloc.add(
DeleteDeviceEvent());
},
);
},
);
},
child: const BodyMedium(
text:
'Disconnect Device and Wipe Data',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager
.textPrimaryColor,
),
),
const Icon(
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
)
],
),
],
),
);
},
);
},
child: const Center(
child: BodyMedium(
text: 'Remove Device',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager.red,
),
),
),
],
);
},
),
), ),
), ),
); );

View File

@ -46,7 +46,7 @@ class SixSceneScreen extends StatelessWidget {
model = state.device; model = state.device;
} }
return DefaultScaffold( return DefaultScaffold(
title: device?.name ?? '6 Scene Switch', title: bloc.deviceInfo.name ,
actions: [ actions: [
InkWell( InkWell(
onTap: () async { onTap: () async {
@ -55,7 +55,7 @@ class SixSceneScreen extends StatelessWidget {
builder: (context) => SettingsPage(device: device!), builder: (context) => SettingsPage(device: device!),
), ),
); );
if (val == null) { if (val == null || val == true) {
bloc.add(const SixSceneInitialInfo()); bloc.add(const SixSceneInitialInfo());
bloc.add(const SixSceneInitial()); bloc.add(const SixSceneInitial());
bloc.add(const SexSceneSwitchInitial()); bloc.add(const SexSceneSwitchInitial());
@ -195,8 +195,8 @@ class SixSceneScreen extends StatelessWidget {
); );
if (value == true) { if (value == true) {
Future.delayed( Future.delayed(
const Duration(milliseconds: 200), const Duration(
() { milliseconds: 200), () {
bloc.add( bloc.add(
const SexSceneSwitchInitial()); const SexSceneSwitchInitial());
}); });

View File

@ -95,17 +95,15 @@ class FlushPresenceRecords extends StatelessWidget {
SizedBox( SizedBox(
child: ListTile( child: ListTile(
leading: Icon( leading: Icon(
record.value == 'true' record.value == "presence"
? Icons.radio_button_checked ? Icons.radio_button_checked
: Icons.radio_button_unchecked, : Icons.radio_button_unchecked,
color: record.value == 'true' color: record.value == "presence"
? Colors.blue ? Colors.blue
: Colors.grey, : Colors.grey,
), ),
title: Text( title: Text(
record.value == 'true' record.value.toString(),
? "Opened"
: "Closed",
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 18, fontSize: 18,

View File

@ -47,7 +47,7 @@ class FourSceneScreen extends StatelessWidget {
} }
return DefaultScaffold( return DefaultScaffold(
title: device?.name ?? '4 Scene', title: _bloc.deviceInfo.name,
actions: [ actions: [
InkWell( InkWell(
onTap: () async { onTap: () async {
@ -56,7 +56,7 @@ class FourSceneScreen extends StatelessWidget {
builder: (context) => SettingsPage(device: device!), builder: (context) => SettingsPage(device: device!),
), ),
); );
if (val == null) { if (val == null || val == true) {
_bloc.add(const FourSceneInitial()); _bloc.add(const FourSceneInitial());
_bloc.add(const FourSceneInitialInfo()); _bloc.add(const FourSceneInitialInfo());
_bloc.add(const FourSceneSwitchInitial()); _bloc.add(const FourSceneSwitchInitial());
@ -164,8 +164,7 @@ class FourSceneScreen extends StatelessWidget {
cancelTab: () { cancelTab: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
confirmTab: confirmTab: (switchSelected) {
(switchSelected) {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (context) => builder: (context) =>

View File

@ -29,7 +29,7 @@ class SosScreen extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
final sensor = BlocProvider.of<SosBloc>(context); final sensor = BlocProvider.of<SosBloc>(context);
return DefaultScaffold( return DefaultScaffold(
title: device?.name, title: sensor.deviceInfo.name,
actions: [ actions: [
InkWell( InkWell(
onTap: () async { onTap: () async {
@ -38,7 +38,7 @@ class SosScreen extends StatelessWidget {
builder: (context) => SettingsPage(device: device!), builder: (context) => SettingsPage(device: device!),
), ),
); );
if (val == null) { if (val == null || val == true) {
sensor.add(SosInitialDeviseInfo()); sensor.add(SosInitialDeviseInfo());
sensor.add(const SosInitial()); sensor.add(const SosInitial());
} }
@ -72,33 +72,38 @@ class SosScreen extends StatelessWidget {
Expanded( Expanded(
flex: 4, flex: 4,
child: InkWell( child: InkWell(
overlayColor: overlayColor: WidgetStateProperty.all(
WidgetStateProperty.all(Colors.transparent), Colors.transparent),
onTap: () { onTap: () {
// Add functionality for the main SOS button here // Add functionality for the main SOS button here
}, },
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment:
CrossAxisAlignment.center,
children: [ children: [
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(890), borderRadius:
BorderRadius.circular(890),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.white.withOpacity(0.1), color:
Colors.white.withOpacity(0.1),
blurRadius: 24, blurRadius: 24,
offset: const Offset(-5, -5), offset: const Offset(-5, -5),
blurStyle: BlurStyle.outer, blurStyle: BlurStyle.outer,
), ),
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.11), color: Colors.black
.withOpacity(0.11),
blurRadius: 25, blurRadius: 25,
offset: const Offset(5, 5), offset: const Offset(5, 5),
blurStyle: BlurStyle.outer, blurStyle: BlurStyle.outer,
), ),
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.13), color: Colors.black
.withOpacity(0.13),
blurRadius: 30, blurRadius: 30,
offset: const Offset(5, 5), offset: const Offset(5, 5),
blurStyle: BlurStyle.inner, blurStyle: BlurStyle.inner,
@ -125,8 +130,9 @@ class SosScreen extends StatelessWidget {
onTap: () { onTap: () {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (context) => SosRecordsScreen( builder: (context) =>
sosId: device!.uuid!), SosRecordsScreen(
sosId: device!.uuid!),
), ),
); );
}, },
@ -181,8 +187,8 @@ class SosScreen extends StatelessWidget {
maxHeight: 46, maxHeight: 46,
maxWidth: 50, maxWidth: 50,
), ),
child: SvgPicture.asset( child: SvgPicture.asset(Assets
Assets.doorNotificationSetting), .doorNotificationSetting),
), ),
const SizedBox(height: 15), const SizedBox(height: 15),
const Flexible( const Flexible(

View File

@ -4,6 +4,7 @@ enum OperationDialogType {
temperature, temperature,
onOff, onOff,
integerSteps, integerSteps,
counterSteps,
listOfOptions, listOfOptions,
none, none,
} }

View File

@ -116,7 +116,7 @@ class FlushFunctionsHelper {
operationName: 'Min Detection Distance', operationName: 'Min Detection Distance',
code: 'near_detection', code: 'near_detection',
functionValue: functionValue, functionValue: functionValue,
operationDialogType: OperationDialogType.integerSteps, operationDialogType: OperationDialogType.counterSteps,
operationalValues: [ operationalValues: [
SceneOperationalValue( SceneOperationalValue(
icon: '', icon: '',
@ -136,10 +136,10 @@ class FlushFunctionsHelper {
operationName: 'Max Detection Distance', operationName: 'Max Detection Distance',
code: 'far_detection', code: 'far_detection',
functionValue: functionValue, functionValue: functionValue,
operationDialogType: OperationDialogType.integerSteps, operationDialogType: OperationDialogType.counterSteps,
operationalValues: [ operationalValues: [
SceneOperationalValue( SceneOperationalValue(
icon: '', icon: Assets.assetsCelsiusDegrees,
value: 0.0, value: 0.0,
description: "m", description: "m",
minValue: 0.0, minValue: 0.0,
@ -156,23 +156,17 @@ class FlushFunctionsHelper {
operationName: 'Trigger Level', operationName: 'Trigger Level',
code: 'sensi_reduce', code: 'sensi_reduce',
functionValue: functionValue, functionValue: functionValue,
operationDialogType: OperationDialogType.listOfOptions, operationDialogType: OperationDialogType.counterSteps,
operationalValues: [ operationalValues: [
SceneOperationalValue( SceneOperationalValue(
icon: Assets.assetsSensitivityOperationIcon, icon: Assets.assetsCelsiusDegrees,
value: 1, value: 1,
description: 1.toString(), description: "",
), minValue: 1,
SceneOperationalValue( maxValue: 3,
icon: Assets.assetsSensitivityOperationIcon, stepValue: 1,
value: 2,
description: 2.toString(),
),
SceneOperationalValue(
icon: Assets.assetsSensitivityOperationIcon,
value: 3,
description: 3.toString(),
), ),
], ],
), ),
SceneStaticFunction( SceneStaticFunction(
@ -183,23 +177,17 @@ class FlushFunctionsHelper {
operationName: 'Indent Level', operationName: 'Indent Level',
code: 'occur_dist_reduce', code: 'occur_dist_reduce',
functionValue: functionValue, functionValue: functionValue,
operationDialogType: OperationDialogType.listOfOptions, operationDialogType: OperationDialogType.counterSteps,
operationalValues: [ operationalValues: [
SceneOperationalValue( SceneOperationalValue(
icon: Assets.assetsSensitivityOperationIcon, icon: Assets.assetsCelsiusDegrees,
value: 1, value: 1,
description: 1.toString(), description: "",
), minValue: 1,
SceneOperationalValue( maxValue: 3,
icon: Assets.assetsSensitivityOperationIcon, stepValue: 1,
value: 2,
description: 2.toString(),
),
SceneOperationalValue(
icon: Assets.assetsSensitivityOperationIcon,
value: 3,
description: 3.toString(),
), ),
], ],
), ),
SceneStaticFunction( SceneStaticFunction(
@ -210,7 +198,7 @@ class FlushFunctionsHelper {
operationName: 'Target Confirm Time', operationName: 'Target Confirm Time',
code: 'presence_delay', code: 'presence_delay',
functionValue: functionValue, functionValue: functionValue,
operationDialogType: OperationDialogType.integerSteps, operationDialogType: OperationDialogType.counterSteps,
operationalValues: [ operationalValues: [
SceneOperationalValue( SceneOperationalValue(
icon: '', icon: '',
@ -235,7 +223,7 @@ class FlushFunctionsHelper {
SceneOperationalValue( SceneOperationalValue(
icon: '', icon: '',
value: 20.0, value: 20.0,
description: "", description: "sec",
minValue: 20.0, minValue: 20.0,
maxValue: 300.0, maxValue: 300.0,
stepValue: 1.0, stepValue: 1.0,

View File

@ -8,6 +8,7 @@ import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
import 'package:syncrow_app/features/scene/model/create_scene_model.dart'; import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_countdown.dart';
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_counter.dart';
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart';
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_slider_steps.dart';
import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialogs/alert_dialog_temperature_body.dart';
@ -132,7 +133,7 @@ mixin SceneLogicHelper {
'presence_delay' || 'presence_delay' ||
action.executorProperty!.functionCode == 'none_delay') { action.executorProperty!.functionCode == 'none_delay') {
action.executorProperty!.functionValue = action.executorProperty!.functionValue =
action.executorProperty!.functionValue * 10; (action.executorProperty!.functionValue * 10).round();
} }
} }
} }
@ -193,12 +194,12 @@ mixin SceneLogicHelper {
if (action.executorProperty!.functionCode == 'near_detection' || if (action.executorProperty!.functionCode == 'near_detection' ||
action.executorProperty!.functionCode == 'far_detection') { action.executorProperty!.functionCode == 'far_detection') {
action.executorProperty!.functionValue = action.executorProperty!.functionValue =
action.executorProperty!.functionValue * 100; (action.executorProperty!.functionValue * 100).round();
} else if (action.executorProperty!.functionCode == } else if (action.executorProperty!.functionCode ==
'presence_delay' || 'presence_delay' ||
action.executorProperty!.functionCode == 'none_delay') { action.executorProperty!.functionCode == 'none_delay') {
action.executorProperty!.functionValue = action.executorProperty!.functionValue =
action.executorProperty!.functionValue * 10; (action.executorProperty!.functionValue * 10).round();
} }
} }
} }
@ -234,6 +235,13 @@ mixin SceneLogicHelper {
functionValue: functionValue ?? taskItem.functionValue, functionValue: functionValue ?? taskItem.functionValue,
isAutomation: isAutomation, isAutomation: isAutomation,
); );
} else if (taskItem.operationDialogType ==
OperationDialogType.counterSteps) {
return AlertDialogCounterSteps(
taskItem: taskItem,
functionValue: functionValue ?? taskItem.functionValue,
isAutomation: isAutomation,
);
} }
return AlertDialogFunctionsOperationsBody( return AlertDialogFunctionsOperationsBody(

View File

@ -1748,7 +1748,7 @@ mixin SceneOperationsDataHelper {
action.deviceName, action.deviceName,
Assets.flushIcon, Assets.flushIcon,
'Min Detection distance', 'Min Detection distance',
OperationDialogType.integerSteps, OperationDialogType.counterSteps,
_createMinDetection(), _createMinDetection(),
isAutomation, isAutomation,
comparator, comparator,
@ -1763,7 +1763,7 @@ mixin SceneOperationsDataHelper {
action.deviceName, action.deviceName,
Assets.flushIcon, Assets.flushIcon,
'Max Detection distance', 'Max Detection distance',
OperationDialogType.integerSteps, OperationDialogType.counterSteps,
_createFarDetection(), _createFarDetection(),
isAutomation, isAutomation,
comparator, comparator,
@ -1778,7 +1778,7 @@ mixin SceneOperationsDataHelper {
action.deviceName, action.deviceName,
Assets.flushIcon, Assets.flushIcon,
"Trigger Level", "Trigger Level",
OperationDialogType.listOfOptions, OperationDialogType.counterSteps,
_createTriggerLevelFunction(), _createTriggerLevelFunction(),
isAutomation, isAutomation,
comparator, comparator,
@ -1789,19 +1789,12 @@ mixin SceneOperationsDataHelper {
List<SceneOperationalValue> _createTriggerLevelFunction() { List<SceneOperationalValue> _createTriggerLevelFunction() {
return [ return [
SceneOperationalValue( SceneOperationalValue(
icon: Assets.assetsSensitivityOperationIcon, icon: Assets.assetsCelsiusDegrees,
description: "1", value: 0,
value: 1, description: '',
), minValue: 0,
SceneOperationalValue( maxValue: 3,
icon: Assets.assetsSensitivityOperationIcon, stepValue: 1,
description: "2",
value: 2,
),
SceneOperationalValue(
icon: Assets.assetsSensitivityOperationIcon,
description: "3",
value: 3,
), ),
]; ];
} }
@ -1813,7 +1806,7 @@ mixin SceneOperationsDataHelper {
action.deviceName, action.deviceName,
Assets.flushIcon, Assets.flushIcon,
'Indent Level', 'Indent Level',
OperationDialogType.listOfOptions, OperationDialogType.counterSteps,
_createIndentLevelFunction(), _createIndentLevelFunction(),
isAutomation, isAutomation,
comparator, comparator,
@ -1824,19 +1817,12 @@ mixin SceneOperationsDataHelper {
List<SceneOperationalValue> _createIndentLevelFunction() { List<SceneOperationalValue> _createIndentLevelFunction() {
return [ return [
SceneOperationalValue( SceneOperationalValue(
icon: Assets.assetsSensitivityOperationIcon, icon: Assets.assetsCelsiusDegrees,
description: "1", value: 0,
value: 1, description: '',
), minValue: 0,
SceneOperationalValue( maxValue: 3,
icon: Assets.assetsSensitivityOperationIcon, stepValue: 1,
description: "2",
value: 2,
),
SceneOperationalValue(
icon: Assets.assetsSensitivityOperationIcon,
description: "3",
value: 3,
), ),
]; ];
} }
@ -1848,7 +1834,7 @@ mixin SceneOperationsDataHelper {
action.deviceName, action.deviceName,
Assets.flushIcon, Assets.flushIcon,
'Target Confirm Time', 'Target Confirm Time',
OperationDialogType.integerSteps, OperationDialogType.counterSteps,
_targetConfirmTimeFun(), _targetConfirmTimeFun(),
isAutomation, isAutomation,
comparator, comparator,
@ -1876,7 +1862,7 @@ mixin SceneOperationsDataHelper {
SceneOperationalValue( SceneOperationalValue(
icon: Assets.flushIcon, icon: Assets.flushIcon,
value: 0.0, value: 0.0,
description: '', description: 'sec',
minValue: 20, minValue: 20,
maxValue: 300, maxValue: 300,
stepValue: 1, stepValue: 1,
@ -1892,7 +1878,7 @@ mixin SceneOperationsDataHelper {
value: 0.0, value: 0.0,
minValue: 0.0, minValue: 0.0,
maxValue: 9.5, maxValue: 9.5,
stepValue: 1, stepValue: 0.10,
), ),
]; ];
} }
@ -1905,7 +1891,7 @@ mixin SceneOperationsDataHelper {
value: 0.0, value: 0.0,
minValue: 0.0, minValue: 0.0,
maxValue: 9.5, maxValue: 9.5,
stepValue: 1, stepValue: 0.10,
), ),
]; ];
} }
@ -1915,7 +1901,7 @@ mixin SceneOperationsDataHelper {
SceneOperationalValue( SceneOperationalValue(
icon: Assets.assetsCelsiusDegrees, icon: Assets.assetsCelsiusDegrees,
value: 0.0, value: 0.0,
description: '', description: 'sec',
minValue: 0.0, minValue: 0.0,
maxValue: 0.5, maxValue: 0.5,
stepValue: 0.1, stepValue: 0.1,

View File

@ -0,0 +1,243 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class AlertDialogCounterSteps extends StatefulWidget {
const AlertDialogCounterSteps({
super.key,
this.functionValue,
required this.taskItem,
required this.isAutomation,
});
final dynamic functionValue;
final SceneStaticFunction taskItem;
final bool isAutomation;
@override
State<AlertDialogCounterSteps> createState() =>
_AlertDialogCounterStepsState();
}
class _AlertDialogCounterStepsState extends State<AlertDialogCounterSteps> {
double? groupValue;
int selectedToggleIndex = 1;
@override
void didChangeDependencies() {
super.didChangeDependencies();
final createSceneBloc = context.read<CreateSceneBloc>();
if (widget.taskItem.comparator != null) {
selectedToggleIndex = _comparatorToIndex(widget.taskItem.comparator);
}
if (widget.isAutomation) {
final automationTempTaskList = createSceneBloc.automationTempTasksList;
final automationComparatorValues =
createSceneBloc.automationComparatorValues;
for (var element in automationTempTaskList) {
if (element.code == widget.taskItem.code) {
groupValue = element.functionValue;
selectedToggleIndex =
_comparatorToIndex(automationComparatorValues[element.code]);
}
}
}
if (widget.taskItem.code == 'temp_current') {
groupValue = widget.functionValue != null
? _normalizeValue(
double.tryParse(widget.functionValue.toString()) ??
widget.taskItem.operationalValues[0].minValue,
)
: widget.taskItem.operationalValues[0].minValue;
} else {
groupValue = widget.functionValue != null
? _normalizeValue(widget.functionValue)
: _normalizeValue(widget.taskItem.operationalValues[0].minValue);
}
setState(() {});
context.read<CreateSceneBloc>().add(
SelectedValueEvent(
value: _deNormalizeValue(groupValue),
code: widget.taskItem.code,
isAutomation: widget.isAutomation,
comparator: _indexToComparator(selectedToggleIndex),
),
);
}
int _comparatorToIndex(String? comparator) {
switch (comparator) {
case "<":
return 0;
case "==":
return 1;
case ">":
return 2;
default:
return 1;
}
}
String _indexToComparator(int index) {
switch (index) {
case 0:
return "<";
case 1:
return "==";
case 2:
return ">";
default:
return "==";
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
if (widget.isAutomation)
ToggleButtons(
isSelected: [
selectedToggleIndex == 0,
selectedToggleIndex == 1,
selectedToggleIndex == 2,
],
onPressed: (index) {
setState(() {
selectedToggleIndex = index;
});
context.read<CreateSceneBloc>().add(
SelectedValueEvent(
value: _deNormalizeValue(groupValue),
code: widget.taskItem.code,
isAutomation: widget.isAutomation,
comparator: _indexToComparator(selectedToggleIndex),
),
);
},
borderRadius: BorderRadius.circular(30),
selectedColor: Colors.white,
color: ColorsManager.blackColor,
fillColor: ColorsManager.primaryColorWithOpacity,
borderColor: ColorsManager.greyColor,
constraints: BoxConstraints.tight(Size(70, 30)),
children: const [
SizedBox(width: 70, height: 30, child: Center(child: Text("<"))),
SizedBox(width: 70, height: 30, child: Center(child: Text("="))),
SizedBox(width: 70, height: 30, child: Center(child: Text(">"))),
],
),
const SizedBox(height: 12),
...widget.taskItem.operationalValues.map(
(operation) => BlocBuilder<CreateSceneBloc, CreateSceneState>(
builder: (context, state) {
final step = operation.stepValue?.toDouble() ?? 1.0;
final min = operation.minValue?.toDouble() ?? 0.0;
final max = operation.maxValue?.toDouble() ?? 100.0;
return Column(
children: [
const SizedBox(height: 12),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.remove),
onPressed: () {
setState(() {
groupValue =
((groupValue ?? min) - step).clamp(min, max);
});
context.read<CreateSceneBloc>().add(
SelectedValueEvent(
value: _deNormalizeValue(groupValue),
code: widget.taskItem.code,
isAutomation: widget.isAutomation,
comparator:
_indexToComparator(selectedToggleIndex),
),
);
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TitleMedium(
text: groupValue != null
? (groupValue! % 1 == 0
? groupValue!.toStringAsFixed(0)
: groupValue!.toStringAsFixed(1))
: "0",
style: context.titleMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity,
fontSize: 30,
),
),
const SizedBox(width: 8),
TitleMedium(
text: operation.description.toString(),
style: context.titleMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity,
fontSize: 30,
),
),
],
),
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
setState(() {
groupValue =
((groupValue ?? 0) + step).clamp(min, max);
});
context.read<CreateSceneBloc>().add(
SelectedValueEvent(
value: _deNormalizeValue(groupValue),
code: widget.taskItem.code,
isAutomation: widget.isAutomation,
comparator:
_indexToComparator(selectedToggleIndex),
),
);
},
),
],
),
const SizedBox(height: 12),
],
);
},
),
),
],
);
}
double _normalizeValue(dynamic value) {
if ((widget.taskItem.code == "temp_set" && value > 199) ||
(widget.taskItem.code == "temp_current" && value >= -99.0)) {
return (value) / 10;
}
return value.toDouble();
}
double _deNormalizeValue(double? value) {
if (widget.taskItem.code == "temp_set" ||
widget.taskItem.code == "temp_current") {
return (value ?? 0) * 10;
}
return value ?? 0;
}
}