Merge pull request #12 from SyncrowIOT/Configure_devices_statuses

Configure devices statuses
This commit is contained in:
Mohammad Salameh
2024-04-14 12:01:57 +03:00
committed by GitHub
71 changed files with 1933 additions and 1194 deletions

6
.vscode/launch.json vendored
View File

@ -11,6 +11,12 @@
"type": "dart", "type": "dart",
"deviceId": "0147FC23-3D6C-406A-BE2C-9E67BAF3DA9B" "deviceId": "0147FC23-3D6C-406A-BE2C-9E67BAF3DA9B"
}, },
{
"name": "Iphone 15 Pro",
"request": "launch",
"type": "dart",
"deviceId": "9C9E6EEF-0E9C-4FA9-B201-CBA8AFB0D1D8"
},
{ {
"name": "Iphone SE", "name": "Iphone SE",
"request": "launch", "request": "launch",

View File

@ -1,5 +1,6 @@
#Wed Apr 03 23:37:40 EET 2024
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip zipStoreBase=GRADLE_USER_HOME

View File

@ -5,6 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart'; import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/app_layout/view/widgets/app_bar_home_dropdown.dart'; import 'package:syncrow_app/features/app_layout/view/widgets/app_bar_home_dropdown.dart';
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart'; import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/room_model.dart'; import 'package:syncrow_app/features/devices/model/room_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart'; import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
import 'package:syncrow_app/features/menu/view/menu_view.dart'; import 'package:syncrow_app/features/menu/view/menu_view.dart';
@ -17,26 +18,35 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
part 'home_state.dart'; part 'home_state.dart';
class HomeCubit extends Cubit<HomeState> { class HomeCubit extends Cubit<HomeState> {
HomeCubit() : super(SpacesInitial()) { HomeCubit._() : super(HomeInitial()) {
if (HomeCubit.spaces != null) {
if (selectedSpace == null) { if (selectedSpace == null) {
fetchSpaces().then((value) { fetchSpaces().then((value) {
if (selectedSpace != null) { if (selectedSpace != null) {
print('selectedSpace: ${selectedSpace!.name}');
fetchRooms(selectedSpace!); fetchRooms(selectedSpace!);
} }
}); });
} }
} else { }
fetchSpaces(); // this is for the first time
static HomeCubit? _instance;
static HomeCubit getInstance() {
// If an instance already exists, return it
_instance ??= HomeCubit._();
return _instance!;
}
void emitSafe(HomeState newState) {
final cubit = this;
if (!cubit.isClosed) {
cubit.emit(newState);
} }
} }
static HomeCubit get(context) => BlocProvider.of(context); static HomeCubit get(context) => BlocProvider.of(context);
static List<SpaceModel>? spaces; List<SpaceModel>? spaces;
static SpaceModel? selectedSpace; SpaceModel? selectedSpace;
RoomModel? selectedRoom; RoomModel? selectedRoom;
@ -46,9 +56,14 @@ class HomeCubit extends Cubit<HomeState> {
var duration = const Duration(milliseconds: 300); var duration = const Duration(milliseconds: 300);
selectSpace(SpaceModel space) { // selectSpace(SpaceModel space) async {
// selectedSpace = space;
// emit(SpaceSelected(space));
// }
changeSelectedSpace(SpaceModel space) {
selectedSpace = space; selectedSpace = space;
emit(SpaceSelected(space)); emitSafe(SpaceSelected(space));
} }
roomSliderPageChanged(int index) { roomSliderPageChanged(int index) {
@ -62,7 +77,7 @@ class HomeCubit extends Cubit<HomeState> {
unselectRoom(); unselectRoom();
} else { } else {
selectedRoom = selectedSpace!.rooms![index - 1]; selectedRoom = selectedSpace!.rooms![index - 1];
emit(RoomSelected(selectedRoom!)); emitSafe(RoomSelected(selectedRoom!));
} }
} }
@ -77,12 +92,12 @@ class HomeCubit extends Cubit<HomeState> {
unselectRoom(); unselectRoom();
} else { } else {
selectedRoom = selectedSpace!.rooms![index - 1]; selectedRoom = selectedSpace!.rooms![index - 1];
emit(RoomSelected(selectedRoom!)); emitSafe(RoomSelected(selectedRoom!));
} }
} }
unselectRoom() { unselectRoom() {
selectedRoom = null; // selectedRoom = null;
devicesPageController.animateToPage( devicesPageController.animateToPage(
0, 0,
duration: duration, duration: duration,
@ -95,35 +110,40 @@ class HomeCubit extends Cubit<HomeState> {
curve: Curves.linear, curve: Curves.linear,
); );
emit(RoomUnSelected()); emitSafe(RoomUnSelected());
} }
//////////////////////////////////////// API ////////////////////////////////////////
fetchSpaces() async { fetchSpaces() async {
emit(GetSpacesLoading()); emitSafe(GetSpacesLoading());
try { try {
spaces = await SpacesAPI.getSpaces(); spaces = await SpacesAPI.getSpaces();
selectedSpace = spaces!.isNotEmpty ? selectSpace(spaces!.first) : null; selectedSpace = spaces!.isNotEmpty
emit(GetSpacesLoaded(spaces!)); ?
// selectSpace(spaces!.first)
selectedSpace = spaces!.first
: null;
emitSafe(GetSpacesLoaded(spaces!));
} on DioException catch (e) { } on DioException catch (e) {
emit(GetSpacesError(ServerFailure.fromDioError(e).errMessage)); emitSafe(GetSpacesError(ServerFailure.fromDioError(e).errMessage));
} }
} }
fetchRooms(SpaceModel space) async { fetchRooms(SpaceModel space) async {
emit(GetSpaceRoomsLoading()); emitSafe(GetSpaceRoomsLoading());
try { try {
space.rooms = await SpacesAPI.getRooms(space.id!); space.rooms = await SpacesAPI.getRoomsBySpaceId(space.id!);
if (space.rooms != null) { if (space.rooms != null) {
emit(GetSpaceRoomsLoaded(space.rooms!)); emitSafe(GetSpaceRoomsLoaded(space.rooms!));
} else { } else {
emit(GetSpaceRoomsError("No rooms found")); emitSafe(GetSpaceRoomsError("No rooms found"));
} }
} on DioException catch (e) { } on DioException catch (e) {
emit(GetSpacesError(ServerFailure.fromDioError(e).errMessage)); emitSafe(GetSpacesError(ServerFailure.fromDioError(e).errMessage));
} }
} }
////////////////////////////////////////Nav//////////////////////////////////////// /////////////////////////////////////// Nav ///////////////////////////////////////
static clear() { static clear() {
pageIndex = 0; pageIndex = 0;
@ -247,7 +267,10 @@ class HomeCubit extends Cubit<HomeState> {
final List<Widget> pages = [ final List<Widget> pages = [
const DashboardView(), const DashboardView(),
// const LayoutPage(), // const LayoutPage(),
const DevicesViewBody(), BlocProvider(
create: (context) => DevicesCubit.getInstance(),
child: const DevicesViewBody(),
),
const SceneView(), const SceneView(),
const MenuView(), const MenuView(),
]; ];
@ -255,7 +278,7 @@ class HomeCubit extends Cubit<HomeState> {
void updatePageIndex(int index) { void updatePageIndex(int index) {
pageIndex = index; pageIndex = index;
emit(NavChangePage()); emitSafe(NavChangePage());
} }
} }

View File

@ -2,7 +2,7 @@ part of 'home_cubit.dart';
abstract class HomeState {} abstract class HomeState {}
class SpacesInitial extends HomeState {} class HomeInitial extends HomeState {}
class GetSpacesLoading extends HomeState {} class GetSpacesLoading extends HomeState {}

View File

@ -6,7 +6,6 @@ import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/app_layout/view/widgets/app_body.dart'; import 'package:syncrow_app/features/app_layout/view/widgets/app_body.dart';
import 'package:syncrow_app/features/app_layout/view/widgets/default_app_bar.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/app_layout/view/widgets/default_nav_bar.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
@ -15,16 +14,9 @@ class AppLayout extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiBlocProvider( return BlocProvider(
providers: [ create: (context) => HomeCubit.getInstance(),
BlocProvider( child: BlocConsumer<HomeCubit, HomeState>(
create: (context) => HomeCubit(),
),
BlocProvider(
create: (context) => DevicesCubit(),
),
],
child: BlocListener<HomeCubit, HomeState>(
listener: (context, state) { listener: (context, state) {
if (state is GetSpacesError) { if (state is GetSpacesError) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
@ -36,7 +28,6 @@ class AppLayout extends StatelessWidget {
.popUntil((route) => route.settings.name == Routes.authLogin); .popUntil((route) => route.settings.name == Routes.authLogin);
} }
}, },
child: BlocBuilder<HomeCubit, HomeState>(
builder: (context, state) { builder: (context, state) {
return AnnotatedRegion( return AnnotatedRegion(
value: SystemUiOverlayStyle( value: SystemUiOverlayStyle(
@ -44,23 +35,32 @@ class AppLayout extends StatelessWidget {
statusBarIconBrightness: Brightness.light, statusBarIconBrightness: Brightness.light,
), ),
child: SafeArea( child: SafeArea(
child: BlocBuilder<HomeCubit, HomeState>( child: Scaffold(
builder: (context, state) {
return const Scaffold(
backgroundColor: ColorsManager.backgroundColor, backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
extendBody: true, extendBody: true,
appBar: DefaultAppBar(), appBar: HomeCubit.getInstance().spaces != null
body: AppBody(), ? const DefaultAppBar()
bottomNavigationBar: DefaultNavBar(), : null,
); body: const AppBody(),
}, bottomNavigationBar: const DefaultNavBar(),
// floatingActionButton: FloatingActionButton(
// onPressed: () {
// Navigator.push(
// context,
// CustomPageRoute(
// builder: (context) =>
// const ThreeGangSwitchesView(),
// ),
// );
// },
// child: const Icon(Icons.arrow_forward_ios_sharp),
// ),
), ),
), ),
); );
}, },
), ),
),
); );
} }
} }

View File

@ -3,23 +3,18 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.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/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../../../../generated/assets.dart';
class AppBarHomeDropdown extends StatelessWidget { class AppBarHomeDropdown extends StatelessWidget {
const AppBarHomeDropdown({ const AppBarHomeDropdown({super.key});
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<HomeCubit, HomeState>( return BlocBuilder<HomeCubit, HomeState>(
builder: (context, state) { builder: (context, state) {
return HomeCubit.selectedSpace == null return Padding(
? const Center(child: BodyMedium(text: 'No Home Selected'))
: Padding(
padding: const EdgeInsets.only(left: 10, right: 10), padding: const EdgeInsets.only(left: 10, right: 10),
child: DropdownButton( child: DropdownButton(
icon: const Icon( icon: const Icon(
@ -30,8 +25,8 @@ class AppBarHomeDropdown extends StatelessWidget {
underline: const SizedBox.shrink(), underline: const SizedBox.shrink(),
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
value: HomeCubit.selectedSpace!.id, value: HomeCubit.getInstance().selectedSpace!.id,
items: HomeCubit.spaces!.map((space) { items: HomeCubit.getInstance().spaces!.map((space) {
return DropdownMenuItem( return DropdownMenuItem(
value: space.id, value: space.id,
child: SizedBox( child: SizedBox(
@ -67,7 +62,9 @@ class AppBarHomeDropdown extends StatelessWidget {
}).toList(), }).toList(),
onChanged: (value) { onChanged: (value) {
if (value != null) { if (value != null) {
HomeCubit.get(context).selectSpace(HomeCubit.spaces! HomeCubit.getInstance().changeSelectedSpace(
HomeCubit.getInstance()
.spaces!
.firstWhere((element) => element.id == value)); .firstWhere((element) => element.id == value));
} }
}, },

View File

@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import '../../../../generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
class AppBody extends StatelessWidget { class AppBody extends StatelessWidget {
const AppBody({ const AppBody({
@ -37,9 +37,10 @@ class AppBody extends StatelessWidget {
} }
}, },
builder: (context, state) { builder: (context, state) {
return state is! GetSpacesLoading || return state is! GetSpacesLoading
state is! GetSpaceRoomsLoading ? state is! GetSpaceRoomsLoading
? HomeCubit.get(context).pages[HomeCubit.pageIndex] ? HomeCubit.getInstance().pages[HomeCubit.pageIndex]
: const Center(child: CircularProgressIndicator())
: const Center(child: CircularProgressIndicator()); : const Center(child: CircularProgressIndicator());
}, },
), ),

View File

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart';
class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
@ -20,11 +19,9 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
leadingWidth: 150, leadingWidth: 150,
toolbarHeight: Constants.appBarHeight, toolbarHeight: Constants.appBarHeight,
leading: HomeCubit.spaces != null leading: HomeCubit.getInstance().spaces!.isNotEmpty
? HomeCubit.spaces!.isNotEmpty
? HomeCubit.appBarLeading[ ? HomeCubit.appBarLeading[
HomeCubit.bottomNavItems[HomeCubit.pageIndex].label] HomeCubit.bottomNavItems[HomeCubit.pageIndex].label]
: const Center(child: BodySmall(text: 'Create Home'))
: null, : null,
actions: HomeCubit.appBarActions[ actions: HomeCubit.appBarActions[
HomeCubit.bottomNavItems[HomeCubit.pageIndex].label], HomeCubit.bottomNavItems[HomeCubit.pageIndex].label],

View File

@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.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/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart';
@ -15,19 +16,22 @@ class DefaultNavBar extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<HomeCubit, HomeState>( return BlocBuilder<HomeCubit, HomeState>(
builder: (context, state) { builder: (context, state) {
var cubit = HomeCubit.get(context); var cubit = HomeCubit.getInstance();
return SizedBox( return SizedBox(
height: Constants.bottomNavBarHeight, height: Constants.bottomNavBarHeight,
child: BottomNavigationBar( child: BottomNavigationBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
onTap: (int index) { onTap: (int index) {
cubit.updatePageIndex(index); cubit.updatePageIndex(index);
if (DevicesCubit.get(context).chosenCategoryView != null) { // if (DevicesCubit.getInstance().chosenCategoryView != null) {
DevicesCubit().clearCategoriesSelection(context); // DevicesCubit.getInstance()
} // .clearCategoriesSelection(context);
if (HomeCubit.get(context).selectedRoom != null) { // }
HomeCubit.get(context).unselectRoom(); // if (HomeCubit.getInstance().selectedRoom != null) {
} // HomeCubit.getInstance().unselectRoom();
// }
HomeCubit.getInstance().updatePageIndex(index);
}, },
currentIndex: HomeCubit.pageIndex, currentIndex: HomeCubit.pageIndex,
selectedItemColor: ColorsManager.primaryColor, selectedItemColor: ColorsManager.primaryColor,

View File

@ -30,6 +30,7 @@ class LoginForm extends StatelessWidget {
TextFormField( TextFormField(
controller: AuthCubit.get(context).emailController, controller: AuthCubit.get(context).emailController,
validator: (value) { validator: (value) {
if (state is! AuthTokenError) {
if (value != null) { if (value != null) {
if (value.isEmpty) { if (value.isEmpty) {
return 'Please enter your email'; return 'Please enter your email';
@ -41,6 +42,7 @@ class LoginForm extends StatelessWidget {
return 'Please enter a valid email'; return 'Please enter a valid email';
} }
} }
}
return null; return null;
}, },
onTapOutside: (event) { onTapOutside: (event) {
@ -57,6 +59,7 @@ class LoginForm extends StatelessWidget {
TextFormField( TextFormField(
controller: AuthCubit.get(context).passwordController, controller: AuthCubit.get(context).passwordController,
validator: (value) { validator: (value) {
if (state is! AuthTokenError) {
if (value != null) { if (value != null) {
if (value.isNotEmpty) { if (value.isNotEmpty) {
if (value.length < 6) { if (value.length < 6) {
@ -66,6 +69,7 @@ class LoginForm extends StatelessWidget {
return 'Please enter your password'; return 'Please enter your password';
} }
} }
}
return null; return null;
}, },
onTapOutside: (event) { onTapOutside: (event) {

View File

@ -3,7 +3,7 @@ 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/features/shared_widgets/united_text.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
import '../../../../generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
class Consumption extends StatelessWidget { class Consumption extends StatelessWidget {
const Consumption({ const Consumption({

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:syncrow_app/features/dashboard/view/widgets/live_monitor_widget.dart'; import 'package:syncrow_app/features/dashboard/view/widgets/live_monitor_widget.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
import '../../../../generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
class LiveMonitorTab extends StatelessWidget { class LiveMonitorTab extends StatelessWidget {
const LiveMonitorTab({ const LiveMonitorTab({

View File

@ -0,0 +1,51 @@
// import 'package:bloc/bloc.dart';
// import 'package:flutter/foundation.dart';
// import 'package:meta/meta.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/model/device_model.dart';
// part 'ac_state.dart';
// class AcCubit extends Cubit<AcState> {
// AcCubit() : super(AcInitial());
// DeviceModel? getSelectedAC() {
// DevicesCategoryModel category = DevicesCubit.allCategories![0];
// for (var device in category.devices) {
// if (device is && device.isSelected) {
// return device;
// }
// }
// return null;
// }
// void setTempToAll(double temperature) {
// for (DeviceModel ac in category.devices) {
// if (ac is DeviceModel) {
// if (ac.temperature != temperature &&
// ac.bounds.min <= temperature &&
// temperature <= ac.bounds.max) {
// setACTemp(ac, temperature);
// }
// }
// }
// universalACTemp = temperature;
// emit(ACsTempChanged(temperature));
// }
// void setACTemp(DeviceModel model, double temp) {
// if (model.bounds.min <= temp && temp <= model.bounds.max) {
// model.temperature = temp;
// }
// emit(ACsTempChanged(temp));
// }
// double getTemp(int index) {
// var device = category.devices[index];
// if (device is DeviceModel) {
// return device.temperature;
// }
// return 0.0; // or any default value you prefer
// }
// }

View File

@ -0,0 +1,6 @@
// part of 'ac_cubit.dart';
// @immutable
// sealed class AcState {}
// final class AcInitial extends AcState {}

View File

@ -8,32 +8,54 @@ import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/devices/model/device_category_model.dart'; import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.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/gateway/gateway_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/lights_view.dart'; import 'package:syncrow_app/features/devices/view/widgets/lights/lights_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights_switches/light_switches.dart'; import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_view.dart'; import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_view.dart';
import 'package:syncrow_app/services/api/devices_api.dart'; import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/network_exception.dart'; import 'package:syncrow_app/services/api/network_exception.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart';
part 'devices_state.dart'; part 'devices_state.dart';
class DevicesCubit extends Cubit<DevicesState> { class DevicesCubit extends Cubit<DevicesState> {
DevicesCubit() : super(DevicesInitial()) { DevicesCubit._() : super(DevicesInitial()) {
if (HomeCubit.selectedSpace != null) { if (HomeCubit.getInstance().selectedSpace != null) {
fetchGroups(HomeCubit.selectedSpace!.id!); fetchGroups(HomeCubit.getInstance().selectedSpace!.id!);
for (var room in HomeCubit.getInstance().selectedSpace!.rooms!) {
fetchDevicesByRoomId(room.id!);
}
} }
} }
bool _isClosed = false; bool _isClosed = false;
static DevicesCubit? _instance;
static DevicesCubit getInstance() {
print('device cubit instance found : ${_instance != null}');
print('selected space : ${HomeCubit.getInstance().selectedSpace != null}');
return _instance ??= DevicesCubit._();
}
DeviceModel? selectedDevice;
@override @override
Future<void> close() { Future<void> close() {
_isClosed = true; _isClosed = true;
_instance = null;
return super.close(); return super.close();
} }
void emitSafe(DevicesState newState) {
final cubit = this;
if (!cubit.isClosed) {
cubit.emit(newState);
}
}
static DevicesCubit get(context) => BlocProvider.of(context); static DevicesCubit get(context) => BlocProvider.of(context);
static List<DevicesCategoryModel>? allCategories; static List<DevicesCategoryModel>? allCategories;
@ -46,14 +68,14 @@ class DevicesCubit extends Cubit<DevicesState> {
allCategories![i].isSelected = false; allCategories![i].isSelected = false;
} }
} }
emit(DevicesCategoryChanged()); emitSafe(DevicesCategoryChanged());
} }
unselectAllCategories() { unselectAllCategories() {
for (var category in allCategories!) { for (var category in allCategories!) {
category.isSelected = false; category.isSelected = false;
} }
emit(DevicesCategoryChanged()); emitSafe(DevicesCategoryChanged());
} }
Widget? get chosenCategoryView { Widget? get chosenCategoryView {
@ -63,14 +85,14 @@ class DevicesCubit extends Cubit<DevicesState> {
switch (category.type) { switch (category.type) {
case DeviceType.AC: case DeviceType.AC:
return const ACsView(); return const ACsView();
case DeviceType.Lights: case DeviceType.LightBulb:
return const LightsView(); return const LightsView();
case DeviceType.DoorLock: case DeviceType.DoorLock:
return const DoorView(); return const DoorView();
case DeviceType.Curtain: case DeviceType.Curtain:
return const CurtainView(); return const CurtainView();
case DeviceType.ThreeGang: // case DeviceType.ThreeGang:
return const LightSwitchesView(); // return const ThreeGangSwitchesView();
case DeviceType.Gateway: case DeviceType.Gateway:
return const GateWayView(); return const GateWayView();
default: default:
@ -97,14 +119,14 @@ class DevicesCubit extends Cubit<DevicesState> {
for (var device in category.devices!) { for (var device in category.devices!) {
if (device.isSelected) { if (device.isSelected) {
category.isSelected = false; category.isSelected = false;
emit(DeviceSelected()); emitSafe(DeviceSelected());
return; return;
} }
} }
} }
} }
device.isSelected = !device.isSelected; device.isSelected = !device.isSelected;
emit(DeviceSelected()); emitSafe(DeviceSelected());
} }
DeviceModel? getSelectedDevice() { DeviceModel? getSelectedDevice() {
@ -125,24 +147,24 @@ class DevicesCubit extends Cubit<DevicesState> {
category.devicesStatus = !category.devicesStatus!; category.devicesStatus = !category.devicesStatus!;
if (category.devices != null) { if (category.devices != null) {
for (var device in category.devices!) { for (var device in category.devices!) {
device.status = category.devicesStatus; device.isOnline = category.devicesStatus;
} }
} }
} else { } else {
category.devicesStatus = true; category.devicesStatus = true;
if (category.devices != null) { if (category.devices != null) {
for (var device in category.devices!) { for (var device in category.devices!) {
device.status = true; device.isOnline = true;
} }
} }
} }
updateDevicesStatus(category); updateDevicesStatus(category);
emit(CategorySwitchChanged()); emitSafe(CategorySwitchChanged());
} }
turnOnOffDevice(DeviceModel device) { turnOnOffDevice(DeviceModel device) {
device.status = !device.status!; device.isOnline = !device.isOnline!;
DevicesCategoryModel category = allCategories!.firstWhere((category) { DevicesCategoryModel category = allCategories!.firstWhere((category) {
if (category.devices != null) { if (category.devices != null) {
return category.devices!.contains(device); return category.devices!.contains(device);
@ -151,26 +173,26 @@ class DevicesCubit extends Cubit<DevicesState> {
} }
}); });
updateDevicesStatus(category); updateDevicesStatus(category);
emit(DeviceSwitchChanged()); emitSafe(DeviceSwitchChanged());
} }
updateDevicesStatus(DevicesCategoryModel category) { updateDevicesStatus(DevicesCategoryModel category) {
if (category.devices != null) { if (category.devices != null) {
if (category.devices!.isNotEmpty) { if (category.devices!.isNotEmpty) {
bool? tempStatus = category.devices![0].status; bool? tempStatus = category.devices![0].isOnline;
for (var ac in category.devices!) { for (var ac in category.devices!) {
//check if there any ac have a different status than the initial ==> turn off the universal switch //check if there any ac have a different status than the initial ==> turn off the universal switch
if (ac.status != tempStatus) { if (ac.isOnline != tempStatus) {
category.devicesStatus = null; category.devicesStatus = null;
emit(DeviceSwitchChanged()); emitSafe(DeviceSwitchChanged());
return; return;
} }
category.devicesStatus = tempStatus; category.devicesStatus = tempStatus;
emit(DeviceSwitchChanged()); emitSafe(DeviceSwitchChanged());
} }
} else { } else {
category.devicesStatus = null; category.devicesStatus = null;
emit(DeviceSwitchChanged()); emitSafe(DeviceSwitchChanged());
} }
} }
} }
@ -179,11 +201,11 @@ class DevicesCubit extends Cubit<DevicesState> {
if (category.devices != null) { if (category.devices != null) {
if (category.devices!.isNotEmpty) { if (category.devices!.isNotEmpty) {
for (var device in category.devices!) { for (var device in category.devices!) {
device.status = false; device.isOnline = false;
} }
changeCategorySwitchValue(category); changeCategorySwitchValue(category);
updateDevicesStatus(category); updateDevicesStatus(category);
emit(CategorySwitchChanged()); emitSafe(CategorySwitchChanged());
} }
} }
} }
@ -192,11 +214,11 @@ class DevicesCubit extends Cubit<DevicesState> {
if (category.devices != null) { if (category.devices != null) {
if (category.devices!.isNotEmpty) { if (category.devices!.isNotEmpty) {
for (var device in category.devices!) { for (var device in category.devices!) {
device.status = true; device.isOnline = true;
} }
changeCategorySwitchValue(category); changeCategorySwitchValue(category);
updateDevicesStatus(category); updateDevicesStatus(category);
emit(CategorySwitchChanged()); emitSafe(CategorySwitchChanged());
} }
} }
} }
@ -204,9 +226,9 @@ class DevicesCubit extends Cubit<DevicesState> {
areAllDevicesOff(DevicesCategoryModel category) { areAllDevicesOff(DevicesCategoryModel category) {
if (category.devices != null) { if (category.devices != null) {
for (var device in category.devices!) { for (var device in category.devices!) {
if (device.status ?? false) { if (device.isOnline ?? false) {
category.devicesStatus = false; category.devicesStatus = false;
emit(CategorySwitchChanged()); emitSafe(CategorySwitchChanged());
return; return;
} }
} }
@ -224,16 +246,34 @@ class DevicesCubit extends Cubit<DevicesState> {
} }
Navigator.popUntil(context, (route) => route.isFirst); Navigator.popUntil(context, (route) => route.isFirst);
emit(DevicesCategoryChanged()); emitSafe(DevicesCategoryChanged());
} }
deviceControl(DeviceControlModel control) async { ///////////////////////// API CALLS //////////////////////////
emit(DeviceControlLoading()); deviceControl(DeviceControlModel control, String deviceId) async {
emitSafe(DeviceControlLoading(
code: control.code,
));
try { try {
await DevicesAPI.controlDevice(control); await DevicesAPI.controlDevice(control).then((response) {
emit(DeviceControlSuccess()); emitSafe(DeviceControlSuccess(
code: control.code,
));
if (response['success'] ?? false) {
Future.delayed(const Duration(milliseconds: 400), () {
getDevicesStatues(
deviceId,
HomeCubit.getInstance().selectedSpace!.rooms!.indexOf(
HomeCubit.getInstance().selectedRoom!,
),
code: control.code);
});
} else {
emitSafe(DeviceControlError('Failed to control the device'));
}
});
} on DioException catch (e) { } on DioException catch (e) {
emit(DeviceControlError(ServerFailure.fromDioError(e).errMessage)); emitSafe(DeviceControlError(ServerFailure.fromDioError(e).errMessage));
} }
} }
@ -241,16 +281,77 @@ class DevicesCubit extends Cubit<DevicesState> {
if (_isClosed) return; if (_isClosed) return;
try { try {
emit(DevicesCategoriesLoading()); emitSafe(DevicesCategoriesLoading());
allCategories = await DevicesAPI.fetchGroups(spaceId); allCategories = await DevicesAPI.fetchGroups(spaceId);
emit(DevicesCategoriesSuccess()); emitSafe(DevicesCategoriesSuccess());
} on DioException catch (error) { } on DioException catch (error) {
emit( emitSafe(
DevicesCategoriesError(ServerFailure.fromDioError(error).errMessage), DevicesCategoriesError(ServerFailure.fromDioError(error).errMessage),
); );
} }
} }
fetchDevicesByRoomId(int? roomId) async {
if (_isClosed) return;
if (roomId == null) return;
try {
emitSafe(GetDevicesLoading());
int roomIndex = HomeCubit.getInstance()
.selectedSpace!
.rooms!
.indexWhere((element) => element.id == roomId);
HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices =
await SpacesAPI.getDevicesByRoomId(roomId);
//get status for each device
for (var device in HomeCubit.getInstance()
.selectedSpace!
.rooms![roomIndex]
.devices!) {
getDevicesStatues(device.id!, roomIndex);
}
emitSafe(GetDevicesSuccess());
} on DioException catch (error) {
emitSafe(
GetDevicesError(ServerFailure.fromDioError(error).errMessage),
);
}
}
getDevicesStatues(String deviceId, int roomIndex, {String? code}) async {
if (_isClosed) return;
try {
emitSafe(GetDeviceStatusLoading(code: code));
int deviceIndex = HomeCubit.getInstance()
.selectedSpace!
.rooms![roomIndex]
.devices!
.indexWhere((element) => element.id == deviceId);
List<StatusModel> statuses = [];
var response = await DevicesAPI.getDeviceStatus(deviceId);
// if (response['result']['status'].length > 4)
// print('response : ${response['result']['status'][4]}');
for (var status in response['result']['status']) {
statuses.add(StatusModel.fromJson(status));
}
HomeCubit.getInstance()
.selectedSpace!
.rooms![roomIndex]
.devices![deviceIndex]
.status = statuses;
emitSafe(GetDeviceStatusSuccess(code: code));
} on DioException catch (error) {
emitSafe(
GetDeviceStatusError(ServerFailure.fromDioError(error).errMessage),
);
}
}
///Lights ///Lights
onHorizontalDragUpdate(DeviceModel light, double dx, double screenWidth) { onHorizontalDragUpdate(DeviceModel light, double dx, double screenWidth) {
double newBrightness = (dx / (screenWidth - 15) * 100); double newBrightness = (dx / (screenWidth - 15) * 100);
@ -272,17 +373,17 @@ class DevicesCubit extends Cubit<DevicesState> {
// setLightingMode(DeviceModel light, LightMode mode) { // setLightingMode(DeviceModel light, LightMode mode) {
// light.lightingMode = // light.lightingMode =
// lightModes.entries.firstWhere((element) => element.value == mode).key; // lightModes.entries.firstWhere((element) => element.value == mode).key;
// emit(LightModeChanged(mode)); // emitSafe(LightModeChanged(mode));
// } // }
// //
// toggleLight(DeviceModel light) { // toggleLight(DeviceModel light) {
// light.status != null ? light.status = !light.status! : light.status = true; // light.isOnline != null ? light.isOnline = !light.isOnline! : light.isOnline = true;
// emit(LightToggled(light)); // emitSafe(LightToggled(light));
// } // }
// //
// setColor(DeviceModel light, int color) { // setColor(DeviceModel light, int color) {
// light.color = color; // light.color = color;
// emit(LightColorChanged(color)); // emitSafe(LightColorChanged(color));
// } // }
// //
// int getBrightness(DeviceModel light) { // int getBrightness(DeviceModel light) {
@ -293,47 +394,8 @@ class DevicesCubit extends Cubit<DevicesState> {
// value = (value / 5).ceil() * 5; // value = (value / 5).ceil() * 5;
// if (value != light.brightness) { // if (value != light.brightness) {
// light.brightness = value; // light.brightness = value;
// emit(LightBrightnessChanged(value)); // emitSafe(LightBrightnessChanged(value));
// } // }
// }
///ACs
// DeviceModel? getSelectedAC() {
// for (var ac in category.devices) {
// if (ac is DeviceModel && ac.isSelected) {
// return ac;
// }
// }
// return null;
// }
//
// void setTempToAll(double temperature) {
// for (DeviceModel ac in category.devices) {
// if (ac is DeviceModel) {
// if (ac.temperature != temperature &&
// ac.bounds.min <= temperature &&
// temperature <= ac.bounds.max) {
// setACTemp(ac, temperature);
// }
// }
// }
// universalACTemp = temperature;
// emit(ACsTempChanged(temperature));
// }
//
// void setACTemp(DeviceModel model, double temp) {
// if (model.bounds.min <= temp && temp <= model.bounds.max) {
// model.temperature = temp;
// }
// emit(ACsTempChanged(temp));
// }
//
// double getTemp(int index) {
// var device = category.devices[index];
// if (device is DeviceModel) {
// return device.temperature;
// }
// return 0.0; // or any default value you prefer
// } // }
} }

View File

@ -14,6 +14,35 @@ class DevicesFailure extends DevicesState {}
class ChangeIndex extends DevicesState {} class ChangeIndex extends DevicesState {}
// Devices // Devices
class GetDeviceStatusLoading extends DevicesState {
final String? code;
GetDeviceStatusLoading({this.code});
}
class GetDeviceStatusSuccess extends DevicesState {
final String? code;
GetDeviceStatusSuccess({this.code});
}
class GetDeviceStatusError extends DevicesState {
final String errorMsg;
GetDeviceStatusError(this.errorMsg);
}
class GetDevicesLoading extends DevicesState {}
class GetDevicesSuccess extends DevicesState {}
class GetDevicesError extends DevicesState {
final String errorMsg;
GetDevicesError(this.errorMsg);
}
class DevicesCategoryChanged extends DevicesState {} class DevicesCategoryChanged extends DevicesState {}
class CategorySwitchChanged extends DevicesState {} class CategorySwitchChanged extends DevicesState {}
@ -23,9 +52,17 @@ class DeviceSwitchChanged extends DevicesState {}
class DeviceSelected extends DevicesState {} class DeviceSelected extends DevicesState {}
// Device Control // Device Control
class DeviceControlLoading extends DevicesState {} class DeviceControlLoading extends DevicesState {
final String? code;
class DeviceControlSuccess extends DevicesState {} DeviceControlLoading({this.code});
}
class DeviceControlSuccess extends DevicesState {
final String? code;
DeviceControlSuccess({this.code});
}
class DeviceControlError extends DevicesState { class DeviceControlError extends DevicesState {
final String errorMsg; final String errorMsg;

View File

@ -24,9 +24,9 @@ class DevicesCategoryModel {
//sets the initial status of the devices //sets the initial status of the devices
if (devices != null) { if (devices != null) {
if (devices!.isNotEmpty) { if (devices!.isNotEmpty) {
bool tempStatus = devices!.first.status ?? false; bool tempStatus = devices!.first.isOnline ?? false;
for (var device in devices!) { for (var device in devices!) {
if (device.status != tempStatus) { if (device.isOnline != tempStatus) {
devicesStatus = false; devicesStatus = false;
break; break;
} }
@ -41,9 +41,9 @@ class DevicesCategoryModel {
DevicesCategoryModel.fromJson(Map<String, dynamic> json) DevicesCategoryModel.fromJson(Map<String, dynamic> json)
: name = json['groupName'], : name = json['groupName'],
id = json['groupId'], id = json['groupId'],
type = deviceTypeMap[json['groupName']] ?? DeviceType.Other, type = devicesTypesMap[json['productType']] ?? DeviceType.Other,
icon = deviceTypeIconMap[ icon = deviceTypeIconMap[
deviceTypeMap[json['groupName']] ?? DeviceType.Other] ?? devicesTypesMap[json['productType']] ?? DeviceType.Other] ??
'', '',
devices = [], devices = [],
isSelected = false; isSelected = false;
@ -53,22 +53,14 @@ class DevicesCategoryModel {
} }
} }
Map<String, DeviceType> deviceTypeMap = {
'Ceiling Presence Sensors': DeviceType.Sensors,
'Wall presence sensor': DeviceType.Sensors,
'Door Locks': DeviceType.DoorLock,
'Gateways': DeviceType.Gateway,
'ACs': DeviceType.AC,
'3Gang': DeviceType.Gang,
};
Map<DeviceType, String> deviceTypeIconMap = { Map<DeviceType, String> deviceTypeIconMap = {
DeviceType.AC: Assets.iconsAC, DeviceType.AC: Assets.iconsAC,
DeviceType.Lights: Assets.iconsLight, DeviceType.LightBulb: Assets.iconsLight,
DeviceType.DoorLock: Assets.iconsDoorLock, DeviceType.DoorLock: Assets.iconsDoorLock,
DeviceType.Curtain: Assets.iconsCurtain, DeviceType.Curtain: Assets.iconsCurtain,
DeviceType.Gateway: Assets.iconsGateway, DeviceType.Gateway: Assets.iconsGateway,
DeviceType.Sensors: Assets.iconsSensors, DeviceType.CeilingSensor: Assets.iconsSensors,
DeviceType.Gang: Assets.iconsGang, DeviceType.WallSensor: Assets.iconsSensors,
DeviceType.ThreeGang: Assets.iconsGang,
DeviceType.Other: Assets.iconsAC, DeviceType.Other: Assets.iconsAC,
}; };

View File

@ -1,7 +1,7 @@
class DeviceControlModel { class DeviceControlModel {
String? deviceId; String? deviceId;
String? code; String? code;
bool? value; dynamic value;
DeviceControlModel({ DeviceControlModel({
required this.deviceId, required this.deviceId,

View File

@ -1,46 +1,146 @@
import 'package:syncrow_app/features/devices/model/function_model.dart'; import 'package:syncrow_app/features/devices/model/function_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart';
class DeviceModel { class DeviceModel {
final int? id; int? activeTime;
final String? name; String? category; //unused
final DeviceType? type; String? categoryName; //unused
bool? status; int? createTime; //unused
final String? image; String? gatewayId; //unused
final double? timer; String? icon; //unused
late final String icon; String? id;
String? ip; //unused
double? lat; //unused
String? localKey;
double? lon; //unused
String? model;
String? name;
String? nodeId; //remove
bool? isOnline;
List<StatusModel> status = [];
String? ownerId; //unused
String? productId; //unused
String? productName;
bool? isSub; //unused
String? timeZone;
int? updateTime;
String? uuid;
DeviceType? productType;
bool isSelected = false; bool isSelected = false;
late List<FunctionModel> functions; late List<FunctionModel> functions;
DeviceModel({ DeviceModel({
required this.id, this.activeTime,
required this.name, this.category,
required this.type, this.categoryName,
this.createTime,
this.gatewayId,
this.icon,
this.id,
this.ip,
this.lat,
this.localKey,
this.lon,
this.model,
this.name,
this.nodeId,
this.isOnline,
required this.status, required this.status,
required this.image, this.ownerId,
required this.timer, this.productId,
required this.functions, this.productName,
this.isSub,
this.timeZone,
this.updateTime,
this.uuid,
this.productType,
}) { }) {
switch (type) { functions = getFunctions(productType!);
case DeviceType.AC: }
icon = Assets.iconsAC;
break; factory DeviceModel.fromJson(Map<String, dynamic> json) {
case DeviceType.Lights: String icon = '';
DeviceType type = devicesTypesMap[json['productId']] ?? DeviceType.Other;
if (type == DeviceType.LightBulb) {
icon = Assets.iconsLight; icon = Assets.iconsLight;
break; } else if (type == DeviceType.CeilingSensor ||
case DeviceType.DoorLock: type == DeviceType.WallSensor) {
icon = Assets.iconsSensors;
} else if (type == DeviceType.AC) {
icon = Assets.iconsAC;
} else if (type == DeviceType.DoorLock) {
icon = Assets.iconsDoorLock; icon = Assets.iconsDoorLock;
break; } else if (type == DeviceType.Curtain) {
case DeviceType.Curtain:
icon = Assets.iconsCurtain; icon = Assets.iconsCurtain;
break; } else if (type == DeviceType.ThreeGang) {
case DeviceType.Gateway: icon = Assets.icons3GangSwitch;
} else if (type == DeviceType.Gateway) {
icon = Assets.iconsGateway; icon = Assets.iconsGateway;
break; } else {
default: icon = Assets.iconsLogo;
icon = '';
} }
return DeviceModel(
activeTime: json['activeTime'],
category: json['category'],
categoryName: json['categoryName'],
createTime: json['createTime'],
gatewayId: json['gatewayId'],
icon: icon,
id: json['id'],
ip: json['ip'],
lat: double.tryParse(json['lat']),
localKey: json['localKey'],
lon: double.tryParse(json['lon']),
model: json['model'],
name: json['name'],
nodeId: json['nodeId'],
isOnline: json['online'],
ownerId: json['ownerId'],
productId: json['productId'],
productName: json['productName'],
isSub: json['sub'],
timeZone: json['timeZone'],
updateTime: json['updateTime'],
uuid: json['uuid'],
productType: type,
status: [],
// json['status']
// .map<StatusModel>((e) => StatusModel.fromJson(e))
// .toList(),
// devicesTypesMap[json['productName']] ?? DeviceType.Other,
);
} }
Map<String, dynamic> toJson() {
return {
'activeTime': activeTime,
'category': category,
'categoryName': categoryName,
'createTime': createTime,
'gatewayId': gatewayId,
'icon': icon,
'id': id,
'ip': ip,
'lat': lat,
'localKey': localKey,
'lon': lon,
'model': model,
'name': name,
'nodeId': nodeId,
'online': isOnline,
'ownerId': ownerId,
'productId': productId,
'productName': productName,
'sub': isSub,
'timeZone': timeZone,
'updateTime': updateTime,
'uuid': uuid,
'productType': productType,
};
}
List<FunctionModel> getFunctions(DeviceType type) =>
devicesFunctionsMap[productType] ?? [];
} }

View File

@ -1,21 +1,10 @@
//{
// "code": "switch_1",
// "desc": "switch 1",
// "name": "switch 1",
// "type": "Boolean",
// "values": "{}"
// }
class FunctionModel { class FunctionModel {
String? code; String? code;
String? desc;
String? name;
String? type; String? type;
String? values; String? values;
FunctionModel({ FunctionModel({
required this.code, required this.code,
required this.desc,
required this.name,
required this.type, required this.type,
required this.values, required this.values,
}); });
@ -23,8 +12,6 @@ class FunctionModel {
factory FunctionModel.fromJson(Map<String, dynamic> json) { factory FunctionModel.fromJson(Map<String, dynamic> json) {
return FunctionModel( return FunctionModel(
code: json['code'], code: json['code'],
desc: json['desc'],
name: json['name'],
type: json['type'], type: json['type'],
values: json['values'], values: json['values'],
); );
@ -33,8 +20,6 @@ class FunctionModel {
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {
'code': code, 'code': code,
'desc': desc,
'name': name,
'type': type, 'type': type,
'values': values, 'values': values,
}; };

View File

@ -1,30 +1,36 @@
import 'package:syncrow_app/features/devices/model/device_category_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
class RoomModel { class RoomModel {
final int? id; final int? id;
final String? name; final String? name;
final List<DevicesCategoryModel>? categories; List<DeviceModel>? devices;
RoomModel({ RoomModel({
required this.id, required this.id,
required this.name, required this.name,
required this.categories, required this.devices,
}); });
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {
'id': id, 'id': id,
'name': name, 'name': name,
'devices': categories, 'devices': devices,
}; };
} }
factory RoomModel.fromJson(Map<String, dynamic> json) { factory RoomModel.fromJson(Map<String, dynamic> json) {
List<DeviceModel> devices = [];
if (json['devices'] != null) {
for (var device in json['devices']) {
devices.add(DeviceModel.fromJson(device));
}
}
return RoomModel( return RoomModel(
id: json['roomId'], id: json['roomId'],
name: json['roomName'], name: json['roomName'],
categories: json['devices'], devices: devices,
); );
} }
} }

View File

@ -0,0 +1,23 @@
class StatusModel {
String? code;
dynamic value;
StatusModel({
required this.code,
required this.value,
});
factory StatusModel.fromJson(Map<String, dynamic> json) {
return StatusModel(
code: json['code'],
value: json['value'],
);
}
Map<String, dynamic> toJson() {
return {
'code': code,
'value': value,
};
}
}

View File

@ -1,20 +1,17 @@
import 'package:flutter/material.dart'; // import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; // import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
class DevicesView extends StatelessWidget { // class DevicesView extends StatelessWidget {
const DevicesView({super.key}); // const DevicesView({super.key});
@override // @override
Widget build(BuildContext context) { // Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>( // print('built DevicesView');
builder: (context, state) => Container( // return Container(
padding: const EdgeInsets.all(8), // padding: const EdgeInsets.all(8),
width: MediaQuery.sizeOf(context).width, // width: MediaQuery.of(context).size.width,
height: MediaQuery.sizeOf(context).height, // height: MediaQuery.of(context).size.height,
child: const DevicesViewBody(), // child: const DevicesViewBody(),
), // );
); // }
} // }
}

View File

@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.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_model.dart'; import 'package:syncrow_app/features/devices/model/device_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_controls.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface_temp_unit.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface_temp_unit.dart';
@ -22,7 +24,18 @@ class AcInterface extends StatelessWidget {
statusBarIconBrightness: Brightness.light, statusBarIconBrightness: Brightness.light,
), ),
child: SafeArea( child: SafeArea(
child: Scaffold( child: BlocConsumer<DevicesCubit, DevicesState>(
listener: (context, state) {
if (state is DeviceControlError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMsg),
),
);
}
},
builder: (context, state) {
return Scaffold(
backgroundColor: ColorsManager.backgroundColor, backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
extendBody: true, extendBody: true,
@ -62,7 +75,7 @@ class AcInterface extends StatelessWidget {
maxHeight: 380, maxHeight: 380,
), ),
child: AcInterfaceTempUnit( child: AcInterfaceTempUnit(
deviceModel: deviceModel, acDevice: deviceModel,
), ),
), ),
const SizedBox( const SizedBox(
@ -81,6 +94,8 @@ class AcInterface extends StatelessWidget {
), ),
), ),
), ),
);
},
), ),
), ),
); );

View File

@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_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_mode_control_unit.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/generated/assets.dart';
import '../../../../../generated/assets.dart';
class AcInterfaceControls extends StatelessWidget { class AcInterfaceControls extends StatelessWidget {
const AcInterfaceControls({ const AcInterfaceControls({
@ -16,9 +17,11 @@ class AcInterfaceControls extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
return Column( return Column(
children: [ children: [
ACModeControlUnit(model: deviceModel), ACModeControlUnit(acDevice: deviceModel),
const SizedBox(height: 10), const SizedBox(height: 10),
Row( Row(
children: [ children: [
@ -49,5 +52,7 @@ class AcInterfaceControls extends StatelessWidget {
) )
], ],
); );
},
);
} }
} }

View File

@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:sleek_circular_slider/sleek_circular_slider.dart'; import 'package:sleek_circular_slider/sleek_circular_slider.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/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.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';
@ -10,20 +11,25 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dar
import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class AcInterfaceTempUnit extends StatelessWidget { class AcInterfaceTempUnit extends StatelessWidget {
const AcInterfaceTempUnit({ const AcInterfaceTempUnit({
super.key, super.key,
required this.deviceModel, required this.acDevice,
}); });
final DeviceModel deviceModel; final DeviceModel acDevice;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>( return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) { builder: (context, state) {
double setToTemp = acDevice.status
.firstWhere((element) => element.code == 'temp_set')
.value /
10;
return DefaultContainer( return DefaultContainer(
child: Column( child: Column(
children: [ children: [
@ -72,14 +78,24 @@ class AcInterfaceTempUnit extends StatelessWidget {
), ),
// min: DeviceModel.bounds.min, // min: DeviceModel.bounds.min,
// max: DeviceModel.bounds.max, // max: DeviceModel.bounds.max,
// initialValue: DeviceModel.temperature, min: 20,
max: 30,
initialValue: acDevice.status
.firstWhere(
(element) => element.code == 'temp_current')
.value /
10,
onChange: (value) { onChange: (value) {
String valueAsString = value.toStringAsFixed(1); String valueAsString = value.toStringAsFixed(1);
if (valueAsString.endsWith(".0") || if (valueAsString.endsWith(".0") ||
valueAsString.endsWith(".5")) { valueAsString.endsWith(".5")) {
value = double.parse(valueAsString); value = double.parse(valueAsString);
// DevicesCubit.get(context) DevicesCubit.getInstance().deviceControl(
// .setACTemp(DeviceModel, value); DeviceControlModel(
deviceId: acDevice.id,
code: 'temp_set',
value: value * 10),
acDevice.id!);
} }
}, },
), ),
@ -94,9 +110,23 @@ class AcInterfaceTempUnit extends StatelessWidget {
dimension: 24, dimension: 24,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
// DevicesCubit.get(context) //TODO refactor the loading check
// .setACTemp(DeviceModel, DeviceModel.coolTo); if (state is GetDeviceStatusLoading &&
// DeviceModel.coolTo -= .5; state.code == 'temp_set' ||
state is DeviceControlSuccess &&
state.code == 'temp_set' ||
state is DeviceControlLoading &&
state.code == 'temp_set') {
return;
}
if (setToTemp > 20) {
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: acDevice.id,
code: 'temp_set',
value: (setToTemp - 0.5) * 10),
acDevice.id!);
}
}, },
child: SvgPicture.asset( child: SvgPicture.asset(
Assets.iconsMinus, Assets.iconsMinus,
@ -107,10 +137,16 @@ class AcInterfaceTempUnit extends StatelessWidget {
children: [ children: [
BodyLarge( BodyLarge(
// text: "${DeviceModel.coolTo}° C", // text: "${DeviceModel.coolTo}° C",
text: '24° C', text: '$setToTemp° C',
style: context.bodyLarge.copyWith( style: context.bodyLarge.copyWith(
color: color: state is GetDeviceStatusLoading &&
ColorsManager.primaryColor.withOpacity(0.6), state.code == 'temp_set' ||
state is DeviceControlSuccess &&
state.code == 'temp_set' ||
state is DeviceControlLoading &&
state.code == 'temp_set'
? Colors.grey
: ColorsManager.primaryColor.withOpacity(0.6),
fontWeight: FontsManager.bold, fontWeight: FontsManager.bold,
fontSize: 30, fontSize: 30,
height: 0), height: 0),
@ -125,9 +161,22 @@ class AcInterfaceTempUnit extends StatelessWidget {
dimension: 24, dimension: 24,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
// DevicesCubit.get(context) if (state is GetDeviceStatusLoading &&
// .setACTemp(DeviceModel, DeviceModel.coolTo); state.code == 'temp_set' ||
// DeviceModel.coolTo += .5; state is DeviceControlSuccess &&
state.code == 'temp_set' ||
state is DeviceControlLoading &&
state.code == 'temp_set') {
return;
}
if (setToTemp < 30) {
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: acDevice.id,
code: 'temp_set',
value: (setToTemp + 0.5) * 10),
acDevice.id!);
}
}, },
child: SvgPicture.asset( child: SvgPicture.asset(
Assets.iconsPlus, Assets.iconsPlus,

View File

@ -1,53 +1,63 @@
import 'package:flutter/material.dart'; 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/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.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/utils/resource_manager/constants.dart';
import '../../../../../generated/assets.dart';
class ACModeControlUnit extends StatefulWidget { class ACModeControlUnit extends StatefulWidget {
const ACModeControlUnit({ const ACModeControlUnit({
super.key, super.key,
required this.model, required this.acDevice,
}); });
final DeviceModel model; final DeviceModel acDevice;
@override @override
State<ACModeControlUnit> createState() => _ACModeControlUnitState(); State<ACModeControlUnit> createState() => _ACModeControlUnitState();
} }
class _ACModeControlUnitState extends State<ACModeControlUnit> { class _ACModeControlUnitState extends State<ACModeControlUnit> {
var fanSpeeds = [
Assets.iconsFan0,
Assets.iconsFan1,
Assets.iconsFan2,
Assets.iconsFan3,
];
var tempModes = [
Assets.iconsSunnyMode,
Assets.iconsColdMode,
Assets.iconsWindyMode,
];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
//TODO Move the fanSpeeds and tempModes to the Cubit return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
FanSpeeds fanSpeed = fanSpeedsMap[widget.acDevice.status
.firstWhere((element) => element.code == 'level')
.value]!;
TempModes tempMode = tempModesMap[widget.acDevice.status
.firstWhere((element) => element.code == 'mode')
.value]!;
return Row( return Row(
children: [ children: [
Flexible( Flexible(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
setState(() { // print(
// widget.model.fanSpeed = // '\n\ncurrentFanSpeed:$fanSpeed \nchanged to:\t${fanSpeedsMap[getNextFanSpeedKey(fanSpeed)]!}\nKey:\t\t\"${reversedFanSpeedsMap[fanSpeedsMap[getNextFanSpeedKey(fanSpeed)]!]!}\"');
// widget.model.fanSpeed == 3 ? 0 : widget.model.fanSpeed + 1;
}); fanSpeed = fanSpeedsMap[getNextFanSpeedKey(fanSpeed)]!;
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: widget.acDevice.id,
code: 'level',
value: reversedFanSpeedsMap[fanSpeed]!),
widget.acDevice.id!);
}, },
child: const DefaultContainer( child: DefaultContainer(
height: 55, height: 55,
child: Center( child: Center(
// child: SvgPicture.asset(fanSpeeds[widget.model.fanSpeed]), child: state is GetDeviceStatusLoading &&
), state.code == 'level' ||
state is DeviceControlSuccess &&
state.code == 'level' ||
state is DeviceControlLoading &&
state.code == 'level'
? const CircularProgressIndicator()
: SvgPicture.asset(fanSpeedsIconMap[fanSpeed]!)),
), ),
), ),
), ),
@ -55,21 +65,32 @@ class _ACModeControlUnitState extends State<ACModeControlUnit> {
Flexible( Flexible(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
setState(() { tempMode = tempModesMap[getNextItem(tempModesMap, tempMode)]!;
// widget.model.tempMode = DevicesCubit.getInstance().deviceControl(
// widget.model.tempMode == 2 ? 0 : widget.model.tempMode + 1; DeviceControlModel(
}); deviceId: widget.acDevice.id,
code: 'mode',
value: reversedTempModesMap[tempMode]!),
widget.acDevice.id!);
}, },
child: const DefaultContainer( child: DefaultContainer(
height: 55, height: 55,
child: Center( child: Center(
// child: SvgPicture.asset(tempModes[widget.model.tempMode]), child: state is GetDeviceStatusLoading &&
state.code == 'mode' ||
state is DeviceControlSuccess &&
state.code == 'mode' ||
state is DeviceControlLoading &&
state.code == 'mode'
? const CircularProgressIndicator()
: SvgPicture.asset(tempModesIconMap[tempMode]!),
), ),
), ),
), ),
), ),
], ],
); );
},
);
} }
} }

View File

@ -8,7 +8,7 @@ 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';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../../../../../generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
class ACTempWidget extends StatelessWidget { class ACTempWidget extends StatelessWidget {
const ACTempWidget( const ACTempWidget(
@ -31,7 +31,7 @@ class ACTempWidget extends StatelessWidget {
dimension: 24, dimension: 24,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
// DevicesCubit.get(context) // DevicesCubit.getInstance()
// .setACTemp(DeviceModel, DeviceModel.temperature - 0.5); // .setACTemp(DeviceModel, DeviceModel.temperature - 0.5);
}, },
child: SvgPicture.asset( child: SvgPicture.asset(
@ -51,7 +51,7 @@ class ACTempWidget extends StatelessWidget {
dimension: 24, dimension: 24,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
// DevicesCubit.get(context) // DevicesCubit.getInstance()
// .setACTemp(DeviceModel, DeviceModel.temperature + 0.5); // .setACTemp(DeviceModel, DeviceModel.temperature + 0.5);
}, },
child: SvgPicture.asset( child: SvgPicture.asset(

View File

@ -27,7 +27,7 @@ class ACsList extends StatelessWidget {
const BodySmall(text: "All ACs"), const BodySmall(text: "All ACs"),
const SizedBox(height: 5), const SizedBox(height: 5),
UniversalSwitch( UniversalSwitch(
category: DevicesCubit.get(context).chosenCategory!, category: DevicesCubit.getInstance().chosenCategory!,
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
const UniversalACTemp(), const UniversalACTemp(),
@ -39,9 +39,9 @@ class ACsList extends StatelessWidget {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
itemCount: itemCount:
DevicesCubit.get(context).chosenCategory!.devices!.length, DevicesCubit.getInstance().chosenCategory!.devices!.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
DeviceModel ac = DevicesCubit.get(context) DeviceModel ac = DevicesCubit.getInstance()
.chosenCategory! .chosenCategory!
.devices![index]; .devices![index];
return Column( return Column(
@ -52,14 +52,14 @@ class ACsList extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
BodySmall( BodySmall(
text: DevicesCubit.get(context) text: DevicesCubit.getInstance()
.chosenCategory! .chosenCategory!
.devices![index] .devices![index]
.name ?? .name ??
""), ""),
IconButton( IconButton(
onPressed: () { onPressed: () {
DevicesCubit.get(context).selectDevice(ac); DevicesCubit.getInstance().selectDevice(ac);
}, },
icon: const Icon( icon: const Icon(
Icons.arrow_forward_ios, Icons.arrow_forward_ios,
@ -84,7 +84,7 @@ class ACsList extends StatelessWidget {
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
ACModeControlUnit( ACModeControlUnit(
model: ac, acDevice: ac,
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
], ],

View File

@ -6,10 +6,9 @@ import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface.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'; import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_list.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/category_view_app_bar.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/category_view_app_bar.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/generated/assets.dart';
import '../../../../../generated/assets.dart';
import '../../../../../utils/resource_manager/color_manager.dart';
class ACsView extends StatelessWidget { class ACsView extends StatelessWidget {
const ACsView({super.key}); const ACsView({super.key});
@ -21,9 +20,9 @@ class ACsView extends StatelessWidget {
return BlocBuilder<DevicesCubit, DevicesState>( return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) { builder: (context, state) {
DeviceModel? selectedAC; DeviceModel? selectedAC;
if (DevicesCubit.get(context).getSelectedDevice() is DeviceModel) { if (DevicesCubit.getInstance().getSelectedDevice() is DeviceModel) {
selectedAC = selectedAC =
DevicesCubit.get(context).getSelectedDevice() as DeviceModel; DevicesCubit.getInstance().getSelectedDevice() as DeviceModel;
} }
return AnnotatedRegion( return AnnotatedRegion(
value: SystemUiOverlayStyle( value: SystemUiOverlayStyle(

View File

@ -2,10 +2,9 @@ import 'package:flutter/material.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/shared_widgets/text_widgets/display_medium.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/display_medium.dart';
import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart';
import '../../../../../utils/resource_manager/color_manager.dart';
class CategoryViewAppBar extends StatelessWidget class CategoryViewAppBar extends StatelessWidget
implements PreferredSizeWidget { implements PreferredSizeWidget {
const CategoryViewAppBar({ const CategoryViewAppBar({
@ -20,7 +19,7 @@ class CategoryViewAppBar extends StatelessWidget
toolbarHeight: Constants.appBarHeight, toolbarHeight: Constants.appBarHeight,
centerTitle: true, centerTitle: true,
title: DisplayMedium( title: DisplayMedium(
text: DevicesCubit.get(context).chosenCategory!.name!, text: DevicesCubit.getInstance().chosenCategory!.name!,
style: context.displayMedium.copyWith( style: context.displayMedium.copyWith(
color: ColorsManager.primaryColor, color: ColorsManager.primaryColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -32,7 +31,7 @@ class CategoryViewAppBar extends StatelessWidget
color: ColorsManager.textPrimaryColor, color: ColorsManager.textPrimaryColor,
), ),
onPressed: () { onPressed: () {
DevicesCubit.get(context).clearCategoriesSelection(context); DevicesCubit.getInstance().clearCategoriesSelection(context);
}, },
), ),
); );

View File

@ -2,12 +2,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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/devices_cubit.dart'; import 'package:syncrow_app/features/devices/bloc/devices_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/context_extension.dart';
import 'package:syncrow_app/generated/assets.dart';
import '../../../../../generated/assets.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../../../../../utils/resource_manager/color_manager.dart';
import '../../../../shared_widgets/default_container.dart';
import '../../../../shared_widgets/text_widgets/body_large.dart';
class UniversalACTemp extends StatelessWidget { class UniversalACTemp extends StatelessWidget {
const UniversalACTemp({ const UniversalACTemp({
@ -27,7 +26,7 @@ class UniversalACTemp extends StatelessWidget {
dimension: 24, dimension: 24,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
// DevicesCubit.get(context) // DevicesCubit.getInstance()
// .setTempToAll(DevicesCubit.universalACTemp - .5); // .setTempToAll(DevicesCubit.universalACTemp - .5);
}, },
child: SvgPicture.asset( child: SvgPicture.asset(
@ -47,7 +46,7 @@ class UniversalACTemp extends StatelessWidget {
dimension: 24, dimension: 24,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
// DevicesCubit.get(context) // DevicesCubit.getInstance()
// .setTempToAll(DevicesCubit.universalACTemp + .5); // .setTempToAll(DevicesCubit.universalACTemp + .5);
}, },
child: SvgPicture.asset( child: SvgPicture.asset(

View File

@ -25,7 +25,7 @@ class CurtainList extends StatelessWidget {
const BodySmall(text: "All Curtains"), const BodySmall(text: "All Curtains"),
const SizedBox(height: 5), const SizedBox(height: 5),
UniversalSwitch( UniversalSwitch(
category: DevicesCubit.get(context).chosenCategory!, category: DevicesCubit.getInstance().chosenCategory!,
), ),
// other ACs controls // other ACs controls
@ -34,16 +34,17 @@ class CurtainList extends StatelessWidget {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
itemCount: itemCount:
DevicesCubit.get(context).chosenCategory!.devices!.length, DevicesCubit.getInstance().chosenCategory!.devices!.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
DeviceModel curtain = DeviceModel curtain = DevicesCubit.getInstance()
DevicesCubit.get(context).chosenCategory!.devices![index]; .chosenCategory!
.devices![index];
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 20), const SizedBox(height: 20),
BodySmall( BodySmall(
text: DevicesCubit.get(context) text: DevicesCubit.getInstance()
.chosenCategory! .chosenCategory!
.devices![index] .devices![index]
.name ?? .name ??

View File

@ -20,13 +20,13 @@ class CurtainView extends StatelessWidget {
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5), statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
statusBarIconBrightness: Brightness.light, statusBarIconBrightness: Brightness.light,
), ),
child: SafeArea(
child: Scaffold( child: Scaffold(
backgroundColor: ColorsManager.backgroundColor, backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
extendBody: true, extendBody: true,
appBar: const CategoryViewAppBar(), appBar: const CategoryViewAppBar(),
body: Container( body: SafeArea(
child: Container(
width: MediaQuery.sizeOf(context).width, width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height, height: MediaQuery.sizeOf(context).height,
decoration: const BoxDecoration( decoration: const BoxDecoration(

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/view/widgets/devices_view_header.dart'; import 'package:syncrow_app/features/devices/view/widgets/devices_view_header.dart';
import 'package:syncrow_app/features/devices/view/widgets/room_page.dart'; import 'package:syncrow_app/features/devices/view/widgets/room_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/rooms_slider.dart'; import 'package:syncrow_app/features/devices/view/widgets/rooms_slider.dart';
@ -9,8 +10,6 @@ import 'package:syncrow_app/features/devices/view/widgets/wizard_page.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/constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart';
import '../../bloc/devices_cubit.dart';
class DevicesViewBody extends StatelessWidget { class DevicesViewBody extends StatelessWidget {
const DevicesViewBody({ const DevicesViewBody({
super.key, super.key,
@ -18,12 +17,32 @@ class DevicesViewBody extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<HomeCubit, HomeState>( return BlocConsumer<DevicesCubit, DevicesState>(
listener: (context, state) {
if (state is GetDevicesError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMsg),
),
);
} else if (state is DevicesCategoriesError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMsg),
),
);
} else if (state is DeviceControlError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMsg),
),
);
}
},
builder: (context, state) { builder: (context, state) {
return BlocBuilder<DevicesCubit, DevicesState>( if (state is DevicesLoading ||
builder: (context, state) { state is GetDevicesLoading ||
//TODO : move to NavigationCubit state is DevicesCategoriesLoading) {
if (state is DevicesLoading) {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else { } else {
return Padding( return Padding(
@ -41,16 +60,16 @@ class DevicesViewBody extends StatelessWidget {
), ),
Expanded( Expanded(
child: PageView( child: PageView(
controller: controller: HomeCubit.getInstance().devicesPageController,
HomeCubit.get(context).devicesPageController,
onPageChanged: (index) { onPageChanged: (index) {
HomeCubit.get(context).devicesPageChanged(index); HomeCubit.getInstance().devicesPageChanged(index);
}, },
children: [ children: [
const WizardPage(), const WizardPage(),
if (HomeCubit.selectedSpace != null) if (HomeCubit.getInstance().selectedSpace != null)
if (HomeCubit.selectedSpace!.rooms != null) if (HomeCubit.getInstance().selectedSpace!.rooms !=
...HomeCubit.selectedSpace!.rooms!.map( null)
...HomeCubit.getInstance().selectedSpace!.rooms!.map(
(room) { (room) {
return RoomPage( return RoomPage(
room: room, room: room,
@ -60,15 +79,19 @@ class DevicesViewBody extends StatelessWidget {
], ],
), ),
), ),
HomeCubit.selectedSpace != null HomeCubit.getInstance().selectedSpace != null
? Padding( ? Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
vertical: 7, vertical: 7,
), ),
child: SmoothPageIndicator( child: SmoothPageIndicator(
controller: controller:
HomeCubit.get(context).devicesPageController, HomeCubit.getInstance().devicesPageController,
count: HomeCubit.selectedSpace!.rooms!.length + 1, count: HomeCubit.getInstance()
.selectedSpace!
.rooms!
.length +
1,
effect: const WormEffect( effect: const WormEffect(
paintStyle: PaintingStyle.stroke, paintStyle: PaintingStyle.stroke,
dotHeight: 8, dotHeight: 8,
@ -85,7 +108,5 @@ class DevicesViewBody extends StatelessWidget {
} }
}, },
); );
},
);
} }
} }

View File

@ -20,7 +20,7 @@ class LightBrightness extends StatelessWidget {
return BlocBuilder<DevicesCubit, DevicesState>( return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) { builder: (context, state) {
return GestureDetector( return GestureDetector(
// onHorizontalDragUpdate: (details) => DevicesCubit().get(context) // onHorizontalDragUpdate: (details) => DevicesCubit.getInstance().get(context)
// .onHorizontalDragUpdate(light, details.localPosition.dx, // .onHorizontalDragUpdate(light, details.localPosition.dx,
// MediaQuery.of(context).size.width - 15), // MediaQuery.of(context).size.width - 15),
child: Stack( child: Stack(

View File

@ -1,10 +1,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.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/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface_contols.dart'; import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface_contols.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface_switch.dart'; import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface_switch.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface_timer.dart'; import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface_timer.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class LightInterface extends StatelessWidget { class LightInterface extends StatelessWidget {
const LightInterface({super.key, required this.light}); const LightInterface({super.key, required this.light});
@ -15,7 +19,25 @@ class LightInterface extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>( return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) { builder: (context, state) {
return Padding( return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
statusBarIconBrightness: Brightness.light,
),
child: Scaffold(
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: light.name ?? "",
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
),
body: Padding(
padding: const EdgeInsets.only(top: 70, right: 20, left: 20), padding: const EdgeInsets.only(top: 70, right: 20, left: 20),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
@ -27,6 +49,8 @@ class LightInterface extends StatelessWidget {
], ],
), ),
), ),
),
),
); );
}, },
); );

View File

@ -27,10 +27,10 @@ class LightInterfaceModes extends StatelessWidget {
Wrap( Wrap(
spacing: 25, spacing: 25,
children: List.generate( children: List.generate(
DevicesCubit.get(context).lightModes.length, DevicesCubit.getInstance().lightModes.length,
(index) => InkWell( (index) => InkWell(
// onTap: () => DevicesCubit.get(context).setLightingMode( // onTap: () => DevicesCubit.getInstance().setLightingMode(
// light, DevicesCubit.get(context).lightModes[index]!), // light, DevicesCubit.getInstance().lightModes[index]!),
child: Column( child: Column(
children: [ children: [
Container( Container(

View File

@ -1,12 +1,12 @@
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/device_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/context_extension.dart'; import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../../../../../generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
import '../../../../../utils/resource_manager/strings_manager.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
import '../../../../shared_widgets/text_widgets/body_medium.dart';
class LightInterfaceRecentColor extends StatelessWidget { class LightInterfaceRecentColor extends StatelessWidget {
const LightInterfaceRecentColor({ const LightInterfaceRecentColor({
@ -34,7 +34,7 @@ class LightInterfaceRecentColor extends StatelessWidget {
4, 4,
(index) => InkWell( (index) => InkWell(
// onTap: () { // onTap: () {
// DevicesCubit.get(context) // DevicesCubit.getInstance()
// .setColor(light, light.recentColors[index]); // .setColor(light, light.recentColors[index]);
// }, // },
child: Container( child: Container(

View File

@ -60,7 +60,7 @@ class LightInterfaceSlider extends StatelessWidget {
// value: light.brightness, // value: light.brightness,
value: 100, value: 100,
onChanged: (value) { onChanged: (value) {
// DevicesCubit.get(context).setBrightness(light, value); // DevicesCubit.getInstance().setBrightness(light, value);
}, },
min: 0, min: 0,
max: 100, max: 100,

View File

@ -1,12 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.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';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
import '../../../../shared_widgets/default_container.dart';
class LightInterfaceSwitch extends StatelessWidget { class LightInterfaceSwitch extends StatelessWidget {
const LightInterfaceSwitch({ const LightInterfaceSwitch({
super.key, super.key,
@ -28,7 +27,7 @@ class LightInterfaceSwitch extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
BodyLarge( BodyLarge(
text: light.status ?? false text: light.isOnline ?? false
? StringsManager.on ? StringsManager.on
: StringsManager.off, : StringsManager.off,
style: style:
@ -37,7 +36,7 @@ class LightInterfaceSwitch extends StatelessWidget {
Container( Container(
width: 35, width: 35,
decoration: ShapeDecoration( decoration: ShapeDecoration(
color: light.status ?? false color: light.isOnline ?? false
? ColorsManager.primaryColorWithOpacity ? ColorsManager.primaryColorWithOpacity
: Colors.grey, : Colors.grey,
shape: const CircleBorder(), shape: const CircleBorder(),
@ -51,7 +50,7 @@ class LightInterfaceSwitch extends StatelessWidget {
iconSize: MaterialStateProperty.all(25), iconSize: MaterialStateProperty.all(25),
), ),
onPressed: () { onPressed: () {
// DevicesCubit.get(context).toggleLight(light); // DevicesCubit.getInstance().toggleLight(light);
}, },
icon: const Icon( icon: const Icon(
Icons.power_settings_new, Icons.power_settings_new,

View File

@ -3,7 +3,7 @@ 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';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
import '../../../../shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart';
class LightInterfaceTimer extends StatelessWidget { class LightInterfaceTimer extends StatelessWidget {
const LightInterfaceTimer({ const LightInterfaceTimer({

View File

@ -2,9 +2,8 @@ import 'package:flutter/material.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/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/light_brightness.dart'; import 'package:syncrow_app/features/devices/view/widgets/lights/light_brightness.dart';
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
import '../../../../shared_widgets/devices_default_switch.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import '../../../../shared_widgets/text_widgets/body_small.dart';
class LightsList extends StatelessWidget { class LightsList extends StatelessWidget {
const LightsList({ const LightsList({
@ -32,7 +31,7 @@ class LightsList extends StatelessWidget {
BodySmall(text: lights[index].name ?? ""), BodySmall(text: lights[index].name ?? ""),
IconButton( IconButton(
onPressed: () { onPressed: () {
DevicesCubit.get(context).selectDevice(lights[index]); DevicesCubit.getInstance().selectDevice(lights[index]);
}, },
icon: const Icon( icon: const Icon(
Icons.arrow_forward_ios, Icons.arrow_forward_ios,

View File

@ -19,9 +19,9 @@ class LightsView extends StatelessWidget {
return BlocBuilder<DevicesCubit, DevicesState>( return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) { builder: (context, state) {
DeviceModel? selectedLight; DeviceModel? selectedLight;
if (DevicesCubit.get(context).getSelectedDevice() is DeviceModel) { if (DevicesCubit.getInstance().getSelectedDevice() is DeviceModel) {
selectedLight = selectedLight =
DevicesCubit.get(context).getSelectedDevice() as DeviceModel; DevicesCubit.getInstance().getSelectedDevice() as DeviceModel;
} }
List<DeviceModel> lights = []; List<DeviceModel> lights = [];
if (DevicesCubit.allCategories![1].devices != null) { if (DevicesCubit.allCategories![1].devices != null) {

View File

@ -1,12 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/lights_list.dart'; import 'package:syncrow_app/features/devices/view/widgets/lights/lights_list.dart';
import 'package:syncrow_app/features/devices/view/widgets/universal_switch.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart';
import '../../../../shared_widgets/text_widgets/body_small.dart';
import '../../../bloc/devices_cubit.dart';
import '../universal_switch.dart';
class LightsViewList extends StatelessWidget { class LightsViewList extends StatelessWidget {
const LightsViewList({ const LightsViewList({
super.key, super.key,

View File

@ -1,71 +0,0 @@
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/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class LightSwitch extends StatelessWidget {
const LightSwitch({
super.key,
required this.control,
});
final DeviceControlModel control;
@override
Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
return state is DeviceControlLoading
? const CircularProgressIndicator()
: InkWell(
overlayColor: MaterialStateProperty.all(Colors.transparent),
onTap: () {
DevicesCubit.get(context)
.deviceControl(control)
.then((value) {
print('Device control response: $value');
if (control.value ?? true) {
control.value = false;
} else {
control.value = true;
}
});
},
child: Stack(
alignment: !control.value!
? Alignment.topCenter
: Alignment.bottomCenter,
children: [
Container(
decoration: BoxDecoration(
borderRadius:
const BorderRadius.all(Radius.circular(100.0)),
color: !control.value!
? ColorsManager.primaryColorWithOpacity
: ColorsManager.switchOffColor,
),
width: 60,
height: 115,
),
Padding(
padding: const EdgeInsets.all(5.0),
child: SizedBox.square(
dimension: 60,
child: SvgPicture.asset(
!control.value!
? Assets.iconsLightSwitchOn
: Assets.iconsLightSwitchOff,
fit: BoxFit.fill,
),
),
),
],
),
);
},
);
}
}

View File

@ -1,87 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/function_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/category_view_app_bar.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights_switches/light_switches_body.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
class LightSwitchesView extends StatelessWidget {
const LightSwitchesView({super.key});
@override
Widget build(BuildContext context) {
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 CategoryViewAppBar(),
body: BlocBuilder<HomeCubit, HomeState>(
builder: (context, state) {
return 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: EdgeInsets.only(
top: Constants.appBarHeight,
left: Constants.defaultPadding,
right: Constants.defaultPadding,
bottom: Constants.bottomNavBarHeight,
),
child: LightSwitchesBody(
device: DeviceModel(
id: 2,
name: 'Bedroom Light',
type: DeviceType.Lights,
status: true,
timer: 0,
image: '',
functions: [
FunctionModel(
code: 'switch_1',
desc: 'switch 1',
name: 'switch 1',
type: 'Boolean',
values: '{}'),
FunctionModel(
code: 'switch_2',
desc: 'switch 2',
name: 'switch 2',
type: 'Boolean',
values: '{}'),
FunctionModel(
code: 'switch_3',
desc: 'switch 3',
name: 'switch 3',
type: 'Boolean',
values: '{}'),
]),
),
),
);
},
)),
),
);
}
}

View File

@ -1,260 +0,0 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights_switches/light_switch.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class LightSwitchesBody extends StatelessWidget {
const LightSwitchesBody({
super.key,
required this.device,
});
final DeviceModel device;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Expanded(child: SizedBox.shrink()),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
children: [
LightSwitch(
control: DeviceControlModel(
deviceId: 'bfe10693d4fd263206ocq9',
code: 'switch_1',
value: true,
),
),
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Bedside Light",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
Column(
children: [
LightSwitch(
control: DeviceControlModel(
deviceId: 'bfe10693d4fd263206ocq9',
code: 'switch_2',
value: true,
),
),
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Ceiling Light",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
Column(
children: [
LightSwitch(
control: DeviceControlModel(
deviceId: 'bfe10693d4fd263206ocq9',
code: 'switch_3',
value: true,
),
),
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Spotlight",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
],
),
Expanded(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: InkWell(
onTap: () {},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: BodySmall(
text: "On",
style: context.bodyMedium.copyWith(
color:
ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
),
const SizedBox(height: 10),
BodySmall(
text: "All On",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
),
),
],
),
const SizedBox(
width: 20,
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: InkWell(
onTap: () {},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: Icon(
Icons.access_time,
color: ColorsManager.primaryColorWithOpacity,
size: 25,
),
),
),
],
),
),
),
const SizedBox(height: 10),
BodySmall(
text: "Timer",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
),
),
],
),
const SizedBox(
width: 20,
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: InkWell(
onTap: () {},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: BodySmall(
text: "Off",
style: context.bodyMedium.copyWith(
color:
ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
),
const SizedBox(height: 10),
BodySmall(
text: "All Off",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
),
),
],
),
],
),
),
),
],
);
}
}

View File

@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.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/device_model.dart';
import 'package:syncrow_app/features/devices/model/room_model.dart'; import 'package:syncrow_app/features/devices/model/room_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart'; import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart';
@ -13,10 +12,6 @@ class RoomPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<DeviceModel> devices = [];
for (var category in room.categories ?? []) {
devices.addAll(category.devices);
}
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: Constants.defaultPadding), padding: const EdgeInsets.symmetric(horizontal: Constants.defaultPadding),
child: SingleChildScrollView( child: SingleChildScrollView(
@ -32,9 +27,9 @@ class RoomPage extends StatelessWidget {
padding: const EdgeInsets.only(top: 10), padding: const EdgeInsets.only(top: 10),
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
itemCount: devices.length, itemCount: room.devices!.length,
itemBuilder: (_, index) { itemBuilder: (context, index) {
return RoomPageSwitch(device: devices[index]); return RoomPageSwitch(device: room.devices![index]);
}, },
); );
}, },

View File

@ -1,7 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.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';
@ -21,25 +25,57 @@ class RoomPageSwitch extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return InkWell(
onTap: () { onTap: () {
//Navigate to the chosen category view without animation switch (device.productType) {
case DeviceType.AC:
// Navigator.push( {
// context, print("AC");
// CustomPageRoute(
// builder: (context) {
// return DevicesCubit.get(context)
// .chosenCategoryView!;
// },
// ),
// );
if (device.type == DeviceType.AC) {
Navigator.push( Navigator.push(
context, context,
CustomPageRoute( CustomPageRoute(
builder: (context) => AcInterface(deviceModel: device), builder: (context) => BlocProvider(
create: (context) => DevicesCubit.getInstance(),
child: AcInterface(deviceModel: device),
),
), ),
); );
break;
}
case DeviceType.WallSensor:
break;
case DeviceType.CeilingSensor:
break;
case DeviceType.Curtain:
break;
case DeviceType.Blind:
break;
case DeviceType.DoorLock:
break;
case DeviceType.Gateway:
break;
case DeviceType.LightBulb:
Navigator.push(
context,
CustomPageRoute(
builder: (context) => BlocProvider(
create: (context) => DevicesCubit.getInstance(),
child: LightInterface(light: device),
),
),
);
case DeviceType.ThreeGang:
Navigator.push(
context,
CustomPageRoute(
builder: (context) => BlocProvider(
create: (context) => DevicesCubit.getInstance(),
child: ThreeGangInterface(
gangSwitch: device,
),
),
),
);
break;
default:
} }
}, },
child: DefaultContainer( child: DefaultContainer(
@ -54,7 +90,7 @@ class RoomPageSwitch extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SvgPicture.asset( SvgPicture.asset(
device.icon, device.icon!,
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
CustomSwitch( CustomSwitch(

View File

@ -18,43 +18,47 @@ class RoomsSlider extends StatelessWidget {
return SizedBox( return SizedBox(
height: 40, height: 40,
child: PageView( child: PageView(
controller: HomeCubit.get(context).roomsPageController, controller: HomeCubit.getInstance().roomsPageController,
onPageChanged: (index) { onPageChanged: (index) {
HomeCubit.get(context).roomSliderPageChanged(index); HomeCubit.getInstance().roomSliderPageChanged(index);
}, },
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 15), padding: const EdgeInsets.symmetric(horizontal: 15),
child: InkWell( child: InkWell(
onTap: () { onTap: () {
HomeCubit.get(context).unselectRoom(); HomeCubit.getInstance().unselectRoom();
}, },
child: TitleMedium( child: TitleMedium(
text: StringsManager.wizard, text: StringsManager.wizard,
style: context.titleMedium.copyWith( style: context.titleMedium.copyWith(
fontSize: 25, fontSize: 25,
color: HomeCubit.get(context).selectedRoom == null color: HomeCubit.getInstance().selectedRoom == null
? ColorsManager.textPrimaryColor ? ColorsManager.textPrimaryColor
: ColorsManager.textPrimaryColor.withOpacity(.2), : ColorsManager.textPrimaryColor.withOpacity(.2),
), ),
), ),
), ),
), ),
if (HomeCubit.selectedSpace != null) if (HomeCubit.getInstance().selectedSpace != null)
if (HomeCubit.selectedSpace!.rooms != null) if (HomeCubit.getInstance().selectedSpace!.rooms != null)
...HomeCubit.selectedSpace!.rooms!.map( ...HomeCubit.getInstance().selectedSpace!.rooms!.map(
(room) => Padding( (room) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 15), padding: const EdgeInsets.symmetric(horizontal: 15),
child: InkWell( child: InkWell(
onTap: () { onTap: () {
HomeCubit.get(context).roomSliderPageChanged( HomeCubit.getInstance().roomSliderPageChanged(
HomeCubit.selectedSpace!.rooms!.indexOf(room)); HomeCubit.getInstance()
.selectedSpace!
.rooms!
.indexOf(room));
}, },
child: TitleMedium( child: TitleMedium(
text: room.name!, text: room.name!,
style: context.titleMedium.copyWith( style: context.titleMedium.copyWith(
fontSize: 25, fontSize: 25,
color: HomeCubit.get(context).selectedRoom == room color:
HomeCubit.getInstance().selectedRoom == room
? ColorsManager.textPrimaryColor ? ColorsManager.textPrimaryColor
: ColorsManager.textPrimaryColor : ColorsManager.textPrimaryColor
.withOpacity(.2), .withOpacity(.2),

View File

@ -0,0 +1,81 @@
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/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class GangSwitch extends StatelessWidget {
const GangSwitch({
super.key,
required this.threeGangSwitch,
required this.control,
});
final DeviceModel threeGangSwitch;
final DeviceControlModel control;
@override
Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
return InkWell(
overlayColor: MaterialStateProperty.all(Colors.transparent),
onTap: () {
var tempControl = DeviceControlModel(
deviceId: control.deviceId,
code: control.code!,
value: !control.value!);
DevicesCubit.getInstance().deviceControl(
tempControl,
control.deviceId!,
);
},
child: Stack(
alignment:
!control.value! ? Alignment.topCenter : Alignment.bottomCenter,
children: [
Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(100.0)),
color: threeGangSwitch.status
.firstWhere((element) => element.code == control.code)
.value!
? ColorsManager.primaryColorWithOpacity
: ColorsManager.switchOffColor,
),
width: 60,
height: 115,
),
Padding(
padding: const EdgeInsets.all(5.0),
child: SizedBox.square(
dimension: 60,
child: state is GetDeviceStatusLoading &&
state.code == control.code ||
state is DeviceControlSuccess &&
state.code == control.code ||
state is DeviceControlLoading &&
state.code == control.code
? const SizedBox(
width: 10,
height: 10,
child: Center(child: CircularProgressIndicator()))
: SvgPicture.asset(
control.value!
? Assets.iconsLightSwitchOn
: Assets.iconsLightSwitchOff,
fit: BoxFit.fill,
),
),
),
],
),
);
},
);
}
}

View File

@ -0,0 +1,65 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface_body.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class ThreeGangInterface extends StatelessWidget {
const ThreeGangInterface({super.key, required this.gangSwitch});
final DeviceModel gangSwitch;
@override
Widget build(BuildContext context) {
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: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: gangSwitch.name ?? "",
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
),
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: EdgeInsets.only(
top: Constants.appBarHeight,
left: Constants.defaultPadding,
right: Constants.defaultPadding,
bottom: Constants.bottomNavBarHeight,
),
child: ThreeGangInterfaceBody(
device: gangSwitch,
),
),
),
),
),
);
}
}

View File

@ -0,0 +1,328 @@
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_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class ThreeGangInterfaceBody extends StatelessWidget {
const ThreeGangInterfaceBody({
super.key,
required this.device,
});
final DeviceModel device;
@override
Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Expanded(child: SizedBox.shrink()),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
children: [
GangSwitch(
threeGangSwitch: device,
control: DeviceControlModel(
deviceId: device.id,
// code: 'switch_1',
code: device.status[0].code,
// value: true,
value: device.status[0].value,
),
),
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Bedside Light",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
Column(
children: [
GangSwitch(
threeGangSwitch: device,
control: DeviceControlModel(
// deviceId: 'bfe10693d4fd263206ocq9',
// code: 'switch_2',
// value: true,
deviceId: device.id,
code: device.status[1].code,
value: device.status[1].value,
),
),
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Ceiling Light",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
Column(
children: [
GangSwitch(
threeGangSwitch: device,
control: DeviceControlModel(
// deviceId: 'bfe10693d4fd263206ocq9',
// code: 'switch_3',
// value: true,
deviceId: device.id,
code: device.status[2].code,
value: device.status[2].value,
),
),
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Spotlight",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
],
),
Expanded(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: InkWell(
onTap: () {
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: device.id,
code: 'switch_1',
value: true,
),
device.id!,
);
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: device.id,
code: 'switch_2',
value: true,
),
device.id!,
);
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: device.id,
code: 'switch_3',
value: true,
),
device.id!,
);
},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: BodySmall(
text: "On",
style: context.bodyMedium.copyWith(
color: ColorsManager
.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
),
const SizedBox(height: 10),
BodySmall(
text: "All On",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
),
),
],
),
const SizedBox(
width: 20,
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: InkWell(
onTap: () {},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: Icon(
Icons.access_time,
color:
ColorsManager.primaryColorWithOpacity,
size: 25,
),
),
),
],
),
),
),
const SizedBox(height: 10),
BodySmall(
text: "Timer",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
),
),
],
),
const SizedBox(
width: 20,
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: InkWell(
onTap: () {
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: device.id,
code: 'switch_1',
value: false,
),
device.id!,
);
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: device.id,
code: 'switch_2',
value: false,
),
device.id!,
);
DevicesCubit.getInstance().deviceControl(
DeviceControlModel(
deviceId: device.id,
code: 'switch_3',
value: false,
),
device.id!,
);
},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: BodySmall(
text: "Off",
style: context.bodyMedium.copyWith(
color: ColorsManager
.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
),
const SizedBox(height: 10),
BodySmall(
text: "All Off",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
),
),
],
),
],
),
),
),
],
);
},
);
}
}

View File

@ -2,11 +2,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.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/device_category_model.dart'; import 'package:syncrow_app/features/devices/model/device_category_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 'package:syncrow_app/utils/resource_manager/strings_manager.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';
class UniversalSwitch extends StatelessWidget { class UniversalSwitch extends StatelessWidget {
const UniversalSwitch({ const UniversalSwitch({
super.key, super.key,
@ -25,7 +24,7 @@ class UniversalSwitch extends StatelessWidget {
Expanded( Expanded(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
DevicesCubit.get(context).turnAllDevicesOn(category); DevicesCubit.getInstance().turnAllDevicesOn(category);
}, },
child: Container( child: Container(
height: 60, height: 60,
@ -57,7 +56,7 @@ class UniversalSwitch extends StatelessWidget {
Expanded( Expanded(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
DevicesCubit.get(context).turnAllDevicesOff(category); DevicesCubit.getInstance().turnAllDevicesOff(category);
}, },
child: Container( child: Container(
height: 60, height: 60,

View File

@ -1,14 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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/shared_widgets/custom_switch.dart'; import 'package:syncrow_app/features/devices/bloc/devices_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';
import 'package:syncrow_app/utils/helpers/custom_page_route.dart'; import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
import '../../bloc/devices_cubit.dart';
class WizartSwitches extends StatelessWidget { class WizartSwitches extends StatelessWidget {
const WizartSwitches({ const WizartSwitches({
super.key, super.key,
@ -35,12 +33,12 @@ class WizartSwitches extends StatelessWidget {
itemBuilder: (_, index) { itemBuilder: (_, index) {
return InkWell( return InkWell(
onTap: () { onTap: () {
DevicesCubit.get(context).selectCategory(index); // DevicesCubit.getInstance().selectCategory(index);
//Navigate to the chosen category view without animation //Navigate to the chosen category view without animation
Navigator.push(context, Navigator.push(context,
CustomPageRoute(builder: (context) { CustomPageRoute(builder: (context) {
return DevicesCubit.get(context) return DevicesCubit.getInstance()
.chosenCategoryView!; .chosenCategoryView!;
})); }));
}, },
@ -61,10 +59,7 @@ class WizartSwitches extends StatelessWidget {
DevicesCubit.allCategories![index].icon!, DevicesCubit.allCategories![index].icon!,
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
CustomSwitch( // CustomSwitch(
category:
DevicesCubit.allCategories![index],
),
], ],
), ),
Expanded( Expanded(

View File

@ -1,7 +1,6 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/menu/model/list_item_model.dart';
import '../model/list_item_model.dart'; import 'package:syncrow_app/features/menu/model/menu_list_model.dart';
import '../model/menu_list_model.dart';
part 'menu_state.dart'; part 'menu_state.dart';

View File

@ -1,10 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.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/syncrow_logo.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/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import '../../../shared_widgets/syncrow_logo.dart';
class ProfileTab extends StatelessWidget { class ProfileTab extends StatelessWidget {
const ProfileTab({ const ProfileTab({
super.key, super.key,

View File

@ -2,34 +2,41 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.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/device_category_model.dart'; import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:collection/collection.dart';
class CustomSwitch extends StatelessWidget { class CustomSwitch extends StatelessWidget {
const CustomSwitch({super.key, this.category, this.device}) const CustomSwitch({super.key, required this.device});
: assert(category != null || device != null);
final DevicesCategoryModel? category;
final DeviceModel? device;
final DeviceModel device;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>( return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) { builder: (context, state) {
bool? status; bool? status;
if (device != null) { if (device.status.isNotEmpty) {
status = device!.status; status = device.status
} else if (category != null) { .firstWhereOrNull((status) => status.code == "switch")
status = category!.devicesStatus; ?.value;
} }
return GestureDetector( return status == null
? const SizedBox()
: GestureDetector(
onTap: () { onTap: () {
if (device != null) { DevicesCubit.getInstance().deviceControl(
DevicesCubit.get(context).turnOnOffDevice(device!); DeviceControlModel(
} else if (category != null) { deviceId: device.id,
DevicesCubit.get(context).changeCategorySwitchValue(category!); code: device.status
} .firstWhere((status) => status.code == "switch")
.code,
value: !device.status
.firstWhere((status) => status.code == "switch")
.value!,
),
device.id!,
);
}, },
child: Container( child: Container(
width: 45.0, width: 45.0,

View File

@ -1,11 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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_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/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';
import '../devices/bloc/devices_cubit.dart';
class DevicesDefaultSwitch extends StatelessWidget { class DevicesDefaultSwitch extends StatelessWidget {
const DevicesDefaultSwitch({ const DevicesDefaultSwitch({
super.key, super.key,
@ -23,12 +22,12 @@ class DevicesDefaultSwitch extends StatelessWidget {
Expanded( Expanded(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
DevicesCubit.get(context).turnOnOffDevice(model); DevicesCubit.getInstance().turnOnOffDevice(model);
}, },
child: Container( child: Container(
height: 60, height: 60,
decoration: BoxDecoration( decoration: BoxDecoration(
color: model.status ?? false color: model.isOnline ?? false
? ColorsManager.primaryColor ? ColorsManager.primaryColor
: Colors.white, : Colors.white,
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
@ -39,7 +38,7 @@ class DevicesDefaultSwitch extends StatelessWidget {
child: Center( child: Center(
child: BodyMedium( child: BodyMedium(
text: "ON", text: "ON",
fontColor: model.status ?? false ? Colors.white : null, fontColor: model.isOnline ?? false ? Colors.white : null,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
@ -49,12 +48,12 @@ class DevicesDefaultSwitch extends StatelessWidget {
Expanded( Expanded(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
DevicesCubit.get(context).turnOnOffDevice(model); DevicesCubit.getInstance().turnOnOffDevice(model);
}, },
child: Container( child: Container(
height: 60, height: 60,
decoration: BoxDecoration( decoration: BoxDecoration(
color: model.status ?? false color: model.isOnline ?? false
? Colors.white ? Colors.white
: ColorsManager.primaryColor, : ColorsManager.primaryColor,
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
@ -65,7 +64,7 @@ class DevicesDefaultSwitch extends StatelessWidget {
child: Center( child: Center(
child: BodyMedium( child: BodyMedium(
text: "OFF", text: "OFF",
fontColor: model.status ?? false ? null : Colors.white, fontColor: model.isOnline ?? false ? null : Colors.white,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),

View File

@ -18,12 +18,8 @@ class MyApp extends StatelessWidget {
MediaQuery.sizeOf(context).height * Constants.appBarHeightPercentage; MediaQuery.sizeOf(context).height * Constants.appBarHeightPercentage;
Constants.bottomNavBarHeight = MediaQuery.sizeOf(context).height * Constants.bottomNavBarHeight = MediaQuery.sizeOf(context).height *
Constants.bottomNavBarHeightPercentage; Constants.bottomNavBarHeightPercentage;
return MultiBlocProvider( return BlocProvider(
providers: [
BlocProvider(
create: (context) => AuthCubit(), create: (context) => AuthCubit(),
),
],
child: MaterialApp( child: MaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
color: ColorsManager.primaryColor, color: ColorsManager.primaryColor,

View File

@ -7,7 +7,6 @@ import 'package:syncrow_app/features/auth/view/widgets/privacy_policy/privacy_po
import 'package:syncrow_app/features/auth/view/widgets/sign_up/sign_up_view.dart'; import 'package:syncrow_app/features/auth/view/widgets/sign_up/sign_up_view.dart';
import 'package:syncrow_app/features/auth/view/widgets/user_agreement/user_agreement_view.dart'; import 'package:syncrow_app/features/auth/view/widgets/user_agreement/user_agreement_view.dart';
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart'; import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
import 'package:syncrow_app/features/devices/view/devices_view.dart';
import 'package:syncrow_app/features/layout/view/layout_view.dart'; import 'package:syncrow_app/features/layout/view/layout_view.dart';
import 'package:syncrow_app/features/menu/view/menu_view.dart'; import 'package:syncrow_app/features/menu/view/menu_view.dart';
import 'package:syncrow_app/features/profile/view/profile_view.dart'; import 'package:syncrow_app/features/profile/view/profile_view.dart';
@ -23,9 +22,9 @@ class Router {
return MaterialPageRoute( return MaterialPageRoute(
builder: (_) => const SplashView(), settings: settings); builder: (_) => const SplashView(), settings: settings);
case Routes.devicesRoute: // case Routes.devicesRoute:
return MaterialPageRoute( // return MaterialPageRoute(
builder: (_) => const DevicesView(), settings: settings); // builder: (_) => const DevicesView(), settings: settings);
case Routes.profileRoute: case Routes.profileRoute:
return MaterialPageRoute( return MaterialPageRoute(

View File

@ -16,6 +16,9 @@ abstract class ApiEndpoints {
// Devices // Devices
static const String control = '$baseUrl/device/control'; static const String control = '$baseUrl/device/control';
static const String devicesByRoom = '$baseUrl/device/room';
// static const String deviceStatus = '$baseUrl/device/status/';
static const String deviceStatus = '$baseUrl/device/';
//groups //groups
static const String groups = '$baseUrl/group'; static const String groups = '$baseUrl/group';

View File

@ -8,6 +8,8 @@ class DevicesAPI {
static Future<Map<String, dynamic>> controlDevice( static Future<Map<String, dynamic>> controlDevice(
DeviceControlModel controlModel) async { DeviceControlModel controlModel) async {
// print(
// 'contoling [${controlModel.deviceId}] with code [${controlModel.code}] and value [${controlModel.value}');
final response = await _httpService.post( final response = await _httpService.post(
path: ApiEndpoints.control, path: ApiEndpoints.control,
body: controlModel.toJson(), body: controlModel.toJson(),
@ -34,4 +36,15 @@ class DevicesAPI {
); );
return response; return response;
} }
static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
final response = await _httpService.get(
path: '${ApiEndpoints.deviceStatus}/$deviceId/functions/status',
showServerMessage: false,
expectedResponseModel: (json) {
return json;
},
);
return response;
}
} }

View File

@ -37,9 +37,6 @@ class HTTPService {
path, path,
queryParameters: queryParameters, queryParameters: queryParameters,
); );
// debugPrint("status code is ${response.statusCode}");
// debugPrint("response data is ${response.data}");
return expectedResponseModel(response.data); return expectedResponseModel(response.data);
} catch (error) { } catch (error) {
debugPrint("******* Error"); debugPrint("******* Error");

View File

@ -28,8 +28,14 @@ class ServerFailure extends Failure {
return ServerFailure("Bad certificate!"); return ServerFailure("Bad certificate!");
case DioExceptionType.badResponse: case DioExceptionType.badResponse:
{
// var document = parser.parse(dioError.response!.data.toString());
// var message = document.body!.text;
return ServerFailure.fromResponse(dioError.response!.statusCode!, return ServerFailure.fromResponse(dioError.response!.statusCode!,
dioError.response!.data!["message"]); dioError.response!.data['message'].toString()
// message
);
}
case DioExceptionType.cancel: case DioExceptionType.cancel:
return ServerFailure("The request to ApiServer was canceled"); return ServerFailure("The request to ApiServer was canceled");
@ -45,8 +51,15 @@ class ServerFailure extends Failure {
} }
factory ServerFailure.fromResponse(int statusCode, dynamic response) { factory ServerFailure.fromResponse(int statusCode, dynamic response) {
if (statusCode == 400 || statusCode == 401 || statusCode == 403) { if (statusCode == 401 || statusCode == 403) {
return ServerFailure(response); return ServerFailure(response);
} else if (statusCode == 400) {
//response is list of errors
List<String> errors = [];
response.forEach((element) {
errors.add(element);
});
return ServerFailure(errors.join('\n'));
} else if (statusCode == 404) { } else if (statusCode == 404) {
return ServerFailure("Your request not found, Please try later!"); return ServerFailure("Your request not found, Please try later!");
} else if (statusCode == 500) { } else if (statusCode == 500) {

View File

@ -1,6 +1,7 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart'; import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/auth/model/user_model.dart'; import 'package:syncrow_app/features/auth/model/user_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/room_model.dart'; import 'package:syncrow_app/features/devices/model/room_model.dart';
import 'package:syncrow_app/services/api/api_links_endpoints.dart'; import 'package:syncrow_app/services/api/api_links_endpoints.dart';
import 'package:syncrow_app/services/api/http_service.dart'; import 'package:syncrow_app/services/api/http_service.dart';
@ -23,7 +24,7 @@ class SpacesAPI {
} }
//get rooms by space id //get rooms by space id
static Future<List<RoomModel>> getRooms(int spaceId) async { static Future<List<RoomModel>> getRoomsBySpaceId(int spaceId) async {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.rooms, path: ApiEndpoints.rooms,
queryParameters: {"homeId": spaceId}, queryParameters: {"homeId": spaceId},
@ -38,4 +39,20 @@ class SpacesAPI {
); );
return response; return response;
} }
static Future<List<DeviceModel>> getDevicesByRoomId(int roomId) async {
final response = await _httpService.get(
path: ApiEndpoints.devicesByRoom,
queryParameters: {"roomId": roomId, "pageSize": 10},
showServerMessage: false,
expectedResponseModel: (json) {
List<DeviceModel> devices = [];
for (var device in json['devices']) {
devices.add(DeviceModel.fromJson(device));
}
return devices;
},
);
return response;
}
} }

View File

@ -23,7 +23,7 @@ class MyBlocObserver extends BlocObserver {
@override @override
void onClose(BlocBase bloc) { void onClose(BlocBase bloc) {
super.onClose(bloc);
print('onClose -- ${bloc.runtimeType}'); print('onClose -- ${bloc.runtimeType}');
super.onClose(bloc);
} }
} }

View File

@ -1,4 +1,7 @@
//ignore_for_file: constant_identifier_names //ignore_for_file: constant_identifier_names
import 'package:syncrow_app/features/devices/model/function_model.dart';
import 'package:syncrow_app/generated/assets.dart';
abstract class Constants { abstract class Constants {
static const String languageCode = "en"; static const String languageCode = "en";
@ -16,12 +19,182 @@ abstract class Constants {
enum DeviceType { enum DeviceType {
AC, AC,
Lights, LightBulb,
DoorLock, DoorLock,
Curtain, Curtain,
Blind,
ThreeGang, ThreeGang,
Gateway, Gateway,
Sensors, CeilingSensor,
Gang, WallSensor,
Other, Other,
} }
// Map<String, DeviceType> devicesTypesMap = {
// "AC": DeviceType.AC,
// "LB": DeviceType.LightBulb,
// "DL": DeviceType.DoorLock,
// "WC": DeviceType.Curtain,
// "WB": DeviceType.Blind,
// "3G": DeviceType.ThreeGang,
// "GW": DeviceType.Gateway,
// "CPS": DeviceType.CeilingSensor,
// "WPS": DeviceType.WallSensor,
// "Other": DeviceType.Other,
// };
//AC wzdcrqh0
// GW wp8ticoo2bhumwgb
// CPS d3ci7gcn
// DL awu7anehyu5q1iu8
// WPS awarhusb
// 3G 1a6vgvyi
Map<String, DeviceType> devicesTypesMap = {
"wzdcrqh0": DeviceType.AC,
"wp8ticoo2bhumwgb": DeviceType.Gateway,
"d3ci7gcn": DeviceType.CeilingSensor,
"awu7anehyu5q1iu8": DeviceType.DoorLock,
"awarhusb": DeviceType.WallSensor,
"1a6vgvyi": DeviceType.ThreeGang,
};
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
DeviceType.AC: [
FunctionModel(code: 'switch', type: 'Boolean', values: '{}'),
FunctionModel(
code: 'mode', type: 'Enum', values: '{"range":["cold","hot","wind"]}'),
FunctionModel(
code: 'temp_set',
type: 'Integer',
values: '{"unit":"℃","min":200,"max":300,"scale":1,"step":5}'),
FunctionModel(
code: 'level',
type: 'Enum',
values: '{"range":["low","middle","high","auto"]}'),
FunctionModel(code: 'child_lock', type: 'Boolean', values: '{}'),
],
DeviceType.Gateway: [
FunctionModel(code: 'switch_alarm_sound', type: 'Boolean', values: '{}'),
FunctionModel(
code: 'master_state',
type: 'Enum',
values: '{"range":["normal","alarm"]}'),
FunctionModel(code: 'factory_reset', type: 'Boolean', values: '{}'),
FunctionModel(
code: 'alarm_active', type: 'String', values: '{"maxlen":255}'),
],
DeviceType.CeilingSensor: [
FunctionModel(
code: 'sensitivity',
type: 'Integer',
values: '{"unit":"","min":1,"max":10,"scale":0,"step":1}'),
],
DeviceType.DoorLock: [
FunctionModel(code: 'remote_no_pd_setkey', type: 'Raw', values: '{}'),
FunctionModel(code: 'remote_no_dp_key', type: 'Raw', values: '{}'),
FunctionModel(code: 'normal_open_switch', type: 'Boolean', values: '{}'),
],
DeviceType.WallSensor: [
FunctionModel(
code: 'far_detection',
type: 'Integer',
values: '{"unit":"cm","min":75,"max":600,"scale":0,"step":75}'),
FunctionModel(
code: 'presence_time',
type: 'Integer',
values: '{"unit":"Min","min":0,"max":65535,"scale":0,"step":1}'),
FunctionModel(
code: 'motion_sensitivity_value',
type: 'Integer',
values: '{"unit":"","min":1,"max":5,"scale":0,"step":1}'),
FunctionModel(
code: 'motionless_sensitivity',
type: 'Integer',
values: '{"unit":"","min":1,"max":5,"scale":0,"step":1}'),
FunctionModel(code: 'indicator', type: 'Boolean', values: '{}'),
],
DeviceType.ThreeGang: [
FunctionModel(code: 'switch_1', type: 'Boolean', values: '{}'),
FunctionModel(code: 'switch_2', type: 'Boolean', values: '{}'),
FunctionModel(code: 'switch_3', type: 'Boolean', values: '{}'),
FunctionModel(
code: 'countdown_1',
type: 'Integer',
values: '{"unit":"s","min":0,"max":43200,"scale":0,"step":1}'),
FunctionModel(
code: 'countdown_2',
type: 'Integer',
values: '{"unit":"s","min":0,"max":43200,"scale":0,"step":1}'),
FunctionModel(
code: 'countdown_3',
type: 'Integer',
values: '{"unit":"s","min":0,"max":43200,"scale":0,"step":1}'),
],
};
enum TempModes { hot, cold, wind }
enum FanSpeeds { auto, low, middle, high }
final Map<FanSpeeds, String> fanSpeedsIconMap = {
FanSpeeds.auto: Assets.iconsFan0,
FanSpeeds.low: Assets.iconsFan1,
FanSpeeds.middle: Assets.iconsFan2,
FanSpeeds.high: Assets.iconsFan3,
};
final Map<TempModes, String> tempModesIconMap = {
TempModes.hot: Assets.iconsSunnyMode,
TempModes.cold: Assets.iconsColdMode,
TempModes.wind: Assets.iconsWindyMode,
};
final Map<String, FanSpeeds> fanSpeedsMap = {
'auto': FanSpeeds.auto,
'low': FanSpeeds.low,
'middle': FanSpeeds.middle,
'high': FanSpeeds.high,
};
final Map<String, TempModes> tempModesMap = {
'hot': TempModes.hot,
'cold': TempModes.cold,
'wind': TempModes.wind,
};
final Map<FanSpeeds, String> reversedFanSpeedsMap =
fanSpeedsMap.map((key, value) => MapEntry(value, key));
final Map<TempModes, String> reversedTempModesMap =
tempModesMap.map((key, value) => MapEntry(value, key));
String getNextFanSpeedKey(FanSpeeds currentFanSpeed) {
const List<FanSpeeds> speeds = FanSpeeds.values;
final int currentIndex = speeds.indexOf(currentFanSpeed);
// Return null if currentFanSpeed is the last value
if (currentIndex == speeds.length - 1) {
return reversedFanSpeedsMap[FanSpeeds.auto]!;
}
final FanSpeeds nextSpeed = speeds[currentIndex + 1];
return reversedFanSpeedsMap[nextSpeed]!;
}
K? getNextItem<K, V>(Map<K, V> map, V value) {
// Iterate over the map entries
for (var entry in map.entries) {
// If the current value matches the provided value
if (entry.value == value) {
// Get the index of the current entry
final index = map.keys.toList().indexOf(entry.key);
// If the index is not the last item, return the next item
if (index < map.length - 1) {
return map.keys.elementAt(index + 1);
}
// If it's the last item, return null
return map.keys.elementAt(0);
}
}
// If the value is not found, return null
return null;
}

View File

@ -97,6 +97,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.3"
csslib:
dependency: transitive
description:
name: csslib
sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -357,6 +365,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.6.7" version: "7.6.7"
html:
dependency: "direct main"
description:
name: html
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
url: "https://pub.dev"
source: hosted
version: "0.15.4"
http: http:
dependency: transitive dependency: transitive
description: description:

View File

@ -36,6 +36,7 @@ dependencies:
firebase_analytics: ^10.8.7 firebase_analytics: ^10.8.7
firebase_crashlytics: ^3.4.16 firebase_crashlytics: ^3.4.16
smooth_page_indicator: ^1.1.0 smooth_page_indicator: ^1.1.0
html: ^0.15.4
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: