Update HVAC fan.
[apps/flutter-ics-homescreen.git] / lib / presentation / screens / settings / settings_screens / audio_settings / widget / slider_widgets.dart
1 import 'package:flutter_ics_homescreen/export.dart';
2 import 'package:flutter_ics_homescreen/presentation/custom_icons/custom_icons.dart';
3
4 class CustomTrebleSlider extends ConsumerStatefulWidget {
5   const CustomTrebleSlider({
6     super.key,
7   });
8
9   @override
10   CustomTrebleSliderState createState() => CustomTrebleSliderState();
11 }
12
13 class CustomTrebleSliderState extends ConsumerState<CustomTrebleSlider> {
14   bool isPressed = false;
15   void _increase() {
16     setState(() {
17       if (_currentVal < 10) {
18         _currentVal++;
19         ref.read(audioStateProvider.notifier).setTreble(_currentVal);
20       }
21     });
22   }
23
24   void _dercrease() {
25     setState(() {
26       if (_currentVal > 0) {
27         _currentVal--;
28         ref.read(audioStateProvider.notifier).setTreble(_currentVal);
29       }
30     });
31   }
32
33   double _currentVal = 5;
34   @override
35   Widget build(BuildContext context) {
36     final trebleValue =
37         ref.watch(audioStateProvider.select((audio) => audio.treble));
38     return Column(
39       //crossAxisAlignment: CrossAxisAlignment.center,
40       children: [
41         const Padding(
42           padding: EdgeInsets.symmetric(vertical: 8),
43           child: Text(
44             'Treble',
45             style: TextStyle(fontSize: 40),
46           ),
47         ),
48         Container(
49           width: 792,
50           height: 160,
51           decoration: const ShapeDecoration(
52             gradient: LinearGradient(
53               colors: <Color>[
54                 AGLDemoColors.neonBlueColor,
55                 AGLDemoColors.resolutionBlueColor,
56                 Color.fromARGB(127, 20, 31, 100),
57                 Color(0xFF2962FF)
58               ],
59               stops: [0, 0, 1, 1],
60             ),
61             shape: StadiumBorder(
62                 side: BorderSide(
63               color: Color(0xFF5477D4),
64               width: 1,
65             )),
66           ),
67           child: Row(
68             mainAxisAlignment: MainAxisAlignment.spaceBetween,
69             children: [
70               Padding(
71                 padding: const EdgeInsets.only(left: 40),
72                 child: InkWell(
73                   onTap: () {
74                     _dercrease();
75                   },
76                   child: const Icon(
77                     Icons.remove,
78                     color: AGLDemoColors.periwinkleColor,
79                     size: 48,
80                   ),
81                 ),
82               ),
83               SizedBox(
84                 width: 584,
85                 child: SliderTheme(
86                   data: SliderThemeData(
87                     showValueIndicator: ShowValueIndicator.always,
88                     trackShape: CustomRoundedRectSliderTrackShape(
89                         silderVal: trebleValue),
90                     activeTickMarkColor: Colors.transparent,
91                     inactiveTickMarkColor: Colors.transparent,
92                     inactiveTrackColor: AGLDemoColors.backgroundInsetColor,
93                     thumbShape: PolygonSliderThumb(
94                         sliderValue: 3, thumbRadius: 23, isPressed: isPressed),
95                     trackHeight: 16,
96                   ),
97                   child: Slider(
98                     divisions: 10,
99                     min: 0,
100                     max: 10,
101                     value: trebleValue,
102                     onChanged: (newValue) {
103                       ref.read(audioStateProvider.notifier).setTreble(newValue);
104                       _currentVal = newValue;
105                     },
106                     onChangeEnd: (value) {
107                       setState(() {
108                         isPressed = false;
109                       });
110                     },
111                     onChangeStart: (value) {
112                       setState(() {
113                         isPressed = true;
114                       });
115                     },
116                   ),
117                 ),
118               ),
119               Padding(
120                 padding: const EdgeInsets.only(
121                   right: 40,
122                 ),
123                 child: InkWell(
124                     onTap: () {
125                       _increase();
126                     },
127                     child: const Icon(
128                       Icons.add,
129                       color: AGLDemoColors.periwinkleColor,
130                       size: 48,
131                     )),
132               ),
133             ],
134           ),
135         ),
136       ],
137     );
138   }
139 }
140
141 class CustomBassSlider extends ConsumerStatefulWidget {
142   const CustomBassSlider({
143     super.key,
144   });
145
146   @override
147   CustomBassSliderState createState() => CustomBassSliderState();
148 }
149
150 class CustomBassSliderState extends ConsumerState<CustomBassSlider> {
151   bool isPressed = false;
152
153   void _increase() {
154     setState(() {
155       if (_currentVal < 10) {
156         _currentVal++;
157         ref.read(audioStateProvider.notifier).setBass(_currentVal);
158       }
159     });
160   }
161
162   void _dercrease() {
163     setState(() {
164       if (_currentVal > 0) {
165         _currentVal--;
166         ref.read(audioStateProvider.notifier).setBass(_currentVal);
167       }
168     });
169   }
170
171   double _currentVal = 5;
172   @override
173   Widget build(BuildContext context) {
174     final bassValue =
175         ref.watch(audioStateProvider.select((audio) => audio.bass));
176
177     return Column(
178       //crossAxisAlignment: CrossAxisAlignment.center,
179       children: [
180         const Padding(
181           padding: EdgeInsets.symmetric(vertical: 8),
182           child: Text(
183             'Bass',
184             style: TextStyle(fontSize: 40),
185           ),
186         ),
187         Container(
188           width: 792,
189           height: 160,
190           decoration: const ShapeDecoration(
191             gradient: LinearGradient(
192               colors: <Color>[
193                 AGLDemoColors.neonBlueColor,
194                 AGLDemoColors.resolutionBlueColor,
195                 Color.fromARGB(127, 20, 31, 100),
196                 Color(0xFF2962FF)
197               ],
198               stops: [0, 0, 1, 1],
199             ),
200             shape: StadiumBorder(
201                 side: BorderSide(
202               color: Color(0xFF5477D4),
203               width: 1,
204             )),
205           ),
206           child: Row(
207             mainAxisAlignment: MainAxisAlignment.spaceBetween,
208             children: [
209               Padding(
210                 padding: const EdgeInsets.only(left: 40),
211                 child: InkWell(
212                     onTap: () {
213                       _dercrease();
214                     },
215                     child: const Icon(
216                       Icons.remove,
217                       color: AGLDemoColors.periwinkleColor,
218                       size: 48,
219                     )),
220               ),
221               SizedBox(
222                 width: 584,
223                 child: SliderTheme(
224                   data: SliderThemeData(
225                     showValueIndicator: ShowValueIndicator.always,
226                     trackShape:
227                         CustomRoundedRectSliderTrackShape(silderVal: bassValue),
228                     activeTickMarkColor: Colors.transparent,
229                     inactiveTickMarkColor: Colors.transparent,
230                     inactiveTrackColor: AGLDemoColors.backgroundInsetColor,
231                     thumbShape: PolygonSliderThumb(
232                         sliderValue: 3, thumbRadius: 23, isPressed: isPressed),
233                     trackHeight: 16,
234                   ),
235                   child: Slider(
236                     divisions: 10,
237                     min: 0,
238                     max: 10,
239                     value: bassValue,
240                     onChanged: (newValue) {
241                       ref.read(audioStateProvider.notifier).setBass(newValue);
242                       _currentVal = newValue;
243                     },
244                     onChangeEnd: (value) {
245                       setState(() {
246                         isPressed = false;
247                       });
248                     },
249                     onChangeStart: (value) {
250                       setState(() {
251                         isPressed = true;
252                       });
253                     },
254                   ),
255                 ),
256               ),
257               Padding(
258                 padding: const EdgeInsets.only(right: 40),
259                 child: InkWell(
260                     onTap: () {
261                       _increase();
262                     },
263                     child: const Icon(
264                       Icons.add,
265                       color: AGLDemoColors.periwinkleColor,
266                       size: 48,
267                     )),
268               ),
269             ],
270           ),
271         ),
272       ],
273     );
274   }
275 }
276
277 class CustomRearFrontSlider extends ConsumerStatefulWidget {
278   const CustomRearFrontSlider({
279     super.key,
280   });
281
282   @override
283   CustomRearFrontState createState() => CustomRearFrontState();
284 }
285
286 class CustomRearFrontState extends ConsumerState<CustomRearFrontSlider> {
287   bool isPressed = false;
288
289   void _increase() {
290     setState(() {
291       if (_currentVal < 10) {
292         _currentVal++;
293         ref.read(audioStateProvider.notifier).setRearFront(_currentVal);
294       }
295     });
296   }
297
298   void _dercrease() {
299     setState(() {
300       if (_currentVal > 0) {
301         _currentVal--;
302         ref.read(audioStateProvider.notifier).setRearFront(_currentVal);
303       }
304     });
305   }
306
307   double _currentVal = 5;
308   @override
309   Widget build(BuildContext context) {
310     final rearFrontValue =
311         ref.watch(audioStateProvider.select((audio) => audio.rearFront));
312     return Column(
313       //crossAxisAlignment: CrossAxisAlignment.center,
314       children: [
315         const Padding(
316           padding: EdgeInsets.symmetric(vertical: 8),
317           child: Text(
318             'Rear/Front',
319             style: TextStyle(fontSize: 40),
320           ),
321         ),
322         Container(
323           width: 792,
324           height: 160,
325           decoration: const ShapeDecoration(
326             gradient: LinearGradient(
327               colors: <Color>[
328                 AGLDemoColors.neonBlueColor,
329                 AGLDemoColors.resolutionBlueColor,
330                 Color.fromARGB(127, 20, 31, 100),
331                 Color(0xFF2962FF)
332               ],
333               stops: [0, 0, 1, 1],
334             ),
335             shape: StadiumBorder(
336                 side: BorderSide(
337               color: Color(0xFF5477D4),
338               width: 1,
339             )),
340           ),
341           child: Row(
342             mainAxisAlignment: MainAxisAlignment.spaceBetween,
343             children: [
344               Padding(
345                 padding: const EdgeInsets.only(left: 40),
346                 child: InkWell(
347                     onTap: () {
348                       _dercrease();
349                     },
350                     child: const Icon(
351                       CustomIcons.slider_rear,
352                       color: AGLDemoColors.periwinkleColor,
353                       size: 48,
354                     )),
355               ),
356               SizedBox(
357                 width: 584,
358                 child: SliderTheme(
359                   data: SliderThemeData(
360                     showValueIndicator: ShowValueIndicator.always,
361                     trackShape: CustomRoundedRectSliderTrackShape(
362                         silderVal: rearFrontValue, isFrontRear: true),
363                     activeTickMarkColor: Colors.transparent,
364                     inactiveTickMarkColor: Colors.transparent,
365                     inactiveTrackColor: AGLDemoColors.backgroundInsetColor,
366                     thumbShape: PolygonSliderThumb(
367                         sliderValue: 3, thumbRadius: 23, isPressed: isPressed),
368                     trackHeight: 16,
369                   ),
370                   child: Slider(
371                     divisions: 10,
372                     min: 0,
373                     max: 10,
374                     value: rearFrontValue,
375                     onChanged: (newValue) {
376                       ref
377                           .read(audioStateProvider.notifier)
378                           .setRearFront(newValue);
379                       _currentVal = newValue;
380                     },
381                     onChangeEnd: (value) {
382                       setState(() {
383                         isPressed = false;
384                       });
385                     },
386                     onChangeStart: (value) {
387                       setState(() {
388                         isPressed = true;
389                       });
390                     },
391                   ),
392                 ),
393               ),
394               Padding(
395                 padding: const EdgeInsets.only(right: 40),
396                 child: InkWell(
397                     onTap: () {
398                       _increase();
399                     },
400                     child: const Icon(
401                       CustomIcons.slider_front,
402                       color: AGLDemoColors.periwinkleColor,
403                       size: 48,
404                     )),
405               ),
406             ],
407           ),
408         ),
409       ],
410     );
411   }
412 }
413
414 class PolygonSliderThumb extends SliderComponentShape {
415   final double thumbRadius;
416   final double sliderValue;
417   final bool isPressed;
418   const PolygonSliderThumb(
419       {required this.thumbRadius,
420       required this.sliderValue,
421       this.isPressed = false});
422
423   @override
424   Size getPreferredSize(bool isEnabled, bool isDiscrete) {
425     return Size.fromRadius(thumbRadius);
426   }
427
428   @override
429   void paint(
430     PaintingContext context,
431     Offset center, {
432     required Animation<double> activationAnimation,
433     required Animation<double> enableAnimation,
434     required bool isDiscrete,
435     required TextPainter labelPainter,
436     required RenderBox parentBox,
437     required SliderThemeData sliderTheme,
438     required TextDirection textDirection,
439     required double value,
440     required double textScaleFactor,
441     required Size sizeWithOverflow,
442   }) {
443     // Define the slider thumb design here
444     final Canvas canvas = context.canvas;
445     var paintStroke = Paint()
446       ..color =
447           isPressed ? AGLDemoColors.jordyBlueColor : AGLDemoColors.neonBlueColor
448       ..strokeWidth = 2
449       ..style = PaintingStyle.stroke
450       ..strokeCap = StrokeCap.round;
451     var paintFill = Paint()
452       ..color = isPressed ? Colors.white : AGLDemoColors.periwinkleColor
453       ..strokeWidth = 2
454       ..style = PaintingStyle.fill
455       ..strokeCap = StrokeCap.round;
456     var path = Path();
457     path.addOval(Rect.fromCircle(
458       center: center,
459       radius: 9,
460     ));
461     canvas.drawCircle(center, isPressed ? 37 : 32, paintFill);
462     canvas.drawShadow(path, Colors.black26, 0.5, false);
463     canvas.drawCircle(center, isPressed ? 21 : 16, paintStroke);
464   }
465 }
466
467 //TODO add border to custom track Shape
468 class CustomRoundedRectSliderTrackShape extends SliderTrackShape
469     with BaseSliderTrackShape {
470   final double silderVal;
471   final bool? isFrontRear;
472
473   CustomRoundedRectSliderTrackShape({
474     required this.silderVal,
475     this.isFrontRear = false,
476   });
477   @override
478   void paint(
479     PaintingContext context,
480     Offset offset, {
481     required RenderBox parentBox,
482     required SliderThemeData sliderTheme,
483     required Animation<double> enableAnimation,
484     required TextDirection textDirection,
485     required Offset thumbCenter,
486     Offset? secondaryOffset,
487     bool isDiscrete = false,
488     bool isEnabled = false,
489     double additionalActiveTrackHeight = 2,
490   }) {
491     assert(sliderTheme.disabledActiveTrackColor != null);
492     assert(sliderTheme.disabledInactiveTrackColor != null);
493     assert(sliderTheme.activeTrackColor != null);
494     assert(sliderTheme.inactiveTrackColor != null);
495     assert(sliderTheme.thumbShape != null);
496     if (sliderTheme.trackHeight == null || sliderTheme.trackHeight! <= 0) {
497       return;
498     }
499
500     final Rect trackRect = getPreferredRect(
501       parentBox: parentBox,
502       offset: offset,
503       sliderTheme: sliderTheme,
504       isEnabled: isEnabled,
505       isDiscrete: isDiscrete,
506     );
507     final Radius trackRadius = Radius.circular(trackRect.height / 2);
508     final Radius activeTrackRadius =
509         Radius.circular((trackRect.height + additionalActiveTrackHeight) / 2);
510     final activeGradientRect = Rect.fromLTRB(
511       trackRect.left,
512       textDirection == TextDirection.ltr
513           ? trackRect.top - (additionalActiveTrackHeight / 2)
514           : trackRect.top,
515       thumbCenter.dx,
516       (textDirection == TextDirection.ltr)
517           ? trackRect.bottom + (additionalActiveTrackHeight / 2)
518           : trackRect.bottom,
519     );
520
521     LinearGradient gradient = const LinearGradient(
522         colors: [AGLDemoColors.jordyBlueColor, Colors.white]);
523     // Assign the track segment paints, which are leading: active and
524     // trailing: inactive.
525     final ColorTween activeTrackColorTween = ColorTween(
526         begin: sliderTheme.disabledActiveTrackColor,
527         end: sliderTheme.activeTrackColor);
528     final ColorTween inactiveTrackColorTween = ColorTween(
529         begin: sliderTheme.disabledInactiveTrackColor,
530         end: sliderTheme.inactiveTrackColor);
531     final Paint activePaint = Paint()
532       ..shader = gradient.createShader(activeGradientRect)
533       ..color = activeTrackColorTween.evaluate(enableAnimation)!;
534     final Paint inactivePaint = Paint()
535       ..color = inactiveTrackColorTween.evaluate(enableAnimation)!;
536     final Paint leftTrackPaint;
537     final Paint rightTrackPaint;
538     switch (textDirection) {
539       case TextDirection.ltr:
540         leftTrackPaint = activePaint;
541         rightTrackPaint = inactivePaint;
542       case TextDirection.rtl:
543         leftTrackPaint = inactivePaint;
544         rightTrackPaint = activePaint;
545     }
546     //center divider
547     final smallRect =
548         Rect.fromLTWH(trackRect.right / 2, trackRect.bottom / 2 + 15, 10, 40);
549     context.canvas.drawRRect(
550         RRect.fromRectAndCorners(smallRect,
551             topLeft: const Radius.circular(25),
552             topRight: const Radius.circular(25),
553             bottomLeft: const Radius.circular(25),
554             bottomRight: const Radius.circular(25)),
555         //silderVal > 5 ? leftTrackPaint : rightTrackPaint);
556         isFrontRear!
557             ? rightTrackPaint
558             : silderVal > 5
559                 ? leftTrackPaint
560                 : rightTrackPaint);
561 //active
562     context.canvas.drawRRect(
563       RRect.fromLTRBAndCorners(
564         trackRect.left,
565         (textDirection == TextDirection.ltr)
566             ? trackRect.top - (additionalActiveTrackHeight / 2)
567             : trackRect.top,
568         thumbCenter.dx,
569         (textDirection == TextDirection.ltr)
570             ? trackRect.bottom + (additionalActiveTrackHeight / 2)
571             : trackRect.bottom,
572         topLeft: (textDirection == TextDirection.ltr)
573             ? activeTrackRadius
574             : trackRadius,
575         bottomLeft: (textDirection == TextDirection.ltr)
576             ? activeTrackRadius
577             : trackRadius,
578       ),
579       isFrontRear! ? rightTrackPaint : leftTrackPaint,
580     );
581     //inactive
582     context.canvas.drawRRect(
583       RRect.fromLTRBAndCorners(
584         thumbCenter.dx,
585         (textDirection == TextDirection.rtl)
586             ? trackRect.top - (additionalActiveTrackHeight / 2)
587             : trackRect.top,
588         trackRect.right,
589         (textDirection == TextDirection.rtl)
590             ? trackRect.bottom + (additionalActiveTrackHeight / 2)
591             : trackRect.bottom,
592         topRight: (textDirection == TextDirection.rtl)
593             ? activeTrackRadius
594             : trackRadius,
595         bottomRight: (textDirection == TextDirection.rtl)
596             ? activeTrackRadius
597             : trackRadius,
598       ),
599       rightTrackPaint,
600     );
601   }
602 }