Merge pull request #3 from SyncrowIOT/lights_list

Lights list
This commit is contained in:
Mohammad Salameh
2024-03-04 14:37:13 +03:00
committed by GitHub
56 changed files with 918 additions and 375 deletions

1
.gitignore vendored
View File

@ -28,7 +28,6 @@ migrate_working_dir/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related

View File

@ -9,14 +9,14 @@ PODS:
- Firebase/Crashlytics (10.20.0):
- Firebase/CoreOnly
- FirebaseCrashlytics (~> 10.20.0)
- firebase_analytics (10.8.6):
- firebase_analytics (10.8.7):
- Firebase/Analytics (= 10.20.0)
- firebase_core
- Flutter
- firebase_core (2.25.4):
- firebase_core (2.25.5):
- Firebase/CoreOnly (= 10.20.0)
- Flutter
- firebase_crashlytics (3.4.15):
- firebase_crashlytics (3.4.16):
- Firebase/Crashlytics (= 10.20.0)
- firebase_core
- Flutter
@ -188,9 +188,9 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
Firebase: 10c8cb12fb7ad2ae0c09ffc86cd9c1ab392a0031
firebase_analytics: 9c600045bfb4d16dd78593d18f32c99bb77e5001
firebase_core: a46c312d8bae4defa3d009b2aa7b5b413aeb394e
firebase_crashlytics: 3054fbdd2b4a4a91f25a15e57c9f1bd2a9ed81ae
firebase_analytics: 2c1c3057d5da3bd3aab819f7e6ee153a4e46c59e
firebase_core: c8628c7ce80f79439149549052bff22f6784fbf5
firebase_crashlytics: 012078b4eec6fc9716f97ba3da0f0e44a04e95b1
FirebaseAnalytics: a2731bf3670747ce8f65368b118d18aa8e368246
FirebaseCore: 28045c1560a2600d284b9c45a904fe322dc890b6
FirebaseCoreExtension: 1c044fd46e95036cccb29134757c499613f3f564

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../../../../generated/assets.dart';
@ -30,9 +29,9 @@ class AppBarHomeDropdown extends StatelessWidget {
BlendMode.srcIn,
),
),
const Gap(5),
const SizedBox(width: 5),
const BodyLarge(text: 'Home'),
const Gap(5),
const SizedBox(width: 5),
const Icon(
Icons.expand_more,
color: Colors.black,

View File

@ -1,5 +1,4 @@
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
part 'auth_state.dart';

View File

@ -1,6 +1,5 @@
part of 'auth_cubit.dart';
@immutable
abstract class AuthState {}
class AuthInitial extends AuthState {}

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/shared_widgets/default_text_button.dart';
import 'package:syncrow_app/features/shared_widgets/syncrow_logo.dart';
@ -26,12 +25,12 @@ class AuthViewBody extends StatelessWidget {
Navigator.popAndPushNamed(context, Routes.homeRoute);
},
),
const Gap(15),
const SizedBox(height: 15),
const DefaultTextButton(
text: 'Sign Up',
isSecondary: true,
),
const Gap(20),
const SizedBox(height: 20),
Center(
child: InkWell(
onTap: () {},
@ -43,7 +42,7 @@ class AuthViewBody extends StatelessWidget {
),
),
),
const Gap(30),
const SizedBox(height: 30),
],
),
);

View File

@ -1,7 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.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/consumption.dart';
import 'package:syncrow_app/features/dashboard/view/widgets/live_monitor_tab.dart';
@ -28,7 +27,7 @@ class DashboardView extends StatelessWidget {
),
),
const LiveMonitorTab(),
const Gap(10),
const SizedBox(height: 10),
const EnergyUsage(),
Container(
padding: const EdgeInsets.only(top: 20),
@ -40,7 +39,7 @@ class DashboardView extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Consumption(),
Gap(20),
SizedBox(height: 20),
CarbonEmission(),
],
),

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/dashboard/view/widgets/card_title.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/features/shared_widgets/united_text.dart';
@ -31,7 +30,7 @@ class CarbonEmission extends StatelessWidget {
const CardTitle(
title: "Carbon Emission",
),
const Gap(10),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
@ -46,7 +45,7 @@ class CarbonEmission extends StatelessWidget {
fit: BoxFit.contain,
),
),
const Gap(5),
const SizedBox(height: 5),
const Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
@ -64,7 +63,7 @@ class CarbonEmission extends StatelessWidget {
),
],
),
const Gap(20),
const SizedBox(width: 20),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
@ -76,7 +75,7 @@ class CarbonEmission extends StatelessWidget {
fit: BoxFit.contain,
),
),
const Gap(5),
const SizedBox(width: 5),
const Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/dashboard/view/widgets/card_title.dart';
import 'package:syncrow_app/features/shared_widgets/united_text.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
@ -44,7 +43,7 @@ class Consumption extends StatelessWidget {
valueWeight: FontWeight.normal,
unit: "Units",
),
const Gap(30),
const SizedBox(width: 30),
UnitedText(
value: "${MediaQuery.sizeOf(context).height.ceil()}",
valueSize: MediaQuery.sizeOf(context).height.ceil() > 680

View File

@ -65,13 +65,13 @@ class EnergyUsage extends StatelessWidget {
case 0:
return SideTitleWidget(
axisSide: meta.axisSide,
child: BodySmall(text: '1'),
child: const BodySmall(text: '1'),
);
case 11:
return SideTitleWidget(
axisSide: meta.axisSide,
child: BodySmall(text: '28'),
child: const BodySmall(text: '28'),
);
default:
return Container();
@ -172,7 +172,7 @@ class EnergyUsage extends StatelessWidget {
return SideTitleWidget(
axisSide: meta.axisSide,
child: BodySmall(text: 'Feb'),
child: const BodySmall(text: 'Feb'),
);
}
}

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
@ -37,7 +36,7 @@ class LiveMonitorWidget extends StatelessWidget {
fit: BoxFit.contain,
),
),
const Gap(5),
const SizedBox(width: 5),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,

View File

