Stabilized UI elements across multiple devices

Synchronized ACs Status functionality
This commit is contained in:
Mohammad Salameh
2024-02-28 12:22:45 +03:00
parent 4c27cce519
commit 3fabd41e72
63 changed files with 432 additions and 384 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><path d="M 23.951172 4 A 1.50015 1.50015 0 0 0 23.072266 4.3222656 L 8.859375 15.519531 C 7.0554772 16.941163 6 19.113506 6 21.410156 L 6 40.5 C 6 41.863594 7.1364058 43 8.5 43 L 18.5 43 C 19.863594 43 21 41.863594 21 40.5 L 21 30.5 C 21 30.204955 21.204955 30 21.5 30 L 26.5 30 C 26.795045 30 27 30.204955 27 30.5 L 27 40.5 C 27 41.863594 28.136406 43 29.5 43 L 39.5 43 C 40.863594 43 42 41.863594 42 40.5 L 42 21.410156 C 42 19.113506 40.944523 16.941163 39.140625 15.519531 L 24.927734 4.3222656 A 1.50015 1.50015 0 0 0 23.951172 4 z M 24 7.4101562 L 37.285156 17.876953 C 38.369258 18.731322 39 20.030807 39 21.410156 L 39 40 L 30 40 L 30 30.5 C 30 28.585045 28.414955 27 26.5 27 L 21.5 27 C 19.585045 27 18 28.585045 18 30.5 L 18 40 L 9 40 L 9 21.410156 C 9 20.030807 9.6307412 18.731322 10.714844 17.876953 L 24 7.4101562 z"/></svg>

Before

Width:  |  Height:  |  Size: 926 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 926 B

View File

@ -1,122 +1,122 @@
{ {
"images" : [ "images" : [
{ {
"size" : "20x20", "filename" : "logo-20@2x.png",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png", "scale" : "2x",
"scale" : "2x" "size" : "20x20"
}, },
{ {
"size" : "20x20", "filename" : "logo-20@3x.png",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png", "scale" : "3x",
"scale" : "3x" "size" : "20x20"
}, },
{ {
"size" : "29x29", "filename" : "logo-29.png",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png", "scale" : "1x",
"scale" : "1x" "size" : "29x29"
}, },
{ {
"size" : "29x29", "filename" : "logo-29@2x.png",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png", "scale" : "2x",
"scale" : "2x" "size" : "29x29"
}, },
{ {
"size" : "29x29", "filename" : "logo-29@3x.png",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png", "scale" : "3x",
"scale" : "3x" "size" : "29x29"
}, },
{ {
"size" : "40x40", "filename" : "logo-40@2x.png",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png", "scale" : "2x",
"scale" : "2x" "size" : "40x40"
}, },
{ {
"size" : "40x40", "filename" : "logo-40@3x.png",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png", "scale" : "3x",
"scale" : "3x" "size" : "40x40"
}, },
{ {
"size" : "60x60", "filename" : "logo-60@2x.png",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png", "scale" : "2x",
"scale" : "2x" "size" : "60x60"
}, },
{ {
"size" : "60x60", "filename" : "logo-60@3x.png",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png", "scale" : "3x",
"scale" : "3x" "size" : "60x60"
}, },
{ {
"size" : "20x20", "filename" : "logo-20.png",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png", "scale" : "1x",
"scale" : "1x" "size" : "20x20"
}, },
{ {
"size" : "20x20", "filename" : "logo-20@2x 1.png",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png", "scale" : "2x",
"scale" : "2x" "size" : "20x20"
}, },
{ {
"size" : "29x29", "filename" : "logo-29 1.png",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png", "scale" : "1x",
"scale" : "1x" "size" : "29x29"
}, },
{ {
"size" : "29x29", "filename" : "logo-29@2x 1.png",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png", "scale" : "2x",
"scale" : "2x" "size" : "29x29"
}, },
{ {
"size" : "40x40", "filename" : "logo-40.png",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png", "scale" : "1x",
"scale" : "1x" "size" : "40x40"
}, },
{ {
"size" : "40x40", "filename" : "logo-40@2x 1.png",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png", "scale" : "2x",
"scale" : "2x" "size" : "40x40"
}, },
{ {
"size" : "76x76", "filename" : "logo-76.png",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png", "scale" : "1x",
"scale" : "1x" "size" : "76x76"
}, },
{ {
"size" : "76x76", "filename" : "logo-76@2x.png",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png", "scale" : "2x",
"scale" : "2x" "size" : "76x76"
}, },
{ {
"size" : "83.5x83.5", "filename" : "logo-83.5@2x.png",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png", "scale" : "2x",
"scale" : "2x" "size" : "83.5x83.5"
}, },
{ {
"size" : "1024x1024", "filename" : "logo-1024.png",
"idiom" : "ios-marketing", "idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png", "scale" : "1x",
"scale" : "1x" "size" : "1024x1024"
} }
], ],
"info" : { "info" : {
"version" : 1, "author" : "xcode",
"author" : "xcode" "version" : 1
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,4 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:syncrow_app/features/dashboard/view/widgets/carbon_emission.dart'; import 'package:syncrow_app/features/dashboard/view/widgets/carbon_emission.dart';
import 'package:syncrow_app/features/dashboard/view/widgets/consumption.dart'; import 'package:syncrow_app/features/dashboard/view/widgets/consumption.dart';
@ -13,31 +15,33 @@ class DashboardView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const Column( return Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
TitleMedium( const TitleMedium(
text: StringsManager.dashboard, text: StringsManager.dashboard,
style: TextStyle( style: TextStyle(
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
LiveMonitorTab(), const LiveMonitorTab(),
Gap(10), const Gap(10),
EnergyUsage(), const EnergyUsage(),
Expanded( Container(
child: Padding( padding: const EdgeInsets.only(top: 20),
padding: EdgeInsets.only(top: 20), constraints: const BoxConstraints(
child: Column( minHeight: 220,
mainAxisAlignment: MainAxisAlignment.start, maxHeight: 240,
children: [ ),
Consumption(), child: const Column(
Gap(20), mainAxisAlignment: MainAxisAlignment.start,
CarbonEmission(), children: [
], Consumption(),
), Gap(20),
CarbonEmission(),
],
), ),
), ),
], ],

View File

@ -15,11 +15,15 @@ class CarbonEmission extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), padding: const EdgeInsets.only(right: 20, left: 20, top: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
), ),
constraints: const BoxConstraints(
minHeight: 80,
maxHeight: 100,
),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

View File

@ -14,7 +14,7 @@ class CardTitle extends StatelessWidget {
return BodySmall( return BodySmall(
text: title, text: title,
fontColor: Colors.grey, fontColor: Colors.grey,
fontSize: 12, fontSize: MediaQuery.sizeOf(context).height.ceil() > 680 ? 12 : 8,
); );
} }
} }

View File

@ -14,41 +14,48 @@ class Consumption extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), padding: const EdgeInsets.only(right: 20, left: 20, top: 10, bottom: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
), ),
constraints: const BoxConstraints(
minHeight: 80,
maxHeight: 100,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
const Column( Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
CardTitle( const CardTitle(
title: StringsManager.ACConsumption, title: StringsManager.ACConsumption,
), ),
Gap(10), const Spacer(),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
UnitedText( UnitedText(
value: "2", value: "2",
valueSize: 35, valueSize: MediaQuery.sizeOf(context).height.ceil() > 680
? 35
: 24,
valueWeight: FontWeight.normal, valueWeight: FontWeight.normal,
unit: "Units", unit: "Units",
), ),
Gap(30), const Gap(30),
UnitedText( UnitedText(
value: "720", value: "${MediaQuery.sizeOf(context).height.ceil()}",
valueSize: 35, valueSize: MediaQuery.sizeOf(context).height.ceil() > 680
? 35
: 24,
valueWeight: FontWeight.normal, valueWeight: FontWeight.normal,
unit: "kWh", unit: "kWh",
), ),
], ],
), ),
const Spacer(),
], ],
), ),
//TODO: Replace with actual pie chart //TODO: Replace with actual pie chart

View File

@ -1,21 +1,46 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart'; import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
part 'ac_state.dart'; part 'ac_state.dart';
class AcCubit extends Cubit<AcState> { class AcCubit extends Cubit<AcState> {
AcCubit() : super(AcInitial()); AcCubit() : super(AcInitial()) {
averageTempForAll();
updateACsStatus();
}
static AcCubit get(context) => BlocProvider.of(context); static AcCubit get(context) => BlocProvider.of(context);
bool areAllACsOff() { void turnACOn(ACModel model) {
for (var ac in DevicesCubit.categories[0].devices) { if (!model.status) {
if (ac.status) { model.status = true;
return false; updateACsStatus();
} emit(ACTurnedOn());
}
}
void turnACOff(ACModel model) {
if (model.status) {
model.status = false;
updateACsStatus();
emit(ACTurnedOff());
}
}
void updateACsStatus() {
bool tempStatus = DevicesCubit.categories[0].devices[0].status;
for (var AC in DevicesCubit.categories[0].devices) {
//check if there any AC have a different status than the initial ==> turn off the universal switch
if (AC.status != tempStatus) {
DevicesCubit.categories[0].devicesStatus = false;
emit(ACsStatusChanged());
return;
}
DevicesCubit.categories[0].devicesStatus = tempStatus;
emit(ACsStatusChanged());
} }
return true;
} }
void turnAllACsOff() { void turnAllACsOff() {
@ -36,21 +61,45 @@ class AcCubit extends Cubit<AcState> {
for (var ac in DevicesCubit.categories[0].devices) { for (var ac in DevicesCubit.categories[0].devices) {
ac.temperature = temperature; ac.temperature = temperature;
} }
emit(ACsTempChanged()); averageTempForAll();
emit(ACsTempChanged(temperature));
} }
double averageTempForAll() { // void setACTemp(int index, double temperature) {
double allTemp = 0; // DevicesCubit.categories[0].devices[index].temperature = temperature;
for (var ac in DevicesCubit.categories[0].devices) { // averageTempForAll();
allTemp += ac.temperature; // emit(ACsTempChanged(temperature));
} // }
emit(ACsTempChanged());
double averageTemp = allTemp / DevicesCubit.categories[0].devices.length; void increaseACTemp(int index) {
DevicesCubit.categories[0].devices[index].temperature += .5;
averageTempForAll();
emit(ACsTempChanged(DevicesCubit.categories[0].devices[index].temperature));
}
void decreaseACTemp(int index) {
DevicesCubit.categories[0].devices[index].temperature -= .5;
averageTempForAll();
emit(ACsTempChanged(DevicesCubit.categories[0].devices[index].temperature));
}
double getTemp(int index) {
return DevicesCubit.categories[0].devices[index].temperature;
}
static double averageTemp = 0;
void averageTempForAll() {
double tempSum = 0;
for (var ac in DevicesCubit.categories[0].devices) {
tempSum += ac.temperature;
}
averageTemp = tempSum / DevicesCubit.categories[0].devices.length;
averageTemp = (averageTemp * 2).round() / 2; averageTemp = (averageTemp * 2).round() / 2;
return averageTemp; emit(ACsAverageTemp());
} }
/// implement the fan speed and temp mode change /// implement the fan speed and temp mode change

View File

@ -5,12 +5,24 @@ abstract class AcState {}
class AcInitial extends AcState {} class AcInitial extends AcState {}
class ACsStatusChanged extends AcState {}
class SwitchACsOff extends AcState {} class SwitchACsOff extends AcState {}
class SwitchACsOn extends AcState {} class SwitchACsOn extends AcState {}
class ACsTempChanged extends AcState {} class ACsTempChanged extends AcState {
final double temperature;
ACsTempChanged(this.temperature);
}
class ACsAverageTemp extends AcState {}
class ACsFanSpeedChanged extends AcState {} class ACsFanSpeedChanged extends AcState {}
class ACsTempModeChanged extends AcState {} class ACsTempModeChanged extends AcState {}
class ACTurnedOn extends AcState {}
class ACTurnedOff extends AcState {}

View File

@ -18,18 +18,13 @@ class DevicesCubit extends Cubit<DevicesState> {
// getCategories(); // getCategories();
} }
/// separate the cubit into different cubits based on devices type
static bool ACSwitchValue = false;
static bool lightsSwitchValue = false;
static bool doorSwitchValue = false;
static bool curtainSwitchValue = false;
static bool screensSwitchValue = false;
static bool gatewaySwitchValue = false;
void changeCategorySwitchValue(DevicesCategoryModel category) { void changeCategorySwitchValue(DevicesCategoryModel category) {
category.switchValue = !category.switchValue; category.devicesStatus = !category.devicesStatus;
for (var device in category.devices) {
device.status = category.devicesStatus;
}
emit(CategorySwitchChanged()); emit(CategorySwitchChanged());
print('${category.name} switch value: ${category.switchValue} '); print('${category.name} switch value: ${category.devicesStatus} ');
} }
static DevicesCubit get(context) => BlocProvider.of(context); static DevicesCubit get(context) => BlocProvider.of(context);
@ -56,7 +51,6 @@ class DevicesCubit extends Cubit<DevicesState> {
], ],
icon: Assets.iconsAC, icon: Assets.iconsAC,
name: 'ACs', name: 'ACs',
switchValue: ACSwitchValue,
type: DeviceType.AC, type: DeviceType.AC,
page: const ACView(), page: const ACView(),
), ),
@ -64,7 +58,6 @@ class DevicesCubit extends Cubit<DevicesState> {
devices: [], devices: [],
icon: Assets.iconsLight, icon: Assets.iconsLight,
name: 'Lights', name: 'Lights',
switchValue: lightsSwitchValue,
type: DeviceType.Lights, type: DeviceType.Lights,
page: const LightsView(), page: const LightsView(),
), ),
@ -72,7 +65,6 @@ class DevicesCubit extends Cubit<DevicesState> {
devices: [], devices: [],
icon: Assets.iconsDoorLock, icon: Assets.iconsDoorLock,
name: 'Doors', name: 'Doors',
switchValue: doorSwitchValue,
type: DeviceType.Door, type: DeviceType.Door,
page: const DoorView(), page: const DoorView(),
), ),
@ -80,7 +72,6 @@ class DevicesCubit extends Cubit<DevicesState> {
devices: [], devices: [],
icon: Assets.iconsCurtain, icon: Assets.iconsCurtain,
name: 'Curtains', name: 'Curtains',
switchValue: curtainSwitchValue,
type: DeviceType.Curtain, type: DeviceType.Curtain,
page: const CurtainView(), page: const CurtainView(),
), ),
@ -88,7 +79,6 @@ class DevicesCubit extends Cubit<DevicesState> {
devices: [], devices: [],
icon: Assets.iconsScreen, icon: Assets.iconsScreen,
name: 'Screens', name: 'Screens',
switchValue: screensSwitchValue,
type: DeviceType.Screens, type: DeviceType.Screens,
page: const ScreensView(), page: const ScreensView(),
), ),
@ -96,13 +86,12 @@ class DevicesCubit extends Cubit<DevicesState> {
devices: [], devices: [],
icon: Assets.iconsGateway, icon: Assets.iconsGateway,
name: 'Gateway', name: 'Gateway',
switchValue: gatewaySwitchValue,
type: DeviceType.Gateway, type: DeviceType.Gateway,
page: const GateWayView(), page: const GateWayView(),
), ),
]; ];
Widget? get chosenCategory { Widget? get chosenCategoryView {
for (var category in categories) { for (var category in categories) {
if (category.isSelected) { if (category.isSelected) {
return category.page; return category.page;
@ -111,7 +100,17 @@ class DevicesCubit extends Cubit<DevicesState> {
return null; return null;
} }
void updateCategory(int index) { void areAllDevicesOff(DevicesCategoryModel category) {
for (var device in category.devices) {
if (device.status) {
category.devicesStatus = false;
emit(CategorySwitchChanged());
return;
}
}
}
void selectCategory(int index) {
for (var i = 0; i < categories.length; i++) { for (var i = 0; i < categories.length; i++) {
if (i == index) { if (i == index) {
categories[i].isSelected = true; categories[i].isSelected = true;

View File

@ -8,7 +8,7 @@ class DevicesCategoryModel {
final Widget page; final Widget page;
bool switchValue; bool devicesStatus = false;
final List<ACModel> devices; final List<ACModel> devices;
final DeviceType type; final DeviceType type;
@ -20,8 +20,21 @@ class DevicesCategoryModel {
required this.type, required this.type,
required this.name, required this.name,
required this.icon, required this.icon,
required this.switchValue, required this.devices}) {
required this.devices}); //sets the initial status of the devices
if (devices.isNotEmpty) {
bool tempStatus = devices.first.status;
for (var device in devices) {
if (device.status != tempStatus) {
devicesStatus = false;
break;
}
}
devicesStatus = tempStatus;
} else {
devicesStatus = false;
}
}
} }
enum DeviceType { enum DeviceType {

View File

@ -51,7 +51,7 @@ class ACView extends StatelessWidget {
), ),
const Gap(10), const Gap(10),
DevicesTempWidget( DevicesTempWidget(
model: DevicesCubit.categories[0].devices[index], index,
), ),
const Gap(10), const Gap(10),
ACControlUnit( ACControlUnit(

View File

@ -1,4 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import '../../../../../utils/resource_manager/color_manager.dart'; import '../../../../../utils/resource_manager/color_manager.dart';
import '../../../../shared_widgets/text_widgets/body_medium.dart'; import '../../../../shared_widgets/text_widgets/body_medium.dart';
@ -11,60 +13,70 @@ class UniversalACSwitch extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool acsStatus = AcCubit.get(context).areAllACsOff();
//TODO: Move these to String Manager "ON" and "OFF" //TODO: Move these to String Manager "ON" and "OFF"
return Row( return BlocBuilder<AcCubit, AcState>(
children: <Widget>[ builder: (context, state) {
Expanded( return Row(
child: InkWell( children: <Widget>[
onTap: () { Expanded(
AcCubit.get(context).turnAllACsOn(); child: InkWell(
}, onTap: () {
child: Container( AcCubit.get(context).turnAllACsOn();
height: 60, },
decoration: BoxDecoration( child: Container(
color: acsStatus ? ColorsManager.primaryColor : Colors.white, height: 60,
borderRadius: const BorderRadius.only( decoration: BoxDecoration(
topLeft: Radius.circular(15), color: DevicesCubit.categories[0].devicesStatus
bottomLeft: Radius.circular(15), ? ColorsManager.primaryColor
), : Colors.white,
), borderRadius: const BorderRadius.only(
child: Center( topLeft: Radius.circular(15),
child: BodyMedium( bottomLeft: Radius.circular(15),
text: "ON", ),
fontColor: acsStatus ? Colors.white : null, ),
fontWeight: FontWeight.bold, child: Center(
child: BodyMedium(
text: "ON",
fontColor: DevicesCubit.categories[0].devicesStatus
? Colors.white
: null,
fontWeight: FontWeight.bold,
),
),
), ),
), ),
), ),
), Expanded(
), child: InkWell(
Expanded( onTap: () {
child: InkWell( AcCubit.get(context).turnAllACsOff();
onTap: () { },
AcCubit.get(context).turnAllACsOff(); child: Container(
}, height: 60,
child: Container( decoration: BoxDecoration(
height: 60, color: DevicesCubit.categories[0].devicesStatus
decoration: BoxDecoration( ? Colors.white
color: acsStatus ? Colors.white : ColorsManager.primaryColor, : ColorsManager.primaryColor,
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
topRight: Radius.circular(15), topRight: Radius.circular(15),
bottomRight: Radius.circular(15), bottomRight: Radius.circular(15),
), ),
), ),
child: Center( child: Center(
child: BodyMedium( child: BodyMedium(
text: "OFF", text: "OFF",
fontColor: acsStatus ? null : Colors.white, fontColor: DevicesCubit.categories[0].devicesStatus
fontWeight: FontWeight.bold, ? null
: Colors.white,
fontWeight: FontWeight.bold,
),
),
), ),
), ),
), ),
), ],
), );
], },
); );
} }
} }

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/bloc/ac_cubit.dart'; import 'package:syncrow_app/features/devices/bloc/ac_cubit.dart';
import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/context_extension.dart';
@ -15,45 +16,48 @@ class UniversalACTemp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double averageTemp = AcCubit.get(context).averageTempForAll(); return BlocBuilder<AcCubit, AcState>(
return DefaultContainer( builder: (context, state) {
height: 60, return DefaultContainer(
child: Row( height: 60,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, child: Row(
children: <Widget>[ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
SizedBox.square( children: <Widget>[
dimension: 24, SizedBox.square(
child: InkWell( dimension: 24,
onTap: () { child: InkWell(
AcCubit.get(context).setTempToAll(averageTemp + .5); onTap: () {
}, AcCubit.get(context).setTempToAll(AcCubit.averageTemp + .5);
child: SvgPicture.asset( },
Assets.iconsMinus, child: SvgPicture.asset(
Assets.iconsMinus,
),
),
), ),
), BodyLarge(
), text: "${AcCubit.averageTemp}° C",
BodyLarge( style: context.bodyLarge.copyWith(
text: "${AcCubit.get(context).averageTempForAll()}° C", color: ColorsManager.primaryColor.withOpacity(0.6),
style: context.bodyLarge.copyWith( fontSize: 23,
color: ColorsManager.primaryColor.withOpacity(0.6), ),
fontSize: 23,
),
),
SizedBox.square(
dimension: 24,
child: InkWell(
onTap: () {
AcCubit.get(context).setTempToAll(averageTemp + .5);
},
child: SvgPicture.asset(
Assets.iconsPlus,
height: 24,
width: 24,
), ),
), SizedBox.square(
dimension: 24,
child: InkWell(
onTap: () {
AcCubit.get(context).setTempToAll(AcCubit.averageTemp + .5);
},
child: SvgPicture.asset(
Assets.iconsPlus,
height: 24,
width: 24,
),
),
),
],
), ),
], );
), },
); );
} }
} }

View File

@ -31,17 +31,19 @@ class CategoriesView extends StatelessWidget {
), ),
Expanded( Expanded(
flex: 3, flex: 3,
child: Column( child: SingleChildScrollView(
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
TitleMedium( children: [
text: StringsManager.wizard, TitleMedium(
style: TextStyle( text: StringsManager.wizard,
fontSize: 28, style: TextStyle(
fontSize: 28,
),
), ),
), Switches(),
Switches(), ],
], ),
), ),
) )
], ],

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart'; import 'package:syncrow_app/features/devices/bloc/ac_cubit.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/context_extension.dart';
@ -8,21 +8,15 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../../../../generated/assets.dart'; import '../../../../generated/assets.dart';
class DevicesTempWidget extends StatefulWidget { class DevicesTempWidget extends StatelessWidget {
const DevicesTempWidget({ const DevicesTempWidget(
this.index, {
super.key, super.key,
required this.model,
}); });
final ACModel model; final int index;
@override
State<DevicesTempWidget> createState() => _DevicesTempWidgetState();
}
class _DevicesTempWidgetState extends State<DevicesTempWidget> {
// double temp = widget.model.temperature; // double temp = widget.model.temperature;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DefaultContainer( return DefaultContainer(
@ -34,10 +28,7 @@ class _DevicesTempWidgetState extends State<DevicesTempWidget> {
dimension: 24, dimension: 24,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
setState(() { AcCubit.get(context).decreaseACTemp(index);
// temp = temp - .5;
widget.model.temperature = widget.model.temperature - .5;
});
}, },
child: SvgPicture.asset( child: SvgPicture.asset(
Assets.iconsMinus, Assets.iconsMinus,
@ -45,7 +36,7 @@ class _DevicesTempWidgetState extends State<DevicesTempWidget> {
), ),
), ),
BodyLarge( BodyLarge(
text: "${widget.model.temperature}° C", text: "${AcCubit.get(context).getTemp(index)}° C",
style: context.bodyLarge.copyWith( style: context.bodyLarge.copyWith(
color: ColorsManager.primaryColor.withOpacity(0.6), color: ColorsManager.primaryColor.withOpacity(0.6),
fontSize: 23, fontSize: 23,
@ -55,10 +46,7 @@ class _DevicesTempWidgetState extends State<DevicesTempWidget> {
dimension: 24, dimension: 24,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
setState(() { AcCubit.get(context).increaseACTemp(index);
// temp = temp + .5
widget.model.temperature = widget.model.temperature + .5;
});
}, },
child: SvgPicture.asset( child: SvgPicture.asset(
Assets.iconsPlus, Assets.iconsPlus,

View File

@ -17,7 +17,7 @@ class DevicesViewBody extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return state is DevicesLoading return state is DevicesLoading
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: DevicesCubit.get(context).chosenCategory ?? : DevicesCubit.get(context).chosenCategoryView ??
const CategoriesView(); const CategoriesView();
}, },
), ),

View File

@ -4,7 +4,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/shared_widgets/custom_switch.dart'; import 'package:syncrow_app/features/shared_widgets/custom_switch.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; import 'package:syncrow_app/utils/context_extension.dart';
import '../../bloc/devices_cubit.dart'; import '../../bloc/devices_cubit.dart';
@ -30,11 +30,10 @@ class Switches extends StatelessWidget {
itemCount: DevicesCubit.categories.length, itemCount: DevicesCubit.categories.length,
itemBuilder: (_, index) { itemBuilder: (_, index) {
return InkWell( return InkWell(
onTap: () => DevicesCubit.get(context).updateCategory(index), onTap: () => DevicesCubit.get(context).selectCategory(index),
child: DefaultContainer( child: DefaultContainer(
child: Padding( child: Padding(
padding: padding: const EdgeInsets.only(top: 10, right: 10, left: 10),
const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -47,15 +46,24 @@ class Switches extends StatelessWidget {
DevicesCubit.categories[index].icon, DevicesCubit.categories[index].icon,
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
CustomSwitch(), CustomSwitch(
category: DevicesCubit.categories[index],
),
], ],
), ),
BodyLarge( Expanded(
text: DevicesCubit.categories[index].name, child: FittedBox(
fontWeight: FontsManager.bold, fit: BoxFit.scaleDown,
fontSize: 24, child: BodyLarge(
fontColor: const Color(0xFF848484), text: DevicesCubit.categories[index].name,
) style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
height: 0,
fontSize: 24,
),
),
),
),
], ],
), ),
), ),

View File

@ -1,69 +1,30 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class CustomSwitch extends StatefulWidget { class CustomSwitch extends StatelessWidget {
// final bool value; const CustomSwitch({super.key, required this.category});
// final ValueChanged<bool> onChanged;
const CustomSwitch({ final DevicesCategoryModel category;
super.key,
// required this.value,
// required this.onChanged,
});
@override
_CustomSwitchState createState() => _CustomSwitchState();
}
class _CustomSwitchState extends State<CustomSwitch>
with SingleTickerProviderStateMixin {
Animation? _circleAnimation;
AnimationController? _animationController;
bool value = false;
void onChange(bool customValue) {
value = customValue;
}
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 300));
_circleAnimation = AlignmentTween(
begin: value ? Alignment.centerRight : Alignment.centerLeft,
end: value ? Alignment.centerLeft : Alignment.centerRight,
).animate(
CurvedAnimation(
parent: _animationController!,
curve: Curves.linear,
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedBuilder( return BlocBuilder<DevicesCubit, DevicesState>(
animation: _animationController!, builder: (context, state) {
builder: (context, child) {
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
setState(() { DevicesCubit.get(context).changeCategorySwitchValue(category);
_animationController!.isCompleted
? _animationController!.reverse()
: _animationController!.forward();
value ? onChange(false) : onChange(true);
});
}, },
child: Container( child: Container(
width: 45.0, width: 45.0,
height: 28.0, height: 28.0,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.0), borderRadius: BorderRadius.circular(24.0),
color: _circleAnimation!.value == Alignment.centerLeft color: category.devicesStatus
? Color(0xFFD9D9D9) ? ColorsManager.primaryColor
: ColorsManager.primaryColor, : const Color(0xFFD9D9D9),
), ),
child: Center( child: Center(
child: Container( child: Container(
@ -76,16 +37,17 @@ class _CustomSwitchState extends State<CustomSwitch>
child: Padding( child: Padding(
padding: const EdgeInsets.all(2.0), padding: const EdgeInsets.all(2.0),
child: Container( child: Container(
alignment: alignment: category.devicesStatus
value ? Alignment.centerRight : Alignment.centerLeft, ? Alignment.centerRight
: Alignment.centerLeft,
child: Container( child: Container(
width: 20.0, width: 20.0,
height: 20.0, height: 20.0,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: _circleAnimation!.value == Alignment.centerLeft color: category.devicesStatus
? Color(0xFFD9D9D9) ? ColorsManager.primaryColor
: ColorsManager.primaryColor, : Colors.grey,
), ),
), ),
), ),

View File

@ -1,9 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/ac_cubit.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart'; import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class DevicesDefaultSwitch extends StatefulWidget { class DevicesDefaultSwitch extends StatelessWidget {
const DevicesDefaultSwitch({ const DevicesDefaultSwitch({
super.key, super.key,
required this.model, required this.model,
@ -11,73 +13,67 @@ class DevicesDefaultSwitch extends StatefulWidget {
final ACModel model; final ACModel model;
@override
State<DevicesDefaultSwitch> createState() => _DevicesDefaultSwitchState();
}
class _DevicesDefaultSwitchState extends State<DevicesDefaultSwitch> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return BlocBuilder<AcCubit, AcState>(
children: <Widget>[ builder: (context, state) {
Expanded( return Row(
child: InkWell( children: <Widget>[
onTap: () { Expanded(
setState(() { child: InkWell(
// isOn = !isOn; onTap: () {
widget.model.status = !widget.model.status; AcCubit.get(context).turnACOn(model);
}); },
}, child: Container(
child: Container( height: 60,
height: 60, decoration: BoxDecoration(
decoration: BoxDecoration( color: model.status
color: widget.model.status ? ColorsManager.primaryColor
? ColorsManager.primaryColor : Colors.white,
: Colors.white, borderRadius: const BorderRadius.only(
borderRadius: const BorderRadius.only( topLeft: Radius.circular(15),
topLeft: Radius.circular(15), bottomLeft: Radius.circular(15),
bottomLeft: Radius.circular(15), ),
), ),
), child: Center(
child: Center( child: BodyMedium(
child: BodyMedium( text: "ON",
text: "ON", fontColor: model.status ? Colors.white : null,
fontColor: widget.model.status ? Colors.white : null, fontWeight: FontWeight.bold,
fontWeight: FontWeight.bold, ),
),
), ),
), ),
), ),
), Expanded(
), child: InkWell(
Expanded( onTap: () {
child: InkWell( AcCubit.get(context).turnACOff(model);
onTap: () { },
setState(() { child: Container(
widget.model.status = !widget.model.status; height: 60,
}); decoration: BoxDecoration(
}, color: model.status
child: Container( ? Colors.white
height: 60, : ColorsManager.primaryColor,
decoration: BoxDecoration( borderRadius: const BorderRadius.only(
color: widget.model.status topRight: Radius.circular(15),
? Colors.white bottomRight: Radius.circular(15),
: ColorsManager.primaryColor, ),
borderRadius: const BorderRadius.only( ),
topRight: Radius.circular(15), child: Center(
bottomRight: Radius.circular(15), child: BodyMedium(
), text: "OFF",
), fontColor: model.status ? null : Colors.white,
child: Center( fontWeight: FontWeight.bold,
child: BodyMedium( ),
text: "OFF", ),
fontColor: widget.model.status ? null : Colors.white,
fontWeight: FontWeight.bold,
), ),
), ),
), ),
), ],
), );
], },
); );
} }
} }

View File

@ -34,7 +34,7 @@ class BodyLarge extends StatelessWidget {
textAlign: textAlign, textAlign: textAlign,
style: style ?? style: style ??
context.bodyLarge.copyWith( context.bodyLarge.copyWith(
height: height ?? 1.5, height: height,
fontWeight: fontWeight, fontWeight: fontWeight,
color: fontColor, color: fontColor,
fontSize: fontSize, fontSize: fontSize,

View File

@ -2,7 +2,6 @@
class Assets { class Assets {
Assets._(); Assets._();
static const String assetsIconsHome = 'assets/icons/home.svg';
static const String fontsAftikaRegular = 'assets/fonts/AftikaRegular.ttf'; static const String fontsAftikaRegular = 'assets/fonts/AftikaRegular.ttf';
static const String iconsAC = 'assets/icons/AC.svg'; static const String iconsAC = 'assets/icons/AC.svg';
static const String iconsActive = 'assets/icons/active.svg'; static const String iconsActive = 'assets/icons/active.svg';
@ -20,18 +19,18 @@ class Assets {
static const String iconsFan3 = 'assets/icons/fan-3.svg'; static const String iconsFan3 = 'assets/icons/fan-3.svg';
static const String iconsFrequency = 'assets/icons/frequency.svg'; static const String iconsFrequency = 'assets/icons/frequency.svg';
static const String iconsGateway = 'assets/icons/Gateway.svg'; static const String iconsGateway = 'assets/icons/Gateway.svg';
static const String iconsHome = 'assets/icons/home.jpg'; static const String iconsHome = 'assets/icons/home.svg';
static const String iconsHome2 = 'assets/icons/home-2.svg';
static const String iconsHot1 = 'assets/icons/hot1.jpg'; static const String iconsHot1 = 'assets/icons/hot1.jpg';
static const String iconsLayout = 'assets/icons/Layout.svg'; static const String iconsLayout = 'assets/icons/Layout.svg';
static const String iconsLayoutFill = 'assets/icons/Layout-fill.svg'; static const String iconsLayoutFill = 'assets/icons/Layout-fill.svg';
static const String iconsLight = 'assets/icons/Light.svg'; static const String iconsLight = 'assets/icons/Light.svg';
static const String iconsLogo = 'assets/icons/logo.png';
static const String iconsMenu = 'assets/icons/Menu.svg'; static const String iconsMenu = 'assets/icons/Menu.svg';
static const String iconsMenuFill = 'assets/icons/Menu-fill.svg'; static const String iconsMenuFill = 'assets/icons/Menu-fill.svg';
static const String iconsMinus = 'assets/icons/minus.svg'; static const String iconsMinus = 'assets/icons/minus.svg';
static const String iconsPlus = 'assets/icons/plus.svg'; static const String iconsPlus = 'assets/icons/plus.svg';
static const String iconsRoutineFill = 'assets/icons/Routine-fill.svg';
static const String iconsRoutines = 'assets/icons/Routines.svg'; static const String iconsRoutines = 'assets/icons/Routines.svg';
static const String iconsRoutinesFill = 'assets/icons/Routines-fill.svg';
static const String iconsScreen = 'assets/icons/Screen.svg'; static const String iconsScreen = 'assets/icons/Screen.svg';
static const String iconsSummer = 'assets/icons/Summer.svg'; static const String iconsSummer = 'assets/icons/Summer.svg';
static const String iconsSummerMode = 'assets/icons/summer_mode.svg'; static const String iconsSummerMode = 'assets/icons/summer_mode.svg';