summaryrefslogtreecommitdiffstats
path: root/lib/presentation/common_widget
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/common_widget
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/common_widget')
-rw-r--r--lib/presentation/common_widget/custom_bottom_bar.dart211
-rw-r--r--lib/presentation/common_widget/custom_title.dart103
-rw-r--r--lib/presentation/common_widget/custom_top_bar.dart106
-rw-r--r--lib/presentation/common_widget/fan_bar.dart188
-rw-r--r--lib/presentation/common_widget/generic_button.dart91
-rw-r--r--lib/presentation/common_widget/settings_top_bar.dart37
-rw-r--r--lib/presentation/common_widget/volume_and_fan_control.dart36
-rw-r--r--lib/presentation/common_widget/volume_bar.dart356
8 files changed, 1128 insertions, 0 deletions
diff --git a/lib/presentation/common_widget/custom_bottom_bar.dart b/lib/presentation/common_widget/custom_bottom_bar.dart
new file mode 100644
index 0000000..13084c0
--- /dev/null
+++ b/lib/presentation/common_widget/custom_bottom_bar.dart
@@ -0,0 +1,211 @@
+// ignore_for_file: prefer_const_constructors
+
+import '../../export.dart';
+
+class CustomBottomBar extends ConsumerStatefulWidget {
+ const CustomBottomBar({super.key});
+
+ @override
+ CustomBottomBarState createState() => CustomBottomBarState();
+}
+
+class CustomBottomBarState extends ConsumerState<CustomBottomBar> {
+ @override
+ void initState() {
+ super.initState();
+ // "ref" can be used in all life-cycles of a StatefulWidget.
+ //ref.read(counterProvider);
+ }
+
+ double iconSize = 57;
+ List<BottomBarItems> navItems = [
+ BottomBarItems(title: "Home", image: "Dashboard"),
+ BottomBarItems(title: "HVAC", image: "HVAC"),
+ BottomBarItems(title: "Media", image: "MediaPlayer"),
+ BottomBarItems(title: "Settings", image: "Settings"),
+ BottomBarItems(title: "Apps", image: "Apps")
+ ];
+ String selectedNav = "Home";
+
+ void _onItemTapped(String title) {
+ AppState status = AppState.dashboard;
+ switch (title) {
+ case "Home":
+ status = AppState.dashboard;
+ case "HVAC":
+ status = AppState.hvac;
+ case "Media":
+ status = AppState.mediaPlayer;
+ case "Settings":
+ status = AppState.settings;
+ case "Apps":
+ status = AppState.apps;
+ }
+ setState(() {
+ selectedNav = title;
+ });
+
+ ref.read(appProvider.notifier).update((state) => state = status);
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.all(24.0),
+ child: Row(
+ children: navItems
+ .map((e) => Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Container(
+
+ margin: const EdgeInsets.symmetric(
+ horizontal: 2,
+ ),
+ decoration: BoxDecoration(
+ gradient: LinearGradient(
+ colors: [
+ selectedNav == e.title
+ ? Color.fromARGB(217, 41, 98, 255)
+ : Color.fromARGB(163, 28, 46, 146),
+ selectedNav == e.title
+ ? Color.fromARGB(0, 41, 98, 255)
+ : Color.fromARGB(0, 41, 98, 255),
+ ],
+ stops: [
+ selectedNav == e.title ? 0.3 : 0,
+ selectedNav == e.title ? 1 : 0.8,
+ ],
+ begin: Alignment.bottomCenter,
+ end: Alignment.topCenter),
+ // color: selectedNav == e
+ // ? AGLDemoColors.neonBlueColor
+ // : AGLDemoColors.buttonFillEnabledColor,
+ border: Border(
+ bottom: const BorderSide(
+ width: 1.0,
+ color: AGLDemoColors.jordyBlueColor),
+ ),
+ ),
+ child: Material(
+ color: Colors.transparent,
+ child: InkWell(
+ onTap: () {
+ _onItemTapped(e.title);
+ },
+ child: Container(
+ padding: const EdgeInsets.symmetric(vertical: 7),
+ decoration: BoxDecoration(
+ border: Border(
+ left: selectedNav == e.title
+ ? const BorderSide(color: Colors.white30)
+ : BorderSide.none,
+ right: selectedNav == e.title
+ ? const BorderSide(color: Colors.white30)
+ : BorderSide.none,
+ // bottom: BorderSide(
+ // color: selectedNav == e.title
+ // ? Colors.white
+ // : Colors.white24,
+ // width:
+ // selectedNav == e.title ? 2 : 1)
+ )),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ SvgPicture.asset(
+ "assets/${e.image}${selectedNav == e.title ? "Selected" : ""}.svg",
+ width: iconSize,
+ height: iconSize,
+ ),
+ Text(
+ e.title,
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ fontSize: 26,
+ shadows: [
+ Shadow(
+ color:
+ Colors.black.withOpacity(0.7),
+ offset: Offset(
+ 1,
+ e.title == selectedNav
+ ? 1.5
+ : 3),
+ blurRadius: e.title == selectedNav
+ ? 1
+ : 3)
+ ],
+ color: e.title == selectedNav
+ ? Colors.white
+ : AGLDemoColors.periwinkleColor,
+ fontWeight: selectedNav == e.title
+ ? FontWeight.bold
+ : FontWeight.w300),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ //if (selectedNav == e.title)
+ Container(
+ margin: const EdgeInsets.symmetric(horizontal: 2),
+ color: selectedNav == e.title
+ ? Colors.white
+ : Colors.transparent,
+ height: 3,
+ )
+ ],
+ )))
+ .toList()),
+ );
+
+ // return Container(
+ // // decoration: const BoxDecoration(
+ // // gradient: LinearGradient(
+ // // begin: Alignment.topCenter,
+ // // end: Alignment.bottomCenter,
+ // // stops: [0.01, 1],
+ // // colors: <Color>[Colors.black, Color(0xFF1A237E)],
+ // // ),
+ // // ),
+ // //color: Color(0xFF0D113F),
+ // child: BottomNavigationBar(
+ // elevation: 0,
+ // showSelectedLabels: true,
+ // showUnselectedLabels: true,
+ // //backgroundColor: Colors.white,
+ // backgroundColor: const Color(0xFF0D113F),
+ // type: BottomNavigationBarType.fixed,
+ // items: const <BottomNavigationBarItem>[
+ // BottomNavigationBarItem(
+ // icon: Icon(Icons.directions_car),
+ // label: 'Home',
+ // backgroundColor: Color(0xFF0D113F)),
+ // BottomNavigationBarItem(icon: Icon(Icons.ac_unit), label: 'HVAC'),
+ // BottomNavigationBarItem(
+ // icon: Icon(Icons.library_music), label: 'Media'),
+ // BottomNavigationBarItem(
+ // icon: Icon(Icons.settings), label: 'Settings'),
+ // BottomNavigationBarItem(icon: Icon(Icons.apps), label: 'Apps'),
+ // ],
+ // currentIndex: _selectedIndex,
+ // selectedItemColor: Colors.white,
+ // unselectedItemColor: Colors.grey,
+
+ // onTap: _onItemTapped,
+ // ),
+ // );
+ }
+}
+
+class BottomBarItems {
+ final String title;
+ final String image;
+
+ BottomBarItems({required this.title, required this.image});
+}
diff --git a/lib/presentation/common_widget/custom_title.dart b/lib/presentation/common_widget/custom_title.dart
new file mode 100644
index 0000000..f60c11e
--- /dev/null
+++ b/lib/presentation/common_widget/custom_title.dart
@@ -0,0 +1,103 @@
+import 'package:flutter_ics_homescreen/export.dart';
+
+class CommonTitle extends StatelessWidget {
+ const CommonTitle(
+ {super.key,
+ required this.title,
+ this.hasBackButton = false,
+ this.onPressed});
+
+ final String title;
+ final bool? hasBackButton;
+ final VoidCallback? onPressed;
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(top: 80),
+ child: SizedBox(
+ //color: Colors.amber,
+ height: 120,
+ child: Stack(
+ fit: StackFit.expand,
+ children: [
+ Container(
+ decoration: BoxDecoration(
+ gradient: LinearGradient(
+ begin: Alignment.bottomCenter,
+ end: Alignment.center,
+ colors: [
+ AGLDemoColors.jordyBlueColor.withOpacity(0.2),
+ AGLDemoColors.jordyBlueColor.withOpacity(0)
+ ],
+ stops: const [
+ 0.0,
+ 1
+ ])),
+ alignment: Alignment.center,
+ child: Text(
+ title,
+ textAlign: TextAlign.center,
+ style: const TextStyle(
+ color: Colors.white,
+ fontSize: 40,
+ fontWeight: FontWeight.w500),
+ ),
+ ),
+ if (hasBackButton!)
+ Align(
+ alignment: AlignmentDirectional.centerStart,
+ child: Padding(
+ padding: const EdgeInsets.only(left: 20.0),
+ child: InkWell(
+ customBorder: const CircleBorder(),
+ onTap: onPressed,
+ child: const Icon(
+ Icons.arrow_back,
+ color: Colors.white,
+ size: 48,
+ )),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ Container(
+ height: 2,
+ decoration: BoxDecoration(
+ gradient: const LinearGradient(
+ begin: Alignment.centerLeft,
+ end: Alignment.centerRight,
+ colors: [
+ Colors.white10,
+ AGLDemoColors.jordyBlueColor,
+ Colors.white10
+ ],
+ ),
+ boxShadow: [
+ BoxShadow(
+ color: Colors.black.withOpacity(0.5),
+ blurRadius: 6,
+ spreadRadius: 3,
+ offset: const Offset(0, 6),
+ ),
+ ],
+ )),
+ Container(
+ height: 48,
+ decoration: BoxDecoration(
+ gradient: LinearGradient(
+ begin: Alignment.topCenter,
+ end: Alignment.bottomCenter,
+ colors: [Colors.black, Colors.black.withOpacity(0.0)],
+ ),
+ ),
+ )
+ ],
+ );
+ }
+}
diff --git a/lib/presentation/common_widget/custom_top_bar.dart b/lib/presentation/common_widget/custom_top_bar.dart
new file mode 100644
index 0000000..c268f53
--- /dev/null
+++ b/lib/presentation/common_widget/custom_top_bar.dart
@@ -0,0 +1,106 @@
+import 'package:intl/intl.dart';
+
+import '../../export.dart';
+
+class CustomTopBar extends ConsumerStatefulWidget
+ implements PreferredSizeWidget {
+ const CustomTopBar({super.key});
+
+ @override
+ CustomTopBarState createState() => CustomTopBarState();
+
+ @override
+ Size get preferredSize => const Size.fromHeight(80);
+}
+
+class CustomTopBarState extends ConsumerState<CustomTopBar> {
+ @override
+ Widget build(BuildContext context) {
+ final singnalsConnection =
+ ref.watch(signalsProvider.select((sinals) => sinals));
+ final user = ref.watch(usersProvider.select((user) => user));
+ final time2 =
+ ref.watch(dateTimeStateProvider.select((dateTime) => dateTime));
+
+ DateFormat dateFormat = DateFormat('HH:mm');
+ //var time = dateFormat.format(DateTime.now());
+ var time = time2.time;
+
+ return AppBar(
+ elevation: 0,
+ backgroundColor: Colors.transparent,
+ //leadingWidth: 100,
+
+ title: Stack(
+ //mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Positioned.fill(
+ child: Align(
+ alignment: Alignment.centerLeft,
+ child: Wrap(
+ children: [
+ RichText(
+ text: TextSpan(
+ text: '$time ',
+ style: const TextStyle(color: Colors.white, fontSize: 26),
+ children: <InlineSpan>[
+ const WidgetSpan(
+ child: SizedBox(width: 16), // 16px space
+ ),
+ TextSpan(
+ text: user.selectedUser.name,
+ style: const TextStyle(fontWeight: FontWeight.bold),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ Align(
+ alignment: Alignment.center,
+ child: Image.asset(
+ 'assets/topBarLogo.png',
+ width: 659,
+ height: 56,
+ ),
+ ),
+ Positioned.fill(
+ child: Align(
+ alignment: Alignment.centerRight,
+ child: Wrap(
+ children: [
+ Icon(
+ singnalsConnection.isBluetoothConnected
+ ? Icons.bluetooth
+ : Icons.bluetooth_disabled,
+ size: 24,
+ ),
+ const SizedBox(
+ width: 24,
+ ),
+ const Icon(
+ Icons.signal_cellular_4_bar_outlined,
+ size: 24,
+ ),
+ const SizedBox(
+ width: 24,
+ ),
+ Icon(
+ singnalsConnection.isWifiConnected
+ ? Icons.wifi
+ : Icons.wifi_off,
+ size: 24,
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+
+ // ),
+ );
+ }
+}
diff --git a/lib/presentation/common_widget/fan_bar.dart b/lib/presentation/common_widget/fan_bar.dart
new file mode 100644
index 0000000..e119089
--- /dev/null
+++ b/lib/presentation/common_widget/fan_bar.dart
@@ -0,0 +1,188 @@
+import '../../export.dart';
+import 'package:flutter_ics_homescreen/presentation/custom_icons/custom_icons.dart';
+
+enum FanMode { off, min, medium, max }
+
+class FanBar extends ConsumerStatefulWidget {
+ const FanBar({super.key});
+
+ @override
+ FanBarState createState() => FanBarState();
+}
+
+class FanBarState extends ConsumerState<FanBar> {
+ int selectedFanSpeed = 0;
+
+ @override
+ Widget build(BuildContext context) {
+ final vehicle = ref.watch(vehicleProvider.select((vehicle) => vehicle));
+ selectedFanSpeed = vehicle.fanSpeed;
+
+ return Column(children: [
+ Container(
+ padding: EdgeInsets.zero,
+ //width: 80,
+ height: 256,
+ decoration: const ShapeDecoration(
+ // gradient: RadialGradient(
+ // colors: [Color.fromARGB(255, 19, 24, 75), Colors.black],
+ // stops: [0, 0.9],
+ // radius: 1,
+ // ),
+ color: AGLDemoColors.buttonFillEnabledColor,
+ shape: StadiumBorder(
+ side: BorderSide(
+ color: Color(0xFF5477D4),
+ width: 1,
+ )),
+ ),
+ //alignment: Alignment.topLeft,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ Material(
+ color: Colors.transparent,
+ child: SizedBox(
+ width: 80,
+ height: 64,
+ child: IconButton(
+ isSelected: selectedFanSpeed == 3,
+ padding: EdgeInsets.zero,
+ color: AGLDemoColors.periwinkleColor,
+ onPressed: () {
+ ref.read(vehicleProvider.notifier).updateFanSpeed(3);
+ },
+ icon: selectedFanSpeed == 3
+ ? Stack(
+ alignment: Alignment.center,
+ children: [
+ SvgPicture.asset('assets/fanButtonBg.svg'),
+ const Icon(
+ CustomIcons.fan_on_enabled,
+ color: Colors.white,
+ size: 40,
+ ),
+ ],
+ )
+ : const Icon(
+ CustomIcons.fan_on_enabled,
+ size: 40,
+ ),
+ ),
+ ),
+ ),
+ Material(
+ color: Colors.transparent,
+ child: SizedBox(
+ width: 64,
+ height: 64,
+ child: IconButton(
+ isSelected: selectedFanSpeed == 2,
+ padding: EdgeInsets.zero,
+ color: AGLDemoColors.periwinkleColor,
+ onPressed: () {
+ ref.read(vehicleProvider.notifier).updateFanSpeed(2);
+ },
+ icon: selectedFanSpeed == 2
+ ? Stack(
+ alignment: Alignment.center,
+ children: [
+ SvgPicture.asset('assets/fanButtonBg.svg'),
+ const Icon(
+ CustomIcons.fan_on_enabled,
+ color: Colors.white,
+ size: 28,
+ ),
+ ],
+ )
+ : const Icon(
+ CustomIcons.fan_on_enabled,
+ size: 28,
+ ),
+ ),
+ ),
+ ),
+ Material(
+ color: Colors.transparent,
+ child: SizedBox(
+ width: 64,
+ height: 64,
+ child: IconButton(
+ isSelected: selectedFanSpeed == 1,
+ iconSize: 20,
+ padding: EdgeInsets.zero,
+ color: AGLDemoColors.periwinkleColor,
+ onPressed: () {
+ ref.read(vehicleProvider.notifier).updateFanSpeed(1);
+ },
+ icon: selectedFanSpeed == 1
+ ? Stack(
+ alignment: Alignment.center,
+ children: [
+ SvgPicture.asset('assets/fanButtonBg.svg'),
+ const Icon(
+ CustomIcons.fan_on_enabled,
+ color: Colors.white,
+ size: 20,
+ ),
+ ],
+ )
+ : const Icon(
+ CustomIcons.fan_on_enabled,
+ size: 20,
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 10),
+ Container(
+ width: 80,
+ height: 80,
+ decoration: const ShapeDecoration(
+ // gradient: RadialGradient(
+ // colors: [Color.fromARGB(255, 19, 24, 75), Colors.black],
+ // stops: [0, 0.9],
+ // radius: 1,
+ // ),
+ color: AGLDemoColors.buttonFillEnabledColor,
+ shape: StadiumBorder(
+ side: BorderSide(
+ color: Color(0xFF5477D4),
+ width: 1,
+ )),
+ ),
+ //alignment: Alignment.topLeft,
+ child: Material(
+ color: Colors.transparent,
+ child: IconButton(
+ isSelected: selectedFanSpeed == 0,
+ padding: EdgeInsets.zero,
+ color: AGLDemoColors.periwinkleColor,
+ onPressed: () {
+ ref.read(vehicleProvider.notifier).updateFanSpeed(0);
+ },
+ icon: selectedFanSpeed == 0
+ ? Stack(
+ alignment: Alignment.center,
+ children: [
+ SvgPicture.asset('assets/fanButtonBg.svg'),
+ const Icon(
+ Icons.mode_fan_off,
+ color: Colors.white,
+ size: 28.4,
+ ),
+ ],
+ )
+ : const Icon(
+ Icons.mode_fan_off,
+ size: 28.4,
+ ),
+ ),
+ )),
+ ]);
+ }
+}
diff --git a/lib/presentation/common_widget/generic_button.dart b/lib/presentation/common_widget/generic_button.dart
new file mode 100644
index 0000000..cca354f
--- /dev/null
+++ b/lib/presentation/common_widget/generic_button.dart
@@ -0,0 +1,91 @@
+import 'package:flutter_ics_homescreen/export.dart';
+
+class GenericButton extends StatefulWidget {
+ final double heigth;
+ final double width;
+ final String text;
+ final Function onTap;
+
+ const GenericButton({
+ super.key,
+ required this.heigth,
+ required this.width,
+ required this.text,
+ required this.onTap,
+ });
+
+ @override
+ State<GenericButton> createState() => _GenericButtonState();
+}
+
+class _GenericButtonState extends State<GenericButton> {
+ LinearGradient gradientEnable1 = const LinearGradient(colors: <Color>[
+ Color(0xFF2962FF),
+ Color(0x802962FF),
+ ]);
+ LinearGradient gradientEnable2 = const LinearGradient(colors: <Color>[
+ Color(0xFF1A237E),
+ Color(0xFF141F64),
+ ]);
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTapDown: (details) {
+ setState(() {
+ gradientEnable1 = const LinearGradient(colors: <Color>[
+ Color(0x802962FF),
+ Color(0xFF2962FF),
+ ]);
+ 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),
+ ]);
+ });
+ widget.onTap();
+ },
+ child: Container(
+ height: widget.heigth,
+ width: widget.width,
+ decoration: BoxDecoration(
+ gradient: Gradient.lerp(gradientEnable1, gradientEnable2, 0.5),
+ boxShadow: const [
+ BoxShadow(
+ color: Colors.black,
+ blurRadius: 2,
+ offset: Offset(0, 2), // Shadow position
+ ),
+ ],
+ border: Border.all(
+ color: const Color(0xFF285DF4),
+ width: 1,
+ ),
+ borderRadius: const BorderRadius.all(
+ Radius.circular(4),
+ ),
+ ),
+ child: Center(
+ child: Text(
+ widget.text,
+ style: const TextStyle(
+ color: Color(0xFFC1D8FF),
+ fontSize: 44,
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/common_widget/settings_top_bar.dart b/lib/presentation/common_widget/settings_top_bar.dart
new file mode 100644
index 0000000..fb4e953
--- /dev/null
+++ b/lib/presentation/common_widget/settings_top_bar.dart
@@ -0,0 +1,37 @@
+import '../../export.dart';
+
+class SettingsTopBar extends ConsumerStatefulWidget
+ implements PreferredSizeWidget {
+ final String title;
+ const SettingsTopBar(this.title, {super.key});
+
+ @override
+ SettingsTopBarState createState() => SettingsTopBarState();
+ @override
+ Size get preferredSize => const Size.fromHeight(50);
+}
+
+class SettingsTopBarState extends ConsumerState<SettingsTopBar> {
+ @override
+ Widget build(
+ BuildContext context,
+ ) {
+ return AppBar(
+ elevation: 0,
+ backgroundColor: const Color(0xFF0D113F),
+ leading: BackButton(
+ onPressed: () {
+ context.flow<AppState>().update((state) => AppState.settings);
+ },
+ ),
+ title: Text(
+ widget.title,
+ style: const TextStyle(
+ fontStyle: FontStyle.normal,
+ fontWeight: FontWeight.normal,
+ fontSize: 20),
+ ),
+ //centerTitle: true,
+ );
+ }
+}
diff --git a/lib/presentation/common_widget/volume_and_fan_control.dart b/lib/presentation/common_widget/volume_and_fan_control.dart
new file mode 100644
index 0000000..051e360
--- /dev/null
+++ b/lib/presentation/common_widget/volume_and_fan_control.dart
@@ -0,0 +1,36 @@
+import '../common_widget/volume_bar.dart';
+import '../common_widget/fan_bar.dart';
+
+import '../../export.dart';
+
+class VolumeFanControl extends ConsumerWidget {
+ const VolumeFanControl({
+ super.key,
+ });
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ final state = ref.watch(appProvider);
+ final size = MediaQuery.of(context).size;
+ final gapSize = size.height * 0.06;
+
+ return Padding(
+ padding: const EdgeInsets.only(left: 10),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Visibility.maintain(
+ visible: state == AppState.mediaPlayer ? false : true,
+ child: const VolumeBar()),
+ SizedBox(
+ height: gapSize,
+ ),
+ Visibility.maintain(
+ visible: state == AppState.hvac ? false : true,
+ child: const FanBar(),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/common_widget/volume_bar.dart b/lib/presentation/common_widget/volume_bar.dart
new file mode 100644
index 0000000..a029698
--- /dev/null
+++ b/lib/presentation/common_widget/volume_bar.dart
@@ -0,0 +1,356 @@
+import 'package:flutter_ics_homescreen/presentation/custom_icons/custom_icons.dart';
+
+import '../../export.dart';
+
+class VolumeBar extends ConsumerStatefulWidget {
+ const VolumeBar({super.key});
+
+ @override
+ VolumeBarState createState() => VolumeBarState();
+}
+
+class VolumeBarState extends ConsumerState<VolumeBar> {
+ double val = 0;
+ @override
+ void initState() {
+ super.initState();
+ // "ref" can be used in all life-cycles of a StatefulWidget.
+ //ref.read(counterProvider);
+ }
+
+ void increaseVolume() {
+ setState(() {
+ if (val < 20) {
+ val++;
+ ref.read(audioStateProvider.notifier).setVolume(val);
+ }
+ });
+ }
+
+ void decreaseVolume() {
+ setState(() {
+ if (val > 0) {
+ val--;
+ ref.read(audioStateProvider.notifier).setVolume(val);
+ }
+ });
+ }
+
+ void setVolume(double newWalue) {
+ setState(() {
+ val = newWalue;
+ ref.read(audioStateProvider.notifier).setVolume(val);
+ });
+ }
+
+ void pause() {}
+
+ @override
+ Widget build(BuildContext context) {
+ final volumeValue =
+ ref.watch(audioStateProvider.select((audio) => audio.volume));
+ val = volumeValue;
+ return Column(
+ // mainAxisAlignment: MainAxisAlignment.center,
+ // crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Container(
+ width: 80,
+ height: 418,
+ //padding: const EdgeInsets.all(16),
+ decoration: const ShapeDecoration(
+ // gradient: RadialGradient(
+ // colors: [Color.fromARGB(255, 19, 24, 75), Colors.black],
+ // stops: [0, 0.9],
+ // radius: 1,
+ // ),
+ color: AGLDemoColors.buttonFillEnabledColor,
+ shape: StadiumBorder(
+ side: BorderSide(
+ color: Color(0xFF5477D4),
+ width: 1,
+ )),
+ ),
+ //alignment: Alignment.topLeft,
+ child: Column(
+ children: [
+ SizedBox(
+ height: 68.0,
+ width: 56.0,
+ child: IconButton(
+ padding: EdgeInsets.zero,
+ color: AGLDemoColors.periwinkleColor,
+ onPressed: () {
+ increaseVolume();
+ },
+ icon: const Icon(
+ CustomIcons.vol_max,
+ size: 56,
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(
+ top: 4, bottom: 4), // Top and bottom padding
+ child: SizedBox(
+ height: 274.0,
+ child: RotatedBox(
+ quarterTurns: 3,
+ child: SliderTheme(
+ data: SliderTheme.of(context).copyWith(
+ activeTrackColor: AGLDemoColors.periwinkleColor,
+ inactiveTrackColor: const Color(0xFF0D113F),
+ trackShape: const GradinetRectangularSliderTrackShape(),
+ //trackShape: CustomTrackShape(),
+ trackHeight: 56.0,
+ //thumbColor: Colors.blueAccent,
+ thumbShape: const RectSliderThumbShape(
+ enabledThumbRadius: 0, disabledThumbRadius: 0),
+ //overlayColor: Colors.red.withAlpha(32),
+ overlayShape:
+ //RoundSliderOverlayShape(overlayRadius: 33.0),
+ //RoundSliderOverlayShape(overlayRadius: 0.0),
+ SliderComponentShape.noOverlay,
+ ),
+ child: Slider(
+ min: 0,
+ max: 20,
+ value: volumeValue,
+ divisions: 20,
+ onChanged: (newValue) {
+ setVolume(newValue);
+ },
+ ),
+ ),
+ ),
+ ),
+ ),
+ SizedBox(
+ height: 56.0,
+ width: 56.0,
+ child: IconButton(
+ padding: EdgeInsets.zero,
+ color: AGLDemoColors.periwinkleColor,
+ onPressed: () {
+ decreaseVolume();
+ },
+ icon: const Icon(
+ CustomIcons.vol_min,
+ size: 56,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 10),
+ Container(
+ width: 80,
+ height: 80,
+ //padding: const EdgeInsets.all(16),
+ decoration: const ShapeDecoration(
+ // gradient: RadialGradient(
+ // colors: [Color.fromARGB(255, 19, 24, 75), Colors.black],
+ // stops: [0, 0.9],
+ // radius: 1,
+ // ),
+ color: AGLDemoColors.buttonFillEnabledColor,
+ shape: StadiumBorder(
+ side: BorderSide(
+ color: Color(0xFF5477D4),
+ width: 1,
+ )),
+ ),
+ //alignment: Alignment.topLeft,
+ child: IconButton(
+ padding: EdgeInsets.zero,
+ color: AGLDemoColors.periwinkleColor,
+ onPressed: () {
+ pause();
+ },
+ icon: const Icon(
+ Icons.pause,
+ size: 30,
+ )),
+ ),
+ ],
+ );
+ }
+}
+
+class RectSliderThumbShape extends SliderComponentShape {
+ /// Create a slider thumb that draws a Rect.
+ const RectSliderThumbShape({
+ this.enabledThumbRadius = 10.0,
+ this.disabledThumbRadius,
+ this.elevation = 1.0,
+ this.pressedElevation = 6.0,
+ });
+
+ final double enabledThumbRadius;
+
+ final double? disabledThumbRadius;
+ double get _disabledThumbRadius => disabledThumbRadius ?? enabledThumbRadius;
+
+ final double elevation;
+
+ final double pressedElevation;
+
+ @override
+ Size getPreferredSize(bool isEnabled, bool isDiscrete) {
+ return Size.fromRadius(
+ isEnabled == true ? enabledThumbRadius : _disabledThumbRadius);
+ }
+
+ @override
+ void paint(
+ PaintingContext context,
+ Offset center, {
+ required Animation<double> activationAnimation,
+ required Animation<double> enableAnimation,
+ required bool isDiscrete,
+ required TextPainter labelPainter,
+ required RenderBox parentBox,
+ required SliderThemeData sliderTheme,
+ required TextDirection textDirection,
+ required double value,
+ required double textScaleFactor,
+ required Size sizeWithOverflow,
+ }) {
+ final Canvas canvas = context.canvas;
+
+ const Color color = Colors.white;
+ //const double radius = 0;
+
+ final Tween<double> elevationTween = Tween<double>(
+ begin: elevation,
+ end: pressedElevation,
+ );
+
+ final double evaluatedElevation =
+ elevationTween.evaluate(activationAnimation);
+
+ final Path path = Path()
+ ..addRect(
+ Rect.fromCenter(
+ center: Offset(center.dx - 3, center.dy + 2), width: 3, height: 54),
+ );
+
+ // canvas.drawRect(
+ // Rect.fromCenter(center: center, width: 4, height: 25),
+ // Paint()..color = color,
+ // );
+ canvas.drawRect(
+ Rect.fromCenter(center: center, width: 4, height: 54),
+ Paint()..color = color,
+ );
+ canvas.drawShadow(path, Colors.black, evaluatedElevation, true);
+ }
+}
+
+class GradinetRectangularSliderTrackShape extends SliderTrackShape
+ with BaseSliderTrackShape {
+ /// Creates a slider track that draws 2 rectangles.
+ const GradinetRectangularSliderTrackShape();
+
+ @override
+ void paint(
+ PaintingContext context,
+ Offset offset, {
+ required RenderBox parentBox,
+ required SliderThemeData sliderTheme,
+ required Animation<double> enableAnimation,
+ required TextDirection textDirection,
+ required Offset thumbCenter,
+ Offset? secondaryOffset,
+ bool isDiscrete = false,
+ bool isEnabled = false,
+ }) {
+ assert(sliderTheme.disabledActiveTrackColor != null);
+ assert(sliderTheme.disabledInactiveTrackColor != null);
+ assert(sliderTheme.activeTrackColor != null);
+ assert(sliderTheme.inactiveTrackColor != null);
+ assert(sliderTheme.thumbShape != null);
+ // If the slider [SliderThemeData.trackHeight] is less than or equal to 0,
+ // then it makes no difference whether the track is painted or not,
+ // therefore the painting can be a no-op.
+ if (sliderTheme.trackHeight! <= 0) {
+ return;
+ }
+
+ LinearGradient gradient = const LinearGradient(
+ colors: <Color>[
+ //AGLDemoColors.periwinkleColor,
+ Color(0xff81A9ED),
+ Colors.white,
+ ],
+ );
+ final Rect trackRect = getPreferredRect(
+ parentBox: parentBox,
+ offset: offset,
+ sliderTheme: sliderTheme,
+ isEnabled: isEnabled,
+ isDiscrete: isDiscrete,
+ );
+ // Assign the track segment paints, which are left: active, right: inactive,
+ // but reversed for right to left text.
+ final ColorTween activeTrackColorTween = ColorTween(
+ begin: sliderTheme.disabledActiveTrackColor,
+ end: sliderTheme.activeTrackColor);
+ final ColorTween inactiveTrackColorTween = ColorTween(
+ begin: sliderTheme.disabledInactiveTrackColor,
+ end: sliderTheme.inactiveTrackColor);
+ final Paint activePaint = Paint()
+ ..shader = gradient.createShader(trackRect)
+ ..color = activeTrackColorTween.evaluate(enableAnimation)!;
+ final Paint inactivePaint = Paint()
+ ..color = inactiveTrackColorTween.evaluate(enableAnimation)!;
+ final Paint leftTrackPaint;
+ final Paint rightTrackPaint;
+ switch (textDirection) {
+ case TextDirection.ltr:
+ leftTrackPaint = activePaint;
+ rightTrackPaint = inactivePaint;
+ case TextDirection.rtl:
+ leftTrackPaint = inactivePaint;
+ rightTrackPaint = activePaint;
+ }
+
+ final Rect leftTrackSegment = Rect.fromLTRB(
+ trackRect.left, trackRect.top, thumbCenter.dx, trackRect.bottom);
+ if (!leftTrackSegment.isEmpty) {
+ context.canvas.drawRect(leftTrackSegment, leftTrackPaint);
+ }
+ final Rect rightTrackSegment = Rect.fromLTRB(
+ thumbCenter.dx, trackRect.top, trackRect.right, trackRect.bottom);
+ if (!rightTrackSegment.isEmpty) {
+ context.canvas.drawRect(rightTrackSegment, rightTrackPaint);
+ }
+
+ final bool showSecondaryTrack = (secondaryOffset != null) &&
+ ((textDirection == TextDirection.ltr)
+ ? (secondaryOffset.dx > thumbCenter.dx)
+ : (secondaryOffset.dx < thumbCenter.dx));
+
+ if (showSecondaryTrack) {
+ final ColorTween secondaryTrackColorTween = ColorTween(
+ begin: sliderTheme.disabledSecondaryActiveTrackColor,
+ end: sliderTheme.secondaryActiveTrackColor);
+ final Paint secondaryTrackPaint = Paint()
+ ..color = secondaryTrackColorTween.evaluate(enableAnimation)!;
+ final Rect secondaryTrackSegment = Rect.fromLTRB(
+ (textDirection == TextDirection.ltr)
+ ? thumbCenter.dx
+ : secondaryOffset.dx,
+ trackRect.top,
+ (textDirection == TextDirection.ltr)
+ ? secondaryOffset.dx
+ : thumbCenter.dx,
+ trackRect.bottom,
+ );
+ if (!secondaryTrackSegment.isEmpty) {
+ context.canvas.drawRect(secondaryTrackSegment, secondaryTrackPaint);
+ }
+ }
+ }
+}