@ -0,0 +1,52 @@
import 'package:flutter/cupertino.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/ac_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
part 'ac_state.dart';
class AcCubit extends Cubit<AcState> {
AcCubit() : super(AcInitial());
static AcCubit get(context) => BlocProvider.of(context);
void selectAC(ACModel model) {
model.isSelected = !model.isSelected;
emit(ACSelected());
}
ACModel? getSelectedAC() {
for (var ac in DevicesCubit.categories[0].devices) {
if (ac is ACModel && ac.isSelected) {
return ac;
}
}
return null;
}
void setTempToAll(double temperature) {
for (DeviceModel ac in DevicesCubit.categories[0].devices) {
if (ac is ACModel) {
setACTemp(ac, temperature);
}
}
universalACTemp = temperature;
emit(ACsTempChanged(temperature));
}
void setACTemp(ACModel model, double temp) {
model.temperature = temp;
emit(ACsTempChanged(temp));
}
double getTemp(int index) {
var device = DevicesCubit.categories[0].devices[index];
if (device is ACModel) {
return device.temperature;
}
return 0.0; // or any default value you prefer
}
static double universalACTemp = 20;
}

View File

@ -1,123 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:meta/meta.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';
class AcCubit extends Cubit<AcState> {
AcCubit() : super(AcInitial()) {
averageTempForAll();
updateACsStatus();
}
static AcCubit get(context) => BlocProvider.of(context);
void selectAC(ACModel model) {
model.isSelected = !model.isSelected;
emit(ACSelected());
}
ACModel? getSelectedAC() {
for (var ac in DevicesCubit.categories[0].devices) {
if (ac.isSelected) {
return ac;
}
}
return null;
}
void turnACOn(ACModel model) {
if (!model.status) {
model.status = true;
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());
}
}
void turnAllACsOff() {
for (var ac in DevicesCubit.categories[0].devices) {
ac.status = false;
}
updateACsStatus();
emit(SwitchACsOff());
}
void turnAllACsOn() {
for (var ac in DevicesCubit.categories[0].devices) {
ac.status = true;
}
updateACsStatus();
emit(SwitchACsOn());
}
void setTempToAll(double temperature) {
for (var ac in DevicesCubit.categories[0].devices) {
ac.temperature = temperature;
}
averageTempForAll();
emit(ACsTempChanged(temperature));
}
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));
}
void setACTemp(ACModel model, double temp) {
model.temperature = temp;
averageTempForAll();
emit(ACsTempChanged(temp));
}
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;
emit(ACsAverageTemp());
}
/// implement the fan speed and temp mode change
}

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/light_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/gateway/gateway_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/screens/screens_view.dart';
@ -14,21 +16,11 @@ import '../view/widgets/lights/lights_view.dart';
part 'devices_state.dart';
class DevicesCubit extends Cubit<DevicesState> {
DevicesCubit() : super(DevicesInitial()) {
// getCategories();
}
void changeCategorySwitchValue(DevicesCategoryModel category) {
category.devicesStatus = !category.devicesStatus;
for (var device in category.devices) {
device.status = category.devicesStatus;
}
emit(CategorySwitchChanged());
}
DevicesCubit() : super(DevicesInitial());
static DevicesCubit get(context) => BlocProvider.of(context);
static var categories = <DevicesCategoryModel>[
static List<DevicesCategoryModel> categories = [
DevicesCategoryModel(
devices: [
ACModel(
@ -38,6 +30,11 @@ class DevicesCubit extends Cubit<DevicesState> {
temperature: 20,
fanSpeed: 0,
tempMode: 0,
coolTo: 20,
type: '',
location: '',
image: '',
timer: null,
),
ACModel(
name: "Master Bedroom AC",
@ -46,6 +43,37 @@ class DevicesCubit extends Cubit<DevicesState> {
temperature: 20,
fanSpeed: 0,
tempMode: 0,
coolTo: 20,
type: '',
location: '',
image: '',
timer: null,
),
ACModel(
name: "Kitchen AC",
id: '2',
status: false,
temperature: 20,
fanSpeed: 0,
tempMode: 0,
coolTo: 20,
type: '',
location: '',
image: '',
timer: null,
),
ACModel(
name: "Bathroom AC",
id: '3',
status: false,
temperature: 20,
fanSpeed: 0,
tempMode: 0,
coolTo: 20,
type: '',
location: '',
image: '',
timer: null,
),
],
icon: Assets.iconsAC,
@ -54,7 +82,68 @@ class DevicesCubit extends Cubit<DevicesState> {
page: const ACsView(),
),
DevicesCategoryModel(
devices: [],
devices: [
LightModel(
name: "Living Room Light",
id: '0',
status: false,
color: 0,
brightness: 20,
lightingMode: 1,
timer: null,
type: '',
location: '',
image: '',
),
LightModel(
name: "Master Bedroom Light",
id: '1',
status: false,
color: 2,
brightness: 40,
lightingMode: 1,
timer: null,
type: '',
location: '',
image: '',
),
LightModel(
name: "Kitchen Light",
id: '2',
status: false,
color: 1,
brightness: 60,
lightingMode: 1,
timer: null,
type: '',
location: '',
image: '',
),
LightModel(
name: "Bathroom Light",
id: '3',
status: false,
color: 3,
brightness: 80,
lightingMode: 1,
timer: null,
type: '',
location: '',
image: '',
),
LightModel(
name: "Balcony Light",
id: '4',
status: false,
color: 4,
brightness: 100,
lightingMode: 1,
timer: null,
type: '',
location: '',
image: '',
),
],
icon: Assets.iconsLight,
name: 'Lights',
type: DeviceType.Lights,
@ -99,9 +188,63 @@ class DevicesCubit extends Cubit<DevicesState> {
return null;
}
void changeCategorySwitchValue(DevicesCategoryModel category) {
if (category.devicesStatus != null) {
category.devicesStatus = !category.devicesStatus!;
for (var device in category.devices) {
device.status = category.devicesStatus;
}
} else {
category.devicesStatus = true;
for (var device in category.devices) {
device.status = true;
}
}
emit(CategorySwitchChanged());
}
void turnOnOffDevice(DeviceModel device) {
device.status = !device.status!;
DevicesCategoryModel category =
categories.firstWhere((category) => category.devices.contains(device));
updateDevicesStatus(category);
emit(DeviceSwitchChanged());
}
void updateDevicesStatus(DevicesCategoryModel category) {
bool? tempStatus = category.devices[0].status;
for (var ac in category.devices) {
//check if there any ac have a different status than the initial ==> turn off the universal switch
if (ac.status != tempStatus) {
category.devicesStatus = null;
emit(DeviceSwitchChanged());
return;
}
category.devicesStatus = tempStatus;
emit(DeviceSwitchChanged());
}
}
void turnAllDevicesOff(DevicesCategoryModel category) {
for (var device in category.devices) {
device.status = false;
}
updateDevicesStatus(category);
emit(CategorySwitchChanged());
}
void turnAllDevicesOn(DevicesCategoryModel category) {
for (var device in category.devices) {
device.status = true;
}
updateDevicesStatus(category);
emit(CategorySwitchChanged());
}
void areAllDevicesOff(DevicesCategoryModel category) {
for (var device in category.devices) {
if (device.status) {
if (device.status ?? false) {
category.devicesStatus = false;
emit(CategorySwitchChanged());
return;

View File

@ -17,8 +17,4 @@ class DevicesCategoryChanged extends DevicesState {}
class CategorySwitchChanged extends DevicesState {}
class SwitchACsOff extends DevicesState {}
class SwitchACsOn extends DevicesState {}
class SetACsTemp extends DevicesState {}
class DeviceSwitchChanged extends DevicesState {}

View File

@ -0,0 +1,32 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/model/light_model.dart';
part 'lights_state.dart';
class LightsCubit extends Cubit<LightsState> {
LightsCubit() : super(LightsInitial());
static LightsCubit get(context) => BlocProvider.of(context);
int getBrightness(LightModel light) {
return light.brightness.toInt();
}
setBrightness(LightModel light, double value) {
value = (value / 5).ceil() * 5;
if (value != light.brightness) {
light.brightness = value;
emit(LightBrightnessChanged(value));
}
}
onHorizontalDragUpdate(LightModel light, double dx, double screenWidth) {
double newBrightness = (dx / (screenWidth - 15) * 100);
if (newBrightness > 100) {
newBrightness = 100;
} else if (newBrightness < 0) {
newBrightness = 0;
}
setBrightness(light, newBrightness);
}
}

View File

@ -0,0 +1,21 @@
part of 'lights_cubit.dart';
abstract class LightsState {}
class LightsInitial extends LightsState {}
class LightsLoading extends LightsState {}
class LightsSuccess extends LightsState {}
class LightsFailure extends LightsState {
final String message;
LightsFailure(this.message);
}
class LightBrightnessChanged extends LightsState {
final double brightness;
LightBrightnessChanged(this.brightness);
}

View File

@ -1,21 +1,56 @@
class ACModel {
final String name;
final String id;
late bool status;
import 'package:syncrow_app/features/devices/model/device_model.dart';
class ACModel extends DeviceModel {
late double temperature;
late int fanSpeed;
late int tempMode;
bool isSelected = false;
late double coolTo;
ACModel({
required this.name,
required this.id,
required this.status,
required this.temperature,
required this.fanSpeed,
required this.tempMode,
required this.coolTo,
required super.id,
required super.name,
required super.type,
required super.status,
required super.location,
required super.image,
required super.timer,
});
Map<String, dynamic> toJson() {
return {
'temperature': temperature,
'fanSpeed': fanSpeed,
'tempMode': tempMode,
'coolTo': coolTo,
'id': id,
'name': name,
'status': status,
'type': type,
'location': location,
'image': image,
};
}
factory ACModel.fromJson(Map<String, dynamic> json) {
return ACModel(
id: json['id'],
name: json['name'],
status: json['status'],
temperature: json['temperature'],
fanSpeed: json['fanSpeed'],
tempMode: json['tempMode'],
type: json['type'],
location: json['location'],
image: json['image'],
timer: json['timer'],
coolTo: json['coolTo'],
);
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart';
// ignore_for_file: constant_identifier_names
import 'ac_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
class DevicesCategoryModel {
final String name;
@ -8,8 +9,8 @@ class DevicesCategoryModel {
final Widget page;
bool devicesStatus = false;
final List<ACModel> devices;
bool? devicesStatus = false;
final List<DeviceModel> devices;
final DeviceType type;
bool isSelected;
@ -23,7 +24,7 @@ class DevicesCategoryModel {
required this.devices}) {
//sets the initial status of the devices
if (devices.isNotEmpty) {
bool tempStatus = devices.first.status;
bool tempStatus = devices.first.status ?? false;
for (var device in devices) {
if (device.status != tempStatus) {
devicesStatus = false;

View File

@ -0,0 +1,20 @@
abstract class DeviceModel {
final String? id;
final String? name;
final String? type;
bool? status;
final String? location;
final String? image;
final double? timer;
bool isSelected = false;
DeviceModel({
required this.id,
required this.name,
required this.type,
required this.status,
required this.location,
required this.image,
required this.timer,
});
}

View File

@ -0,0 +1,51 @@
import 'package:syncrow_app/features/devices/model/device_model.dart';
class LightModel extends DeviceModel {
late double brightness;
late int color;
late int lightingMode;
LightModel({
required this.brightness,
required this.color,
required this.lightingMode,
required super.id,
required super.name,
required super.type,
required super.status,
required super.location,
required super.image,
required super.timer,
});
Map<String, dynamic> toJson() {
return {
'luminance': brightness,
'color': color,
'lightingMode': lightingMode,
'timer': timer,
'id': id,
'name': name,
'status': status,
'type': type,
'location': location,
'image': image,
};
}
factory LightModel.fromJson(Map<String, dynamic> json) {
return LightModel(
id: json['id'],
name: json['name'],
status: json['status'],
brightness: json['luminance'],
color: json['color'],
lightingMode: json['lightingMode'],
timer: json['timer'],
type: json['type'],
location: json['location'],
image: json['image'],
);
}
}

View File

@ -1,7 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface_controls.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface_temp_unit.dart';
@ -17,7 +16,7 @@ class AcInterface extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Gap(20),
const SizedBox(height: 20),
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: 400,

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_mode_control_unit.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
@ -17,42 +16,39 @@ class AcInterfaceControls extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Expanded(
flex: 3,
child: Column(
children: [
const Gap(10),
ACModeControlUnit(model: acModel),
Gap(10),
Row(
children: [
Expanded(
child: InkWell(
onTap: () {},
child: DefaultContainer(
height: 55,
child: Center(
child: SvgPicture.asset(Assets.iconsAutomatedClock),
),
return Column(
children: [
const SizedBox(height: 10),
ACModeControlUnit(model: acModel),
const SizedBox(height: 10),
Row(
children: [
Expanded(
child: InkWell(
onTap: () {},
child: DefaultContainer(
height: 55,
child: Center(
child: SvgPicture.asset(Assets.iconsAutomatedClock),
),
),
),
const Gap(10),
Expanded(
child: InkWell(
onTap: () {},
child: DefaultContainer(
height: 55,
child: Center(
child: SvgPicture.asset(Assets.iconsLock),
),
),
const SizedBox(width: 10),
Expanded(
child: InkWell(
onTap: () {},
child: DefaultContainer(
height: 55,
child: Center(
child: SvgPicture.asset(Assets.iconsLock),
),
),
),
],
)
],
),
),
],
)
],
);
}
}

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:sleek_circular_slider/sleek_circular_slider.dart';
import 'package:syncrow_app/features/devices/bloc/ac_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/AC/ac_cubit.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_medium.dart';
@ -23,6 +23,7 @@ class AcInterfaceTempUnit extends StatelessWidget {
@override
Widget build(BuildContext context) {
//TODO: use the coolTo value from the model
double coolTo = acModel.temperature;
return BlocBuilder<AcCubit, AcState>(
builder: (context, state) {

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
@ -53,7 +52,7 @@ class _ACModeControlUnitState extends State<ACModeControlUnit> {
),
),
),
const Gap(10),
const SizedBox(width: 10),
Expanded(
child: InkWell(
onTap: () {

View File

@ -1,21 +1,21 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.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/devices/bloc/AC/ac_cubit.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/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../../../../../generated/assets.dart';
import '../../../model/ac_model.dart';
class ACTempWidget extends StatelessWidget {
const ACTempWidget(
this.index, {
this.acModel, {
super.key,
});
final int index;
final ACModel acModel;
@override
Widget build(BuildContext context) {
@ -30,7 +30,8 @@ class ACTempWidget extends StatelessWidget {
dimension: 24,
child: InkWell(
onTap: () {
AcCubit.get(context).decreaseACTemp(index);
AcCubit.get(context)
.setACTemp(acModel, acModel.temperature - 0.5);
},
child: SvgPicture.asset(
Assets.iconsMinus,
@ -38,7 +39,7 @@ class ACTempWidget extends StatelessWidget {
),
),
BodyLarge(
text: "${AcCubit.get(context).getTemp(index)}° C",
text: "${acModel.temperature}° C",
style: context.bodyLarge.copyWith(
color: ColorsManager.primaryColor.withOpacity(0.6),
fontSize: 23,
@ -48,7 +49,8 @@ class ACTempWidget extends StatelessWidget {
dimension: 24,
child: InkWell(
onTap: () {
AcCubit.get(context).increaseACTemp(index);
AcCubit.get(context)
.setACTemp(acModel, acModel.temperature + 0.5);
},
child: SvgPicture.asset(
Assets.iconsPlus,

View File

@ -1,14 +1,16 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/devices/bloc/ac_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/AC/ac_cubit.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/features/devices/view/widgets/ACs/ac_mode_control_unit.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_temp_widget.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/universal_ac_switch.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/universal_ac_temp.dart';
import 'package:syncrow_app/features/devices/view/widgets/universal_switch.dart';
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import '../../../model/ac_model.dart';
class ACsList extends StatelessWidget {
const ACsList({
super.key,
@ -16,26 +18,30 @@ class ACsList extends StatelessWidget {
@override
Widget build(BuildContext context) {
DevicesCategoryModel category = DevicesCubit.categories[0];
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// universal AC controller
const Gap(10),
const SizedBox(height: 10),
const BodySmall(text: "All ACs"),
const Gap(5),
const UniversalACSwitch(),
const Gap(10),
const SizedBox(height: 5),
UniversalSwitch(
category: category,
),
const SizedBox(height: 10),
const UniversalACTemp(),
const Gap(10),
const SizedBox(height: 10),
// other ACs controls
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
itemCount: DevicesCubit.categories[0].devices.length,
itemCount: category.devices.length,
itemBuilder: (context, index) {
ACModel ac = category.devices[index] as ACModel;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -43,12 +49,13 @@ class ACsList extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
BodySmall(
text: DevicesCubit.categories[0].devices[index].name),
BodySmall(text: category.devices[index].name ?? ""),
IconButton(
onPressed: () {
AcCubit.get(context).selectAC(
DevicesCubit.categories[0].devices[index]);
var device = category.devices[index];
if (device is ACModel) {
AcCubit.get(context).selectAC(device);
}
},
icon: const Icon(
Icons.arrow_forward_ios,
@ -63,19 +70,21 @@ class ACsList extends StatelessWidget {
),
],
),
const Gap(5),
DevicesDefaultSwitch(
model: DevicesCubit.categories[0].devices[index],
),
const Gap(10),
const SizedBox(height: 5),
if (category.devices[index] is ACModel)
DevicesDefaultSwitch(
model: ac,
),
const SizedBox(height: 10),
ACTempWidget(
index,
ac,
),
const Gap(10),
ACModeControlUnit(
model: DevicesCubit.categories[0].devices[index],
),
const Gap(10),
const SizedBox(height: 10),
if (category.devices[index] is ACModel)
ACModeControlUnit(
model: ac,
),
const SizedBox(height: 10),
],
);
},

View File

@ -3,7 +3,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/view/widgets/default_app_bar.dart';
import 'package:syncrow_app/features/app_layout/view/widgets/default_nav_bar.dart';
import 'package:syncrow_app/features/devices/bloc/ac_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/AC/ac_cubit.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_list.dart';

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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/ac_cubit.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import '../../../../../generated/assets.dart';
@ -27,7 +27,8 @@ class UniversalACTemp extends StatelessWidget {
dimension: 24,
child: InkWell(
onTap: () {
AcCubit.get(context).setTempToAll(AcCubit.averageTemp + .5);
AcCubit.get(context)
.setTempToAll(AcCubit.universalACTemp - .5);
},
child: SvgPicture.asset(
Assets.iconsMinus,
@ -35,7 +36,7 @@ class UniversalACTemp extends StatelessWidget {
),
),
BodyLarge(
text: "${AcCubit.averageTemp}° C",
text: "${AcCubit.universalACTemp}° C",
style: context.bodyLarge.copyWith(
color: ColorsManager.primaryColor.withOpacity(0.6),
fontSize: 23,
@ -45,7 +46,8 @@ class UniversalACTemp extends StatelessWidget {
dimension: 24,
child: InkWell(
onTap: () {
AcCubit.get(context).setTempToAll(AcCubit.averageTemp + .5);
AcCubit.get(context)
.setTempToAll(AcCubit.universalACTemp + .5);
},
child: SvgPicture.asset(
Assets.iconsPlus,

View File

@ -4,14 +4,14 @@ import 'package:syncrow_app/features/devices/view/widgets/switches.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
class CategoriesView extends StatelessWidget {
const CategoriesView({
class DevicesCategoriesView extends StatelessWidget {
const DevicesCategoriesView({
super.key,
});
@override
Widget build(BuildContext context) {
return const Column(
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
@ -34,7 +33,7 @@ class DevicesModeTab extends StatelessWidget {
fit: BoxFit.contain,
),
),
const Gap(5),
const SizedBox(width: 5),
const BodySmall(
text: StringsManager.winter,
fontWeight: FontWeight.bold,
@ -62,7 +61,7 @@ class DevicesModeTab extends StatelessWidget {
fit: BoxFit.contain,
),
),
const Gap(5),
const SizedBox(width: 5),
const BodySmall(
text: StringsManager.summer,
fontWeight: FontWeight.bold,

View File

@ -1,8 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/view/widgets/categories_view.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
import 'package:syncrow_app/features/devices/view/widgets/devices_categories_view.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import '../../../../utils/resource_manager/strings_manager.dart';
import '../../bloc/devices_cubit.dart';
import 'switches.dart';
class DevicesViewBody extends StatelessWidget {
const DevicesViewBody({
@ -15,9 +19,101 @@ class DevicesViewBody extends StatelessWidget {
create: (context) => DevicesCubit(),
child: BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
PageController pageController = PageController();
return state is DevicesLoading
? const Center(child: CircularProgressIndicator())
: const CategoriesView();
: Column(
children: [
SizedBox(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height - 252,
child: PageView(
controller: pageController,
children: const [
DevicesCategoriesView(),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TitleMedium(
text: "Home",
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
],
),
),
Expanded(
flex: 3,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
TitleMedium(
text: StringsManager.wizard,
style: TextStyle(
fontSize: 28,
),
),
Switches(),
],
),
),
)
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TitleMedium(
text: "Office",
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
],
),
),
Expanded(
flex: 3,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
TitleMedium(
text: StringsManager.wizard,
style: TextStyle(
fontSize: 28,
),
),
Switches(),
],
),
),
)
],
),
],
),
),
SmoothPageIndicator(
controller: pageController,
count: 3,
effect: const WormEffect()),
],
);
},
),
);

View File

@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/lights/lights_cubit.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/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../../../model/light_model.dart';
class LightBrightness extends StatelessWidget {
const LightBrightness({
super.key,
required this.light,
});
final LightModel light;
@override
Widget build(BuildContext context) {
return BlocBuilder<LightsCubit, LightsState>(
builder: (context, state) {
return GestureDetector(
onHorizontalDragUpdate: (details) => LightsCubit.get(context)
.onHorizontalDragUpdate(light, details.localPosition.dx,
MediaQuery.of(context).size.width - 15),
child: Stack(
alignment: Alignment.center,
children: [
const DefaultContainer(
height: 60,
child: SizedBox.expand(),
),
AnimatedPositioned(
left: 0,
duration: const Duration(milliseconds: 50),
child: Container(
height: 60,
width: (MediaQuery.of(context).size.width - 30) *
light.brightness /
100,
decoration: BoxDecoration(
color: ColorsManager.primaryColor.withOpacity(0.6),
borderRadius: light.brightness != 100
? const BorderRadius.only(
topLeft: Radius.circular(20),
bottomLeft: Radius.circular(20),
)
: BorderRadius.circular(20),
),
),
),
BodyLarge(
text: "${light.brightness}%",
style: context.bodyLarge.copyWith(
color: Colors.black,
fontSize: 23,
),
),
],
),
);
},
);
}
}

View File

@ -0,0 +1,58 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/light_brightness.dart';
import '../../../../shared_widgets/devices_default_switch.dart';
import '../../../../shared_widgets/text_widgets/body_small.dart';
import '../../../model/light_model.dart';
class LightsList extends StatelessWidget {
const LightsList({
super.key,
required this.lights,
});
final List<LightModel> lights;
@override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
itemCount: lights.length,
itemBuilder: (context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
BodySmall(text: lights[index].name ?? ""),
IconButton(
onPressed: () {
// LightsCubit.get(context).selectAC(device);
},
icon: const Icon(
Icons.arrow_forward_ios,
),
style: ButtonStyle(
padding: MaterialStateProperty.all(
const EdgeInsets.all(0),
),
iconSize: MaterialStateProperty.all(15),
alignment: Alignment.bottomRight,
),
),
],
),
const SizedBox(height: 5),
DevicesDefaultSwitch(model: lights[index]),
const SizedBox(height: 10),
LightBrightness(light: lights[index]),
],
);
},
);
}
}

View File

@ -1,10 +1,81 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/lights_list.dart';
import '../../../../../generated/assets.dart';
import '../../../../../utils/resource_manager/color_manager.dart';
import '../../../../app_layout/view/widgets/default_app_bar.dart';
import '../../../../app_layout/view/widgets/default_nav_bar.dart';
import '../../../../shared_widgets/text_widgets/body_small.dart';
import '../../../bloc/devices_cubit.dart';
import '../../../bloc/lights/lights_cubit.dart';
import '../../../model/light_model.dart';
import '../universal_switch.dart';
class LightsView extends StatelessWidget {
const LightsView({super.key});
@override
Widget build(BuildContext context) {
return const Placeholder();
return BlocProvider(
create: (context) => LightsCubit(),
child: BlocBuilder<LightsCubit, LightsState>(
builder: (context, state) {
List<LightModel> lights = [];
for (var device in DevicesCubit.categories[1].devices) {
if (device is LightModel) {
lights.add(device);
}
}
return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
statusBarIconBrightness: Brightness.light,
),
child: SafeArea(
child: Scaffold(
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar: const DefaultAppBar(),
body: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.imagesBackground,
),
fit: BoxFit.cover,
opacity: 0.4,
),
),
child: Padding(
padding: const EdgeInsets.only(
top: 70, right: 15, left: 15, bottom: 80),
child: SizedBox.expand(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const BodySmall(text: "All Lights"),
UniversalSwitch(
category: DevicesCubit.categories[1],
),
LightsList(lights: lights),
],
),
),
),
),
),
bottomNavigationBar: const DefaultNavBar(),
),
),
);
},
),
);
}
}

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/shared_widgets/default_text_button.dart';
import 'package:syncrow_app/generated/assets.dart';
@ -20,7 +19,7 @@ class NoDevicesView extends StatelessWidget {
scale: 1,
width: 140,
),
const Gap(15),
const SizedBox(height: 15),
const Text(
'No Devices',
style: TextStyle(
@ -28,7 +27,7 @@ class NoDevicesView extends StatelessWidget {
fontSize: 18,
),
),
const Gap(15),
const SizedBox(height: 15),
const DefaultTextButton(
text: 'Add Device',
),

View File

@ -5,6 +5,7 @@ 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/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
import '../../bloc/devices_cubit.dart';
@ -32,7 +33,9 @@ class Switches extends StatelessWidget {
return InkWell(
onTap: () {
DevicesCubit.get(context).selectCategory(index);
Navigator.push(context, MaterialPageRoute(builder: (context) {
//Navigate to the chosen category view without animation
Navigator.push(context, CustomPageRoute(builder: (context) {
return DevicesCubit.get(context).chosenCategoryView!;
}));
},

View File

@ -1,33 +1,39 @@
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/strings_manager.dart';
import '../../../../../utils/resource_manager/color_manager.dart';
import '../../../../shared_widgets/text_widgets/body_medium.dart';
import '../../../bloc/ac_cubit.dart';
import '../../../../utils/resource_manager/color_manager.dart';
import '../../../shared_widgets/text_widgets/body_medium.dart';
class UniversalACSwitch extends StatelessWidget {
const UniversalACSwitch({
class UniversalSwitch extends StatelessWidget {
const UniversalSwitch({
super.key,
required this.category,
});
final DevicesCategoryModel category;
@override
Widget build(BuildContext context) {
//TODO: Move these to String Manager "ON" and "OFF"
return BlocBuilder<AcCubit, AcState>(
return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
bool? status = category.devicesStatus;
return Row(
children: <Widget>[
Expanded(
child: InkWell(
onTap: () {
AcCubit.get(context).turnAllACsOn();
DevicesCubit.get(context).turnAllDevicesOn(category);
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: DevicesCubit.categories[0].devicesStatus
? ColorsManager.primaryColor
color: status != null
? status
? ColorsManager.primaryColor
: Colors.white
: Colors.white,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15),
@ -36,9 +42,11 @@ class UniversalACSwitch extends StatelessWidget {
),
child: Center(
child: BodyMedium(
text: "ON",
fontColor: DevicesCubit.categories[0].devicesStatus
? Colors.white
text: StringsManager.on,
fontColor: status != null
? status
? Colors.white
: null
: null,
fontWeight: FontWeight.bold,
),
@ -49,14 +57,16 @@ class UniversalACSwitch extends StatelessWidget {
Expanded(
child: InkWell(
onTap: () {
AcCubit.get(context).turnAllACsOff();
DevicesCubit.get(context).turnAllDevicesOff(category);
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: DevicesCubit.categories[0].devicesStatus
? Colors.white
: ColorsManager.primaryColor,
color: status != null
? status
? Colors.white
: ColorsManager.primaryColor
: Colors.white,
borderRadius: const BorderRadius.only(
topRight: Radius.circular(15),
bottomRight: Radius.circular(15),
@ -64,10 +74,12 @@ class UniversalACSwitch extends StatelessWidget {
),
child: Center(
child: BodyMedium(
text: "OFF",
fontColor: DevicesCubit.categories[0].devicesStatus
? null
: Colors.white,
text: StringsManager.off,
fontColor: status != null
? status
? null
: Colors.white
: null,
fontWeight: FontWeight.bold,
),
),

View File

@ -1,5 +1,4 @@
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
part 'layout_state.dart';

View File

@ -1,6 +1,5 @@
part of 'layout_cubit.dart';
@immutable
abstract class LayoutState {}
class LayoutInitial extends LayoutState {}

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/menu/model/menu_list_model.dart';
import 'package:syncrow_app/features/menu/view/widgets/menu_list_divider.dart';
import 'package:syncrow_app/features/menu/view/widgets/menu_list_item.dart';
@ -19,11 +18,11 @@ class MenuList extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Gap(5),
const SizedBox(height: 5),
BodySmall(
text: listModel.label!,
),
const Gap(5),
const SizedBox(height: 5),
DefaultContainer(
child: ListView.separated(
shrinkWrap: true,
@ -37,7 +36,7 @@ class MenuList extends StatelessWidget {
},
separatorBuilder: (context, index) => const MenuListDivider()),
),
const Gap(5),
const SizedBox(height: 5),
],
);
}

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
@ -20,7 +19,7 @@ class ProfileTab extends StatelessWidget {
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Gap(20),
SizedBox(height: 20),
DefaultContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,

View File

@ -1,5 +1,4 @@
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
part 'profile_state.dart';

View File

@ -1,6 +1,5 @@
part of 'profile_cubit.dart';
@immutable
abstract class ProfileState {}
class ProfileInitial extends ProfileState {}

View File

@ -1,5 +1,4 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:meta/meta.dart';
import 'package:syncrow_app/features/scene/model/scene_model.dart';
part 'scene_state.dart';

View File

@ -1,6 +1,5 @@
part of 'scene_cubit.dart';
@immutable
abstract class SceneState {}
class SceneInitial extends SceneState {}

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/scene/bloc/scene_cubit.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
@ -29,7 +28,7 @@ class SceneView extends StatelessWidget {
fontWeight: FontWeight.bold,
),
),
const Gap(20),
const SizedBox(height: 20),
const BodySmall(
text: StringsManager.tapToRunRoutine,
),
@ -71,7 +70,7 @@ class SceneView extends StatelessWidget {
),
),
),
const Gap(10),
const SizedBox(width: 10),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:syncrow_app/features/shared_widgets/default_text_button.dart';
import 'package:syncrow_app/generated/assets.dart';
@ -22,13 +21,13 @@ class SceneViewNoScenes extends StatelessWidget {
opacity: const AlwaysStoppedAnimation(.5),
width: 140,
),
const Gap(15),
const SizedBox(height: 15),
const Text(
'Home automation saves your time and effort by automating routine tasks.',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.grey),
),
const Gap(20),
const SizedBox(height: 20),
const DefaultTextButton(
text: 'Create Scene',
)

View File

@ -22,8 +22,10 @@ class CustomSwitch extends StatelessWidget {
height: 28.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.0),
color: category.devicesStatus
? ColorsManager.primaryColor
color: category.devicesStatus != null
? category.devicesStatus!
? ColorsManager.primaryColor
: const Color(0xFFD9D9D9)
: const Color(0xFFD9D9D9),
),
child: Center(
@ -37,16 +39,20 @@ class CustomSwitch extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
alignment: category.devicesStatus
? Alignment.centerRight
alignment: category.devicesStatus != null
? category.devicesStatus!
? Alignment.centerRight
: Alignment.centerLeft
: Alignment.centerLeft,
child: Container(
width: 20.0,
height: 20.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: category.devicesStatus
? ColorsManager.primaryColor
color: category.devicesStatus != null
? category.devicesStatus!
? ColorsManager.primaryColor
: Colors.grey
: Colors.grey,
),
),

View File

@ -6,19 +6,22 @@ class DefaultContainer extends StatelessWidget {
required this.child,
this.height,
this.width,
this.color,
});
final double? height;
final double? width;
final Widget child;
final Color? color;
@override
Widget build(BuildContext context) {
return Container(
height: height,
width: width,
decoration: BoxDecoration(
color: Colors.white,
color: color ?? Colors.white,
borderRadius: BorderRadius.circular(20),
),
padding: const EdgeInsets.all(10),

View File

@ -1,33 +1,34 @@
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/device_model.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../devices/bloc/devices_cubit.dart';
class DevicesDefaultSwitch extends StatelessWidget {
const DevicesDefaultSwitch({
super.key,
required this.model,
});
final ACModel model;
final DeviceModel model;
@override
Widget build(BuildContext context) {
return BlocBuilder<AcCubit, AcState>(
return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
return Row(
children: <Widget>[
Expanded(
child: InkWell(
onTap: () {
AcCubit.get(context).turnACOn(model);
DevicesCubit.get(context).turnOnOffDevice(model);
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: model.status
color: model.status ?? false
? ColorsManager.primaryColor
: Colors.white,
borderRadius: const BorderRadius.only(
@ -38,7 +39,7 @@ class DevicesDefaultSwitch extends StatelessWidget {
child: Center(
child: BodyMedium(
text: "ON",
fontColor: model.status ? Colors.white : null,
fontColor: model.status ?? false ? Colors.white : null,
fontWeight: FontWeight.bold,
),
),
@ -48,12 +49,12 @@ class DevicesDefaultSwitch extends StatelessWidget {
Expanded(
child: InkWell(
onTap: () {
AcCubit.get(context).turnACOff(model);
DevicesCubit.get(context).turnOnOffDevice(model);
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: model.status
color: model.status ?? false
? Colors.white
: ColorsManager.primaryColor,
borderRadius: const BorderRadius.only(
@ -64,7 +65,7 @@ class DevicesDefaultSwitch extends StatelessWidget {
child: Center(
child: BodyMedium(
text: "OFF",
fontColor: model.status ? null : Colors.white,
fontColor: model.status ?? false ? null : Colors.white,
fontWeight: FontWeight.bold,
),
),

View File

@ -0,0 +1,11 @@
import 'package:flutter/material.dart';
class CustomPageRoute extends MaterialPageRoute {
CustomPageRoute({
required super.builder,
super.settings,
});
@override
Duration get transitionDuration => const Duration(milliseconds: 0);
}

View File

@ -1,4 +1,4 @@
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: lines_longer_than_80_chars, constant_identifier_names
class StringsManager {
static const noRouteFound = 'No route found';
@ -22,4 +22,6 @@ class StringsManager {
static const winterMode = 'Winter Mode';
static const summer = 'Summer';
static const summerMode = 'Summer Mode';
static const on = 'ON';
static const off = 'OFF';
}

View File

@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: _flutterfire_internals
sha256: "737321f9be522620ed3794937298fb0027a48a402624fa2500f7532f94aea810"
sha256: fe4c077084ddda88f327dc1c96d16631cd68d4948644593fcbcd911c2c89e2fa
url: "https://pub.dev"
source: hosted
version: "1.3.22"
version: "1.3.23"
args:
dependency: transitive
description:
@ -149,34 +149,34 @@ packages:
dependency: "direct main"
description:
name: firebase_analytics
sha256: "54681f6a8c35ec782c86680919953edbae66517a718fe7606a7ba52cfa1b36ca"
sha256: c6220b23397f9302a42617227ee8fb1c5d718097a5351fcce53561d73fc10339
url: "https://pub.dev"
source: hosted
version: "10.8.6"
version: "10.8.7"
firebase_analytics_platform_interface:
dependency: transitive
description:
name: firebase_analytics_platform_interface
sha256: cf7378f407c26fd1f1cc808c0d791f2a15dd4f1fe0626bb2ce6a96663c4d8470
sha256: "7f1c02cdd93a5e0a561af2f551465ffb6abdd541dbd0c8a9b8628d9ae0a5d024"
url: "https://pub.dev"
source: hosted
version: "3.9.6"
version: "3.9.7"
firebase_analytics_web:
dependency: transitive
description:
name: firebase_analytics_web
sha256: f62c7a2514771f6e122c5b55227c0c7fdaa253cc2fe6efce768897c0fb68a5ab
sha256: ebb857c23f35fed52220b6c3271c12eeb6137de3930845223e3d0590b6fd0649
url: "https://pub.dev"
source: hosted
version: "0.5.5+18"
version: "0.5.5+19"
firebase_core:
dependency: "direct main"
description:
name: firebase_core
sha256: "7e049e32a9d347616edb39542cf92cd53fdb4a99fb6af0a0bff327c14cd76445"
sha256: "797379ea206eaeeb62499775de812761493d0692890fdc7f90b6183a3369176d"
url: "https://pub.dev"
source: hosted
version: "2.25.4"
version: "2.25.5"
firebase_core_platform_interface:
dependency: transitive
description:
@ -189,26 +189,26 @@ packages:
dependency: transitive
description:
name: firebase_core_web
sha256: "57e61d6010e253b36d38191cefd6199d7849152cdcd234b61ca290cdb278a0ba"
sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492
url: "https://pub.dev"
source: hosted
version: "2.11.4"
version: "2.11.5"
firebase_crashlytics:
dependency: "direct main"
description:
name: firebase_crashlytics
sha256: "4c754db28a7daabe03c4cbf1079dbe81e6f0681284fed6d07e0e640b7f1027c4"
sha256: "0126fa101b74fb981796b3e6f47ccf7fc40237ec918327aaec7c0a06fd1bb4c1"
url: "https://pub.dev"
source: hosted
version: "3.4.15"
version: "3.4.16"
firebase_crashlytics_platform_interface:
dependency: transitive
description:
name: firebase_crashlytics_platform_interface
sha256: "08c5d7b5f93dbad7306d26702935abd8b579313ea256eb27006562a1867df249"
sha256: cdfa0a20d66e1b32de542883c0ddf651ee9b66b12cebf73067e4d2cdc0865d17
url: "https://pub.dev"
source: hosted
version: "3.6.22"
version: "3.6.23"
fixnum:
dependency: transitive
description:
@ -335,10 +335,10 @@ packages:
dependency: "direct main"
description:
name: flutter_svg
sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c
sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2"
url: "https://pub.dev"
source: hosted
version: "2.0.9"
version: "2.0.10+1"
flutter_test:
dependency: "direct dev"
description: flutter
@ -349,14 +349,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
gap:
dependency: "direct main"
description:
name: gap
sha256: f19387d4e32f849394758b91377f9153a1b41d79513ef7668c088c77dbc6955d
url: "https://pub.dev"
source: hosted
version: "3.0.1"
get_it:
dependency: "direct main"
description:
@ -642,6 +634,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
smooth_page_indicator:
dependency: "direct main"
description:
name: smooth_page_indicator
sha256: "725bc638d5e79df0c84658e1291449996943f93bacbc2cec49963dbbab48d8ae"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
source_span:
dependency: transitive
description:
@ -734,10 +734,10 @@ packages:
dependency: "direct main"
description:
name: url_launcher
sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c
sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e"
url: "https://pub.dev"
source: hosted
version: "6.2.4"
version: "6.2.5"
url_launcher_android:
dependency: transitive
description:
@ -806,26 +806,26 @@ packages:
dependency: transitive
description:
name: vector_graphics
sha256: "4ac59808bbfca6da38c99f415ff2d3a5d7ca0a6b4809c71d9cf30fba5daf9752"
sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3"
url: "https://pub.dev"
source: hosted
version: "1.1.10+1"
version: "1.1.11+1"
vector_graphics_codec:
dependency: transitive
description:
name: vector_graphics_codec
sha256: f3247e7ab0ec77dc759263e68394990edc608fb2b480b80db8aa86ed09279e33
sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da
url: "https://pub.dev"
source: hosted
version: "1.1.10+1"
version: "1.1.11+1"
vector_graphics_compiler:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: "18489bdd8850de3dd7ca8a34e0c446f719ec63e2bab2e7a8cc66a9028dd76c5a"
sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81"
url: "https://pub.dev"
source: hosted
version: "1.1.10+1"
version: "1.1.11+1"
vector_math:
dependency: transitive
description:

View File

@ -17,25 +17,25 @@ dependencies:
cupertino_icons: ^1.0.6
shared_preferences: ^2.2.2
flutter_animated_dialog: ^2.0.1
gap: ^3.0.1
flutter_svg: ^2.0.9
sleek_circular_slider: ^2.0.1
flutter_svg: ^2.0.10+1
fl_chart: ^0.66.2
sleek_circular_slider: ^2.0.1
# Utility Packages
flutter_secure_storage: ^9.0.0
cached_network_image: ^3.3.1
flutter_dotenv: ^5.1.0
intl: ^0.18.1
# noinspection YAMLSchemaValidation
intl: ^0.18.0
get_it: ^7.6.7
url_launcher: ^6.2.4
url_launcher: ^6.2.5
dio: ^5.4.1
flutter_localization: ^0.2.0
flutter_bloc: ^8.1.4
firebase_core: ^2.25.4
firebase_analytics: ^10.8.6
firebase_crashlytics: ^3.4.15
firebase_core: ^2.25.5
firebase_analytics: ^10.8.7
firebase_crashlytics: ^3.4.16
smooth_page_indicator: ^1.1.0
dev_dependencies:
flutter_test:
@ -49,7 +49,6 @@ flutter:
- assets/images/
- assets/icons/
- assets/fonts/
- assets/
fonts:
- family: Aftika
fonts: