summaryrefslogtreecommitdiffstats
path: root/lib/presentation/screens/hvac
diff options
context:
space:
mode:
authorLisandro Pérez Meyer <lpmeyer@ics.com>2023-11-14 17:20:58 -0300
committerLisandro Pérez Meyer <lpmeyer@ics.com>2023-11-14 17:31:12 -0300
commit70ec8a79a121471a004e7e4c23157d10157e136f (patch)
treea4f9c0a4fac4e4274ec4324a289b6ef62e1c5653 /lib/presentation/screens/hvac
Initial cleanup push.
Based on agldemo2024 on commit 2a5dc04d801134338150c3f6afc67eaa65599763 Disable device preview. Disable Lottie animation. The original commit was b3c493c340fcb4bb0a937692838fc830bec3e9ea but I am just keeping this change, because the json did not really needed to change. I think. Signed-off-by: Lisandro Pérez Meyer <lpmeyer@ics.com>
Diffstat (limited to 'lib/presentation/screens/hvac')
-rw-r--r--lib/presentation/screens/hvac/hvac.dart45
-rw-r--r--lib/presentation/screens/hvac/hvac_content.dart249
-rw-r--r--lib/presentation/screens/hvac/widgets/climate_controls.dart80
-rw-r--r--lib/presentation/screens/hvac/widgets/fan_focus.dart116
-rw-r--r--lib/presentation/screens/hvac/widgets/fan_speed_controls.dart251
-rw-r--r--lib/presentation/screens/hvac/widgets/semi_circle_painter.dart109
-rw-r--r--lib/presentation/screens/hvac/widgets/temperature_control.dart255
7 files changed, 1105 insertions, 0 deletions
diff --git a/lib/presentation/screens/hvac/hvac.dart b/lib/presentation/screens/hvac/hvac.dart
new file mode 100644
index 0000000..ebdaea4
--- /dev/null
+++ b/lib/presentation/screens/hvac/hvac.dart
@@ -0,0 +1,45 @@
+import '/export.dart';
+
+class HvacPage extends StatelessWidget {
+ const HvacPage({super.key});
+
+ static Page<void> page() => const MaterialPage<void>(child: HvacPage());
+ @override
+ Widget build(BuildContext context) {
+ // print(MediaQuery.of(context).size);
+ // print(MediaQuery.of(context).size.width *
+ // MediaQuery.of(context).devicePixelRatio);
+ // print(MediaQuery.of(context).size.height *
+ // MediaQuery.of(context).devicePixelRatio);
+ return Stack(
+ children: [
+ // SizedBox(
+ // width: double.infinity,
+ // height: double.infinity,
+ // //color: Colors.black,
+ // // decoration:
+ // // BoxDecoration(gradient: AGLDemoColors.gradientBackgroundColor),
+ // child: SvgPicture.asset(
+ // 'assets/HVACBackground.svg',
+ // alignment: Alignment.center,
+ // fit: BoxFit.cover,
+ // //width: 200,
+ // //height: 200,
+ // ),
+ // ),
+ SizedBox(
+ width: double.infinity,
+ height: double.infinity,
+ // color: Colors.black,
+ child: SvgPicture.asset(
+ 'assets/backgroundTextures.svg',
+ alignment: Alignment.center,
+ //width: 200,
+ //height: 200,
+ ),
+ ),
+ const SingleChildScrollView(child: HVAC()),
+ ],
+ );
+ }
+}
diff --git a/lib/presentation/screens/hvac/hvac_content.dart b/lib/presentation/screens/hvac/hvac_content.dart
new file mode 100644
index 0000000..f79ec14
--- /dev/null
+++ b/lib/presentation/screens/hvac/hvac_content.dart
@@ -0,0 +1,249 @@
+import 'package:flutter_ics_homescreen/export.dart';
+
+class HVAC extends ConsumerStatefulWidget {
+ const HVAC({super.key});
+
+ @override
+ HVACState createState() => HVACState();
+}
+
+class HVACState extends ConsumerState<HVAC> {
+ bool isFanFocusLeftTopSelected = false;
+ bool isFanFocusRightTopSelected = true;
+ bool isFanFocusLeftBottomSelected = true;
+ bool isFanFocusRightBottomSelected = false;
+
+ late bool isACSelected;
+ bool isSYNCSelected = true;
+ late bool isFrontDefrostSelected;
+ bool isAutoSelected = true;
+ late bool isRecirculationSelected;
+ late bool isRearDefrostSelected;
+
+ int temperatureLeft = 26;
+ int temperatureRight = 26;
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ TextStyle climateControlTextStyle = GoogleFonts.raleway(
+ color: AGLDemoColors.periwinkleColor,
+ fontSize: 44,
+ height: 1.25,
+ fontWeight: FontWeight.w500,
+ shadows: [
+ Shadow(
+ offset: const Offset(1, 2),
+ blurRadius: 3,
+ color: Colors.black.withOpacity(0.7))
+ ]);
+ TextStyle climateControlSelectedTextStyle = GoogleFonts.raleway(
+ color: Colors.white,
+ fontWeight: FontWeight.bold,
+ fontSize: 44,
+ height: 1.25,
+ shadows: [
+ Shadow(
+ offset: const Offset(1, 2),
+ blurRadius: 3,
+ color: Colors.black.withOpacity(0.7))
+ ]);
+
+ @override
+ Widget build(BuildContext context) {
+ final vehicle = ref.watch(vehicleProvider.select((vehicle) => vehicle));
+ isACSelected = vehicle.isAirConditioningActive;
+ isFrontDefrostSelected = vehicle.isFrontDefrosterActive;
+ isRearDefrostSelected = vehicle.isRearDefrosterActive;
+ isRecirculationSelected = vehicle.isRecirculationActive;
+ Size size = MediaQuery.sizeOf(context);
+
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ const SizedBox(
+ height: 83,
+ ),
+ Row(
+ children: [
+ SizedBox(
+ width: size.width * 0.125,
+ ),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ const Padding(
+ padding: EdgeInsets.symmetric(vertical: 20),
+ child: Text(
+ "Left",
+ style: TextStyle(color: Colors.white, fontSize: 40),
+ textAlign: TextAlign.center,
+ ),
+ ),
+ FanFocus(
+ onPressed: () {
+ setState(() {
+ isFanFocusLeftTopSelected = !isFanFocusLeftTopSelected;
+ });
+ },
+ isSelected: isFanFocusLeftTopSelected,
+ focusType: "top_half"),
+ const SizedBox(
+ height: 12,
+ ),
+ FanFocus(
+ onPressed: () {
+ setState(() {
+ isFanFocusLeftBottomSelected =
+ !isFanFocusLeftBottomSelected;
+ });
+ },
+ isSelected: isFanFocusLeftBottomSelected,
+ focusType: "bottom_half")
+ ],
+ )),
+ SizedBox(
+ width: size.width * 0.05,
+ ),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ const Padding(
+ padding: EdgeInsets.symmetric(vertical: 20),
+ child: Text(
+ "Right",
+ style: TextStyle(color: Colors.white, fontSize: 40),
+ textAlign: TextAlign.center,
+ ),
+ ),
+ FanFocus(
+ onPressed: () {
+ setState(() {
+ isFanFocusRightTopSelected =
+ !isFanFocusRightTopSelected;
+ });
+ },
+ isSelected: isFanFocusRightTopSelected,
+ focusType: "top_half"),
+ const SizedBox(
+ height: 12,
+ ),
+ FanFocus(
+ onPressed: () {
+ setState(() {
+ isFanFocusRightBottomSelected =
+ !isFanFocusRightBottomSelected;
+ });
+ },
+ isSelected: isFanFocusRightBottomSelected,
+ focusType: "bottom_half")
+ ],
+ )),
+ SizedBox(
+ width: size.width * 0.1,
+ ),
+ ],
+ ),
+ const SizedBox(
+ height: 80,
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ TemperatureControl(temperature: temperatureLeft),
+ TemperatureControl(temperature: temperatureRight)
+ ],
+ ),
+ const SizedBox(
+ height: 170,
+ ),
+ const FanSpeedControls(),
+ const SizedBox(
+ height: 70,
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ ClimateControls(
+ isSelected: isACSelected,
+ onPressed: () {
+ ref
+ .read(vehicleProvider.notifier)
+ .setHVACMode(mode: 'airCondition');
+ },
+ child: Text(
+ "A/C",
+ style: isACSelected
+ ? climateControlSelectedTextStyle
+ : climateControlTextStyle,
+ )),
+ ClimateControls(
+ onPressed: () {
+ setState(() {
+ isSYNCSelected = !isSYNCSelected;
+ });
+ },
+ isSelected: isSYNCSelected,
+ child: Text(
+ "SYNC",
+ style: isSYNCSelected
+ ? climateControlSelectedTextStyle
+ : climateControlTextStyle,
+ )),
+ ClimateControls(
+ onPressed: () {
+ ref
+ .read(vehicleProvider.notifier)
+ .setHVACMode(mode: 'frontDefrost');
+ },
+ isSelected: isFrontDefrostSelected,
+ child: SvgPicture.asset(
+ "assets/${isFrontDefrostSelected ? "FrontDefrostFilled.svg" : "FrontDefrost.svg"}",
+ ))
+ ],
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ ClimateControls(
+ isSelected: isAutoSelected,
+ onPressed: () {
+ setState(() {
+ isAutoSelected = !isAutoSelected;
+ });
+ },
+ child: Text(
+ "AUTO",
+ style: isAutoSelected
+ ? climateControlSelectedTextStyle
+ : climateControlTextStyle,
+ )),
+ ClimateControls(
+ onPressed: () {
+ ref
+ .read(vehicleProvider.notifier)
+ .setHVACMode(mode: 'recirculation');
+ },
+ isSelected: isRecirculationSelected,
+ child: SvgPicture.asset(
+ "assets/${isRecirculationSelected ? "RecirculationFilled.svg" : "Recirculation.svg"}",
+ )),
+ ClimateControls(
+ onPressed: () {
+ ref
+ .read(vehicleProvider.notifier)
+ .setHVACMode(mode: 'rearDefrost');
+ },
+ isSelected: isRearDefrostSelected,
+ child: SvgPicture.asset(
+ "assets/${isRearDefrostSelected ? "BackDefrostFilled.svg" : "BackDefrost.svg"}",
+ ))
+ ],
+ )
+ ],
+ );
+ }
+}
diff --git a/lib/presentation/screens/hvac/widgets/climate_controls.dart b/lib/presentation/screens/hvac/widgets/climate_controls.dart
new file mode 100644
index 0000000..c7dcd52
--- /dev/null
+++ b/lib/presentation/screens/hvac/widgets/climate_controls.dart
@@ -0,0 +1,80 @@
+import 'package:flutter_ics_homescreen/export.dart';
+
+class ClimateControls extends StatefulWidget {
+ const ClimateControls(
+ {super.key,
+ required this.child,
+ required this.isSelected,
+ required this.onPressed});
+ final Widget child;
+ final bool isSelected;
+ final VoidCallback onPressed;
+
+ @override
+ State<ClimateControls> createState() => _ClimateControlsState();
+}
+
+class _ClimateControlsState extends State<ClimateControls> {
+ @override
+ Widget build(BuildContext context) {
+ Size size = MediaQuery.sizeOf(context);
+
+ return Container(
+ margin: const EdgeInsets.all(8),
+ width: size.width * 0.23,
+ height: size.height * 0.07,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(2),
+ boxShadow: [
+ BoxShadow(
+ offset: Offset(
+ widget.isSelected ? 0 : 1, widget.isSelected ? 4 : 2),
+ blurRadius: widget.isSelected ? 4 : 3,
+ spreadRadius: 0,
+ color: Colors.black.withOpacity(widget.isSelected ? 0.25 : 0.7))
+ ],
+ gradient: LinearGradient(
+ colors: widget.isSelected
+ ? [
+ AGLDemoColors.periwinkleColor,
+ AGLDemoColors.periwinkleColor.withOpacity(0.25)
+ ]
+ : [
+ AGLDemoColors.neonBlueColor,
+ AGLDemoColors.neonBlueColor.withOpacity(0.2)
+ ],
+ begin: Alignment.centerLeft,
+ end: Alignment.centerRight),
+ border: Border.all(color: Colors.white12)),
+ child: Container(
+ padding: const EdgeInsets.all(2),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(2),
+ boxShadow: [
+ BoxShadow(
+ offset: Offset(
+ widget.isSelected ? 0 : 1, widget.isSelected ? 4 : 2),
+ blurRadius: widget.isSelected ? 4 : 3,
+ spreadRadius: 0,
+ color:
+ Colors.black.withOpacity(widget.isSelected ? 0.25 : 0.7))
+ ],
+ color: widget.isSelected
+ ? AGLDemoColors.neonBlueColor
+ : AGLDemoColors.buttonFillEnabledColor,
+ border: Border.all(color: Colors.white12)),
+ child: Material(
+ color: Colors.transparent,
+ child: InkWell(
+ onTap: widget.onPressed,
+ child: Center(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 8),
+ child: widget.child,
+ )),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/screens/hvac/widgets/fan_focus.dart b/lib/presentation/screens/hvac/widgets/fan_focus.dart
new file mode 100644
index 0000000..556c2c7
--- /dev/null
+++ b/lib/presentation/screens/hvac/widgets/fan_focus.dart
@@ -0,0 +1,116 @@
+import 'package:flutter_ics_homescreen/export.dart';
+
+class FanFocus extends StatefulWidget {
+ const FanFocus(
+ {super.key,
+ required this.isSelected,
+ required this.focusType,
+ required this.onPressed});
+ final bool isSelected;
+ final String focusType;
+ final VoidCallback onPressed;
+ @override
+ State<FanFocus> createState() => _FanFocusState();
+}
+
+class _FanFocusState extends State<FanFocus> {
+ @override
+ Widget build(BuildContext context) {
+ double height = MediaQuery.sizeOf(context).height * 0.10;
+ double iconSize = 32;
+
+ return Container(
+ height: height,
+ decoration: BoxDecoration(
+ gradient: LinearGradient(
+ colors: widget.isSelected
+ ? [
+ AGLDemoColors.periwinkleColor,
+ AGLDemoColors.periwinkleColor.withOpacity(0.25)
+ ]
+ : [
+ AGLDemoColors.jordyBlueColor,
+ AGLDemoColors.jordyBlueColor.withOpacity(0.2)
+ ]),
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(widget.focusType == "top_half" ? 16 : 0),
+ topRight: Radius.circular(widget.focusType == "top_half" ? 16 : 0),
+ bottomLeft:
+ Radius.circular(widget.focusType == "bottom_half" ? 16 : 0),
+ bottomRight:
+ Radius.circular(widget.focusType == "bottom_half" ? 16 : 0)),
+ ),
+ child: Container(
+ margin: const EdgeInsets.all(1),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(widget.focusType == "top_half" ? 16 : 0),
+ topRight:
+ Radius.circular(widget.focusType == "top_half" ? 16 : 0),
+ bottomLeft:
+ Radius.circular(widget.focusType == "bottom_half" ? 16 : 0),
+ bottomRight:
+ Radius.circular(widget.focusType == "bottom_half" ? 16 : 0)),
+ color: widget.isSelected
+ ? AGLDemoColors.neonBlueColor
+ : AGLDemoColors.buttonFillEnabledColor,
+ image: const DecorationImage(
+ image: AssetImage("assets/PlusVector.png"),
+ opacity: 0.5,
+ fit: BoxFit.cover),
+ ),
+ child: Material(
+ color: Colors.transparent,
+ child: InkWell(
+ borderRadius: BorderRadius.only(
+ topLeft:
+ Radius.circular(widget.focusType == "top_half" ? 16 : 0),
+ topRight:
+ Radius.circular(widget.focusType == "top_half" ? 16 : 0),
+ bottomLeft:
+ Radius.circular(widget.focusType == "bottom_half" ? 16 : 0),
+ bottomRight: Radius.circular(
+ widget.focusType == "bottom_half" ? 16 : 0)),
+ onTap: widget.onPressed,
+ child: Row(
+ crossAxisAlignment: widget.focusType == "top_half"
+ ? CrossAxisAlignment.end
+ : CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(top: 38),
+ child: Icon(
+ Icons.arrow_forward,
+ color: Colors.white,
+ size: iconSize,
+ shadows: [
+ Shadow(
+ offset: Offset(1, widget.isSelected ? 2 : 4),
+ blurRadius: widget.isSelected ? 3 : 4,
+ color: Colors.black.withOpacity(0.7))
+ ],
+ ),
+ ),
+ Image.asset(
+ "assets/${widget.focusType == "top_half" ? widget.isSelected ? "head_selected" : "head" : widget.isSelected ? "legs_selected" : "legs"}.png",
+ //fit: BoxFit.contain,
+ // alignment: Alignment.bottomRight,
+ // width: widget.focusType == "top_half" ? 108 : 250,
+ // height: 180,
+ ),
+ ],
+ ),
+ SizedBox(
+ width: widget.focusType == "top_half" ? 5 : 40,
+ )
+ ]),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/screens/hvac/widgets/fan_speed_controls.dart b/lib/presentation/screens/hvac/widgets/fan_speed_controls.dart
new file mode 100644
index 0000000..00f1181
--- /dev/null
+++ b/lib/presentation/screens/hvac/widgets/fan_speed_controls.dart
@@ -0,0 +1,251 @@
+import 'package:flutter_ics_homescreen/export.dart';
+import 'package:gradient_borders/gradient_borders.dart';
+import 'package:rive/rive.dart' as rive;
+
+class FanSpeedControls extends ConsumerStatefulWidget {
+ const FanSpeedControls({super.key});
+
+ @override
+ FanSpeedControlsState createState() => FanSpeedControlsState();
+}
+
+class FanSpeedControlsState extends ConsumerState<FanSpeedControls>
+ with TickerProviderStateMixin {
+ bool isPressed = false;
+ LinearGradient gradientEnable1 = const LinearGradient(colors: <Color>[
+ Color(0xFF2962FF),
+ Color(0x802962FF),
+ ]);
+ LinearGradient gradientEnable2 = const LinearGradient(colors: <Color>[
+ Color(0xFF1A237E),
+ Color(0xFF141F64),
+ ]);
+ bool isMainACSelected = false;
+ late AnimationController animationController;
+ double controlProgress = 0.0;
+ int selectedFanSpeed = 0;
+ late rive.RiveAnimationController _controller;
+
+ bool _isPlaying = false;
+
+ /// Tracks if the animation is playing by whether controller is running
+ bool get isPlaying => _controller.isActive;
+
+ @override
+ void initState() {
+ super.initState();
+ _controller = rive.OneShotAnimation(
+ 'Fan Spin',
+ autoplay: false,
+ onStop: () => setState(() => _isPlaying = false),
+ onStart: () => setState(() => _isPlaying = true),
+ );
+ animationController = AnimationController(
+ vsync: this,
+ duration: const Duration(seconds: 1),
+ );
+
+ animationController.addListener(() {
+ setState(() {
+ // _currentColorIndex = (_currentColorIndex + 1) % colorsList.length;
+ }); // Trigger a rebuild to repaint the CustomPaint
+ });
+ animationController.forward();
+ }
+
+ @override
+ void dispose() {
+ animationController.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ double size = MediaQuery.sizeOf(context).height * 0.13021;
+ double fanSpeedWidth = MediaQuery.sizeOf(context).width * 0.35;
+ double fanSpeedHeight = MediaQuery.sizeOf(context).height * 0.15;
+ double strokeWidth = MediaQuery.sizeOf(context).height * 0.03;
+
+ double iconSize = 80;
+
+ final vehicle = ref.watch(vehicleProvider.select((vehicle) => vehicle));
+ selectedFanSpeed = vehicle.fanSpeed;
+ controlProgress = selectedFanSpeed * 0.3;
+
+ return Stack(
+ children: [
+ Center(
+ child: CustomPaint(
+ size: Size(
+ fanSpeedWidth, fanSpeedHeight), // Set the desired size here
+ painter: AnimatedColorPainter(
+ animationController,
+ controlProgress,
+ AGLDemoColors.blueGlowFillColor,
+ AGLDemoColors.backgroundInsetColor,
+ strokeWidth,
+ ),
+ ),
+ ),
+ Center(
+ child: Container(
+ margin: const EdgeInsets.only(top: 3),
+ // decoration: BoxDecoration(
+ // shape: BoxShape.circle,
+ // gradient: LinearGradient(
+ // colors: !isMainACSelected
+ // ? [
+ // AGLDemoColors.neonBlueColor,
+ // AGLDemoColors.neonBlueColor.withOpacity(0.2)
+ // ]
+ // : [
+ // const Color.fromARGB(255, 255, 193, 193)
+ // .withOpacity(0.2),
+ // const Color.fromARGB(255, 255, 193, 193)
+ // ]),
+ // boxShadow: isMainACSelected
+ // ? [
+ // BoxShadow(
+ // offset: Offset(
+ // isMainACSelected ? 1 : 1, isMainACSelected ? 2 : 2),
+ // blurRadius: isMainACSelected ? 16 : 16,
+ // spreadRadius: 0,
+ // color: isMainACSelected
+ // ? Colors.black.withOpacity(0.5)
+ // : Colors.black)
+ // ]
+ // : [],
+ // ),
+ //border: Border.all(color: Colors.white12, width: 1)),
+ //width: 90,
+ //height: 90,
+ child: Container(
+ margin: const EdgeInsets.all(1),
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ image: const DecorationImage(
+ image: AssetImage("assets/PlusVector.png"),
+ ),
+ gradient: Gradient.lerp(gradientEnable1, gradientEnable2, 0.5),
+ // border: Border.all(
+ // color: isMainACSelected
+ // ? AGLDemoColors.buttonFillEnabledColor
+ // : Colors.white12,
+ // width: isMainACSelected ? 3 : 1),
+ border: const GradientBoxBorder(
+ width: 2,
+ gradient: LinearGradient(
+ colors: [
+ Color(0x30C1D8FF),
+ Color(0xFFC1D8FF),
+ ],
+ ),
+ ),
+ ),
+ alignment: Alignment.center,
+ child: Material(
+ color: Colors.transparent,
+ child: InkWell(
+ splashColor: Colors.transparent,
+ hoverColor: Colors.transparent,
+ highlightColor: Colors.transparent,
+ customBorder: const CircleBorder(),
+ onTap: () {
+ _isPlaying ? null : _controller.isActive = true;
+ setState(() {
+ if (controlProgress >= 0.80) {
+ controlProgress = 0.0;
+ isMainACSelected = false;
+ animationController.reverse();
+ } else {
+ isMainACSelected = true;
+ _controller.isActive = true;
+ _isPlaying = true;
+ controlProgress += 0.30;
+ animationController.forward();
+ }
+ ref
+ .read(vehicleProvider.notifier)
+ .updateFanSpeed(controlProgress ~/ 0.3);
+
+ // isMainACSelected = !isMainACSelected;
+ // if (controlProgress != 0.0) {
+ // previousProgress = controlProgress;
+ // }
+ // if (isMainACSelected) {
+ // controlProgress = previousProgress;
+ // animationController.forward();
+ // } else {
+ // controlProgress = 0.0;
+ // animationController.reverse();
+ // }
+ });
+ },
+ onTapDown: (details) {
+ setState(() {
+ gradientEnable1 = LinearGradient(colors: <Color>[
+ const Color(0xFF2962FF).withOpacity(0.15),
+ const Color(0x802962FF).withOpacity(0.15),
+ ]);
+ gradientEnable2 = const LinearGradient(colors: <Color>[
+ Color(0xFF1A237E),
+ Color(0xFF1C2D92),
+ ]);
+ });
+ //change style
+ },
+ onTapUp: (details) {
+ setState(() {
+ gradientEnable1 = const LinearGradient(colors: <Color>[
+ Color(0xFF2962FF),
+ Color(0x802962FF),
+ ]);
+ gradientEnable2 = const LinearGradient(colors: <Color>[
+ Color(0xFF1A237E),
+ Color(0xFF141F64),
+ ]);
+ });
+ },
+ child: Container(
+ width: size,
+ height: size,
+ alignment: Alignment.center,
+ child: !_isPlaying && controlProgress == 0.0
+ ? SvgPicture.asset(
+ "assets/ACMainButtonOff.svg",
+ width: iconSize,
+ height: iconSize,
+ )
+ // : !_isPlaying && controlProgress > 0.8
+ // ? SvgPicture.asset(
+ // "assets/ACMainButton.svg",
+ // width: iconSize,
+ // height: iconSize,
+ // )
+ : SizedBox(
+ width: iconSize,
+ height: iconSize,
+ child: rive.RiveAnimation.asset(
+ 'assets/new_file.riv',
+ controllers: [_controller],
+ onInit: (_) => setState(() {
+ _controller.isActive = true;
+ }))))
+ // Container(
+ // width: size,
+ // height: size,
+ // alignment: Alignment.center,
+ // child: SvgPicture.asset(
+ // "assets/ACMainButton.svg",
+ // width: iconSize,
+ // height: iconSize,
+ // ),
+ // ),
+ ),
+ ),
+ ),
+ ))
+ ],
+ );
+ }
+}
diff --git a/lib/presentation/screens/hvac/widgets/semi_circle_painter.dart b/lib/presentation/screens/hvac/widgets/semi_circle_painter.dart
new file mode 100644
index 0000000..e2003c5
--- /dev/null
+++ b/lib/presentation/screens/hvac/widgets/semi_circle_painter.dart
@@ -0,0 +1,109 @@
+import 'package:flutter_ics_homescreen/export.dart';
+import 'dart:math' as math;
+
+class AnimatedColorPainter extends CustomPainter {
+ final AnimationController animationController;
+ final double progress;
+ final Color progressColor; // New parameter for progress color
+ final Color backgroundColor;
+ final double strokeWidth;
+
+ AnimatedColorPainter(this.animationController, this.progress,
+ this.progressColor, this.backgroundColor, this.strokeWidth);
+
+ @override
+ void paint(Canvas canvas, Size size) {
+ // const strokeWidth = 25.0;
+ const borderWidth = 2.0;
+
+ // Divide the arc into equal parts based on the number of colors
+ const arcAngle = math.pi;
+ const arcPart = arcAngle / 3;
+ const gapAngle = arcAngle / 150;
+
+ // Calculate the current color index based on animation progress and progress value
+ final double normalizedProgress = progress * 3;
+ int currentColorIndex =
+ (animationController.value * normalizedProgress).floor();
+ if (progress == 0.0) {
+ currentColorIndex = -1; // Force background color when progress is 0
+ }
+ // Draw each part with a border and inner color
+ double startAngle = -math.pi; // Start from left
+ for (int i = 0; i < 3; i++) {
+ Color? currentColor = backgroundColor;
+ if (i <= currentColorIndex) {
+ // Use progress color if within progress range
+ currentColor = progressColor;
+ } else {
+ // Use background color if outside progress range
+ currentColor = backgroundColor;
+ }
+
+ // Draw border
+ final borderPaint = Paint()
+ ..strokeWidth = strokeWidth + borderWidth
+ ..style = PaintingStyle.stroke
+ ..color = Colors.white12;
+ canvas.drawArc(
+ Rect.fromCircle(
+ center: Offset(size.width / 2, size.height / 2),
+ radius: size.width / 2,
+ ),
+ startAngle,
+ arcPart - 2 * gapAngle,
+ false, // Draw clockwise
+ borderPaint,
+ );
+
+ // Draw inner color
+ final colorPaint = Paint()
+ ..strokeWidth = strokeWidth
+ ..style = PaintingStyle.stroke
+ ..shader = _createColorShader(currentColor, size);
+ canvas.drawArc(
+ Rect.fromCircle(
+ center: Offset(size.width / 2, size.height / 2),
+ radius: size.width / 2,
+ ),
+ startAngle,
+ arcPart - 2 * gapAngle,
+ false, // Draw clockwise
+ colorPaint,
+ );
+
+ startAngle += arcPart + gapAngle;
+ }
+ }
+
+ @override
+ bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
+
+ Shader _createColorShader(Color color, Size size) {
+ if (color == progressColor) {
+ return const RadialGradient(
+ center: Alignment.center,
+ radius: 2,
+ tileMode: TileMode.repeated,
+ focal: Alignment.center,
+ focalRadius: 8,
+ colors: [
+ AGLDemoColors.blueGlowFillColor,
+ AGLDemoColors.jordyBlueColor,
+ AGLDemoColors.neonBlueColor
+ ],
+ ).createShader(
+ Rect.fromCircle(
+ center: Offset(size.width / 2, size.height / 2),
+ radius: size.width / 2,
+ ),
+ );
+ }
+ return LinearGradient(colors: [color, color]).createShader(
+ Rect.fromCircle(
+ center: Offset(size.width / 2, size.height / 2),
+ radius: size.width / 2,
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/screens/hvac/widgets/temperature_control.dart b/lib/presentation/screens/hvac/widgets/temperature_control.dart
new file mode 100644
index 0000000..df83840
--- /dev/null
+++ b/lib/presentation/screens/hvac/widgets/temperature_control.dart
@@ -0,0 +1,255 @@
+import 'package:flutter_ics_homescreen/export.dart';
+
+class TemperatureControl extends StatefulWidget {
+ const TemperatureControl({super.key, required this.temperature});
+ final int temperature;
+
+ @override
+ State<TemperatureControl> createState() => _TemperatureControlState();
+}
+
+class _TemperatureControlState extends State<TemperatureControl> {
+ int temperature = 0;
+ bool isUpButtonHighlighted = false;
+ bool isDownButtonHighlighted = false;
+
+ @override
+ void initState() {
+ super.initState();
+ setState(() {
+ temperature = widget.temperature;
+ });
+ }
+
+ onPressed({required String type}) {
+ setState(() {
+ if (type == "add") {
+ temperature = temperature + 1;
+ } else if (type == "subtract") {
+ temperature = temperature - 1;
+ }
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ double iconSize = 32;
+ double height = MediaQuery.sizeOf(context).height * 0.0417;
+ double width = MediaQuery.sizeOf(context).width * 0.2112;
+
+ return Column(
+ children: [
+ Material(
+ color: Colors.transparent,
+ child: InkWell(
+ onHighlightChanged: (value) {
+ setState(() {
+ isUpButtonHighlighted = value;
+ });
+ },
+ onTap: () {
+ onPressed(type: "add");
+ },
+ child: SizedBox(
+ height: height,
+ width: width,
+ child: Image.asset(
+ "assets/${isUpButtonHighlighted ? 'UpPressed' : 'Up'}.png")),
+ ),
+ ),
+ // ClipRect(
+ // clipper: MyCustomClipper(type: "top"),
+ // child: ClipRRect(
+ // borderRadius: const BorderRadius.only(
+ // bottomLeft: Radius.circular(22),
+ // bottomRight: Radius.circular(22)),
+ // child: Container(
+ // height: height,
+ // width: width,
+ // decoration: BoxDecoration(
+ // boxShadow: [
+ // BoxShadow(
+ // offset: const Offset(1, 2),
+ // blurRadius: 3,
+ // color: Colors.black.withOpacity(0.7)),
+ // ],
+ // gradient: LinearGradient(colors: [
+ // AGLDemoColors.neonBlueColor,
+ // AGLDemoColors.neonBlueColor.withOpacity(0.20)
+ // ]),
+ // borderRadius: const BorderRadius.only(
+ // topLeft: Radius.circular(100),
+ // topRight: Radius.circular(100),
+ // bottomLeft: Radius.circular(10),
+ // bottomRight: Radius.circular(10))),
+ // child: Container(
+ // margin: const EdgeInsets.all(1),
+ // decoration: const BoxDecoration(
+ // color: AGLDemoColors.buttonFillEnabledColor,
+ // borderRadius: BorderRadius.only(
+ // topLeft: Radius.circular(100),
+ // topRight: Radius.circular(100),
+ // bottomLeft: Radius.circular(10),
+ // bottomRight: Radius.circular(10))),
+ // child: Material(
+ // color: Colors.transparent,
+ // child: InkWell(
+ // onTap: () {
+ // onPressed(type: "add");
+ // },
+ // child: Padding(
+ // padding: const EdgeInsets.only(bottom: 10),
+ // child: Icon(
+ // Icons.arrow_upward,
+ // color: Colors.white,
+ // size: iconSize,
+ // shadows: [
+ // BoxShadow(
+ // offset: const Offset(1, 2),
+ // blurRadius: 3,
+ // color: Colors.black.withOpacity(0.7)),
+ // ],
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+ Padding(
+ padding: const EdgeInsets.symmetric(vertical: 10),
+ child: Text(
+ "$temperature°C",
+ style: GoogleFonts.brunoAce(fontSize: 44, height: 1.25),
+ ),
+ ),
+ Material(
+ color: Colors.transparent,
+ child: InkWell(
+ onHighlightChanged: (value) {
+ setState(() {
+ isDownButtonHighlighted = value;
+ });
+ },
+ onTap: () {
+ onPressed(type: "subtract");
+ },
+ child: SizedBox(
+ height: height,
+ width: width,
+ child: Image.asset(
+ "assets/${isDownButtonHighlighted ? 'DownPressed' : 'Down'}.png")),
+ ),
+ ),
+ // ClipRect(
+ // clipper: MyCustomClipper(type: "bottom"),
+ // child: ClipRRect(
+ // borderRadius: const BorderRadius.only(
+ // topLeft: Radius.circular(20), topRight: Radius.circular(20)),
+ // child: Container(
+ // height: height,
+ // width: width,
+ // decoration: BoxDecoration(
+ // boxShadow: [
+ // BoxShadow(
+ // offset: const Offset(1, 2),
+ // blurRadius: 3,
+ // color: Colors.black.withOpacity(0.7)),
+ // ],
+ // gradient: LinearGradient(colors: [
+ // AGLDemoColors.neonBlueColor,
+ // AGLDemoColors.neonBlueColor.withOpacity(0.20)
+ // ]),
+ // border: Border.all(color: Colors.white12),
+ // borderRadius: const BorderRadius.only(
+ // bottomLeft: Radius.circular(100),
+ // bottomRight: Radius.circular(100),
+ // topLeft: Radius.circular(10),
+ // topRight: Radius.circular(10))),
+ // child: Container(
+ // margin: const EdgeInsets.all(1),
+ // decoration: const BoxDecoration(
+ // color: AGLDemoColors.buttonFillEnabledColor,
+ // borderRadius: BorderRadius.only(
+ // bottomLeft: Radius.circular(100),
+ // bottomRight: Radius.circular(100),
+ // topLeft: Radius.circular(10),
+ // topRight: Radius.circular(10))),
+ // child: Material(
+ // color: Colors.transparent,
+ // child: InkWell(
+ // onTap: () {
+ // onPressed(type: "subtract");
+ // },
+ // child: Padding(
+ // padding: const EdgeInsets.only(top: 10),
+ // child: Icon(
+ // Icons.arrow_downward,
+ // color: Colors.white,
+ // size: iconSize,
+ // shadows: [
+ // BoxShadow(
+ // offset: const Offset(1, 2),
+ // blurRadius: 3,
+ // color: Colors.black.withOpacity(0.7)),
+ // ],
+ // ),
+ // ),
+ // ),
+ // ),
+ // )),
+ // )),
+ ],
+ );
+ }
+}
+
+class MyCustomClipper extends CustomClipper<Rect> {
+ final String type;
+
+ MyCustomClipper({super.reclip, required this.type});
+ @override
+ Rect getClip(Size size) {
+ // Clip 10 pixels from the top of the container
+ return Rect.fromPoints(
+ Offset(0, type == "top" ? 0 : 10),
+ Offset(size.width, type == "top" ? size.height - 10 : size.height),
+ );
+ }
+
+ @override
+ bool shouldReclip(CustomClipper<Rect> oldClipper) {
+ return false;
+ }
+}
+
+class CustomShapePainter extends CustomPainter {
+ @override
+ void paint(Canvas canvas, Size size) {
+ final paint = Paint()
+ ..color = Colors.blue
+ ..strokeWidth = 5.0;
+
+ final path = Path();
+
+ // Draw the top part of the oval
+ path.moveTo(0.0, size.height / 2.0);
+ path.quadraticBezierTo(
+ size.width / 3.0, size.height / 2.0, size.width / 2.0, size.height);
+
+ // Draw the straight line for the bottom part
+ path.lineTo(size.width / 2.0, size.height);
+
+ // Draw the left part of the oval
+ path.quadraticBezierTo(size.width / 3.0, 0.0, 0.0, 0.0);
+
+ // Close the path
+ path.close();
+
+ canvas.drawPath(path, paint);
+ }
+
+ @override
+ bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
+}