Compare commits

...

77 Commits

Author SHA1 Message Date
2b0e504f05 Refactor device name display in Action and Condition models 2025-04-23 10:07:14 +03:00
a656d5981e Merge pull request #88 from SyncrowIOT/Fix-Save-Display-Condition
Fix save display condition
2025-04-22 15:42:42 +03:00
3f49a18130 remove unused code 2025-04-21 15:19:14 +03:00
a51c4d9679 Refactor device name display in RoomPageSwitch widget 2025-04-21 15:00:31 +03:00
caeed8e73f Merge pull request #87 from SyncrowIOT/FE-Complete-the-Device-Name-as
Refactor device name display in RoomPageSwitch widget
2025-04-21 10:43:22 +03:00
dc5ac9be5b Refactor device name display in RoomPageSwitch widget 2025-04-21 10:36:43 +03:00
5c9b30895f Merge pull request #86 from SyncrowIOT/SP-1286-FE-Add-Device-to-Routine-2-Gang
add tow gang and change gang device ui
2025-04-17 16:29:24 +03:00
06b14a3964 add tow gang and change gang device ui 2025-04-17 16:14:48 +03:00
3c92ea3047 Merge pull request #85 from SyncrowIOT/SP-1285-FE-Add-Device-to-Routine
Sp 1285 fe add device to routine
2025-04-17 10:42:06 +03:00
73d28a1800 Refactor Action class to use type annotations for actionExecutor and entityId 2025-04-17 10:41:01 +03:00
5493ca6fb0 Refactor device filtering logic to improve code readability 2025-04-17 10:38:25 +03:00
7005d8ba83 Refactor device filtering logic and improve code readability
- Extracted the logic for filtering implemented devices into a separate method `_getOnlyImplementedDevices`
- Created a set `allowedDevices` to store the allowed device types
- Updated the filtering logic to use the `allowedDevices` set for checking device types
- Removed unnecessary conditions for filtering devices

Fix nullability issues in `Action` model

- Added null checks for `actionExecutor`, `entityId`, `name`, `type`, and `productType` properties in the `fromJson` method of the `Action` model
- Set default values for `actionExecutor` and `entityId` if they are null
- Updated the type casting for `name`, `type`, and `productType` properties to avoid potential nullability issues
2025-04-17 10:16:10 +03:00
cb79627038 Merge pull request #83 from SyncrowIOT/SP-1397-FE-Create-Routine-SceneRoomsTabBarDevicesView-throws-TabBarController-initialization-error
Sp 1397 fe create routine scene rooms tab bar devices view throws tab bar controller initialization error
2025-04-17 09:47:46 +03:00
1cff69d496 change icon 2025-04-17 09:39:58 +03:00
60df77efad add OneGang product type to routine 2025-04-17 09:32:20 +03:00
9e84048f81 Merge pull request #84 from SyncrowIOT:SP-1416
fixed typo
2025-04-16 20:57:45 +04:00
99adb1c286 fixed typo 2025-04-16 20:57:13 +04:00
f2412aa867 refactor: extract device fetching logic into a separate method for improved readability 2025-04-16 16:10:36 +03:00
e4768c95aa refactor: rename tab change events and states for consistency, and to match blocs naming convention. 2025-04-16 16:07:30 +03:00
f25b4dbf6d implement SceneDevicesBodyTabBar for improved tab management in SceneDevicesBody. 2025-04-16 15:57:21 +03:00
9eff9ab371 refactor: consolidate device loading and error handling in SceneDevicesBody and implement SceneDevicesList widget 2025-04-16 15:46:56 +03:00
a2e68d6194 fix: restore title in DefaultScaffold for SceneRoomsTabBarDevicesView 2025-04-16 15:25:23 +03:00
94c94b170f fix: correct order of dispose method calls in SceneRoomsTabBarDevicesView 2025-04-16 15:24:47 +03:00
253cf15559 refactor: simplify SceneDevicesBody widget structure and improve loading indicator handling 2025-04-16 15:24:37 +03:00
443eea9421 SP-1397 2025-04-16 15:11:43 +03:00
87a2c08f64 Merge pull request #82 from SyncrowIOT/SP-1416
added client token login
2025-04-16 12:35:31 +04:00
dd66e7c747 added client token login 2025-04-16 12:02:19 +04:00
7af61d2f65 added client id and secret 2025-04-16 11:34:24 +04:00
f37eacb0ee Merge pull request #81 from SyncrowIOT/feat/update-additional-device-endpoints
updated endpoint for device
2025-04-14 15:11:36 +03:00
c7dcc297aa fix conflict 2025-04-14 15:11:02 +03:00
aefe5ad081 Merge branch 'dev' into feat/update-additional-device-endpoints 2025-04-14 15:10:42 +03:00
8d9af8519d Merge pull request #78 from SyncrowIOT/SP-1246
updated device endpoint
2025-04-14 14:58:09 +03:00
b1d52937c9 Merge branch 'dev' of https://github.com/SyncrowIOT/syncrow-app into feat/update-additional-device-endpoints 2025-04-14 10:31:09 +04:00
5fedf37421 updated endpoint for device 2025-04-14 10:30:48 +04:00
ccde857c29 Merge pull request #80 from SyncrowIOT/SP-1398-FE-in-the-wizerd-the-batch-control-title-doesn-t-represent-the-the-accurate-device-name
SP-1398-FE-in-the-wizerd-the-batch-control-title-doesn-t-represent-the-the-accurate-device-name
2025-04-13 16:23:49 +03:00
b2a8086e0e Merge pull request #79 from SyncrowIOT/sp-1268-rework-v2
Sp 1268 rework v2
2025-04-13 16:20:10 +03:00
408e78962c SP-1398 2025-04-13 16:18:49 +03:00
dcdbc02ca0 Adds AppLoadingIndicator widget and replaces CircularProgressIndicator in SceneView. 2025-04-13 15:50:52 +03:00
31025e9176 Refactors SceneView constructor and improves conditional rendering for automation list 2025-04-13 15:49:13 +03:00
8219de6821 Injects SceneBloc using the new factory. 2025-04-13 15:28:44 +03:00
fbdf3817ab Created a factory helper to create a SceneBloc. 2025-04-13 15:25:48 +03:00
17422edd0d sp-1268-rework-v2. 2025-04-13 15:21:20 +03:00
4c8f2c72df Merge branch 'dev' of https://github.com/SyncrowIOT/syncrow-app into SP-1246 2025-04-03 10:47:27 +04:00
fb867e5df3 updated device endpoint 2025-04-03 10:47:09 +04:00
9472390284 Merge pull request #76 from SyncrowIOT/bugifx/empty-subspace-routine-creation
fixed issue on empty subspace
2025-03-28 11:38:14 +04:00
731ba0f3d6 Merge pull request #77 from SyncrowIOT/SP-1268-FE-Implement-UX-Behavior-for-No-Tab-to-Run-Scene-in-Device-Screen
Sp 1268 fe implement ux behavior for no tab to run scene in device screen
2025-03-26 15:24:34 +03:00
56407c6426 indentation and trailing commas. 2025-03-26 13:49:54 +03:00
02d61ca0bb Refactor DevicesViewBody and SceneView to improve widget structure and replace CreateUnitWidget with EmptyDevicesWidget for better handling of empty states. 2025-03-26 13:44:49 +03:00
99ee4b9878 Add EmptyDevicesWidget to display message when no routines are available. 2025-03-26 13:34:07 +03:00
19edd0a275 Added /android/app/.cxx/ to .gitIgnore, because they're auto generated files that dont need to be checked into source control. 2025-03-26 13:14:23 +03:00
ef5e7c3154 fixed issue on empty subspace 2025-03-25 14:15:14 +04:00
80dd0f696f Merge pull request #75 from SyncrowIOT/SP-1245
updated endpoint for automation
2025-03-17 09:34:46 +04:00
a64a41548f updated delete endpoint for automation 2025-03-14 13:02:14 +04:00
0d50aa68fa updated endpoint for update automation 2025-03-14 12:58:12 +04:00
88aac86b10 updated endpoint for getting automation by id 2025-03-14 12:55:33 +04:00
0673548745 changed endpoint for getting automations by space 2025-03-14 12:53:29 +04:00
c2fc8fa0ae changed endpoint for create automation endpoint 2025-03-14 12:40:52 +04:00
cbf10bbf78 Merge pull request #74 from SyncrowIOT/real_time_app
Real time app
2025-03-03 17:34:34 +03:00
d95588ce84 remove unused code 2025-03-03 17:34:15 +03:00
7e2e591d71 remove unused code 2025-03-01 15:19:15 +03:00
2ec81bda9c connect the real time for all devices 2025-03-01 15:08:51 +03:00
3b0f51473c Merge pull request #73 from SyncrowIOT/SP-1190
Sp 1190
2025-02-26 12:20:06 +03:00
13757d89ee Merged with dev 2025-02-26 12:17:57 +03:00
d3068b8e14 changes in threeGang 2025-02-26 10:58:32 +03:00
7c5d7e1dda remove unused code 2025-02-25 12:45:23 +03:00
0a97a4867d disconnect real-time to some devices 2025-02-25 12:41:49 +03:00
6e55b488aa Merge pull request #72 from SyncrowIOT/feat/change-hardcode-projectid
updated project hardcoded values
2025-02-24 12:06:06 +03:00
22789234fe Sensitivity Start from 1 2025-02-23 16:30:50 +03:00
8393ec353a fetchDevices by projectUuid 2025-02-20 16:02:25 +03:00
0b45d61b25 Fixed list issue in the manage home screen 2025-02-20 10:50:47 +03:00
450b773921 set default values in the devices models instead of late, and fixed issues in the AC bloc 2025-02-20 04:13:37 +03:00
3f7f7ce49f updated project hardcoded values 2025-02-16 20:55:13 +04:00
2dc4e16a75 connect all devices to real-time and change the channel function 2025-02-16 14:54:39 +03:00
cd41720244 active the implemented device 2025-02-16 10:04:34 +03:00
67209961b4 added project model 2025-02-15 11:54:02 +04:00
9098276223 Merge pull request #71 from SyncrowIOT/fixes_bugs_sprint15
fixes bugs and add project id staging
2025-02-12 12:47:09 +03:00
36dfe2c85e change the key 2025-02-12 12:06:00 +03:00
94 changed files with 3868 additions and 1838 deletions

View File

@ -1,3 +1,5 @@
ENV_NAME=development
BASE_URL=https://syncrow-dev.azurewebsites.net
projectId=0e62577c-06fa-41b9-8a92-99a21fbaf51c
PROJECT_ID=0e62577c-06fa-41b9-8a92-99a21fbaf51c
CLIENT_ID=c024573d191a327ce74db7d4502fdc29
CLIENT_SECRET=fec6ccbc33664f94a3b84a45c7cceef3f3ebd1613ef4307db8946ede530cd1ed

View File

@ -1,3 +1,3 @@
ENV_NAME=production
BASE_URL=https://syncrow-staging.azurewebsites.net
projectId=bcda711e-9fc2-4168-a05e-171b4026d1ff
PROJECT_ID=bcda711e-9fc2-4168-a05e-171b4026d1ff

View File

@ -1,3 +1,3 @@
ENV_NAME=staging
BASE_URL=https://syncrow-staging.azurewebsites.net
projectId=bcda711e-9fc2-4168-a05e-171b4026d1ff
PROJECT_ID=bcda711e-9fc2-4168-a05e-171b4026d1ff

1
.gitignore vendored
View File

@ -42,3 +42,4 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
/android/app/.cxx/

View File

@ -0,0 +1,10 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_7302_4118)">
<path d="M11.1049 10.0001L19.7712 1.33381C20.0763 1.02869 20.0763 0.534007 19.7712 0.228929C19.4661 -0.0761485 18.9714 -0.0761876 18.6663 0.228929L9.99999 8.89524L1.33372 0.228929C1.0286 -0.0761876 0.533915 -0.0761876 0.228837 0.228929C-0.0762401 0.534046 -0.0762792 1.02873 0.228837 1.33381L8.89511 10.0001L0.228837 18.6664C-0.0762792 18.9715 -0.0762792 19.4662 0.228837 19.7713C0.381376 19.9238 0.581337 20.0001 0.781297 20.0001C0.981258 20.0001 1.18118 19.9238 1.33376 19.7713L9.99999 11.105L18.6663 19.7713C18.8188 19.9238 19.0188 20.0001 19.2187 20.0001C19.4187 20.0001 19.6186 19.9238 19.7712 19.7713C20.0763 19.4662 20.0763 18.9715 19.7712 18.6664L11.1049 10.0001Z" fill="#999999"/>
</g>
<defs>
<clipPath id="clip0_7302_4118">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 939 B

View File

@ -0,0 +1,10 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_7302_4149)">
<path d="M19.9969 4.94279C19.986 4.83232 19.943 4.72146 19.8674 4.62924C19.8382 4.59358 20.1367 4.89431 15.4141 0.17176C15.3015 0.0591838 15.1487 8.30277e-05 14.9996 0.00012209C14.6443 0.00012209 2.11177 0.00012209 1.75779 0.00012209C0.788544 0.00012209 0 0.788666 0 1.75791V18.2421C0 19.2113 0.788544 19.9998 1.75779 19.9998H18.2419C19.2112 19.9998 19.9997 19.2113 19.9997 18.2421C19.9998 4.01624 20.0013 4.98771 19.9969 4.94279ZM13.4764 1.17198V5.00005C13.4764 5.32314 13.2136 5.58598 12.8905 5.58598H12.1483V1.17198H13.4764ZM10.9765 1.17198V5.58598H5.54684C5.22376 5.58598 4.96091 5.32314 4.96091 5.00005V1.17198H10.9765ZM13.4764 12.539H4.96091V11.7968C4.96091 11.4738 5.22376 11.2109 5.54684 11.2109H12.8905C13.2136 11.2109 13.4764 11.4738 13.4764 11.7968V12.539ZM4.96091 18.828V13.7109H13.4764V18.828H4.96091ZM18.8279 18.2421C18.8279 18.5651 18.5651 18.828 18.242 18.828H14.6483C14.6483 18.0641 14.6483 12.6676 14.6483 11.7968C14.6483 10.8276 13.8597 10.039 12.8905 10.039H5.54684C4.57759 10.039 3.78905 10.8276 3.78905 11.7968V18.828H1.75783C1.43475 18.828 1.1719 18.5651 1.1719 18.2421V1.75791C1.1719 1.43483 1.43475 1.17198 1.75783 1.17198H3.78905V5.00005C3.78905 5.9693 4.57759 6.75784 5.54684 6.75784H12.8905C13.8597 6.75784 14.6483 5.9693 14.6483 5.00005V1.17198H14.7571L18.8279 5.24278V18.2421Z" fill="#023DFE" fill-opacity="0.6"/>
</g>
<defs>
<clipPath id="clip0_7302_4149">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -10,6 +10,7 @@ import 'package:share_plus/share_plus.dart';
import 'package:syncrow_app/features/app_layout/model/permission_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/auth/model/project_model.dart';
import 'package:syncrow_app/features/auth/model/user_model.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
@ -28,6 +29,7 @@ import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/profile_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
part 'home_state.dart';
@ -67,6 +69,8 @@ class HomeCubit extends Cubit<HomeState> {
var uuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
user = await ProfileApi().fetchUserInfo(uuid);
project = user?.project;
emit(HomeUserInfoLoaded(user!));
} catch (e) {
return;
@ -175,6 +179,8 @@ class HomeCubit extends Cubit<HomeState> {
SubSpaceModel? selectedRoom;
Project? project;
PageController devicesPageController = PageController();
PageController roomsPageController = PageController();
@ -324,8 +330,8 @@ class HomeCubit extends Cubit<HomeState> {
//////////////////////////////////////// API ////////////////////////////////////////
generateInvitation(SpaceModel unit) async {
try {
final invitationCode =
await SpacesAPI.generateInvitationCode(unit.id, unit.community.uuid);
final invitationCode = await SpacesAPI.generateInvitationCode(unit.id,
unit.community.uuid, project?.uuid ?? TempConst.projectIdDev);
if (invitationCode.isNotEmpty) {
Share.share('The invitation code is $invitationCode');
CustomSnackBar.displaySnackBar(
@ -380,8 +386,10 @@ class HomeCubit extends Cubit<HomeState> {
fetchRoomsByUnitId(SpaceModel space) async {
emitSafe(GetSpaceRoomsLoading());
try {
space.subspaces =
await SpacesAPI.getSubSpaceBySpaceId(space.community.uuid, space.id);
space.subspaces = await SpacesAPI.getSubSpaceBySpaceId(
space.community.uuid,
space.id,
project?.uuid ?? TempConst.projectIdDev);
} catch (failure) {
emitSafe(GetSpaceRoomsError(failure.toString()));
return;
@ -414,7 +422,6 @@ class HomeCubit extends Cubit<HomeState> {
emitSafe(ActivationError(errMessage: errorMsg));
return false;
}
}
/////////////////////////////////////// Nav ///////////////////////////////////////

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:syncrow_app/features/auth/model/login_with_email_model.dart';
import 'package:syncrow_app/features/auth/model/signup_model.dart';
@ -217,9 +218,22 @@ class AuthCubit extends Cubit<AuthState> {
signUp() async {
emit(AuthLoginLoading());
final response;
final clientId = dotenv.env['CLIENT_ID'] ?? '';
final clientSecret = dotenv.env['CLIENT_SECRET'] ?? '';
try {
List<String> userFullName = fullName.split(' ');
final clientToken = await AuthenticationAPI.fetchClientToken(
clientId: clientId,
clientSecret: clientSecret,
);
final accessToken = clientToken['accessToken'];
response = await AuthenticationAPI.signUp(
accessToken: accessToken,
model: SignUpModel(
hasAcceptedAppAgreement: true,
email: email.toLowerCase(),

View File

@ -0,0 +1,27 @@
class Project {
final String uuid;
final String name;
final String description;
const Project({
required this.uuid,
required this.name,
required this.description,
});
factory Project.fromJson(Map<String, dynamic> json) {
return Project(
uuid: json['uuid'] as String,
name: json['name'] as String,
description: json['description'] as String,
);
}
Map<String, dynamic> toJson() {
return {
'uuid': uuid,
'name': name,
'description': description,
};
}
}

View File

@ -1,5 +1,6 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/auth/model/token.dart';
class UserModel {
@ -20,6 +21,7 @@ class UserModel {
final bool? hasAcceptedAppAgreement;
final DateTime? appAgreementAcceptedAt;
final Role? role;
final Project? project;
UserModel({
required this.uuid,
@ -38,6 +40,7 @@ class UserModel {
required this.hasAcceptedAppAgreement,
required this.appAgreementAcceptedAt,
required this.role,
required this.project,
});
factory UserModel.fromJson(Map<String, dynamic> json) {
@ -62,6 +65,8 @@ class UserModel {
? DateTime.parse(json['appAgreementAcceptedAt'])
: null,
role: json['role'] != null ? Role.fromJson(json['role']) : null,
project:
json['project'] != null ? Project.fromJson(json['project']) : null,
);
}
@ -88,7 +93,7 @@ class UserModel {
? DateTime.parse(tempJson['appAgreementAcceptedAt'])
: null,
role: tempJson['role'] != null ? Role.fromJson(tempJson['role']) : null,
);
project: null);
}
static Uint8List? decodeBase64Image(String? base64String) {
@ -137,8 +142,10 @@ class Role {
factory Role.fromJson(Map<String, dynamic> json) {
return Role(
uuid: json['uuid'],
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null,
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null,
createdAt:
json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null,
updatedAt:
json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null,
type: json['type'],
);
}

View File

@ -0,0 +1,19 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class ProjectCubit extends Cubit<String?> {
final FlutterSecureStorage storage;
static const String projectKey = "selected_project_uuid";
ProjectCubit(this.storage) : super(null);
Future<void> setProjectUUID(String newUUID) async {
await storage.write(key: projectKey, value: newUUID);
emit(newUUID);
}
Future<void> clearProjectUUID() async {
await storage.delete(key: projectKey);
emit(null);
}
}

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
@ -16,6 +17,7 @@ import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/scene_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class SixSceneBloc extends Bloc<SixSceneEvent, SixSceneState> {
@ -112,8 +114,9 @@ class SixSceneBloc extends Bloc<SixSceneEvent, SixSceneState> {
FetchRoomsEvent event, Emitter<SixSceneState> emit) async {
try {
emit(SixSceneLoadingState());
Project? project = HomeCubit.getInstance().project;
roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
event.unit.community.uuid, event.unit.id, project?.uuid ?? TempConst.projectIdDev);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(SixSceneFailedState(errorMessage: e.toString()));
@ -125,12 +128,14 @@ class SixSceneBloc extends Bloc<SixSceneEvent, SixSceneState> {
try {
emit(SixSceneLoadingState());
if (_hasSelectionChanged) {
Project? project = HomeCubit.getInstance().project;
await HomeManagementAPI.assignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, sixSceneId);
event.unit.community.uuid, event.unit.id, event.roomId, sixSceneId, project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
allDevices.forEach((element) {
allDevicesIds.add(element.uuid!);
@ -341,8 +346,10 @@ class SixSceneBloc extends Bloc<SixSceneEvent, SixSceneState> {
emit(SixSceneLoadingState());
try {
Project? project = HomeCubit.getInstance().project;
allScenes = await SceneApi.getScenesByUnitId(
event.unitId, event.unit.community.uuid,
event.unitId, event.unit.community.uuid, project?.uuid ?? TempConst.projectIdDev,
showInDevice: event.showInDevice);
filteredScenes = allScenes;

View File

@ -4,7 +4,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
@ -28,7 +27,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
bool allAcsPage = false;
bool allAcsOn = true;
bool allTempSame = true;
int globalTemp = 25;
int globalTemp = 250;
Timer? _timer;
ACsBloc({required this.acId}) : super(AcsInitialState()) {
@ -69,11 +68,10 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus =
AcStatusModel.fromJson(response['productUuid'], statusModelList);
deviceStatus = AcStatusModel.fromJson(response['productUuid'], statusModelList);
emit(GetAcStatusState(acStatusModel: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
_listenToChanges(acId);
}
} catch (e) {
emit(AcsFailedState(errorMessage: e.toString()));
@ -81,29 +79,38 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(acId) {
try {
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$acId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) {
_streamSubscription = stream.listen((DatabaseEvent event) {
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList
.add(StatusModel(code: element['code'], value: element['value']));
statusList.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus =
AcStatusModel.fromJson(usersMap['productUuid'], statusList);
add(AcUpdated());
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_onAcUpdated(AcUpdated event, Emitter<AcsState> emit) {
emit(GetAcStatusState(acStatusModel: deviceStatus));
}
@ -115,15 +122,16 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', 'AC');
for (int i = 0; i < devicesList.length; i++) {
_listenToChanges(devicesList[i].uuid);
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatusList.add(
AcStatusModel.fromJson(response['productUuid'], statusModelList));
deviceStatusList.add(AcStatusModel.fromJson(devicesList[i].uuid ?? '', statusModelList));
}
_setAllAcsTempsAndSwitches();
}
@ -132,7 +140,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.acSwitch = acSwitchValue;
}
}
@ -145,8 +153,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
emit(AcModifyingState(acStatusModel: deviceStatus));
}
await _runDeBouncerForOneDevice(
deviceId: event.deviceId, code: 'switch', value: acSwitchValue);
await _runDeBouncerForOneDevice(deviceId: event.deviceId, code: 'switch', value: acSwitchValue);
}
void _changeAllAcSwitch(ChangeAllSwitch event, Emitter<AcsState> emit) async {
@ -207,8 +214,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
deviceStatus.childLock = lockValue;
emit(AcModifyingState(acStatusModel: deviceStatus));
await _runDeBouncerForOneDevice(
deviceId: acId, code: 'child_lock', value: lockValue);
await _runDeBouncerForOneDevice(deviceId: acId, code: 'child_lock', value: lockValue);
}
void _increaseCoolTo(IncreaseCoolToTemp event, Emitter<AcsState> emit) async {
@ -224,7 +230,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.tempSet = value;
}
}
@ -236,8 +242,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
emit(AcModifyingState(acStatusModel: deviceStatus));
}
await _runDeBouncerForOneDevice(
deviceId: event.deviceId, code: 'temp_set', value: value);
await _runDeBouncerForOneDevice(deviceId: event.deviceId, code: 'temp_set', value: value);
}
void _decreaseCoolTo(DecreaseCoolToTemp event, Emitter<AcsState> emit) async {
@ -253,7 +258,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.tempSet = value;
}
}
@ -265,8 +270,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
emit(AcModifyingState(acStatusModel: deviceStatus));
}
await _runDeBouncerForOneDevice(
deviceId: event.deviceId, code: 'temp_set', value: value);
await _runDeBouncerForOneDevice(deviceId: event.deviceId, code: 'temp_set', value: value);
}
void _changeAcMode(ChangeAcMode event, Emitter<AcsState> emit) async {
@ -274,7 +278,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.modeString = getACModeString(tempMode);
ac.acMode = AcStatusModel.getACMode(getACModeString(tempMode));
}
@ -288,9 +292,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
}
await _runDeBouncerForOneDevice(
deviceId: event.deviceId,
code: 'mode',
value: getACModeString(tempMode));
deviceId: event.deviceId, code: 'mode', value: getACModeString(tempMode));
}
void _changeFanSpeed(ChangeFanSpeed event, Emitter<AcsState> emit) async {
@ -301,25 +303,21 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.fanSpeedsString = getNextFanSpeedKey(fanSpeed);
ac.acFanSpeed =
AcStatusModel.getFanSpeed(getNextFanSpeedKey(fanSpeed));
ac.acFanSpeed = AcStatusModel.getFanSpeed(getNextFanSpeedKey(fanSpeed));
}
}
_emitAcsStatus(emit);
} else {
emit(AcChangeLoading(acStatusModel: deviceStatus));
deviceStatus.fanSpeedsString = getNextFanSpeedKey(fanSpeed);
deviceStatus.acFanSpeed =
AcStatusModel.getFanSpeed(getNextFanSpeedKey(fanSpeed));
deviceStatus.acFanSpeed = AcStatusModel.getFanSpeed(getNextFanSpeedKey(fanSpeed));
emit(AcModifyingState(acStatusModel: deviceStatus));
}
await _runDeBouncerForOneDevice(
deviceId: event.deviceId,
code: 'level',
value: getNextFanSpeedKey(fanSpeed));
deviceId: event.deviceId, code: 'level', value: getNextFanSpeedKey(fanSpeed));
}
String getACModeString(TempModes value) {
@ -338,17 +336,15 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
allAcsOn = true;
allTempSame = true;
if (deviceStatusList.isNotEmpty) {
int temp = deviceStatusList[0].tempSet;
deviceStatusList.firstWhere((element) {
int temp = deviceStatusList.first.tempSet;
for (var element in deviceStatusList) {
if (!element.acSwitch) {
allAcsOn = false;
}
if (element.tempSet != temp) {
allTempSame = false;
}
return true;
});
}
if (allTempSame) {
globalTemp = temp;
}
@ -364,8 +360,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
for (int i = 0; i < deviceStatusList.length; i++) {
try {
await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: devicesList[i].uuid, code: code, value: value),
DeviceControlModel(deviceId: devicesList[i].uuid, code: code, value: value),
devicesList[i].uuid ?? '');
} catch (_) {
await Future.delayed(const Duration(milliseconds: 500));
@ -387,10 +382,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
_timer = Timer(const Duration(seconds: 1), () async {
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: allAcsPage ? deviceId : acId,
code: code,
value: value),
DeviceControlModel(deviceId: allAcsPage ? deviceId : acId, code: code, value: value),
allAcsPage ? deviceId : acId);
if (!response['success']) {
@ -407,8 +399,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (value >= 20 && value <= 30) {
return true;
} else {
emit(const AcsFailedState(
errorMessage: 'The temperature must be between 20 and 30'));
emit(const AcsFailedState(errorMessage: 'The temperature must be between 20 and 30'));
emit(GetAllAcsStatusState(
allAcsStatues: deviceStatusList,
allAcs: devicesList,
@ -434,9 +425,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
try {
seconds = event.seconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: acId, code: 'countdown_time', value: event.duration),
acId);
DeviceControlModel(deviceId: acId, code: 'countdown_time', value: event.duration), acId);
if (response['success'] ?? false) {
deviceStatus.countdown1 = seconds;
@ -463,8 +452,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus =
AcStatusModel.fromJson(response['productUuid'], statusModelList);
deviceStatus = AcStatusModel.fromJson(response['productUuid'], statusModelList);
deviceStatus.countdown1;
var duration;
if (deviceStatus.countdown1 == 5) {

View File

@ -1,4 +1,4 @@
import 'dart:convert';
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
@ -35,35 +35,49 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
}
deviceStatus = CeilingSensorModel.fromJson(statusModelList);
emit(UpdateState(ceilingSensorModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
Timer? _timer;
void _listenToChanges() {
try {
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) {
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = CeilingSensorModel.fromJson(statusList);
if (!isClosed) {
add(CeilingSensorUpdated());
}
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_onCeilingSensorUpdated(
CeilingSensorUpdated event, Emitter<CeilingSensorState> emit) {
emit(UpdateState(ceilingSensorModel: deviceStatus));

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:firebase_database/firebase_database.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/bloc/curtain_bloc/curtain_event.dart';
@ -30,6 +32,7 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
on<InitialWizardEvent>(_fetchWizardStatus);
on<GroupAllOffEvent>(_groupAllOff);
on<GroupAllOnEvent>(_groupAllOn);
on<UpdateCurtainEvent>(_updateCurtain);
}
Future<void> _onOpenCurtain(
@ -161,7 +164,10 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
void _fetchStatus(InitCurtain event, Emitter<CurtainState> emit) async {
try {
emit(CurtainLoadingState());
_listenToChanges(curtainId);
var response = await DevicesAPI.getDeviceStatus(curtainId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -169,7 +175,6 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
openPercentage = double.tryParse(statusModelList[1].value.toString())!;
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
emit(CurtainsOpening(
curtainWidth: curtainWidth,
blindHeight: blindHeight,
@ -181,6 +186,76 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
}
}
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(curtainId) {
try {
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$curtainId');
Stream<DatabaseEvent> stream = ref.onValue;
_streamSubscription = stream.listen((DatabaseEvent event) {
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
openPercentage = double.tryParse(statusList[1].value.toString())!;
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
add(UpdateCurtainEvent());
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
// _listenToChanges(curtainId) {
// try {
// print('curtainId=$curtainId');
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$curtainId');
// Stream<DatabaseEvent> stream = ref.onValue;
// stream.listen((DatabaseEvent event) async {
// if (_timer != null) {
// await Future.delayed(const Duration(seconds: 2));
// }
// Map<dynamic, dynamic> usersMap =
// event.snapshot.value as Map<dynamic, dynamic>;
// List<StatusModel> statusModelList = [];
// for (var status in usersMap['status']) {
// statusModelList.add(StatusModel.fromJson(status));
// print('statusModelList==${statusModelList}');
// }
// openPercentage = double.tryParse(statusModelList[1].value.toString())!;
// curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
// blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
// add(UpdateCurtainEvent());
// });
// } catch (_) {}
// }
_updateCurtain(UpdateCurtainEvent event, Emitter<CurtainState> emit) {
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
emit(CurtainsOpening(
curtainWidth: curtainWidth,
blindHeight: blindHeight,
openPercentage: openPercentage,
));
}
List<GroupCurtainModel> groupList = [];
bool allSwitchesOn = true;
List<DeviceModel> devicesList = [];

View File

@ -33,6 +33,7 @@ class InitCurtain extends CurtainEvent {}
class PauseCurtain extends CurtainEvent {}
class useCurtainEvent extends CurtainEvent {}
class InitialWizardEvent extends CurtainEvent {}
class UpdateCurtainEvent extends CurtainEvent {}
class ChangeFirstWizardSwitchStatusEvent extends CurtainEvent {

View File

@ -2,6 +2,8 @@ import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_event.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart';
@ -10,6 +12,7 @@ import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
@ -27,11 +30,16 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
static List<DevicesCategoryModel>? allCategories;
Future<void> _onFetchAllDevices(FetchAllDevices event, Emitter<DeviceManagerState> emit) async {
Future<void> _onFetchAllDevices(
FetchAllDevices event, Emitter<DeviceManagerState> emit) async {
emit(state.copyWith(loading: true));
try {
final allDevices = await HomeManagementAPI.fetchDevicesByUnitId();
emit(state.copyWith(devices: _getOnlyImplementedDevices(allDevices), loading: false));
Project? project = HomeCubit.getInstance().project;
final allDevices = await HomeManagementAPI.fetchDevicesByUnitId(
project?.uuid ?? TempConst.projectIdDev);
emit(state.copyWith(
devices: _getOnlyImplementedDevices(allDevices), loading: false));
} catch (e) {
emit(state.copyWith(error: e.toString(), loading: false));
}
@ -41,26 +49,31 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
FetchDevicesByRoomId event, Emitter<DeviceManagerState> emit) async {
emit(state.copyWith(loading: true));
try {
Project? project = HomeCubit.getInstance().project;
final devices = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId,
);
projectId: project?.uuid ?? TempConst.projectIdDev);
emit(state.copyWith(devices: _getOnlyImplementedDevices(devices), loading: false));
emit(state.copyWith(
devices: _getOnlyImplementedDevices(devices), loading: false));
} catch (e) {
emit(state.copyWith(error: e.toString(), loading: false));
}
}
void _onSelectCategory(SelectCategory event, Emitter<DeviceManagerState> emit) {
void _onSelectCategory(
SelectCategory event, Emitter<DeviceManagerState> emit) {
for (var i = 0; i < allCategories!.length; i++) {
allCategories![i].isSelected = i == event.index;
}
emit(state.copyWith(categoryChanged: true));
}
void _onUnselectAllCategories(UnselectAllCategories event, Emitter<DeviceManagerState> emit) {
void _onUnselectAllCategories(
UnselectAllCategories event, Emitter<DeviceManagerState> emit) {
for (var category in allCategories!) {
category.isSelected = false;
}
@ -104,7 +117,8 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
_updateDevicesStatus(category, emit);
}
void _onTurnOnOffDevice(TurnOnOffDevice event, Emitter<DeviceManagerState> emit) {
void _onTurnOnOffDevice(
TurnOnOffDevice event, Emitter<DeviceManagerState> emit) {
var device = event.device;
device.isOnline = !device.isOnline!;
DevicesCategoryModel category = allCategories!.firstWhere((category) {
@ -127,7 +141,8 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
emit(state.copyWith(categoryChanged: true)); // Set category changed state
}
void _updateDevicesStatus(DevicesCategoryModel category, Emitter<DeviceManagerState> emit) {
void _updateDevicesStatus(
DevicesCategoryModel category, Emitter<DeviceManagerState> emit) {
if (category.devices != null && category.devices!.isNotEmpty) {
bool? tempStatus = category.devices![0].isOnline;
for (var device in category.devices!) {
@ -147,24 +162,27 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
try {
final deviceFunctions = await DevicesAPI.deviceFunctions(event.deviceId);
emit(state.copyWith(functionsLoading: false, deviceFunctions: deviceFunctions));
emit(state.copyWith(
functionsLoading: false, deviceFunctions: deviceFunctions));
} catch (e) {
emit(state.copyWith(functionsLoading: false, error: e.toString()));
}
}
_getOnlyImplementedDevices(List<DeviceModel> devices) {
List<DeviceModel> implementedDevices = [];
for (int i = 0; i < devices.length; i++) {
if (devices[i].productType == DeviceType.AC ||
devices[i].productType == DeviceType.DoorLock ||
devices[i].productType == DeviceType.Gateway ||
devices[i].productType == DeviceType.WallSensor ||
devices[i].productType == DeviceType.CeilingSensor ||
devices[i].productType == DeviceType.ThreeGang) {
implementedDevices.add(devices[i]);
}
}
return implementedDevices;
List<DeviceModel> _getOnlyImplementedDevices(List<DeviceModel> devices) {
const allowedDeviceTypes = {
DeviceType.AC,
DeviceType.DoorLock,
DeviceType.Gateway,
DeviceType.WallSensor,
DeviceType.CeilingSensor,
DeviceType.ThreeGang,
DeviceType.OneGang,
DeviceType.TwoGang
};
return devices
.where((device) => allowedDeviceTypes.contains(device.productType))
.toList();
}
}

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/device_settings_bloc/device_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/device_settings_bloc/device_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
@ -18,6 +19,7 @@ import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class DeviceSettingBloc extends Bloc<DeviceSettingEvent, DeviceSettingState> {
@ -349,13 +351,20 @@ class DeviceSettingBloc extends Bloc<DeviceSettingEvent, DeviceSettingState> {
AssignRoomEvent event, Emitter<DeviceSettingState> emit) async {
try {
emit(DeviceSettingLoadingState());
Project? project = HomeCubit.getInstance().project;
if (_hasSelectionChanged) {
await HomeManagementAPI.assignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, deviceId);
event.unit.community.uuid,
event.unit.id,
event.roomId,
deviceId,
project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
allDevices.forEach((element) {
allDevicesIds.add(element.uuid!);
@ -375,8 +384,12 @@ class DeviceSettingBloc extends Bloc<DeviceSettingEvent, DeviceSettingState> {
FetchRoomsEvent event, Emitter<DeviceSettingState> emit) async {
try {
emit(DeviceSettingLoadingState());
Project? project = HomeCubit.getInstance().project;
roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
event.unit.community.uuid,
event.unit.id,
project?.uuid ?? TempConst.projectIdDev);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(

View File

@ -1,10 +1,14 @@
// ignore_for_file: constant_identifier_names, unused_import
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.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/model/space_model.dart';
import 'package:syncrow_app/features/auth/model/project_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';
@ -19,6 +23,7 @@ import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/network_exception.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
part 'devices_state.dart';
@ -61,6 +66,43 @@ class DevicesCubit extends Cubit<DevicesState> {
}
}
Timer? _timer;
final Map<String, StreamSubscription<DatabaseEvent>> _deviceSubscriptions =
{};
void _listenToChanges(deviceId) {
try {
if (_deviceSubscriptions.containsKey(deviceId)) {
_deviceSubscriptions[deviceId]?.cancel();
_deviceSubscriptions.remove(deviceId);
}
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
final subscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
// print('object-----${usersMap['status']}');
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
emitSafe(GetDevicesLoading());
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceId);
if (deviceIndex != -1) {
allDevices[deviceIndex].status = statusList;
}
emitSafe(GetDevicesSuccess(allDevices));
});
_deviceSubscriptions[deviceId] = subscription;
} catch (_) {}
}
static DevicesCubit get(context) => BlocProvider.of(context);
List<DevicesCategoryModel>? allCategories;
@ -309,11 +351,14 @@ class DevicesCubit extends Cubit<DevicesState> {
.subspaces
.indexWhere((element) => element.id == roomId);
try {
Project? project = HomeCubit.getInstance().project;
HomeCubit.getInstance().selectedSpace!.subspaces[roomIndex].devices =
await DevicesAPI.getDevicesByRoomId(
communityUuid: unit!.community.uuid,
spaceUuid: unit.id,
roomId: roomId);
roomId: roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
} catch (e) {
emitSafe(GetDevicesError(e.toString()));
return;
@ -410,11 +455,26 @@ class DevicesCubit extends Cubit<DevicesState> {
Future<void> fetchAllDevices(SpaceModel? unit) async {
emitSafe(GetDevicesLoading());
try {
Project? project = HomeCubit.getInstance().project;
final devices = await DevicesAPI.getAllDevices(
communityUuid: unit!.community.uuid,
spaceUuid: unit.id,
);
projectId: project?.uuid ?? TempConst.projectIdDev);
allDevices = devices;
for (var deviceId in allDevices) {
if (deviceId.type == "3G" ||
deviceId.type == "2G" ||
deviceId.type == "1G" ||
deviceId.type == "3GT" ||
deviceId.type == "2GT" ||
deviceId.type == "1GT" ||
deviceId.type == "WH" ||
deviceId.type == "CUR" ||
deviceId.type == "AC") {
_listenToChanges(deviceId.uuid);
}
}
emitSafe(GetDevicesSuccess(allDevices));
} catch (e) {
emitSafe(GetDevicesError(e.toString()));
@ -473,25 +533,35 @@ class DevicesCubit extends Cubit<DevicesState> {
}
final device = allDevices[deviceIndex];
final switches = ['switch_1', 'switch_2', 'switch_3'];
final anySwitchOff = device.status.any(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == false),
);
final targetState = anySwitchOff ? true : false;
for (final switchCode in switches) {
final statusIndex =
device.status.indexWhere((s) => s.code == switchCode);
if (statusIndex != -1) {
final toggledValue = control.value;
final currentValue = device.status[statusIndex].value ?? false;
if (!targetState && !currentValue) {
continue;
}
final controlRequest = DeviceControlModel(
code: switchCode, value: toggledValue, deviceId: deviceUuid);
code: switchCode, value: targetState, deviceId: deviceUuid);
final response =
await DevicesAPI.controlDevice(controlRequest, deviceUuid);
if (response['success'] != true) {
throw Exception('Failed to toggle $switchCode');
}
device.status[statusIndex].value = toggledValue;
device.status[statusIndex].value = targetState;
}
}
final anySwitchOff = device.status.any(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == false),
device.toggleStatus = device.status.every(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == true),
);
device.toggleStatus = !anySwitchOff;
allDevices[deviceIndex] = device;
emit(DeviceControlSuccess(code: control.code));
} catch (failure) {
@ -590,7 +660,6 @@ class DevicesCubit extends Cubit<DevicesState> {
code: 'switch_1', value: toggledValue, deviceId: deviceUuid);
final response =
await DevicesAPI.controlDevice(controlRequest, deviceUuid);
print(response);
if (response['result'] != true) {
throw Exception('Failed to toggle switch_1');
}

View File

@ -21,13 +21,14 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
on<ToggleClosingReminderEvent>(_toggleClosingReminder);
on<ToggleDoorAlarmEvent>(_toggleDoorAlarm);
}
Timer? _timer;
bool lowBattery = false;
bool closingReminder = false;
bool doorAlarm = false;
DoorSensorModel deviceStatus = DoorSensorModel(doorContactState: false, batteryPercentage: 0);
DoorSensorModel deviceStatus =
DoorSensorModel(doorContactState: false, batteryPercentage: 0);
void _fetchStatus(DoorSensorInitial event, Emitter<DoorSensorState> emit) async {
void _fetchStatus(
DoorSensorInitial event, Emitter<DoorSensorState> emit) async {
emit(DoorSensorLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(DSId);
@ -40,7 +41,7 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
);
emit(UpdateState(doorSensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(DoorSensorFailedState(errorMessage: e.toString()));
return;
@ -48,7 +49,8 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
}
// Toggle functions for each switch
void _toggleLowBattery(ToggleLowBatteryEvent event, Emitter<DoorSensorState> emit) async {
void _toggleLowBattery(
ToggleLowBatteryEvent event, Emitter<DoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
lowBattery = event.isLowBatteryEnabled;
@ -89,7 +91,8 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
}
}
void _toggleDoorAlarm(ToggleDoorAlarmEvent event, Emitter<DoorSensorState> emit) async {
void _toggleDoorAlarm(
ToggleDoorAlarmEvent event, Emitter<DoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
doorAlarm = event.isDoorAlarmEnabled;
@ -108,9 +111,11 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
}
}
DeviceReport recordGroups = DeviceReport(startTime: '0', endTime: '0', data: []);
DeviceReport recordGroups =
DeviceReport(startTime: '0', endTime: '0', data: []);
Future<void> fetchLogsForLastMonth(ReportLogsInitial event, Emitter<DoorSensorState> emit) async {
Future<void> fetchLogsForLastMonth(
ReportLogsInitial event, Emitter<DoorSensorState> emit) async {
DateTime now = DateTime.now();
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
@ -133,22 +138,27 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
}
}
_listenToChanges() {
// real-time database
Timer? _timer;
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$DSId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$DSId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: true));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = DoorSensorModel.fromJson(statusList);
if (!isClosed) {
add(
@ -158,4 +168,11 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
}

View File

@ -1,6 +1,8 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
@ -14,6 +16,7 @@ import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/scene_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
@ -230,6 +233,7 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
deviceStatus = FourSceneModelState.fromJson(
statusModelList,
);
// _listenToChanges();
add(const FourSceneSwitchInitial());
} catch (e) {
emit(FourSceneFailedState(errorMessage: e.toString()));
@ -299,9 +303,11 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
LoadScenes event, Emitter<FourSceneState> emit) async {
emit(FourSceneLoadingState());
try {
Project? project = HomeCubit.getInstance().project;
if (event.unitId.isNotEmpty) {
allScenes = await SceneApi.getScenesByUnitId(
event.unitId, event.unit.community.uuid,
event.unitId, event.unit.community.uuid, project?.uuid ?? TempConst.projectIdDev,
showInDevice: event.showInDevice);
filteredScenes = allScenes;
@ -327,4 +333,33 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
}).toList();
emit(SearchResultsState());
}
// Real-time database
// Timer? _timer;
// _listenToChanges() {
// try {
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$fourSceneId');
// Stream<DatabaseEvent> stream = ref.onValue;
// stream.listen((DatabaseEvent event) async {
// if (_timer != null) {
// await Future.delayed(const Duration(seconds: 2));
// }
// Map<dynamic, dynamic> usersMap =
// event.snapshot.value as Map<dynamic, dynamic>;
// List<StatusModel> statusList = [];
// usersMap['status'].forEach((element) {
// statusList.add(StatusModel(code: element['code'], value: true));
// });
// deviceStatus = FourSceneModelState.fromJson(statusList);
// // if (!isClosed) {
// // add(
// // DoorSensorSwitch(switchD: deviceStatus.doorContactState),
// // );
// // }
// });
// } catch (_) {}
// }
}

View File

@ -42,7 +42,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
on<ToggleAlarmEvent>(_toggleAlarmEvent);
on<DeleteScheduleEvent>(deleteSchedule);
//_toggleAlarmEvent
on<UpdateStateEvent>(_updateState);
}
void _onClose(OnClose event, Emitter<GarageDoorSensorState> emit) {
_timer?.cancel();
@ -81,7 +82,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
toggleDoor = deviceStatus.switch1;
emit(UpdateState(garageSensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(GarageDoorFailedState(errorMessage: e.toString()));
return;
@ -180,33 +181,59 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
_listenToChanges() {
// Real-time db
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$GDId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
await Future.delayed(const Duration(seconds: 1));
}
if (event.snapshot.value != null) {
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: true));
});
deviceStatus = GarageDoorModel.fromJson(statusList);
if (!isClosed) {
// add(
// DoorSensorSwitch(switchD: deviceStatus.doorContactState),
// );
usersMap['status'].forEach((element) {
statusList.add(
StatusModel(code: element['code'], value: element['value']));
});
deviceStatus.tr_timecon = statusList
.firstWhere((status) => status.code == "tr_timecon",
orElse: () => StatusModel(code: "tr_timecon", value: 0))
.value as int;
deviceStatus.switch1 = statusList
.firstWhere((status) => status.code == "switch_1",
orElse: () => StatusModel(code: "switch_1", value: false))
.value as bool;
secondSelected = deviceStatus.tr_timecon;
toggleDoor = deviceStatus.switch1;
add(UpdateStateEvent());
}
});
} catch (_) {}
}
Future<void> _updateState(
UpdateStateEvent event, Emitter<GarageDoorSensorState> emit) async {
emit(GarageDoorLoadingState());
emit(UpdateState(garageSensor: deviceStatus));
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
List<Map<String, String>> days = [
{"day": "Sun", "key": "Sun"},
{"day": "Mon", "key": "Mon"},

View File

@ -109,6 +109,8 @@ class GetScheduleEvent extends GarageDoorEvent {}
class ScheduleSaveapp extends GarageDoorEvent {}
class UpdateStateEvent extends GarageDoorEvent {}
class ToggleScheduleEvent extends GarageDoorEvent {
final String id;
final bool toggle;

View File

@ -26,7 +26,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
bool oneGangGroup = false;
List<DeviceModel> devicesList = [];
OneGangBloc({required this.oneGangId, required this.switchCode}) : super(InitialState()) {
OneGangBloc({required this.oneGangId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchOneGangStatus);
on<OneGangUpdated>(_oneGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -49,7 +50,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
on<GroupAllOffEvent>(_groupAllOff);
}
void _fetchOneGangStatus(InitialEvent event, Emitter<OneGangState> emit) async {
void _fetchOneGangStatus(
InitialEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(oneGangId);
@ -59,42 +61,51 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
deviceStatus = OneGangModel.fromJson(statusModelList);
emit(UpdateState(oneGangModel: deviceStatus));
// _listenToChanges();
_listenToChanges(oneGangId);
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
// Real-time db
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(String id) {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$oneGangId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$id');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
_streamSubscription = stream.listen((DatabaseEvent event) {
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = OneGangModel.fromJson(statusList);
if (!isClosed) {
add(OneGangUpdated());
}
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_oneGangUpdated(OneGangUpdated event, Emitter<OneGangState> emit) {
emit(LoadingInitialState());
emit(UpdateState(oneGangModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<OneGangState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.value;
@ -119,17 +130,20 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<OneGangState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<OneGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<OneGangState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: oneGangId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: oneGangId, code: event.deviceCode, value: seconds),
oneGangId);
if (response['success'] ?? false) {
@ -152,7 +166,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<OneGangState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(oneGangId);
@ -241,7 +256,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
deviceId: oneGangId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -252,12 +268,13 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -276,7 +293,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -296,7 +314,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -325,7 +344,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<OneGangState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<OneGangState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
@ -334,7 +354,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
List<GroupOneGangModel> groupOneGangList = [];
bool allSwitchesOn = true;
void _fetchOneGangWizardStatus(InitialWizardEvent event, Emitter<OneGangState> emit) async {
void _fetchOneGangWizardStatus(
InitialWizardEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
@ -344,7 +365,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '1G');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -365,15 +387,16 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
return true;
});
}
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<OneGangState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -386,7 +409,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
});
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -414,7 +438,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: true));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupOneGangList.map((device) => device.deviceId).toList();
// First call for switch_1
final response = await DevicesAPI.deviceBatchController(
@ -446,7 +471,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: false));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupOneGangList.map((device) => device.deviceId).toList();
// First call for switch_1
final response = await DevicesAPI.deviceBatchController(

View File

@ -30,7 +30,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
bool oneTouchGroup = false;
List<DeviceModel> devicesList = [];
OneTouchBloc({required this.oneTouchId, required this.switchCode}) : super(InitialState()) {
OneTouchBloc({required this.oneTouchId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchOneTouchStatus);
on<OneTouchUpdated>(_oneTouchUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -53,7 +54,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
on<ChangeStatusEvent>(_changeStatus);
}
void _fetchOneTouchStatus(InitialEvent event, Emitter<OneTouchState> emit) async {
void _fetchOneTouchStatus(
InitialEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(oneTouchId);
@ -62,43 +64,59 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = OneTouchModel.fromJson(statusModelList);
_listenToChanges(oneTouchId);
emit(UpdateState(oneTouchModel: deviceStatus));
// _listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(String id) {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$oneTouchId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$id');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
_streamSubscription = stream.listen((DatabaseEvent event) {
if (event.snapshot.value != null) {
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value']));
statusList.add(
StatusModel(code: element['code'], value: element['value']));
});
var switchStatus = statusList.firstWhere(
(status) => status.code == "switch_1",
orElse: () => StatusModel(code: "switch_1", value: false));
deviceStatus = OneTouchModel.fromJson(statusList);
if (!isClosed) {
deviceStatus.firstSwitch = switchStatus.value as bool;
add(OneTouchUpdated());
}
});
} catch (_) {}
} catch (_) {
}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_oneTouchUpdated(OneTouchUpdated event, Emitter<OneTouchState> emit) {
emit(LoadingNewSate(oneTouchModel: deviceStatus));
emit(UpdateState(oneTouchModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<OneTouchState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingNewSate(oneTouchModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.value;
@ -123,17 +141,20 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<OneTouchState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<OneTouchState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<OneTouchState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<OneTouchState> emit) async {
emit(LoadingNewSate(oneTouchModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: oneTouchId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: oneTouchId, code: event.deviceCode, value: seconds),
oneTouchId);
if (response['success'] ?? false) {
@ -156,7 +177,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<OneTouchState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(oneTouchId);
@ -245,7 +267,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
deviceId: oneTouchId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -256,12 +279,13 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<OneTouchState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<OneTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -280,7 +304,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<OneTouchState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<OneTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -300,7 +325,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneTouchState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<OneTouchState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -329,7 +355,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<OneTouchState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<OneTouchState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
@ -338,7 +365,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
List<GroupOneTouchModel> groupOneTouchList = [];
bool allSwitchesOn = true;
void _fetchOneTouchWizardStatus(InitialWizardEvent event, Emitter<OneTouchState> emit) async {
void _fetchOneTouchWizardStatus(
InitialWizardEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
@ -348,7 +376,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '1GT');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -369,15 +398,16 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
return true;
});
}
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
oneTouchList: groupOneTouchList, allSwitches: allSwitchesOn));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<OneTouchState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<OneTouchState> emit) async {
emit(LoadingNewSate(oneTouchModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -395,7 +425,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
value: !event.value,
);
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
oneTouchList: groupOneTouchList, allSwitches: allSwitchesValue));
if (response['success']) {
add(InitialEvent(groupScreen: oneTouchGroup));
}
@ -413,10 +444,12 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
// Emit the state with updated values
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: true));
emit(
UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: true));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneTouchList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupOneTouchList.map((device) => device.deviceId).toList();
// First call for switch_1
final response1 = await DevicesAPI.deviceBatchController(
@ -445,10 +478,12 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
// Emit the state with updated values
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: false));
emit(UpdateGroupState(
oneTouchList: groupOneTouchList, allSwitches: false));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneTouchList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupOneTouchList.map((device) => device.deviceId).toList();
// First call for switch_1
final response1 = await DevicesAPI.deviceBatchController(
@ -472,7 +507,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
String statusSelected = '';
String optionSelected = '';
Future<void> _changeStatus(ChangeStatusEvent event, Emitter<OneTouchState> emit) async {
Future<void> _changeStatus(
ChangeStatusEvent event, Emitter<OneTouchState> emit) async {
try {
emit(LoadingInitialState());
@ -497,7 +533,10 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
final selectedControl = controlMap[optionSelected]?[statusSelected];
if (selectedControl != null) {
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: oneTouchId, code: optionSelected, value: selectedControl),
DeviceControlModel(
deviceId: oneTouchId,
code: optionSelected,
value: selectedControl),
oneTouchId,
);
} else {

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:math';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
@ -37,7 +38,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
on<SelectTimeEvent>(selectTimeOfLinePassword);
on<SelectTimeOnlinePasswordEvent>(selectTimeOnlinePassword);
on<DeletePasswordEvent>(deletePassword);
on<GenerateAndSavePasswordTimeLimitEvent>(generateAndSavePasswordTimeLimited);
on<GenerateAndSavePasswordTimeLimitEvent>(
generateAndSavePasswordTimeLimited);
on<GenerateAndSavePasswordOneTimeEvent>(generateAndSavePasswordOneTime);
on<ToggleDaySelectionEvent>(toggleDaySelection);
on<RenamePasswordEvent>(_renamePassword);
@ -59,7 +61,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
List<OfflinePasswordModel>? oneTimePasswords = [];
List<OfflinePasswordModel>? timeLimitPasswords = [];
Future generate7DigitNumber(GeneratePasswordEvent event, Emitter<SmartDoorState> emit) async {
Future generate7DigitNumber(
GeneratePasswordEvent event, Emitter<SmartDoorState> emit) async {
emit(LoadingInitialState());
passwordController.clear();
Random random = Random();
@ -71,7 +74,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
Future generateAndSavePasswordOneTime(
GenerateAndSavePasswordOneTimeEvent event, Emitter<SmartDoorState> emit) async {
GenerateAndSavePasswordOneTimeEvent event,
Emitter<SmartDoorState> emit) async {
try {
if (isSavingPassword) return;
isSavingPassword = true;
@ -92,7 +96,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
}
void _fetchSmartDoorStatus(InitialEvent event, Emitter<SmartDoorState> emit) async {
void _fetchSmartDoorStatus(
InitialEvent event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getDeviceStatus(deviceId);
@ -102,42 +107,63 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
deviceStatus = SmartDoorModel.fromJson(statusModelList);
emit(UpdateState(smartDoorModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
Timer? _timer;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) {
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = SmartDoorModel.fromJson(statusList);
if (!isClosed) {
add(DoorLockUpdated());
}
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_doorLockUpdated(DoorLockUpdated event, Emitter<SmartDoorState> emit) {
unlockRequest = deviceStatus.unlockRequest;
emit(UpdateState(smartDoorModel: deviceStatus));
}
void _renamePassword(RenamePasswordEvent event, Emitter<SmartDoorState> emit) async {
void _renamePassword(
RenamePasswordEvent event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
await DevicesAPI.renamePass(
name: passwordNameController.text, doorLockUuid: deviceId, passwordId: passwordId);
name: passwordNameController.text,
doorLockUuid: deviceId,
passwordId: passwordId);
add(InitialOneTimePassword());
add(InitialTimeLimitPassword());
emit(UpdateState(smartDoorModel: deviceStatus));
@ -147,46 +173,58 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
}
void getTemporaryPasswords(InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
void getTemporaryPasswords(
InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getTemporaryPasswords(
deviceId,
);
if (response is List) {
temporaryPasswords = response.map((item) => TemporaryPassword.fromJson(item)).toList();
} else if (response is Map && response.containsKey('data')) {
temporaryPasswords =
(response['data'] as List).map((item) => TemporaryPassword.fromJson(item)).toList();
response.map((item) => TemporaryPassword.fromJson(item)).toList();
} else if (response is Map && response.containsKey('data')) {
temporaryPasswords = (response['data'] as List)
.map((item) => TemporaryPassword.fromJson(item))
.toList();
}
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
emit(TemporaryPasswordsLoadedState(
temporaryPassword: temporaryPasswords!));
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
}
}
void getOneTimePasswords(InitialOneTimePassword event, Emitter<SmartDoorState> emit) async {
void getOneTimePasswords(
InitialOneTimePassword event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getOneTimePasswords(deviceId);
if (response is List) {
oneTimePasswords = response.map((item) => OfflinePasswordModel.fromJson(item)).toList();
oneTimePasswords = response
.map((item) => OfflinePasswordModel.fromJson(item))
.toList();
}
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
emit(TemporaryPasswordsLoadedState(
temporaryPassword: temporaryPasswords!));
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
}
}
void getTimeLimitPasswords(InitialTimeLimitPassword event, Emitter<SmartDoorState> emit) async {
void getTimeLimitPasswords(
InitialTimeLimitPassword event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getTimeLimitPasswords(deviceId);
if (response is List) {
timeLimitPasswords = response.map((item) => OfflinePasswordModel.fromJson(item)).toList();
timeLimitPasswords = response
.map((item) => OfflinePasswordModel.fromJson(item))
.toList();
}
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
emit(TemporaryPasswordsLoadedState(
temporaryPassword: temporaryPasswords!));
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
}
@ -207,7 +245,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
return repeat;
}
bool setStartEndTime(SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
bool setStartEndTime(
SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
emit(LoadingInitialState());
isStartEndTime = event.val;
emit(IsStartEndState(isStartEndTime: isStartEndTime));
@ -230,7 +269,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
emit(UpdateState(smartDoorModel: deviceStatus));
}
Future<void> selectTimeOfLinePassword(SelectTimeEvent event, Emitter<SmartDoorState> emit) async {
Future<void> selectTimeOfLinePassword(
SelectTimeEvent event, Emitter<SmartDoorState> emit) async {
emit(ChangeTimeState());
final DateTime? picked = await showDatePicker(
context: event.context,
@ -260,20 +300,27 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
).millisecondsSinceEpoch ~/
1000; // Divide by 1000 to remove milliseconds
if (event.isEffective) {
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
if (expirationTimeTimeStamp != null &&
selectedTimestamp > expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar(
'Effective Time cannot be later than Expiration Time.');
} else {
effectiveTime =
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
effectiveTime = selectedDateTime
.toString()
.split('.')
.first; // Remove seconds and milliseconds
effectiveTimeTimeStamp = selectedTimestamp;
}
} else {
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
if (effectiveTimeTimeStamp != null &&
selectedTimestamp < effectiveTimeTimeStamp!) {
CustomSnackBar.displaySnackBar(
'Expiration Time cannot be earlier than Effective Time.');
} else {
expirationTime =
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
expirationTime = selectedDateTime
.toString()
.split('.')
.first; // Remove seconds and milliseconds
expirationTimeTimeStamp = selectedTimestamp;
}
}
@ -329,20 +376,27 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
).millisecondsSinceEpoch ~/
1000; // Divide by 1000 to remove milliseconds
if (event.isEffective) {
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
if (expirationTimeTimeStamp != null &&
selectedTimestamp > expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar(
'Effective Time cannot be later than Expiration Time.');
} else {
effectiveTime =
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
effectiveTime = selectedDateTime
.toString()
.split('.')
.first; // Remove seconds and milliseconds
effectiveTimeTimeStamp = selectedTimestamp;
}
} else {
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
if (effectiveTimeTimeStamp != null &&
selectedTimestamp < effectiveTimeTimeStamp!) {
CustomSnackBar.displaySnackBar(
'Expiration Time cannot be earlier than Effective Time.');
} else {
expirationTime =
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
expirationTime = selectedDateTime
.toString()
.split('.')
.first; // Remove seconds and milliseconds
expirationTimeTimeStamp = selectedTimestamp;
}
}
@ -351,7 +405,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
}
Future<void> savePassword(SavePasswordEvent event, Emitter<SmartDoorState> emit) async {
Future<void> savePassword(
SavePasswordEvent event, Emitter<SmartDoorState> emit) async {
if (_validateInputs() || isSavingPassword) return;
try {
isSavingPassword = true;
@ -381,7 +436,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
Future<void> generateAndSavePasswordTimeLimited(
GenerateAndSavePasswordTimeLimitEvent event, Emitter<SmartDoorState> emit) async {
GenerateAndSavePasswordTimeLimitEvent event,
Emitter<SmartDoorState> emit) async {
if (timeLimitValidate() || isSavingPassword) return;
try {
isSavingPassword = true;
@ -407,10 +463,12 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
}
Future<void> deletePassword(DeletePasswordEvent event, Emitter<SmartDoorState> emit) async {
Future<void> deletePassword(
DeletePasswordEvent event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
await DevicesAPI.deletePassword(deviceId: deviceId, passwordId: event.passwordId)
await DevicesAPI.deletePassword(
deviceId: deviceId, passwordId: event.passwordId)
.then((value) async {
add(InitialPasswordsPage());
});
@ -445,7 +503,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
if (repeat == true && (endTime == null || startTime == null)) {
CustomSnackBar.displaySnackBar('Start Time and End time and the days required ');
CustomSnackBar.displaySnackBar(
'Start Time and End time and the days required ');
return true;
}
return false;

View File

@ -1,10 +1,12 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.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/model/community_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_event.dart';
import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
@ -19,6 +21,7 @@ import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class SosBloc extends Bloc<SosEvent, SosState> {
@ -171,6 +174,7 @@ class SosBloc extends Bloc<SosEvent, SosState> {
);
emit(UpdateState(sensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
} catch (e) {
emit(SosFailedState(errorMessage: e.toString()));
return;
@ -184,8 +188,12 @@ class SosBloc extends Bloc<SosEvent, SosState> {
FetchRoomsEvent event, Emitter<SosState> emit) async {
try {
emit(SosLoadingState());
Project? project = HomeCubit.getInstance().project;
roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
event.unit.community.uuid,
event.unit.id,
project?.uuid ?? TempConst.projectIdDev);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(const SosFailedState(errorMessage: 'Something went wrong'));
@ -223,13 +231,19 @@ class SosBloc extends Bloc<SosEvent, SosState> {
void _assignDevice(AssignRoomEvent event, Emitter<SosState> emit) async {
try {
emit(SosLoadingState());
Project? project = HomeCubit.getInstance().project;
await HomeManagementAPI.assignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, sosId);
event.unit.community.uuid,
event.unit.id,
event.roomId,
sosId,
project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
@ -249,13 +263,16 @@ class SosBloc extends Bloc<SosEvent, SosState> {
void _unassignDevice(UnassignRoomEvent event, Emitter<SosState> emit) async {
try {
Map<String, bool> roomDevicesId = {};
Project? project = HomeCubit.getInstance().project;
emit(SosLoadingState());
await HomeManagementAPI.unAssignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, sosId);
event.unit.community.uuid, event.unit.id, event.roomId, sosId, project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
@ -419,4 +436,39 @@ class SosBloc extends Bloc<SosEvent, SosState> {
emit(SosFailedState(errorMessage: e.toString()));
}
}
//real-time db
// StreamSubscription<DatabaseEvent>? _streamSubscription;
// Timer? _timer;
// void _listenToChanges() {
// try {
// _streamSubscription?.cancel();
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$sosId');
// Stream<DatabaseEvent> stream = ref.onValue;
// _streamSubscription = stream.listen((DatabaseEvent event) async {
// if (_timer != null) {
// await Future.delayed(const Duration(seconds: 2));
// }
// Map<dynamic, dynamic> usersMap =
// event.snapshot.value as Map<dynamic, dynamic>;
// List<StatusModel> statusList = [];
// usersMap['status'].forEach((element) {
// statusList
// .add(StatusModel(code: element['code'], value: element['value']));
// });
// deviceStatus = SosModel.fromJson(statusList);
// });
// } catch (_) {}
// }
// @override
// Future<void> close() async {
// _streamSubscription?.cancel();
// _streamSubscription = null;
// return super.close();
// }
}

View File

@ -31,7 +31,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
List<GroupThreeGangModel> groupThreeGangList = [];
bool allSwitchesOn = true;
ThreeGangBloc({required this.threeGangId, required this.switchCode}) : super(InitialState()) {
ThreeGangBloc({required this.threeGangId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchThreeGangStatus);
on<ThreeGangUpdated>(_threeGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -57,7 +58,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
}
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
void _fetchThreeGangStatus(
InitialEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingInitialState());
try {
threeGangGroup = event.groupScreen;
@ -69,7 +71,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '3G');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -86,13 +89,16 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (groupThreeGangList.isNotEmpty) {
groupThreeGangList.firstWhere((element) {
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesOn = false;
}
return true;
});
}
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesOn));
} else {
var response = await DevicesAPI.getDeviceStatus(threeGangId);
List<StatusModel> statusModelList = [];
@ -101,7 +107,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
deviceStatus = ThreeGangModel.fromJson(statusModelList);
emit(UpdateState(threeGangModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
}
} catch (e) {
emit(FailedState(error: e.toString()));
@ -109,22 +115,26 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeGangId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$threeGangId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
await Future.delayed(const Duration(seconds: 1));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = ThreeGangModel.fromJson(statusList);
if (!isClosed) {
add(ThreeGangUpdated());
@ -133,11 +143,19 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_threeGangUpdated(ThreeGangUpdated event, Emitter<ThreeGangState> emit) {
emit(UpdateState(threeGangModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
if (threeGangGroup) {
@ -146,11 +164,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (element.deviceId == event.deviceId) {
element.firstSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
} else {
deviceStatus.firstSwitch = !event.value;
emit(UpdateState(threeGangModel: deviceStatus));
@ -187,11 +208,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (element.deviceId == event.deviceId) {
element.secondSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
} else {
deviceStatus.secondSwitch = !event.value;
emit(UpdateState(threeGangModel: deviceStatus));
@ -217,7 +241,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void _changeThirdSwitch(ChangeThirdSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
void _changeThirdSwitch(
ChangeThirdSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
if (threeGangGroup) {
@ -226,11 +251,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (element.deviceId == event.deviceId) {
element.thirdSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
} else {
deviceStatus.thirdSwitch = !event.value;
emit(UpdateState(threeGangModel: deviceStatus));
@ -269,15 +297,21 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: threeGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: threeGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_3', value: deviceStatus.thirdSwitch),
deviceId: threeGangId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeGangId),
]);
@ -303,15 +337,21 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: threeGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: threeGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_3', value: deviceStatus.thirdSwitch),
deviceId: threeGangId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeGangId),
]);
@ -333,9 +373,11 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
groupThreeGangList[i].secondSwitch = true;
groupThreeGangList[i].thirdSwitch = true;
}
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: true));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: true));
List<String> allDeviceIds = groupThreeGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupThreeGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -365,7 +407,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void _groupAllOff(GroupAllOffEvent event, Emitter<ThreeGangState> emit) async {
void _groupAllOff(
GroupAllOffEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
for (int i = 0; i < groupThreeGangList.length; i++) {
@ -373,8 +416,10 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
groupThreeGangList[i].secondSwitch = false;
groupThreeGangList[i].thirdSwitch = false;
}
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: false));
List<String> allDeviceIds = groupThreeGangList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: false));
List<String> allDeviceIds =
groupThreeGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -404,17 +449,20 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<ThreeGangState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeGangId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: threeGangId, code: event.deviceCode, value: seconds),
threeGangId);
if (response['success'] ?? false) {
@ -441,7 +489,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<ThreeGangState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(threeGangId);
@ -551,7 +600,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
deviceId: threeGangId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -562,12 +612,13 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -586,7 +637,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -606,13 +658,15 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();

View File

@ -38,7 +38,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
List<GroupThreeTouchModel> groupThreeTouchList = [];
bool allSwitchesOn = true;
ThreeTouchBloc({required this.threeTouchId, required this.switchCode}) : super(InitialState()) {
ThreeTouchBloc({required this.threeTouchId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchThreeTouchStatus);
on<ThreeTouchUpdated>(_threeTouchUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -63,7 +64,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
on<ChangeStatusEvent>(_changeStatus);
}
void _fetchThreeTouchStatus(InitialEvent event, Emitter<ThreeTouchState> emit) async {
void _fetchThreeTouchStatus(
InitialEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingInitialState());
try {
threeTouchGroup = event.groupScreen;
@ -75,7 +77,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '3GT');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -92,13 +95,16 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (groupThreeTouchList.isNotEmpty) {
groupThreeTouchList.firstWhere((element) {
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesOn = false;
}
return true;
});
}
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList, allSwitches: allSwitchesOn));
} else {
var response = await DevicesAPI.getDeviceStatus(threeTouchId);
List<StatusModel> statusModelList = [];
@ -107,7 +113,7 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
deviceStatus = ThreeTouchModel.fromJson(statusModelList);
emit(UpdateState(threeTouchModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
}
} catch (e) {
emit(FailedState(error: e.toString()));
@ -117,18 +123,21 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
_listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeTouchId');
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$threeTouchId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = ThreeTouchModel.fromJson(statusList);
@ -143,7 +152,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
emit(UpdateState(threeTouchModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
try {
if (threeTouchGroup) {
@ -152,11 +162,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (element.deviceId == event.deviceId) {
element.firstSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList,
allSwitches: allSwitchesValue));
} else {
deviceStatus.firstSwitch = !event.value;
emit(UpdateState(threeTouchModel: deviceStatus));
@ -183,8 +197,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _changeSecondSwitch(
ChangeSecondSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event,
Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
try {
if (threeTouchGroup) {
@ -193,11 +207,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (element.deviceId == event.deviceId) {
element.secondSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList,
allSwitches: allSwitchesValue));
} else {
deviceStatus.secondSwitch = !event.value;
emit(UpdateState(threeTouchModel: deviceStatus));
@ -223,7 +241,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _changeThirdSwitch(ChangeThirdSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
void _changeThirdSwitch(
ChangeThirdSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
try {
if (threeTouchGroup) {
@ -232,11 +251,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (element.deviceId == event.deviceId) {
element.thirdSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList,
allSwitches: allSwitchesValue));
} else {
deviceStatus.thirdSwitch = !event.value;
emit(UpdateState(threeTouchModel: deviceStatus));
@ -275,15 +298,21 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: threeTouchId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: threeTouchId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_3', value: deviceStatus.thirdSwitch),
deviceId: threeTouchId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeTouchId),
]);
@ -309,15 +338,21 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: threeTouchId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: threeTouchId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_3', value: deviceStatus.thirdSwitch),
deviceId: threeTouchId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeTouchId),
]);
@ -339,8 +374,10 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
groupThreeTouchList[i].secondSwitch = true;
groupThreeTouchList[i].thirdSwitch = true;
}
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: true));
List<String> allDeviceIds = groupThreeTouchList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList, allSwitches: true));
List<String> allDeviceIds =
groupThreeTouchList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
@ -369,7 +406,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _groupAllOff(GroupAllOffEvent event, Emitter<ThreeTouchState> emit) async {
void _groupAllOff(
GroupAllOffEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
try {
for (int i = 0; i < groupThreeTouchList.length; i++) {
@ -377,8 +415,10 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
groupThreeTouchList[i].secondSwitch = false;
groupThreeTouchList[i].thirdSwitch = false;
}
List<String> allDeviceIds = groupThreeTouchList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: false));
List<String> allDeviceIds =
groupThreeTouchList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList, allSwitches: false));
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
@ -407,17 +447,20 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<ThreeTouchState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<ThreeTouchState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<ThreeTouchState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeTouchId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: threeTouchId, code: event.deviceCode, value: seconds),
threeTouchId);
if (response['success'] ?? false) {
@ -444,7 +487,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<ThreeTouchState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(threeTouchId);
@ -554,7 +598,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
deviceId: threeTouchId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -565,12 +610,13 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<ThreeTouchState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<ThreeTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -589,7 +635,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<ThreeTouchState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<ThreeTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -609,13 +656,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<ThreeTouchState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<ThreeTouchState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<ThreeTouchState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<ThreeTouchState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -633,7 +682,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
String statusSelected = '';
String optionSelected = '';
Future<void> _changeStatus(ChangeStatusEvent event, Emitter<ThreeTouchState> emit) async {
Future<void> _changeStatus(
ChangeStatusEvent event, Emitter<ThreeTouchState> emit) async {
try {
emit(LoadingInitialState());
final Map<String, Map<String, String>> controlMap = {
@ -667,11 +717,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
final selectedControl = controlMap[optionSelected]?[statusSelected];
if (selectedControl != null) {
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeTouchId, code: optionSelected, value: selectedControl),
DeviceControlModel(
deviceId: threeTouchId,
code: optionSelected,
value: selectedControl),
threeTouchId,
);
} else {
emit(const FailedState(error: 'Invalid statusSelected or optionSelected'));
emit(const FailedState(
error: 'Invalid statusSelected or optionSelected'));
}
} on DioException catch (e) {
final errorData = e.response!.data;

View File

@ -35,7 +35,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
bool createSchedule = false;
List<ScheduleModel> listSchedule = [];
TwoGangBloc({required this.twoGangId, required this.switchCode}) : super(InitialState()) {
TwoGangBloc({required this.twoGangId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchTwoGangStatus);
on<TwoGangUpdated>(_twoGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -65,13 +66,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<TwoGangState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<TwoGangState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<TwoGangState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<TwoGangState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -79,7 +82,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
emit(UpdateCreateScheduleState(createSchedule));
}
void _fetchTwoGangStatus(InitialEvent event, Emitter<TwoGangState> emit) async {
void _fetchTwoGangStatus(
InitialEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(twoGangId);
@ -89,42 +93,50 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
deviceStatus = TwoGangModel.fromJson(statusModelList);
emit(UpdateState(twoGangModel: deviceStatus));
// _listenToChanges();
_listenToChanges(twoGangId);
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(String id) {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$twoGangId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$id');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
_streamSubscription = stream.listen((DatabaseEvent event) {
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = TwoGangModel.fromJson(statusList);
if (!isClosed) {
add(TwoGangUpdated());
}
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_twoGangUpdated(TwoGangUpdated event, Emitter<TwoGangState> emit) {
emit(LoadingNewSate(twoGangModel: deviceStatus));
emit(UpdateState(twoGangModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.value;
@ -135,7 +147,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
_timer = Timer(const Duration(milliseconds: 100), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoGangId, code: 'switch_1', value: !event.value),
DeviceControlModel(
deviceId: twoGangId, code: 'switch_1', value: !event.value),
twoGangId);
if (!response['success']) {
@ -147,7 +160,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
void _changeSecondSwitch(
ChangeSecondSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
deviceStatus.secondSwitch = !event.value;
@ -157,7 +171,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
_timer = Timer(const Duration(milliseconds: 100), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoGangId, code: 'switch_2', value: !event.value),
DeviceControlModel(
deviceId: twoGangId, code: 'switch_2', value: !event.value),
twoGangId);
if (!response['success']) {
@ -180,11 +195,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: twoGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
twoGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: twoGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
twoGangId),
]);
@ -207,11 +226,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: twoGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
twoGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: twoGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
twoGangId),
]);
if (response.every((element) => !element['success'])) {
@ -232,7 +255,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
groupTwoGangList[i].secondSwitch = true;
}
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: true));
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -267,7 +291,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: false));
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -292,17 +317,20 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<TwoGangState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<TwoGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<TwoGangState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoGangId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: twoGangId, code: event.deviceCode, value: seconds),
twoGangId);
if (response['success'] ?? false) {
@ -327,7 +355,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<TwoGangState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState());
try {
add(GetScheduleEvent());
@ -435,7 +464,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
deviceId: twoGangId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -446,12 +476,13 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleRepeat(ToggleScheduleEvent event, Emitter<TwoGangState> emit) async {
Future toggleRepeat(
ToggleScheduleEvent event, Emitter<TwoGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -470,7 +501,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<TwoGangState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<TwoGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -490,7 +522,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _fetchTwoGangWizardStatus(InitialWizardEvent event, Emitter<TwoGangState> emit) async {
void _fetchTwoGangWizardStatus(
InitialWizardEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
@ -500,7 +533,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '2G');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -523,15 +557,16 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
return true;
});
}
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesOn));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -544,9 +579,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
});
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
@ -561,8 +598,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _changeSecondWizardSwitch(
ChangeSecondWizardSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
void _changeSecondWizardSwitch(ChangeSecondWizardSwitchStatusEvent event,
Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -574,9 +611,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
allSwitchesValue = false;
}
});
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_2',

View File

@ -99,41 +99,61 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
deviceStatus = TwoTouchModel.fromJson(statusModelList);
emit(UpdateState(twoTouchModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$twoTouchId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
await Future.delayed(const Duration(seconds: 1));
}
if (event.snapshot.value != null) {
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList
.add(StatusModel(code: element['code'], value: element['value']));
statusList.add(
StatusModel(code: element['code'], value: element['value']));
});
var switch1Status = statusList.firstWhere(
(status) => status.code == "switch_1",
orElse: () => StatusModel(code: "switch_1", value: false));
var switch2Status = statusList.firstWhere(
(status) => status.code == "switch_2",
orElse: () => StatusModel(code: "switch_2", value: false));
deviceStatus.firstSwitch = switch1Status.value as bool;
deviceStatus.secondSwitch = switch2Status.value as bool;
deviceStatus = TwoTouchModel.fromJson(statusList);
if (!isClosed) {
add(TwoTouchUpdated());
}
});
} catch (_) {}
} catch (_) {
}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_twoTouchUpdated(TwoTouchUpdated event, Emitter<TwoTouchState> emit) {
emit(LoadingInitialState());
emit(UpdateState(twoTouchModel: deviceStatus));
}

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_state.dart';
@ -21,7 +23,8 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
on<GetDeviceReportsEvent>(_getDeviceReports);
}
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<WallSensorState> emit) async {
void _fetchCeilingSensorStatus(
InitialEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(deviceId);
@ -31,41 +34,62 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
}
deviceStatus = WallSensorModel.fromJson(statusModelList);
emit(UpdateState(wallSensorModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
Timer? _timer;
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) {
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = WallSensorModel.fromJson(statusList);
if (!isClosed) {
add(WallSensorUpdatedEvent());
}
});
} catch (_) {}
}
_wallSensorUpdated(WallSensorUpdatedEvent event, Emitter<WallSensorState> emit) {
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_wallSensorUpdated(
WallSensorUpdatedEvent event, Emitter<WallSensorState> emit) {
emit(UpdateState(wallSensorModel: deviceStatus));
}
void _changeIndicator(ChangeIndicatorEvent event, Emitter<WallSensorState> emit) async {
void _changeIndicator(
ChangeIndicatorEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingNewSate(wallSensorModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: 'indicator', value: !event.value), deviceId);
DeviceControlModel(
deviceId: deviceId, code: 'indicator', value: !event.value),
deviceId);
if (response['success'] ?? false) {
deviceStatus.indicator = !event.value;
@ -74,11 +98,14 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
emit(UpdateState(wallSensorModel: deviceStatus));
}
void _changeValue(ChangeValueEvent event, Emitter<WallSensorState> emit) async {
void _changeValue(
ChangeValueEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingNewSate(wallSensorModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: event.code, value: event.value), deviceId);
DeviceControlModel(
deviceId: deviceId, code: event.code, value: event.value),
deviceId);
if (response['success'] ?? false) {
if (event.code == 'far_detection') {
@ -93,7 +120,8 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
emit(UpdateState(wallSensorModel: deviceStatus));
}
void _getDeviceReports(GetDeviceReportsEvent event, Emitter<WallSensorState> emit) async {
void _getDeviceReports(
GetDeviceReportsEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingInitialState());
try {

View File

@ -35,7 +35,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
List<ScheduleModel> listSchedule = [];
DateTime? selectedTime = DateTime.now();
WaterHeaterBloc({required this.whId, required this.switchCode}) : super(WHInitialState()) {
WaterHeaterBloc({required this.whId, required this.switchCode})
: super(WHInitialState()) {
on<WaterHeaterInitial>(_fetchWaterHeaterStatus);
on<WaterHeaterSwitch>(_changeFirstSwitch);
on<SetCounterValue>(_setCounterValue);
@ -60,7 +61,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
on<WaterHeaterUpdated>(_waterHeaterUpdated);
}
void _fetchWaterHeaterStatus(WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async {
void _fetchWaterHeaterStatus(
WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(whId);
@ -72,29 +74,33 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
statusModelList,
);
emit(UpdateState(whModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(WHFailedState(errorMessage: e.toString()));
return;
}
}
_listenToChanges() {
//real-time db
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$whId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$whId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: element['value']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = WHModel.fromJson(statusList);
if (!isClosed) {
add(WaterHeaterUpdated());
@ -103,12 +109,21 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
} catch (_) {}
}
_waterHeaterUpdated(WaterHeaterUpdated event, Emitter<WaterHeaterState> emit) async {
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_waterHeaterUpdated(
WaterHeaterUpdated event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
emit(UpdateState(whModel: deviceStatus));
}
void _changeFirstSwitch(WaterHeaterSwitch event, Emitter<WaterHeaterState> emit) async {
void _changeFirstSwitch(
WaterHeaterSwitch event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.whSwitch;
@ -118,7 +133,10 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
_timer = Timer(const Duration(milliseconds: 500), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: whId, code: 'switch_1', value: deviceStatus.firstSwitch),
DeviceControlModel(
deviceId: whId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
whId);
if (!response['success']) {
@ -132,13 +150,16 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
//=====================---------- timer ----------------------------------------
void _setCounterValue(SetCounterValue event, Emitter<WaterHeaterState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: whId, code: event.deviceCode, value: seconds), whId);
DeviceControlModel(
deviceId: whId, code: event.deviceCode, value: seconds),
whId);
if (response['success'] ?? false) {
if (event.deviceCode == 'countdown_1') {
@ -160,7 +181,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<WaterHeaterState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(whId);
@ -250,7 +272,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
deviceId: whId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(WHInitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -261,12 +284,13 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<WaterHeaterState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<WaterHeaterState> emit) async {
try {
emit(WHLoadingState());
final response = await DevicesAPI.changeSchedule(
@ -284,7 +308,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<WaterHeaterState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<WaterHeaterState> emit) async {
try {
emit(WHLoadingState());
final response = await DevicesAPI.deleteSchedule(
@ -303,7 +328,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
void _toggleCreateCirculate(ToggleCreateCirculate event, Emitter<WaterHeaterState> emit) {
void _toggleCreateCirculate(
ToggleCreateCirculate event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState());
createCirculate = !createCirculate;
selectedDays.clear();
@ -311,13 +337,15 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
emit(UpdateCreateScheduleState(createCirculate));
}
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -366,8 +394,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
List<GroupWHModel> groupWaterHeaterList = [];
bool allSwitchesOn = true;
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<WaterHeaterState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -379,7 +407,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -394,7 +423,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
void _fetchWHWizardStatus(InitialWizardEvent event, Emitter<WaterHeaterState> emit) async {
void _fetchWHWizardStatus(
InitialWizardEvent event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
try {
devicesList = [];
@ -404,7 +434,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', 'WH');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -426,23 +457,27 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
return true;
});
}
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesOn));
} catch (e) {
// emit(FailedState(error: e.toString()));
return;
}
}
void _groupAllOn(GroupAllOnEvent event, Emitter<WaterHeaterState> emit) async {
void _groupAllOn(
GroupAllOnEvent event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
for (int i = 0; i < groupWaterHeaterList.length; i++) {
groupWaterHeaterList[i].firstSwitch = true;
}
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: true));
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: true));
List<String> allDeviceIds = groupWaterHeaterList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupWaterHeaterList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -460,15 +495,18 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
void _groupAllOff(GroupAllOffEvent event, Emitter<WaterHeaterState> emit) async {
void _groupAllOff(
GroupAllOffEvent event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
for (int i = 0; i < groupWaterHeaterList.length; i++) {
groupWaterHeaterList[i].firstSwitch = false;
}
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: false));
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: false));
List<String> allDeviceIds = groupWaterHeaterList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupWaterHeaterList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',

View File

@ -1,6 +1,5 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_event.dart';
import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_state.dart';
@ -21,7 +20,6 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
on<ToggleClosingReminderEvent>(_toggleClosingReminder);
on<ToggleWaterLeakAlarmEvent>(_toggleWaterLeakAlarm);
}
Timer? _timer;
bool lowBattery = false;
bool closingReminder = false;
bool waterAlarm = false;
@ -134,32 +132,42 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
emit(WaterLeakFailedState(errorMessage: errorMessage));
}
}
// Timer? _timer;
// StreamSubscription<DatabaseEvent>? _streamSubscription;
// void _listenToChanges() {
// try {
// _streamSubscription?.cancel();
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$WLId');
// Stream<DatabaseEvent> stream = ref.onValue;
_listenToChanges() {
try {
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$WLId');
Stream<DatabaseEvent> stream = ref.onValue;
// _streamSubscription = stream.listen((DatabaseEvent event) async {
// if (_timer != null) {
// await Future.delayed(const Duration(seconds: 2));
// }
// Map<dynamic, dynamic> usersMap =
// event.snapshot.value as Map<dynamic, dynamic>;
// List<StatusModel> statusList = [];
// usersMap['status'].forEach((element) {
// statusList
// .add(StatusModel(code: element['code'], value: element['value']));
// });
// deviceStatus = WaterLeakModel.fromJson(statusList);
// if (!isClosed) {
// add(
// WaterLeakSwitch(switchD: deviceStatus.waterContactState),
// );
// }
// });
// } catch (_) {}
// }
stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
// @override
// Future<void> close() async {
// _streamSubscription?.cancel();
// _streamSubscription = null;
// return super.close();
// }
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: true));
});
deviceStatus = WaterLeakModel.fromJson(statusList);
if (!isClosed) {
add(
WaterLeakSwitch(switchD: deviceStatus.waterContactState),
);
}
});
} catch (_) {}
}
}

View File

@ -27,24 +27,24 @@ class AcStatusModel {
}
factory AcStatusModel.fromJson(String id, List<StatusModel> jsonList) {
late bool _acSwitch;
late String _mode;
late int _tempSet;
late int _currentTemp;
late String _fanSpeeds;
late int _countdown1;
late bool _childLock;
bool _acSwitch = false;
String _mode = '';
int _tempSet = 210;
int _currentTemp = 210;
String _fanSpeeds = '';
int _countdown1 = 0;
bool _childLock = false;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'switch') {
_acSwitch = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'mode') {
_mode = jsonList[i].value ?? TempModes.cold;
_mode = jsonList[i].value ?? '';
} else if (jsonList[i].code == 'temp_set') {
_tempSet = jsonList[i].value ?? 210;
} else if (jsonList[i].code == 'temp_current') {
_currentTemp = jsonList[i].value ?? 210;
} else if (jsonList[i].code == 'level') {
_fanSpeeds = jsonList[i].value ?? 210;
_fanSpeeds = jsonList[i].value ?? '';
} else if (jsonList[i].code == 'child_lock') {
_childLock = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'countdown_time') {

View File

@ -23,9 +23,9 @@ class CeilingSensorModel {
required this.bodyMovement});
factory CeilingSensorModel.fromJson(List<StatusModel> jsonList) {
late String _presenceState;
late int _sensitivity;
late String _checkingResult;
String _presenceState = 'none';
int _sensitivity = 1;
String _checkingResult = '';
int _presenceRange = 1;
int _sportsPara = 1;
int _moving_max_dis = 0;

View File

@ -10,11 +10,11 @@ class CurtainModel {
});
factory CurtainModel.fromJson(List<StatusModel> jsonList) {
late String _control;
late int _percent;
String _control = '';
int _percent = 0;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'control') {
_control = jsonList[i].value ?? false;
_control = jsonList[i].value ?? '';
}
if (jsonList[i].code == 'percent_control') {
_percent = jsonList[i].value ?? 0;

View File

@ -1,5 +1,3 @@
import 'dart:convert';
class DeviceInfoModel {
final int activeTime;
final String category;

View File

@ -1,22 +1,17 @@
import 'package:syncrow_app/features/devices/model/status_model.dart';
class DoorSensorModel {
bool doorContactState;
int batteryPercentage;
DoorSensorModel(
{required this.doorContactState,
DoorSensorModel({
required this.doorContactState,
required this.batteryPercentage,
});
factory DoorSensorModel.fromJson(List<StatusModel> jsonList) {
late bool _doorContactState;
late int _batteryPercentage;
bool _doorContactState = false;
int _batteryPercentage = 0;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'doorcontact_state') {

View File

@ -24,15 +24,15 @@ class GarageDoorModel {
});
factory GarageDoorModel.fromJson(List<StatusModel> jsonList) {
late bool _switch1 = false;
late bool _doorContactState = false;
late int _countdown1 = 0;
late int _countdownAlarm = 0;
late String _doorControl1 = "closed";
late bool _voiceControl1 = false;
late String _doorState1 = "closed";
late int _batteryPercentage = 0;
late int _tr_timecon = 0;
bool _switch1 = false;
bool _doorContactState = false;
int _countdown1 = 0;
int _countdownAlarm = 0;
String _doorControl1 = "closed";
bool _voiceControl1 = false;
String _doorState1 = "closed";
int _batteryPercentage = 0;
int _tr_timecon = 0;
for (var status in jsonList) {
switch (status.code) {

View File

@ -1,19 +1,17 @@
import 'package:syncrow_app/features/devices/model/status_model.dart';
class OneGangModel {
bool firstSwitch;
int firstCountDown;
OneGangModel(
{required this.firstSwitch,
OneGangModel({
required this.firstSwitch,
required this.firstCountDown,
});
factory OneGangModel.fromJson(List<StatusModel> jsonList) {
late bool _switch;
late int _count;
bool _switch = false;
int _count = 0;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'switch_1') {

View File

@ -1,5 +1,3 @@
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
@ -15,15 +13,14 @@ class OneTouchModel {
required this.firstCountDown,
required this.light_mode,
required this.relay,
required this.relay_status_1
});
required this.relay_status_1});
factory OneTouchModel.fromJson(List<StatusModel> jsonList) {
late bool _switch;
late int _count;
late String _relay;
late String _light_mode;
late String relay_status_1;
bool _switch = false;
int _count = 0;
String _relay = '';
String _light_mode = '';
String relay_status_1 = '';
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'switch_1') {
@ -43,8 +40,6 @@ class OneTouchModel {
firstCountDown: _count,
light_mode: lightStatusExtension.fromString(_light_mode),
relay: StatusExtension.fromString(_relay),
relay_status_1: StatusExtension.fromString(relay_status_1 )
);
relay_status_1: StatusExtension.fromString(relay_status_1));
}
}

View File

@ -22,14 +22,14 @@ class SixSceneModel {
});
factory SixSceneModel.fromJson(List<StatusModel> jsonList) {
late dynamic _scene_1;
late dynamic _scene_2;
late dynamic _scene_3;
late dynamic _scene_4;
late dynamic _scene_5;
late dynamic _scene_6;
late dynamic _scene_id_group_id;
late dynamic _switch_backlight;
dynamic _scene_1 = '';
dynamic _scene_2 = '';
dynamic _scene_3 = '';
dynamic _scene_4 = '';
dynamic _scene_5 = '';
dynamic _scene_6 = '';
dynamic _scene_id_group_id = 0;
dynamic _switch_backlight = false;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'scene_1') {

View File

@ -39,23 +39,23 @@ class SmartDoorModel {
required this.normalOpenSwitch});
factory SmartDoorModel.fromJson(List<StatusModel> jsonList) {
late int _unlockFingerprint;
late int _unlockPassword;
late int _unlockTemporary;
late int _unlockCard;
late String _unlockAlarm;
late int _unlockRequest;
late int _residualElectricity;
late bool _reverseLock;
late int _unlockApp;
late bool _hijack;
late bool _doorbell;
late String _unlockOfflinePd;
late String _unlockOfflineClear;
late String _unlockDoubleKit;
late String _remoteNoPdSetkey;
late String _remoteNoDpKey;
late bool _normalOpenSwitch;
int _unlockFingerprint = 0;
int _unlockPassword = 0;
int _unlockTemporary = 0;
int _unlockCard = 0;
String _unlockAlarm = '';
int _unlockRequest = 0;
int _residualElectricity = 0;
bool _reverseLock = false;
int _unlockApp = 0;
bool _hijack = false;
bool _doorbell = false;
String _unlockOfflinePd = '';
String _unlockOfflineClear = '';
String _unlockDoubleKit = '';
String _remoteNoPdSetkey = '';
String _remoteNoDpKey = '';
bool _normalOpenSwitch = false;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'unlock_fingerprint') {

View File

@ -10,8 +10,8 @@ class SosModel {
});
factory SosModel.fromJson(List<StatusModel> jsonList) {
late String _sosContactState;
late int _batteryPercentage;
String _sosContactState = '';
int _batteryPercentage = 0;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'sos') {

View File

@ -31,7 +31,7 @@ class ACsList extends StatelessWidget {
List<DeviceModel> devicesList = [];
bool allOn = false;
bool allTempSame = false;
int temperature = 20;
int temperature = 250;
if (state is GetAllAcsStatusState) {
devicesStatuesList = state.allAcsStatues;
devicesList = state.allAcs;

View File

@ -23,6 +23,7 @@ class ACsView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => ACsBloc(acId: deviceModel?.uuid ?? '')
..add(AcsInitial(allAcs: deviceModel != null ? false : true)),
child: BlocBuilder<ACsBloc, AcsState>(

View File

@ -332,7 +332,7 @@ class CeilingSensorInterface extends StatelessWidget {
title: title.toString(),
sensor: ceilingSensor,
value: model.sensitivity,
min: 0,
min: 1,
max: 10,
));
if (result != null) {

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
import 'package:syncrow_app/features/devices/bloc/devices_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/all_devices.dart';
import 'package:syncrow_app/features/devices/view/widgets/room_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/rooms_slider.dart';
@ -15,7 +15,7 @@ import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
class DevicesViewBody extends StatelessWidget {
const DevicesViewBody({Key? key}) : super(key: key);
const DevicesViewBody({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<HomeCubit, HomeState>(
@ -80,10 +80,7 @@ class DevicesViewBody extends StatelessWidget {
),
],
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.1,
child: const SceneView(pageType: true),
),
const SceneView(pageType: true),
const SizedBox(height: 20),
const RoomsSlider(),
const SizedBox(height: 10),

View File

@ -8,8 +8,7 @@ import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart'
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
class GarageList extends StatelessWidget {
const GarageList(
{super.key, required this.garageList, required this.allSwitches});
const GarageList({super.key, required this.garageList, required this.allSwitches});
final List<GroupGarageModel> garageList;
final bool allSwitches;
@ -23,43 +22,42 @@ class GarageList extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 10),
const BodySmall(text: 'All Lights'),
const BodySmall(text: 'All Garages'),
const SizedBox(height: 5),
DevicesDefaultSwitch(
off: 'OFF',
on: 'ON',
off: 'Close',
on: 'Open',
switchValue: allSwitches,
action: () {
BlocProvider.of<GarageDoorBloc>(context)
.add(GroupAllOnEvent());
},
secondAction: () {
BlocProvider.of<GarageDoorBloc>(context)
.add(GroupAllOffEvent());
},
action: () => BlocProvider.of<GarageDoorBloc>(context).add(
GroupAllOnEvent(),
),
secondAction: () => BlocProvider.of<GarageDoorBloc>(context).add(
GroupAllOffEvent(),
),
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
padding: EdgeInsetsDirectional.zero,
itemCount: garageList.length,
itemBuilder: (context, index) {
final garageDoor = garageList[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 10),
BodySmall(text: garageList[index].deviceName),
BodySmall(text: garageDoor.deviceName),
const SizedBox(height: 5),
DevicesDefaultSwitch(
off: 'OFF',
on: 'ON',
switchValue: garageList[index].firstSwitch,
action: () {
BlocProvider.of<GarageDoorBloc>(context).add(
off: 'Close',
on: 'Open',
switchValue: garageDoor.firstSwitch,
action: () => BlocProvider.of<GarageDoorBloc>(context).add(
ChangeFirstWizardSwitchStatusEvent(
value: garageList[index].firstSwitch,
deviceId: garageList[index].deviceId));
},
value: garageDoor.firstSwitch,
deviceId: garageDoor.deviceId,
),
),
),
],
);

View File

@ -20,7 +20,8 @@ class OneGangScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => OneGangBloc(switchCode: 'switch_1', oneGangId: device?.uuid ?? '')
create: (context) =>
OneGangBloc(switchCode: 'switch_1', oneGangId: device?.uuid ?? '')
..add(const InitialEvent(groupScreen: false)),
child: BlocBuilder<OneGangBloc, OneGangState>(
builder: (context, state) {
@ -36,13 +37,15 @@ class OneGangScreen extends StatelessWidget {
}
return state is LoadingInitialState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
BlocProvider.of<OneGangBloc>(context)
.add(InitialEvent(groupScreen: device != null ? false : true));
BlocProvider.of<OneGangBloc>(context).add(InitialEvent(
groupScreen: device != null ? false : true));
},
child: ListView(
children: [
@ -55,7 +58,8 @@ class OneGangScreen extends StatelessWidget {
const Expanded(child: SizedBox.shrink()),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisAlignment:
MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
@ -64,9 +68,10 @@ class OneGangScreen extends StatelessWidget {
threeGangSwitch: device!,
value: oneGangModel.firstSwitch,
action: () {
BlocProvider.of<OneGangBloc>(context).add(
ChangeFirstSwitchStatusEvent(
value: oneGangModel.firstSwitch));
BlocProvider.of<OneGangBloc>(context)
.add(ChangeFirstSwitchStatusEvent(
value: oneGangModel
.firstSwitch));
},
),
const SizedBox(height: 20),
@ -74,7 +79,8 @@ class OneGangScreen extends StatelessWidget {
width: 70,
child: BodySmall(
text: " Entrance Light",
fontColor: ColorsManager.textPrimaryColor,
fontColor:
ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
@ -94,19 +100,23 @@ class OneGangScreen extends StatelessWidget {
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
borderRadius:
BorderRadius.circular(100),
),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder:
(context, animation1, animation2) =>
pageBuilder: (context,
animation1,
animation2) =>
TimerScheduleScreen(
switchCode: 'switch_1',
switchCode:
'switch_1',
device: device!,
deviceCode: 'countdown_1',
deviceCode:
'countdown_1',
)));
},
child: Stack(
@ -117,7 +127,9 @@ class OneGangScreen extends StatelessWidget {
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
borderRadius:
BorderRadius.circular(
100),
),
),
Container(
@ -125,12 +137,15 @@ class OneGangScreen extends StatelessWidget {
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
borderRadius:
BorderRadius.circular(
100),
),
child: Center(
child: Icon(
Icons.access_time,
color: ColorsManager.primaryColorWithOpacity,
color: ColorsManager
.primaryColorWithOpacity,
size: 25,
),
),

View File

@ -76,21 +76,38 @@ class RoomPageSwitch extends StatelessWidget {
: const SizedBox(),
],
),
Flexible(
child: FittedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
device.name ?? "",
overflow: TextOverflow.ellipsis,
maxLines: 2,
LayoutBuilder(
builder: (context, constraints) {
final text = device.name ?? "";
final textPainter = TextPainter(
text: TextSpan(
text: text,
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.grey,
),
),
maxLines: 1,
textDirection: TextDirection.ltr,
);
textPainter.layout(maxWidth: constraints.maxWidth);
final exceeded = textPainter.didExceedMaxLines;
return Text(
exceeded ? '${text.substring(0, 10)}...' : text,
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.grey,
),
overflow: TextOverflow.clip,
maxLines: 1,
);
},
),
Text(
device.subspace!.subspaceName ?? '',
overflow: TextOverflow.ellipsis,
@ -103,10 +120,6 @@ class RoomPageSwitch extends StatelessWidget {
],
),
),
),
],
),
),
);
}
}
@ -119,6 +132,7 @@ Future<void> showDeviceInterface(
required BuildContext context,
required isAllDevices,
List<DeviceModel>? allDevices}) async {
final devicesCubit = context.read<DevicesCubit>();
switch (device.productType) {

View File

@ -8,7 +8,11 @@ import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart'
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
class WHList extends StatelessWidget {
const WHList({super.key, required this.whList, required this.allSwitches});
const WHList({
required this.whList,
required this.allSwitches,
super.key,
});
final List<GroupWHModel> whList;
final bool allSwitches;
@ -22,43 +26,42 @@ class WHList extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 10),
const BodySmall(text: 'All Lights'),
const BodySmall(text: 'All Water Heaters'),
const SizedBox(height: 5),
DevicesDefaultSwitch(
off: 'OFF',
on: 'ON',
switchValue: allSwitches,
action: () {
BlocProvider.of<WaterHeaterBloc>(context)
.add(GroupAllOnEvent());
},
secondAction: () {
BlocProvider.of<WaterHeaterBloc>(context)
.add(GroupAllOffEvent());
},
action: () => context.read<WaterHeaterBloc>().add(
GroupAllOnEvent(),
),
secondAction: () => context.read<WaterHeaterBloc>().add(
GroupAllOffEvent(),
),
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
padding: EdgeInsetsDirectional.zero,
itemCount: whList.length,
itemBuilder: (context, index) {
final waterHeater = whList[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 10),
BodySmall(text: whList[index].deviceName),
BodySmall(text: waterHeater.deviceName),
const SizedBox(height: 5),
DevicesDefaultSwitch(
off: 'OFF',
on: 'ON',
switchValue: whList[index].firstSwitch,
action: () {
BlocProvider.of<WaterHeaterBloc>(context).add(
switchValue: waterHeater.firstSwitch,
action: () => context.read<WaterHeaterBloc>().add(
ChangeFirstWizardSwitchStatusEvent(
value: whList[index].firstSwitch,
deviceId: whList[index].deviceId));
},
value: waterHeater.firstSwitch,
deviceId: waterHeater.deviceId,
),
),
),
],
);

View File

@ -1,10 +1,12 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/auth/model/user_model.dart';
import 'package:syncrow_app/features/menu/bloc/create_unit_bloc/create_unit_event.dart';
import 'package:syncrow_app/features/menu/bloc/create_unit_bloc/create_unit_state.dart';
import 'package:syncrow_app/services/api/home_creation_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class CreateUnitBloc extends Bloc<CreateUnitEvent, CreateUnitState> {
@ -239,8 +241,13 @@ Future<String> _createNewRoom(
required String communityId}) async {
try {
Map<String, String> body = {'subspaceName': roomName};
Project? project = HomeCubit.getInstance().project;
final response = await HomeCreation.createRoom(
communityId: communityId, spaceId: unitId, body: body);
communityId: communityId,
spaceId: unitId,
body: body,
projectId: project?.uuid ?? TempConst.projectIdDev);
// if (response['data']['uuid'] != '') {
// final result = await _assignToRoom(roomId: response['data']['uuid'], userId: userId);

View File

@ -1,5 +1,6 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_event.dart';
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_state.dart';
@ -7,6 +8,7 @@ import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_creation_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
List<DeviceModel> allDevices = [];
@ -24,8 +26,12 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
FetchRoomsEvent event, Emitter<ManageUnitState> emit) async {
try {
emit(LoadingState());
Project? project = HomeCubit.getInstance().project;
final roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
event.unit.community.uuid,
event.unit.id,
project?.uuid ?? TempConst.projectIdDev);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(const ErrorState(message: 'Something went wrong'));
@ -37,12 +43,16 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
FetchDevicesByRoomIdEvent event, Emitter<ManageUnitState> emit) async {
try {
Map<String, bool> roomDevicesId = {};
Project? project = HomeCubit.getInstance().project;
emit(LoadingState());
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
allDevices = await HomeManagementAPI.fetchDevicesByUserId();
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
allDevices = await HomeManagementAPI.fetchDevices(
project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
@ -72,14 +82,21 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
AssignRoomEvent event, Emitter<ManageUnitState> emit) async {
try {
Map<String, bool> roomDevicesId = {};
Project? project = HomeCubit.getInstance().project;
emit(LoadingState());
await HomeManagementAPI.assignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, event.deviceId);
event.unit.community.uuid,
event.unit.id,
event.roomId,
event.deviceId,
project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
@ -105,19 +122,25 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
}
}
void _unassignDevice(
UnassignRoomEvent event, Emitter<ManageUnitState> emit) async {
try {
Map<String, bool> roomDevicesId = {};
Project? project = HomeCubit.getInstance().project;
emit(LoadingState());
await HomeManagementAPI.unAssignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, event.deviceId);
event.unit.community.uuid,
event.unit.id,
event.roomId,
event.deviceId,
project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
@ -143,18 +166,22 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
}
}
_addNewRoom(AddNewRoom event, Emitter<ManageUnitState> emit) async {
Map<String, String> body = {'subspaceName': event.roomName};
try {
emit(LoadingState());
Project? project = HomeCubit.getInstance().project;
final response = await HomeCreation.createRoom(
communityId: event.unit.community.uuid,
spaceId: event.unit.id,
body: body);
body: body,
projectId: project?.uuid ?? TempConst.projectIdDev);
if (response['data']['uuid'] != '') {
final roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
event.unit.community.uuid,
event.unit.id,
project?.uuid ?? TempConst.projectIdDev);
allDevices = await HomeManagementAPI.fetchDevicesByUserId();
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
await HomeCubit.getInstance().fetchUnitsByUserId();

View File

@ -23,8 +23,8 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
String timeZoneSelected = '';
String regionSelected = '';
final TextEditingController searchController = TextEditingController();
final TextEditingController nameController =
TextEditingController(text: '${HomeCubit.user!.firstName} ${HomeCubit.user!.lastName}');
final TextEditingController nameController = TextEditingController(
text: '${HomeCubit.user!.firstName} ${HomeCubit.user!.lastName}');
List<RegionModel> allRegions = [];
List<TimeZone> allTimeZone = [];
@ -77,10 +77,13 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
emit(NameEditingState(editName: editName));
}
void _fetchUserInfo(InitialProfileEvent event, Emitter<ProfileState> emit) async {
void _fetchUserInfo(
InitialProfileEvent event, Emitter<ProfileState> emit) async {
try {
emit(LoadingInitialState());
HomeCubit.user = await ProfileApi().fetchUserInfo(HomeCubit.user!.uuid);
HomeCubit.getInstance().project = HomeCubit.user?.project;
emit(SaveState());
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
@ -88,7 +91,8 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future _fetchTimeZone(TimeZoneInitialEvent event, Emitter<ProfileState> emit) async {
Future _fetchTimeZone(
TimeZoneInitialEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
try {
allTimeZone = await ProfileApi.fetchTimeZone();
@ -100,7 +104,8 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future selectTimeZone(SelectTimeZoneEvent event, Emitter<ProfileState> emit) async {
Future selectTimeZone(
SelectTimeZoneEvent event, Emitter<ProfileState> emit) async {
try {
emit(LoadingInitialState());
timeZoneSelected = event.val;
@ -112,7 +117,8 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future selectRegion(SelectRegionEvent event, Emitter<ProfileState> emit) async {
Future selectRegion(
SelectRegionEvent event, Emitter<ProfileState> emit) async {
try {
emit(LoadingInitialState());
await ProfileApi.saveRegion(regionUuid: event.val);
@ -124,7 +130,8 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future<void> searchRegion(SearchRegionEvent event, Emitter<ProfileState> emit) async {
Future<void> searchRegion(
SearchRegionEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
final query = event.query.toLowerCase();
if (allRegions.isEmpty) {
@ -140,7 +147,8 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future<void> searchTimeZone(SearchTimeZoneEvent event, Emitter<ProfileState> emit) async {
Future<void> searchTimeZone(
SearchTimeZoneEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
final query = event.query.toLowerCase();
if (allTimeZone.isEmpty) {
@ -156,7 +164,8 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
void _fetchRegion(RegionInitialEvent event, Emitter<ProfileState> emit) async {
void _fetchRegion(
RegionInitialEvent event, Emitter<ProfileState> emit) async {
try {
emit(LoadingInitialState());
allRegions = await ProfileApi.fetchRegion();
@ -166,7 +175,8 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future<void> _selectImage(SelectImageEvent event, Emitter<ProfileState> emit) async {
Future<void> _selectImage(
SelectImageEvent event, Emitter<ProfileState> emit) async {
try {
if (await _requestPermission()) {
emit(ChangeImageState());
@ -283,7 +293,8 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
return false;
} else {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
bool firstClick = sharedPreferences.getBool('firstPermission') ?? true;
await sharedPreferences.setBool('firstPermission', false);
if (firstClick == false) {

View File

@ -28,8 +28,7 @@ class AssignDeviceView extends StatelessWidget {
listener: (context, state) {
if (state is FetchDeviceByRoomIdState) {
if (state.allDevices.isEmpty) {
CustomSnackBar.displaySnackBar(
'You do not have the permission to assign devices');
CustomSnackBar.displaySnackBar('You do not have the devices');
Navigator.of(context).pop();
}
}

View File

@ -16,23 +16,16 @@ class ManageHomeView extends StatelessWidget {
var spaces = HomeCubit.getInstance().spaces;
return DefaultScaffold(
title: 'Manage Your Home',
child: spaces == null
height: MediaQuery.sizeOf(context).height,
child: spaces.isEmpty
? const Center(
child: BodyMedium(text: 'No spaces found'),
)
: Column(
children: [
DefaultContainer(
padding: const EdgeInsets.symmetric(
horizontal: 25,
vertical: 20,
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: List.generate(
spaces.length,
(index) {
: DefaultContainer(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 25),
child: ListView.builder(
itemCount: spaces.length,
itemBuilder: (context, index) {
if (index == spaces.length - 1) {
return InkWell(
onTap: () {
@ -74,7 +67,7 @@ class ManageHomeView extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyMedium(text: HomeCubit.getInstance().spaces![index].name),
BodyMedium(text: HomeCubit.getInstance().spaces[index].name),
const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
@ -90,11 +83,7 @@ class ManageHomeView extends StatelessWidget {
],
),
);
},
),
),
),
],
}),
));
}
}

View File

@ -1,6 +1,8 @@
import 'dart:async';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
@ -348,15 +350,18 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
emit(CreateSceneLoading());
try {
dynamic response;
Project? project = HomeCubit.getInstance().project;
if (event.createSceneModel != null) {
response = event.updateScene
? await SceneApi.updateScene(event.createSceneModel!, event.sceneId)
: await SceneApi.createScene(event.createSceneModel!);
} else if (event.createAutomationModel != null) {
response = event.updateScene
? await SceneApi.updateAutomation(
event.createAutomationModel!, event.sceneId)
: await SceneApi.createAutomation(event.createAutomationModel!);
? await SceneApi.updateAutomation(event.createAutomationModel!,
event.sceneId, project?.uuid ?? '')
: await SceneApi.createAutomation(
event.createAutomationModel!, project?.uuid ?? '');
}
if (response['success'] == true) {
@ -421,6 +426,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
emit(CreateSceneLoading());
try {
Project? project = HomeCubit.getInstance().project;
tasksList.clear();
tempTasksList.clear();
selectedValues.clear();
@ -436,7 +443,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
conditionRule = 'or';
final response = event.isAutomation
? await SceneApi.getAutomationDetails(event.sceneId)
? await SceneApi.getAutomationDetails(
event.sceneId, project?.uuid ?? '')
: await SceneApi.getSceneDetails(event.sceneId);
if (response.id.isNotEmpty) {
if (event.isAutomation) {
@ -605,10 +613,14 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
emit(DeleteSceneLoading());
try {
Project? project = HomeCubit.getInstance().project;
final response =
sceneType.name == CreateSceneEnum.deviceStatusChanges.name
? await SceneApi.deleteAutomation(
automationId: event.sceneId, unitUuid: event.unitUuid)
automationId: event.sceneId,
unitUuid: event.unitUuid,
projectId: project?.uuid ?? '')
: await SceneApi.deleteScene(
sceneId: event.sceneId,
);

View File

@ -2,9 +2,12 @@ import 'dart:async';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
import 'package:syncrow_app/services/api/scene_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
part 'scene_state.dart';
@ -23,9 +26,11 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
emit(SceneLoading());
try {
Project? project = HomeCubit.getInstance().project;
if (event.unitId.isNotEmpty) {
scenes = await SceneApi.getScenesByUnitId(
event.unitId, event.unit.community.uuid,
scenes = await SceneApi.getScenesByUnitId(event.unitId,
event.unit.community.uuid, project?.uuid ?? TempConst.projectIdDev,
showInDevice: event.showInDevice);
emit(SceneLoaded(scenes, automationList));
} else {
@ -41,8 +46,11 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
emit(SceneLoading());
try {
Project? project = HomeCubit.getInstance().project;
if (event.unitId.isNotEmpty) {
automationList = await SceneApi.getAutomationByUnitId(event.unitId);
automationList = await SceneApi.getAutomationByUnitId(
event.unitId, event.communityId, project?.uuid ?? '');
emit(SceneLoaded(scenes, automationList));
} else {
emit(const SceneError(message: 'Unit ID is empty'));
@ -91,11 +99,17 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
));
try {
Project? project = HomeCubit.getInstance().project;
final success = await SceneApi.updateAutomationStatus(
event.automationId, event.automationStatusUpdate);
event.automationId,
event.automationStatusUpdate,
project?.uuid ?? '');
if (success) {
automationList = await SceneApi.getAutomationByUnitId(
event.automationStatusUpdate.spaceUuid);
event.automationStatusUpdate.spaceUuid,
event.communityId,
project?.uuid ?? '');
newLoadingStates[event.automationId] = false;
emit(SceneLoaded(
currentState.scenes,

View File

@ -22,11 +22,13 @@ class LoadScenes extends SceneEvent {
class LoadAutomation extends SceneEvent {
final String unitId;
final String communityId;
const LoadAutomation(this.unitId);
const LoadAutomation(this.unitId, this.communityId);
@override
List<Object> get props => [unitId];
List<Object> get props => [unitId, communityId];
}
class SceneTrigger extends SceneEvent {
@ -43,8 +45,9 @@ class SceneTrigger extends SceneEvent {
class UpdateAutomationStatus extends SceneEvent {
final String automationId;
final AutomationStatusUpdate automationStatusUpdate;
final String communityId;
const UpdateAutomationStatus({required this.automationStatusUpdate, required this.automationId});
const UpdateAutomationStatus({required this.automationStatusUpdate, required this.automationId, required this.communityId});
@override
List<Object> get props => [automationStatusUpdate];

View File

@ -1,5 +1,3 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_event.dart';
@ -7,19 +5,31 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
class TabBarBloc extends Bloc<TabBarEvent, TabBarState> {
final DeviceManagerBloc deviceManagerBloc;
TabBarBloc(this.deviceManagerBloc) : super(const Initial()) {
on<TabChanged>(_handleTabChanged);
TabBarBloc(this.deviceManagerBloc) : super(const TabBarInitialState()) {
on<TabBarTabChangedEvent>(_onTabBarTabChangedEvent);
}
FutureOr<void> _handleTabChanged(
TabChanged event, Emitter<TabBarState> emit) {
final DeviceManagerBloc deviceManagerBloc;
void _onTabBarTabChangedEvent(
TabBarTabChangedEvent event,
Emitter<TabBarState> emit,
) {
_getDevices(event);
emit(
TabBarTabSelectedState(
roomId: event.roomId,
selectedTabIndex: event.selectedIndex,
),
);
}
void _getDevices(TabBarTabChangedEvent event) {
if (event.roomId == "-1") {
deviceManagerBloc.add(FetchAllDevices());
} else {
deviceManagerBloc.add(FetchDevicesByRoomId(event.roomId, event.unit));
}
emit(TabSelected(
roomId: event.roomId, selectedTabIndex: event.selectedIndex));
}
}

View File

@ -4,10 +4,14 @@ abstract class TabBarEvent {
const TabBarEvent();
}
class TabChanged extends TabBarEvent {
class TabBarTabChangedEvent extends TabBarEvent {
const TabBarTabChangedEvent({
required this.selectedIndex,
required this.roomId,
required this.unit,
});
final int selectedIndex;
final String roomId;
final SpaceModel unit;
const TabChanged(
{required this.selectedIndex, required this.roomId, required this.unit});
}

View File

@ -2,12 +2,16 @@ abstract class TabBarState {
const TabBarState();
}
class Initial extends TabBarState {
const Initial();
class TabBarInitialState extends TabBarState {
const TabBarInitialState();
}
class TabSelected extends TabBarState {
class TabBarTabSelectedState extends TabBarState {
const TabBarTabSelectedState({
required this.roomId,
required this.selectedTabIndex,
});
final int selectedTabIndex;
final String roomId;
const TabSelected({required this.roomId, required this.selectedTabIndex});
}

View File

@ -0,0 +1,78 @@
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
import 'package:syncrow_app/generated/assets.dart';
class OneGangHelperFunctions {
static List<SceneStaticFunction> oneGangHelperFunctions(
String deviceId, String deviceName, functionValue) {
return [
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'Light Switch',
code: 'switch_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'Light CountDown',
code: 'countdown_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.countdown,
operationalValues: [
SceneOperationalValue(icon: '', value: 0),
],
),
];
}
static List<SceneStaticFunction> oneGangAutomationFunctions(
String deviceId, String deviceName, functionValue) {
return [
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'Light Switch',
code: 'switch_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'Light CountDown',
code: 'countdown_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.integerSteps,
operationalValues: [
SceneOperationalValue(
icon: '',
description: "sec",
value: 0.0,
minValue: 0,
maxValue: 43200,
stepValue: 1,
),
],
),
];
}
}

View File

@ -10,7 +10,7 @@ class ThreeGangHelperFunctions {
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'Light 1 Switch',
operationName: 'L - Light Switch',
code: 'switch_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
@ -21,11 +21,23 @@ class ThreeGangHelperFunctions {
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'L - Light Countdown',
code: 'countdown_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.countdown,
operationalValues: [
SceneOperationalValue(icon: '', value: 0),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'Light 2 Switch',
operationName: 'M - Light Switch',
code: 'switch_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
@ -36,11 +48,23 @@ class ThreeGangHelperFunctions {
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'M - Light Countdown',
code: 'countdown_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.countdown,
operationalValues: [
SceneOperationalValue(icon: '', value: 0),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'Light 3 Switch',
operationName: 'R - Light Switch',
code: 'switch_3',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
@ -55,31 +79,7 @@ class ThreeGangHelperFunctions {
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'Light 1 CountDown',
code: 'countdown_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.countdown,
operationalValues: [
SceneOperationalValue(icon: '', value: 0),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'Light 2 CountDown',
code: 'countdown_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.countdown,
operationalValues: [
SceneOperationalValue(icon: '', value: 0),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'Light 3 CountDown',
operationName: 'R - Light Countdown',
code: 'countdown_3',
functionValue: functionValue,
operationDialogType: OperationDialogType.countdown,
@ -97,7 +97,7 @@ class ThreeGangHelperFunctions {
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'Light 1 Switch',
operationName: 'L - Light Switch',
code: 'switch_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
@ -108,41 +108,11 @@ class ThreeGangHelperFunctions {
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'Light 2 Switch',
code: 'switch_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'Light 3 Switch',
code: 'switch_3',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'Light 1 CountDown',
operationName: 'L - Light Countdown',
code: 'countdown_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.integerSteps,
@ -157,11 +127,26 @@ class ThreeGangHelperFunctions {
),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'M - Light Switch',
code: 'switch_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'Light 2 CountDown',
operationName: 'M - Light Countdown',
code: 'countdown_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.integerSteps,
@ -176,11 +161,26 @@ class ThreeGangHelperFunctions {
),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'R - Light Switch',
code: 'switch_3',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'Light 3 CountDown',
operationName: 'R - Light Countdown',
code: 'countdown_3',
functionValue: functionValue,
operationDialogType: OperationDialogType.integerSteps,

View File

@ -0,0 +1,139 @@
import 'package:syncrow_app/features/scene/enum/operation_dialog_type.dart';
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
import 'package:syncrow_app/generated/assets.dart';
class TowGangHelperFunctions {
static List<SceneStaticFunction> towGangHelperFunctions(
String deviceId, String deviceName, functionValue) {
return [
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'L - Light Switch',
code: 'switch_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'L - Light CountDown',
code: 'countdown_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.countdown,
operationalValues: [
SceneOperationalValue(icon: '', value: 0),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'R - Light Switch',
code: 'switch_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'R - Light CountDown',
code: 'countdown_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.countdown,
operationalValues: [
SceneOperationalValue(icon: '', value: 0),
],
),
];
}
static List<SceneStaticFunction> towGangAutomationFunctions(
String deviceId, String deviceName, functionValue) {
return [
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'L - Light Switch',
code: 'switch_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'R - Light CountDown',
code: 'countdown_1',
functionValue: functionValue,
operationDialogType: OperationDialogType.integerSteps,
operationalValues: [
SceneOperationalValue(
icon: '',
description: "sec",
value: 0.0,
minValue: 0,
maxValue: 43200,
stepValue: 1,
),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsAcPower,
operationName: 'R - Light Switch',
code: 'switch_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.onOff,
operationalValues: [
SceneOperationalValue(
icon: Assets.assetsAcPower, description: "ON", value: true),
SceneOperationalValue(
icon: Assets.assetsAcPowerOFF, description: "OFF", value: false),
],
),
SceneStaticFunction(
deviceId: deviceId,
deviceName: deviceName,
icon: Assets.assetsLightCountdown,
operationName: 'R - Light CountDown',
code: 'countdown_2',
functionValue: functionValue,
operationDialogType: OperationDialogType.integerSteps,
operationalValues: [
SceneOperationalValue(
icon: '',
description: "sec",
value: 0.0,
minValue: 0,
maxValue: 43200,
stepValue: 1,
),
],
),
];
}
}

View File

@ -0,0 +1,48 @@
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/app_layout/model/community_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
abstract final class SceneBlocFactory {
static SceneBloc create({
required bool pageType,
required HomeCubit homeCubit,
}) {
final selectedSpace = homeCubit.selectedSpace;
final defaultSpace = SpaceModel(
id: '-1',
name: '',
community: Community(
uuid: '-1',
name: '',
),
);
final spaceId = selectedSpace?.id ?? defaultSpace.id;
final space = selectedSpace ?? defaultSpace;
final communityUuid =
selectedSpace?.community.uuid ?? defaultSpace.community.uuid;
final sceneBloc = SceneBloc();
sceneBloc.add(
LoadScenes(
spaceId,
space,
showInDevice: pageType,
),
);
if (!pageType) {
sceneBloc.add(
LoadAutomation(
spaceId,
communityUuid,
),
);
}
return sceneBloc;
}
}

View File

@ -6,16 +6,19 @@ import 'package:syncrow_app/features/scene/helper/functions_per_device/ac_functi
import 'package:syncrow_app/features/scene/helper/functions_per_device/door_lock_functions.dart';
import 'package:syncrow_app/features/scene/helper/functions_per_device/gateway_functions.dart';
import 'package:syncrow_app/features/scene/helper/functions_per_device/human_presence_functions.dart';
import 'package:syncrow_app/features/scene/helper/functions_per_device/one_gang_functions.dart';
import 'package:syncrow_app/features/scene/helper/functions_per_device/presence_sensor.dart';
import 'package:syncrow_app/features/scene/helper/functions_per_device/three_gang_functions.dart';
import 'package:syncrow_app/features/scene/helper/functions_per_device/tow_gang_helper_functions.dart';
import 'package:syncrow_app/features/scene/model/scene_details_model.dart';
import 'package:syncrow_app/features/scene/model/scene_static_function.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
mixin SceneOperationsDataHelper {
final Map<DeviceType, Function(List<FunctionModel>, String, String, dynamic, bool)> _functionMap =
{
final Map<DeviceType,
Function(List<FunctionModel>, String, String, dynamic, bool)>
_functionMap = {
DeviceType.LightBulb: lightBulbFunctions,
DeviceType.CeilingSensor: ceilingSensorFunctions,
DeviceType.WallSensor: wallSensorFunctions,
@ -24,6 +27,8 @@ mixin SceneOperationsDataHelper {
DeviceType.Curtain: curtainFunctions,
DeviceType.ThreeGang: threeGangFunctions,
DeviceType.Gateway: gatewayFunctions,
DeviceType.OneGang: oneGangFunctions,
DeviceType.TwoGang: towGangFunctions,
};
final Map<DeviceType, String> _titleMap = {
@ -35,8 +40,39 @@ mixin SceneOperationsDataHelper {
DeviceType.Curtain: 'Curtain Functions',
DeviceType.ThreeGang: '3G Light Switch Functions',
DeviceType.Gateway: 'Gateway Functions',
DeviceType.OneGang: '1G Light Switch Conditions',
DeviceType.TwoGang: '2G Light Switch Conditions',
};
//one gang functions
static List<SceneStaticFunction> oneGangFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
if (isAutomation) {
return OneGangHelperFunctions.oneGangAutomationFunctions(
deviceId, deviceName, functionValue);
}
return OneGangHelperFunctions.oneGangHelperFunctions(
deviceId, deviceName, functionValue);
}
static List<SceneStaticFunction> towGangFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
if (isAutomation) {
return TowGangHelperFunctions.towGangAutomationFunctions(
deviceId, deviceName, functionValue);
}
return TowGangHelperFunctions.towGangHelperFunctions(
deviceId, deviceName, functionValue);
}
List<SceneStaticFunction> getFunctionsWithIcons({
DeviceType? type,
required List<FunctionModel> functions,
@ -45,16 +81,22 @@ mixin SceneOperationsDataHelper {
required bool isAutomation,
}) {
final functionValue = null;
return _functionMap[type]?.call(functions, deviceId, deviceName, functionValue, isAutomation) ??
lightBulbFunctions(functions, deviceId, deviceName, functionValue, isAutomation);
return _functionMap[type]?.call(
functions, deviceId, deviceName, functionValue, isAutomation) ??
lightBulbFunctions(
functions, deviceId, deviceName, functionValue, isAutomation);
}
String getTitle({DeviceType? type}) {
return _titleMap[type] ?? '';
}
static List<SceneStaticFunction> ceilingSensorFunctions(List<FunctionModel> functions,
String deviceId, String deviceName, dynamic functionValue, bool isAutomation) {
static List<SceneStaticFunction> ceilingSensorFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
if (isAutomation) {
return PresenceSensorHelperFunctions.automationPresenceSensorFunctions(
deviceId, deviceName, functionValue);
@ -63,22 +105,35 @@ mixin SceneOperationsDataHelper {
deviceId, deviceName, functionValue);
}
static List<SceneStaticFunction> curtainFunctions(List<FunctionModel> functions, String deviceId,
String deviceName, dynamic functionValue, bool isAutomation) {
static List<SceneStaticFunction> curtainFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
return [];
}
static List<SceneStaticFunction> doorLockFunctions(List<FunctionModel> functions, String deviceId,
String deviceName, dynamic functionValue, bool isAutomation) {
static List<SceneStaticFunction> doorLockFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
if (isAutomation) {
return DoorLockHelperFunctions.doorLockAutomationFunctions(
deviceId, deviceName, functionValue);
}
return DoorLockHelperFunctions.doorLockTapToRunFunctions(deviceId, deviceName, functionValue);
return DoorLockHelperFunctions.doorLockTapToRunFunctions(
deviceId, deviceName, functionValue);
}
static List<SceneStaticFunction> wallSensorFunctions(List<FunctionModel> functions,
String deviceId, String deviceName, dynamic functionValue, bool isAutomation) {
static List<SceneStaticFunction> wallSensorFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
if (isAutomation) {
return HumanPresenceHelperFunctions.automationHumanPresenceFunctions(
deviceId, deviceName, functionValue);
@ -87,31 +142,51 @@ mixin SceneOperationsDataHelper {
deviceId, deviceName, functionValue);
}
static List<SceneStaticFunction> lightBulbFunctions(List<FunctionModel> functions,
String deviceId, String deviceName, dynamic functionValue, bool isAutomation) {
static List<SceneStaticFunction> lightBulbFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
return [];
}
static List<SceneStaticFunction> gatewayFunctions(List<FunctionModel> functions, String deviceId,
String deviceName, dynamic functionValue, bool isAutomation) {
return GatewayHelperFunctions.tabToRunGatewayFunctions(deviceId, deviceName, functionValue);
static List<SceneStaticFunction> gatewayFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
return GatewayHelperFunctions.tabToRunGatewayFunctions(
deviceId, deviceName, functionValue);
}
static List<SceneStaticFunction> threeGangFunctions(List<FunctionModel> functions,
String deviceId, String deviceName, dynamic functionValue, bool isAutomation) {
static List<SceneStaticFunction> threeGangFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
if (isAutomation) {
return ThreeGangHelperFunctions.threeGangAutomationFunctions(
deviceId, deviceName, functionValue);
}
return ThreeGangHelperFunctions.threeGangHelperFunctions(deviceId, deviceName, functionValue);
return ThreeGangHelperFunctions.threeGangHelperFunctions(
deviceId, deviceName, functionValue);
}
static List<SceneStaticFunction> acFunctions(List<FunctionModel> functions, String deviceId,
String deviceName, dynamic functionValue, bool isAutomation) {
static List<SceneStaticFunction> acFunctions(
List<FunctionModel> functions,
String deviceId,
String deviceName,
dynamic functionValue,
bool isAutomation) {
if (isAutomation) {
return ACFunctionsHelper.automationAcFunctions(deviceId, deviceName, functionValue);
return ACFunctionsHelper.automationAcFunctions(
deviceId, deviceName, functionValue);
}
return ACFunctionsHelper.tabToRunAcFunctions(deviceId, deviceName, functionValue);
return ACFunctionsHelper.tabToRunAcFunctions(
deviceId, deviceName, functionValue);
}
List<SceneStaticFunction> getTaskListFunctionsFromApi({
@ -149,8 +224,12 @@ mixin SceneOperationsDataHelper {
SceneStaticFunction(
deviceId: action.entityId,
deviceName: action.name.toString(),
deviceIcon: action.type == 'automation' ? Assets.player : Assets.handClickIcon,
icon: action.type == 'automation' ? Assets.player : Assets.handClickIcon,
deviceIcon: action.type == 'automation'
? Assets.player
: Assets.handClickIcon,
icon: action.type == 'automation'
? Assets.player
: Assets.handClickIcon,
operationName: action.type.toString(),
operationDialogType: OperationDialogType.onOff,
functionValue: action.actionExecutor,
@ -170,7 +249,8 @@ mixin SceneOperationsDataHelper {
),
);
} else {
functions.add(_mapExecutorPropertyToSceneFunction(action, isAutomation));
functions
.add(_mapExecutorPropertyToSceneFunction(action, isAutomation));
}
}
@ -179,6 +259,8 @@ mixin SceneOperationsDataHelper {
for (var condition in conditions) {
// Create a dummy Action from Condition to reuse _mapExecutorPropertyToSceneFunction
Action dummyAction = Action(
deviceName: condition.deviceName,
productType: condition.productType,
actionExecutor: 'device_report',
entityId: condition.entityId,
executorProperty: ExecutorProperty(
@ -206,7 +288,9 @@ mixin SceneOperationsDataHelper {
}) {
final executorProperty = action.executorProperty;
final Map<String, SceneStaticFunction Function(Action, bool, String?, String?)> functionMap = {
final Map<String,
SceneStaticFunction Function(Action, bool, String?, String?)>
functionMap = {
'sensitivity': _createSensitivityFunction,
'normal_open_switch': _createNormalOpenSwitchFunction,
'unlock_fingerprint': _createUnlockFingerprintFunction,
@ -282,14 +366,16 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createSensitivityFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createSensitivityFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Sensitivity',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.listOfOptions,
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.listOfOptions,
isAutomation ? _createIntegerStepsOptions() : _createSensitivityOptions(),
isAutomation,
comparator,
@ -297,11 +383,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createNormalOpenSwitchFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createNormalOpenSwitchFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Set Door lock Normal Open',
OperationDialogType.onOff,
@ -351,11 +437,11 @@ mixin SceneOperationsDataHelper {
];
}
SceneStaticFunction _createUnlockFingerprintFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createUnlockFingerprintFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Fingerprint Unlock',
OperationDialogType.integerSteps,
@ -366,11 +452,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createUnlockPasswordFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createUnlockPasswordFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Password Unlock',
OperationDialogType.integerSteps,
@ -381,11 +467,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createUnlockCardFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createUnlockCardFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Card Unlock',
OperationDialogType.integerSteps,
@ -396,11 +482,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createAlarmLockFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createAlarmLockFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Lock Alarm',
OperationDialogType.listOfOptions,
@ -411,11 +497,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createUnlockRequestFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createUnlockRequestFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Remote Unlock Request',
OperationDialogType.integerSteps,
@ -426,11 +512,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createResidualElectricityFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createResidualElectricityFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Residual Electricity',
OperationDialogType.integerSteps,
@ -441,11 +527,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createReverseLockFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createReverseLockFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Double Lock',
OperationDialogType.onOff,
@ -456,11 +542,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createUnlockAppFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createUnlockAppFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Remote Unlock Via App',
OperationDialogType.integerSteps,
@ -471,11 +557,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createHijackFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createHijackFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Hijack Alarm',
OperationDialogType.onOff,
@ -486,11 +572,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createDoorbellFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createDoorbellFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Doorbell',
OperationDialogType.onOff,
@ -501,11 +587,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createUnlockTemporaryFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createUnlockTemporaryFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'WIFI LOCK PRO',
action.deviceName,
Assets.assetsIconsDoorLock,
'Temporary Password Unlock',
OperationDialogType.integerSteps,
@ -516,11 +602,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createFarDetectionFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createFarDetectionFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Far Detection',
OperationDialogType.listOfOptions,
@ -531,11 +617,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createMotionSensitivityFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createMotionSensitivityFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Motion Detection Sensitivity',
OperationDialogType.listOfOptions,
@ -546,11 +632,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createMotionlessSensitivityFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createMotionlessSensitivityFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Motionless Detection Sensitivity',
OperationDialogType.listOfOptions,
@ -561,11 +647,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createIndicatorFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createIndicatorFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Indicator',
OperationDialogType.onOff,
@ -576,11 +662,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createPresenceTimeFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createPresenceTimeFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Nobody Time',
OperationDialogType.countdown,
@ -591,11 +677,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createPresenceStateFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createPresenceStateFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Presence State',
OperationDialogType.listOfOptions,
@ -606,14 +692,16 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createDisCurrentFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createDisCurrentFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Current Distance',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.countdown,
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
_createCurrentDistanceOptions(),
isAutomation,
comparator,
@ -621,11 +709,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createIlluminanceValueFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createIlluminanceValueFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Illuminance Value',
OperationDialogType.integerSteps,
@ -636,11 +724,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createCheckingResultFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createCheckingResultFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Human Presence Sensor',
action.deviceName,
Assets.assetsIconsSensors,
'Self-Test Result',
OperationDialogType.listOfOptions,
@ -651,11 +739,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createSwitchFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createSwitchFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Power',
OperationDialogType.onOff,
@ -666,26 +754,30 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createTempSetFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createTempSetFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Set Temperature',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.temperature,
isAutomation ? _createAutomationTemperatureOptions() : _createTemperatureOptions(),
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.temperature,
isAutomation
? _createAutomationTemperatureOptions()
: _createTemperatureOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
}
SceneStaticFunction _createTempCurrentFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createTempCurrentFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Current Temperature',
OperationDialogType.integerSteps,
@ -696,11 +788,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createModeFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createModeFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Mode',
OperationDialogType.listOfOptions,
@ -711,11 +803,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createLevelFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createLevelFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Fan Speed',
OperationDialogType.listOfOptions,
@ -726,11 +818,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createChildLockFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createChildLockFunction(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Smart AC Thermostat - Grey - Model A',
action.deviceName,
Assets.assetsIconsAC,
'Child Lock',
OperationDialogType.onOff,
@ -741,11 +833,13 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createSwitch1Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createSwitch1Function(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
switch (action.productType) {
case "3G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 1 Switch',
OperationDialogType.onOff,
@ -754,13 +848,52 @@ mixin SceneOperationsDataHelper {
comparator,
uniqueCustomId,
);
}
SceneStaticFunction _createSwitch2Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
case "2G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.twoGang,
'Light 1 Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
case "1G":
return _createSceneFunction(
action,
action.deviceName,
Assets.oneGang,
'Light 1 Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
default:
return _createSceneFunction(
action,
'None',
Assets.assetsRemoteUnlockReq,
'None',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
}
}
SceneStaticFunction _createSwitch2Function(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
switch (action.productType) {
case "3G":
return _createSceneFunction(
action,
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 2 Switch',
OperationDialogType.onOff,
@ -769,13 +902,38 @@ mixin SceneOperationsDataHelper {
comparator,
uniqueCustomId,
);
}
SceneStaticFunction _createSwitch3Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
case "2G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.twoGang,
'Light 2 Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
default:
return _createSceneFunction(
action,
action.deviceName,
Assets.oneGang,
'Light Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
}
}
SceneStaticFunction _createSwitch3Function(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 3 Switch',
OperationDialogType.onOff,
@ -786,56 +944,138 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createCountdown1Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createCountdown1Function(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
switch (action.productType) {
case "3G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 1 CountDown',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.countdown,
isAutomation ? _createAutomationCountDownOptions() : _createCountdownOptions(),
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
case "2G":
return _createSceneFunction(
action,
action.deviceName,
Assets.twoGang,
'Light 1 CountDown',
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
default:
return _createSceneFunction(
action,
action.deviceName,
Assets.oneGang,
'Light CountDown',
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
}
}
SceneStaticFunction _createCountdown2Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createCountdown2Function(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
switch (action.productType) {
case "3G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 2 CountDown',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.countdown,
isAutomation ? _createAutomationCountDownOptions() : _createCountdownOptions(),
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
case "2G":
return _createSceneFunction(
action,
action.deviceName,
Assets.twoGang,
'Light 2 CountDown',
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
default:
return _createSceneFunction(
action,
action.deviceName,
Assets.oneGang,
'Light CountDown',
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
}
}
SceneStaticFunction _createCountdown3Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createCountdown3Function(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
action.deviceName,
Assets.assetsIcons3GangSwitch,
'Light 3 CountDown',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.countdown,
isAutomation ? _createAutomationCountDownOptions() : _createCountdownOptions(),
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
}
SceneStaticFunction _createSwitchAlarmSoundFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createSwitchAlarmSoundFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Gateway',
action.deviceName,
Assets.assetsIconsGateway,
'Switch Alarm Sound',
OperationDialogType.onOff,
@ -846,11 +1086,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createMasterStateFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createMasterStateFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Gateway',
action.deviceName,
Assets.assetsIconsGateway,
'Master State',
OperationDialogType.listOfOptions,
@ -861,11 +1101,11 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createFactoryResetFunction(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createFactoryResetFunction(Action action,
bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'Gateway',
action.deviceName,
Assets.assetsIconsGateway,
'Factory Reset',
OperationDialogType.onOff,
@ -1180,8 +1420,12 @@ mixin SceneOperationsDataHelper {
uniqueCustomId: taskItem.uniqueCustomId,
deviceId: taskItem.deviceId,
deviceName: taskItem.deviceName.toString(),
deviceIcon: taskItem.operationName == 'automation' ? Assets.player : Assets.handClickIcon,
icon: taskItem.operationName == 'automation' ? Assets.player : Assets.handClickIcon,
deviceIcon: taskItem.operationName == 'automation'
? Assets.player
: Assets.handClickIcon,
icon: taskItem.operationName == 'automation'
? Assets.player
: Assets.handClickIcon,
operationName: taskItem.operationName,
operationDialogType: OperationDialogType.onOff,
functionValue: taskItem.functionValue == 'rule_enable' ? true : false,
@ -1204,6 +1448,8 @@ mixin SceneOperationsDataHelper {
return [
_mapExecutorPropertyToSceneFunction(
Action(
deviceName: taskItem.deviceName,
productType: '',
entityId: deviceId,
executorProperty: ExecutorProperty(
functionCode: taskItem.code,

View File

@ -74,6 +74,9 @@ class Action {
ExecutorProperty? executorProperty;
String? name;
String? type;
final String productType;
final String deviceName;
Action({
required this.actionExecutor,
@ -81,6 +84,8 @@ class Action {
this.executorProperty,
this.name,
this.type,
required this.productType,
required this.deviceName,
});
String toRawJson() => json.encode(toJson());
@ -88,10 +93,12 @@ class Action {
static Action? fromJson(Map<String, dynamic> json) {
if (json['name'] != null && json['type'] != null) {
return Action(
actionExecutor: json["actionExecutor"],
entityId: json["entityId"],
name: json['name'],
type: json['type'],
actionExecutor: json["actionExecutor"] as String,
entityId: json["entityId"] as String,
name: json['name'] as String?,
type: json['type'] as String?,
productType: json['productType'] as String,
deviceName: json['deviceName'] as String,
);
}
if (json["executorProperty"] == null) {
@ -99,9 +106,11 @@ class Action {
}
return Action(
actionExecutor: json["actionExecutor"],
entityId: json["entityId"],
actionExecutor: json["actionExecutor"] as String,
entityId: json["entityId"] as String,
executorProperty: ExecutorProperty.fromJson(json["executorProperty"]),
productType: json['productType'] as String,
deviceName: json['deviceName'] as String,
);
}
@ -142,12 +151,16 @@ class Condition {
final String entityId;
final String entityType;
final Expr expr;
final String productType;
final String deviceName;
Condition({
required this.code,
required this.entityId,
required this.entityType,
required this.expr,
required this.productType,
required this.deviceName,
});
factory Condition.fromRawJson(String str) =>
@ -160,6 +173,8 @@ class Condition {
entityId: json["entityId"],
entityType: json["entityType"],
expr: Expr.fromJson(json["expr"]),
productType: json['productType'] as String,
deviceName: json['deviceName'] as String,
);
Map<String, dynamic> toJson() => {

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.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/scene/bloc/create_scene/create_scene_bloc.dart';
@ -11,11 +12,10 @@ import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/light_divider.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigate_to_route.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class DeviceFunctionsView extends StatelessWidget
@ -51,22 +51,14 @@ class DeviceFunctionsView extends StatelessWidget
.add(AddTaskEvent(isAutomation: isAutomation));
navigateToRoute(context, Routes.sceneTasksRoute);
},
child: BodyMedium(
text: 'Save',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.secondaryColor.withOpacity(0.6),
),
child: SvgPicture.asset(Assets.saveRoutinesIcon),
),
],
leading: TextButton(
onPressed: () {
_cancelOperation(context, device, isAutomation);
},
child: BodyMedium(
text: 'Cancel',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.textPrimaryColor.withOpacity(0.6),
),
child: SvgPicture.asset(Assets.cancelIcon),
),
leadingWidth: 80,
padding: EdgeInsets.zero,
@ -75,6 +67,63 @@ class DeviceFunctionsView extends StatelessWidget
itemCount: functions.length,
padding: const EdgeInsets.only(top: 24.0),
itemBuilder: (context, index) {
if (device.productType!.name.toString() == 'ThreeGang' ||
device.productType!.name.toString() == 'TwoGang') {
final bool isFirstInPair = index % 2 == 0;
final bool isLastInPair =
index % 2 == 1 || index == functions.length - 1;
final bool isLastItem = index == functions.length - 1;
return Column(mainAxisSize: MainAxisSize.min, children: [
if (isFirstInPair && index != 0) const SizedBox(height: 16),
DefaultContainer(
padding: EdgeInsets.only(
top: isFirstInPair ? 8 : 0,
bottom: isLastInPair ? 8 : 0,
),
margin: EdgeInsets.zero,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(isFirstInPair ? 20 : 0),
topRight: Radius.circular(isFirstInPair ? 20 : 0),
bottomLeft: Radius.circular(isLastInPair ? 20 : 0),
bottomRight: Radius.circular(isLastInPair ? 20 : 0),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
BlocBuilder<CreateSceneBloc, CreateSceneState>(
builder: (context, state) {
return SceneListTile(
iconsSize: 22,
minLeadingWidth: 20,
assetPath: functions[index].icon,
titleString: functions[index].operationName,
trailingWidget: const Icon(
Icons.arrow_forward_ios_rounded,
color: ColorsManager.greyColor,
size: 16,
),
onPressed: () {
if (isAutomation) {
_showAutomationDialog(
context, functions[index], device);
} else {
_showTabToRunDialog(
context, functions[index], device);
}
},
);
},
),
if (isFirstInPair && !isLastItem)
SizedBox(
width: context.width * 0.8,
child: const LightDivider(),
),
],
),
)
]);
} else {
return DefaultContainer(
padding: index == 0
? const EdgeInsets.only(top: 8)
@ -82,13 +131,23 @@ class DeviceFunctionsView extends StatelessWidget
? const EdgeInsets.only(bottom: 8)
: EdgeInsets.zero,
margin: EdgeInsets.zero,
borderRadius: index == 0
borderRadius: index == 0 && index == functions.length - 1
? const BorderRadius.only(
topLeft: Radius.circular(20), topRight: Radius.circular(20))
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
)
: index == 0
? const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
)
: index == functions.length - 1
? const BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20))
bottomRight: Radius.circular(20),
)
: BorderRadius.zero,
child: Column(
mainAxisSize: MainAxisSize.min,
@ -113,28 +172,22 @@ class DeviceFunctionsView extends StatelessWidget
onPressed: () {
if (isAutomation) {
_showAutomationDialog(
context,
functions[index],
device,
);
context, functions[index], device);
} else {
_showTabToRunDialog(
context,
functions[index],
device,
);
context, functions[index], device);
}
},
);
},
),
}),
index != functions.length - 1
? SizedBox(
width: context.width * 0.8, child: const LightDivider())
width: context.width * 0.8,
child: const LightDivider())
: const SizedBox(),
],
),
);
));
}
},
),
);

View File

@ -20,69 +20,69 @@ class SceneRoomsTabBarDevicesView extends StatefulWidget {
_SceneRoomsTabBarDevicesViewState();
}
class _SceneRoomsTabBarDevicesViewState
extends State<SceneRoomsTabBarDevicesView>
class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesView>
with SingleTickerProviderStateMixin {
late final TabController _tabController;
List<SubSpaceModel>? rooms = [];
late final SpaceModel selectedSpace;
var rooms = <SubSpaceModel>[];
@override
void initState() {
super.initState();
selectedSpace = HomeCubit.getInstance().selectedSpace!;
rooms = List.from(HomeCubit.getInstance().selectedSpace?.subspaces ?? []);
if (rooms != null) {
if (rooms![0].id != '-1') {
rooms?.insert(
0,
SubSpaceModel(
rooms = List.from(selectedSpace.subspaces);
final defaultSubSpaceModel = SubSpaceModel(
name: 'All Devices',
devices: context.read<DevicesCubit>().allDevices,
id: '-1',
),
);
if (rooms.isNotEmpty) {
final isFirstRoomIdValid = rooms[0].id != '-1';
if (isFirstRoomIdValid) {
rooms.insert(0, defaultSubSpaceModel);
}
} else {
rooms = [defaultSubSpaceModel];
}
_tabController =
TabController(length: rooms!.length, vsync: this, initialIndex: 0);
_tabController = TabController(length: rooms.length, vsync: this);
_tabController.addListener(_handleTabSwitched);
super.initState();
}
void _handleTabSwitched() {
if (_tabController.indexIsChanging) {
final value = _tabController.index;
/// select tab
context.read<TabBarBloc>().add(TabChanged(
selectedIndex: value,
roomId: rooms?[value].id ?? '',
unit: selectedSpace));
return;
}
}
@override
void dispose() {
super.dispose();
_tabController.dispose();
_tabController.removeListener(() {});
_tabController.dispose();
}
void _handleTabSwitched() {
if (_tabController.indexIsChanging) {
final index = _tabController.index;
context.read<TabBarBloc>().add(
TabBarTabChangedEvent(
selectedIndex: index,
roomId: rooms[index].id ?? '',
unit: selectedSpace,
),
);
return;
}
}
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: StringsManager.createScene,
padding: EdgeInsets.zero,
padding: EdgeInsetsDirectional.zero,
leading: IconButton(
onPressed: () {
navigateToRoute(context, Routes.sceneTasksRoute);
},
icon: const Icon(
Icons.arrow_back_ios,
),
onPressed: () => navigateToRoute(context, Routes.sceneTasksRoute),
icon: const Icon(Icons.arrow_back_ios),
),
title: StringsManager.createScene,
child: SceneDevicesBody(tabController: _tabController, rooms: rooms),
);
}

View File

@ -1,75 +1,45 @@
import 'package:flutter/material.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/model/community_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/scene_listview.dart';
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
import 'package:syncrow_app/features/scene/helper/scene_bloc_factory.dart';
import 'package:syncrow_app/features/scene/widgets/empty_devices_widget.dart';
import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_view.dart';
import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_header.dart';
import 'package:syncrow_app/features/shared_widgets/create_unit.dart';
import 'package:syncrow_app/features/shared_widgets/app_loading_indicator.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/resource_manager/color_manager.dart';
class SceneView extends StatelessWidget {
const SceneView({
this.pageType = false,
super.key,
});
final bool pageType;
const SceneView({super.key, this.pageType = false});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) {
if (pageType) {
return SceneBloc()
..add(LoadScenes(
HomeCubit.getInstance().selectedSpace?.id ?? '',
HomeCubit.getInstance().selectedSpace ??
SpaceModel(
id: '-1',
name: '',
community: Community(
uuid: '-1',
name: '',
)),
showInDevice: pageType));
} else {
return SceneBloc()
..add(LoadScenes(
HomeCubit.getInstance().selectedSpace?.id ?? '',
HomeCubit.getInstance().selectedSpace ??
SpaceModel(
id: '-1',
name: '',
community: Community(
uuid: '-1',
name: '',
)),
showInDevice: pageType))
..add(LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? ''));
}
},
create: (context) => SceneBlocFactory.create(
pageType: pageType,
homeCubit: HomeCubit.getInstance(),
),
child: BlocBuilder<CreateSceneBloc, CreateSceneState>(
builder: (context, state) {
final selectedSpace = HomeCubit.getInstance().selectedSpace;
if (state is DeleteSceneSuccess) {
if (state.success) {
BlocProvider.of<SceneBloc>(context).add(LoadScenes(
HomeCubit.getInstance().selectedSpace!.id, HomeCubit.getInstance().selectedSpace!,
showInDevice: pageType));
BlocProvider.of<SceneBloc>(context)
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id));
}
if (state.success) _loadScenesAndAutomations(context, selectedSpace);
}
if (state is CreateSceneWithTasks) {
if (state.success == true) {
BlocProvider.of<SceneBloc>(context).add(LoadScenes(
HomeCubit.getInstance().selectedSpace!.id, HomeCubit.getInstance().selectedSpace!,
showInDevice: pageType));
BlocProvider.of<SceneBloc>(context)
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id));
if (state.success) {
_loadScenesAndAutomations(context, selectedSpace);
context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent());
}
}
@ -77,23 +47,24 @@ class SceneView extends StatelessWidget {
listener: (context, state) {
if (state is SceneTriggerSuccess) {
context.showCustomSnackbar(
message: 'Scene ${state.sceneName} triggered successfully!');
message: 'Scene ${state.sceneName} triggered successfully!',
);
}
},
child: HomeCubit.getInstance().spaces?.isEmpty ?? true
? const CreateUnitWidget()
child: HomeCubit.getInstance().spaces.isEmpty
? const EmptyDevicesWidget()
: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (pageType == false) const SceneHeader(),
if (pageType == false) const SizedBox(height: 8),
if (!pageType) ...[
const SceneHeader(),
const SizedBox(height: 8),
],
BlocBuilder<SceneBloc, SceneState>(
builder: (context, state) {
if (state is SceneLoading) {
return const Center(
child: CircularProgressIndicator(),
);
return const AppLoadingIndicator();
}
if (state is SceneError) {
return Center(
@ -103,80 +74,83 @@ class SceneView extends StatelessWidget {
if (state is SceneLoaded) {
final scenes = state.scenes;
final automationList = state.automationList;
if (scenes.isEmpty) return const EmptyDevicesWidget();
return pageType
? Expanded(
if (pageType) {
return SizedBox(
height: context.height * 0.1,
child: SceneListview(
scenes: scenes,
loadingSceneId: state.loadingSceneId,
))
: Expanded(
),
);
}
return Theme(
data: Theme.of(context).copyWith(
dividerColor: Colors.transparent,
),
child: Expanded(
child: ListView(
children: [
Theme(
data: ThemeData()
.copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
tilePadding: const EdgeInsets.symmetric(horizontal: 6),
ExpansionTile(
tilePadding: const EdgeInsets.symmetric(
horizontal: 6,
),
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
title: const BodyMedium(text: 'Tap to run routines'),
title: const BodyMedium(
text: 'Tap to run routines',
),
children: [
scenes.isNotEmpty
? SceneGrid(
if (scenes.isNotEmpty)
SceneGrid(
scenes: scenes,
loadingSceneId: state.loadingSceneId,
disablePlayButton: false,
loadingStates:
state.loadingStates, // Add this line
loadingStates: state.loadingStates,
)
: const Center(
else
const Center(
child: BodyMedium(
text: 'No scenes have been added yet',
),
),
const SizedBox(
height: 10,
),
const SizedBox(height: 10),
],
),
),
Theme(
data: ThemeData()
.copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
ExpansionTile(
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
tilePadding: const EdgeInsets.symmetric(horizontal: 6),
tilePadding: const EdgeInsets.symmetric(
horizontal: 6,
),
title: const BodyMedium(text: 'Automation'),
children: [
automationList.isNotEmpty
? SceneGrid(
if (automationList.isNotEmpty)
SceneGrid(
scenes: automationList,
loadingSceneId: state.loadingSceneId,
disablePlayButton: true,
loadingStates:
state.loadingStates, // Add this line
loadingStates: state.loadingStates,
)
: const Center(
else
const Center(
child: BodyMedium(
text: 'No automations have been added yet',
text:
'No automations have been added yet',
),
),
const SizedBox(
height: 10,
),
const SizedBox(height: 10),
],
),
),
const SizedBox(
height: 15,
),
const SizedBox(height: 15),
],
),
),
);
}
return const SizedBox();
return const SizedBox.shrink();
},
),
],
@ -186,4 +160,21 @@ class SceneView extends StatelessWidget {
),
);
}
void _loadScenesAndAutomations(BuildContext context, SpaceModel? selectedSpace) {
BlocProvider.of<SceneBloc>(context)
..add(
LoadScenes(
selectedSpace!.id,
selectedSpace,
showInDevice: pageType,
),
)
..add(
LoadAutomation(
selectedSpace.id,
selectedSpace.community.uuid,
),
);
}
}

View File

@ -25,7 +25,7 @@ class DeleteRoutineButton extends StatelessWidget {
BlocProvider.of<SceneBloc>(context).add(LoadScenes(
HomeCubit.getInstance().selectedSpace!.id, HomeCubit.getInstance().selectedSpace!));
BlocProvider.of<SceneBloc>(context)
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id));
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id,HomeCubit.getInstance().selectedSpace!.community.uuid));
}
}
},

View File

@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class EmptyDevicesWidget extends StatelessWidget {
const EmptyDevicesWidget({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 48),
child: Text(
"No routines.\nEnable 'Show on Home Screen' to add routines",
textAlign: TextAlign.center,
style: TextStyle(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400,
fontSize: 12,
),
),
);
}
}

View File

@ -1,6 +1,5 @@
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/device_manager_bloc/device_manager_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
@ -8,60 +7,44 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart'
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_body_tab_bar.dart';
import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_list.dart';
import 'package:syncrow_app/features/shared_widgets/app_loading_indicator.dart';
class SceneDevicesBody extends StatelessWidget {
const SceneDevicesBody({
super.key,
required TabController tabController,
required this.tabController,
required this.rooms,
}) : _tabController = tabController;
super.key,
});
final TabController _tabController;
final List<SubSpaceModel>? rooms;
final TabController tabController;
final List<SubSpaceModel> rooms;
@override
Widget build(BuildContext context) {
final isAutomationDeviceStatus =
((ModalRoute.of(context)?.settings.arguments as SceneSettingsRouteArguments?)?.sceneType ==
CreateSceneEnum.deviceStatusChanges.name);
return BlocBuilder<TabBarBloc, TabBarState>(
builder: (context, tabState) {
builder: (context, state) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
TabBar(
controller: _tabController,
dividerColor: Colors.transparent,
indicatorColor: Colors.transparent,
tabs: [
...rooms!.map((e) => Tab(
child: BodyLarge(
text: e.name ?? '',
textAlign: TextAlign.start,
style: context.bodyLarge.copyWith(
color: (tabState is TabSelected) && tabState.roomId == e.id
? ColorsManager.textPrimaryColor
: ColorsManager.textPrimaryColor.withOpacity(0.2),
),
),
)),
],
isScrollable: true,
tabAlignment: TabAlignment.start,
SceneDevicesBodyTabBar(
tabController: tabController,
rooms: rooms,
selectedRoomId: state is TabBarTabSelectedState ? state.roomId : '-1',
),
Expanded(
child: TabBarView(
controller: _tabController,
physics: const NeverScrollableScrollPhysics(),
children:
rooms!.map((e) => _buildRoomTab(e, context, isAutomationDeviceStatus)).toList(),
controller: tabController,
children: rooms
.map(
(room) => _buildRoomTab(
room,
_isAutomationDeviceStatus(context),
),
)
.toList(),
),
),
],
@ -70,52 +53,46 @@ class SceneDevicesBody extends StatelessWidget {
);
}
Widget _buildRoomTab(SubSpaceModel room, BuildContext context, bool isAutomationDeviceStatus) {
bool _isAutomationDeviceStatus(BuildContext context) {
final routeArguments =
ModalRoute.of(context)?.settings.arguments as SceneSettingsRouteArguments?;
final deviceStatusChangesScene = CreateSceneEnum.deviceStatusChanges.name;
final sceneType = routeArguments?.sceneType;
return sceneType == deviceStatusChangesScene;
}
Widget _buildRoomTab(
SubSpaceModel room,
bool isAutomationDeviceStatus,
) {
return BlocBuilder<DeviceManagerBloc, DeviceManagerState>(
builder: (context, state) {
if (state.loading && state.devices == null) {
return const Center(child: CircularProgressIndicator());
} else if (state.devices != null && state.devices!.isNotEmpty) {
return ListView.builder(
itemCount: state.devices!.length,
itemBuilder: (context, index) {
final device = state.devices![index];
return DefaultContainer(
child: SceneListTile(
minLeadingWidth: 40,
leadingWidget: SvgPicture.asset(device.icon ?? ''),
titleWidget: BodyMedium(
text: device.name ?? '',
style: context.titleSmall.copyWith(
color: ColorsManager.secondaryTextColor,
fontWeight: FontWeight.w400,
fontSize: 20,
final isLoading = state.loading && state.devices == null;
final hasData =
state.devices != null && (state.devices?.isNotEmpty ?? false);
final hasError = state.error != null;
final widgets = <bool, Widget>{
isLoading: const AppLoadingIndicator(),
hasError: Center(child: Text('${state.error}')),
hasData: SceneDevicesList(
devices: state.devices ?? [],
isAutomationDeviceStatus: isAutomationDeviceStatus,
),
),
trailingWidget: const Icon(
Icons.arrow_forward_ios_rounded,
color: ColorsManager.greyColor,
size: 16,
),
onPressed: () {
Navigator.pushNamed(
context,
Routes.deviceFunctionsRoute,
arguments: {
"device": device,
"isAutomationDeviceStatus": isAutomationDeviceStatus
},
};
final invalidWidgetEntry = MapEntry(
true,
Center(child: Text('This subspace has no devices')),
);
},
),
final validWidgetEntry = widgets.entries.firstWhere(
(entry) => entry.key == true,
orElse: () => invalidWidgetEntry,
);
},
);
} else if (state.error != null) {
return const Center(child: Text('Something went wrong'));
} else {
return const SizedBox();
}
return validWidgetEntry.value;
},
);
}

View File

@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SceneDevicesBodyTabBar extends StatelessWidget {
const SceneDevicesBodyTabBar({
required this.tabController,
required this.rooms,
required this.selectedRoomId,
super.key,
});
final String selectedRoomId;
final TabController tabController;
final List<SubSpaceModel> rooms;
@override
Widget build(BuildContext context) {
return TabBar(
controller: tabController,
dividerColor: Colors.transparent,
indicatorColor: Colors.transparent,
isScrollable: true,
tabAlignment: TabAlignment.start,
tabs: rooms.map((e) {
final isSelected = selectedRoomId == e.id;
return Tab(
child: BodyLarge(
text: e.name ?? '',
textAlign: TextAlign.start,
style: context.bodyLarge.copyWith(
color: isSelected
? ColorsManager.textPrimaryColor
: ColorsManager.textPrimaryColor.withValues(
alpha: 0.2,
),
),
),
);
}).toList(),
);
}
}

View File

@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SceneDevicesList extends StatelessWidget {
const SceneDevicesList({
required this.isAutomationDeviceStatus,
required this.devices,
super.key,
});
final List<DeviceModel> devices;
final bool isAutomationDeviceStatus;
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: devices.length,
itemBuilder: (context, index) => _buildDeviceTile(context, devices[index]),
);
}
Widget _buildDeviceTile(
BuildContext context,
DeviceModel device,
) {
return DefaultContainer(
child: SceneListTile(
minLeadingWidth: 40,
leadingWidget: SvgPicture.asset(device.icon ?? ''),
titleWidget: BodyMedium(
text: device.name ?? '',
style: context.titleSmall.copyWith(
color: ColorsManager.secondaryTextColor,
fontWeight: FontWeight.w400,
fontSize: 20,
),
),
trailingWidget: const Icon(
Icons.arrow_forward_ios_rounded,
color: ColorsManager.greyColor,
size: 16,
),
onPressed: () => _navigateToDeviceFunctions(context, device),
),
);
}
void _navigateToDeviceFunctions(
BuildContext context,
DeviceModel device,
) {
Navigator.of(context).pushNamed(
Routes.deviceFunctionsRoute,
arguments: {
"device": device,
"isAutomationDeviceStatus": isAutomationDeviceStatus,
},
);
}
}

View File

@ -132,6 +132,10 @@ class SceneItem extends StatelessWidget {
spaceUuid: HomeCubit.getInstance()
.selectedSpace!
.id),
communityId: HomeCubit.getInstance()
.selectedSpace!
.community
.uuid,
automationId: scene.id));
},
),

View File

@ -22,7 +22,7 @@ class SmartEnableAutomation extends StatelessWidget {
child: BlocBuilder<SceneBloc, SceneState>(
bloc: context.read<SceneBloc>()
..add(
LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? '')),
LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? '',HomeCubit.getInstance().selectedSpace?.community.uuid ?? '')),
builder: (context, state) {
if (state is SceneLoading) {
return const Align(

View File

@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
class AppLoadingIndicator extends StatelessWidget {
const AppLoadingIndicator({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: CircularProgressIndicator.adaptive(),
);
}
}

View File

@ -1142,5 +1142,9 @@ class Assets {
static const String toggleSwitchSmall = 'assets/icons/toggleSwitchSmall.svg';
static const String offToggleSwitchSmall = 'assets/icons/offToggleSwitchSmall.svg';
static const String saveRoutinesIcon = 'assets/icons/save_routines_icon.svg';
static const String cancelIcon = 'assets/icons/cancel_icon.svg';
}

View File

@ -3,8 +3,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/model/community_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/app_layout/view/app_layout.dart';
import 'package:syncrow_app/features/auth/view/otp_view.dart';
import 'package:syncrow_app/features/auth/view/login_view.dart';
import 'package:syncrow_app/features/auth/view/otp_view.dart';
import 'package:syncrow_app/features/auth/view/sign_up_view.dart';
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
@ -17,11 +17,12 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart'
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart';
import 'package:syncrow_app/features/scene/view/device_functions_view.dart';
import 'package:syncrow_app/features/scene/view/scene_auto_settings.dart';
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
import 'package:syncrow_app/features/scene/view/scene_rooms_tabbar.dart';
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
import 'package:syncrow_app/features/scene/view/scene_view.dart';
import 'package:syncrow_app/features/scene/view/smart_automation_select_route.dart';
import 'package:syncrow_app/features/splash/view/splash_view.dart';
import 'routing_constants.dart';
class Router {
@ -88,7 +89,7 @@ class Router {
BlocProvider(
create: (BuildContext context) =>
TabBarBloc(context.read<DeviceManagerBloc>())
..add(TabChanged(
..add(TabBarTabChangedEvent(
selectedIndex: 0,
roomId: '-1',
unit: SpaceModel(

View File

@ -11,7 +11,7 @@ abstract class ApiEndpoints {
static const String sendOtp = '/authentication/user/send-otp';
static const String verifyOtp = '/authentication/user/verify-otp';
static const String forgetPassword = '/authentication/user/forget-password';
static const String clientLogin = '/client/token';
////////////////////////////////////// Spaces ///////////////////////////////////////
///Community Module
@ -88,6 +88,8 @@ abstract class ApiEndpoints {
//SPACE Module
//GET
static const String userSpaces = '/user/{userUuid}/spaces';
static const String devices = '/projects/{projectUuid}/devices';
static const String spaceDevices =
'/projects/{projectUuid}/communities/{communityUuid}/spaces/{spaceUuid}/devices';
@ -109,9 +111,9 @@ abstract class ApiEndpoints {
//POST
static const String addDeviceToRoom = '/device/room';
static const String addDeviceToGroup = '/device/group';
static const String controlDevice = '/device/{deviceUuid}/control';
static const String controlDevice = '/devices/{deviceUuid}/command';
static const String firmwareDevice =
'/device/{deviceUuid}/firmware/{firmwareVersion}';
'/devices/{deviceUuid}/firmware/{firmwareVersion}';
static const String getDevicesByUserId = '/device/user/{userId}';
static const String getDevicesByUnitId = '/device/unit/{unitUuid}';
static const String openDoorLock = '/door-lock/open/{doorLockUuid}';
@ -119,13 +121,13 @@ abstract class ApiEndpoints {
//GET
static const String deviceByRoom =
'/projects/{projectUuid}/communities/{communityUuid}/spaces/{spaceUuid}/subspaces/{subSpaceUuid}/devices';
static const String deviceByUuid = '/device/{deviceUuid}';
static const String deviceFunctions = '/device/{deviceUuid}/functions';
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices';
static const String deviceByUuid = '/devices/{deviceUuid}';
static const String deviceFunctions = '/devices/{deviceUuid}/functions';
static const String gatewayApi = '/devices/gateway/{gatewayUuid}/devices';
static const String deviceFunctionsStatus =
'/device/{deviceUuid}/functions/status';
'/devices/{deviceUuid}/functions/status';
static const String powerClamp =
'/device/{powerClampUuid}/power-clamp/status';
'/devices/{deviceUuid}/functions/status';
///Device Permission Module
//POST
@ -142,7 +144,7 @@ abstract class ApiEndpoints {
/// POST
static const String createScene = '/scene/tap-to-run';
static const String triggerScene = '/scene/tap-to-run/{sceneId}/trigger';
static const String createAutomation = '/automation';
static const String createAutomation = '/projects/{projectId}/automations';
/// GET
static const String getUnitScenes =
@ -151,23 +153,26 @@ abstract class ApiEndpoints {
static const String getScene = '/scene/tap-to-run/{sceneId}';
static const String getIconScene = '/scene/icon';
static const String getUnitAutomation = '/automation/{unitUuid}';
static const String getUnitAutomation =
'/projects/{projectId}/communities/{communityId}/spaces/{unitUuid}/automations';
static const String getAutomationDetails =
'/automation/details/{automationId}';
'/projects/{projectId}/automations/{automationId}';
/// PUT
static const String updateScene = '/scene/tap-to-run/{sceneId}';
static const String updateAutomation = '/automation/{automationId}';
static const String updateAutomation =
'/projects/{projectId}/automations/{automationId}';
static const String updateAutomationStatus =
'/automation/status/{automationId}';
'/projects/{projectId}/automations/{automationId}';
/// DELETE
static const String deleteScene = '/scene/tap-to-run/{sceneId}';
static const String deleteAutomation = '/automation/{automationId}';
static const String deleteAutomation =
'/projects/{projectId}/automations/{automationId}';
//////////////////////Door Lock //////////////////////
//online
@ -211,18 +216,18 @@ abstract class ApiEndpoints {
static const String changeSchedule = '/schedule/enable/{deviceUuid}';
static const String deleteSchedule = '/schedule/{deviceUuid}/{scheduleId}';
static const String reportLogs =
'/device/report-logs/{deviceUuid}?code={code}&startTime={startTime}&endTime={endTime}';
static const String controlBatch = '/device/control/batch';
static const String statusBatch = '/device/status/batch';
static const String deviceScene = '/device/{deviceUuid}/scenes';
'/devices/report-logs/{deviceUuid}?code={code}&startTime={startTime}&endTime={endTime}';
static const String controlBatch = '/devices/batch';
static const String statusBatch = '/devices/batch';
static const String deviceScene = '/devices/{deviceUuid}/scenes';
static const String fourSceneByName =
'/device/{deviceUuid}/scenes?switchName={switchName}';
'/devices/{deviceUuid}/scenes?switchName={switchName}';
static const String resetDevice = '/factory/reset/{deviceUuid}';
static const String unAssignScenesDevice =
'/device/{deviceUuid}/scenes?switchName={switchName}';
static const String getDeviceLogs = '/device/report-logs/{uuid}?code={code}';
'/devices/{deviceUuid}/scenes?switchName={switchName}';
static const String getDeviceLogs = '/devices/report-logs/{uuid}?code={code}';
static const String terms = '/terms';
static const String policy = '/policy';
static const String getPermission = '/permission/{roleUuid}';

View File

@ -25,11 +25,15 @@ class AuthenticationAPI {
return response;
}
static Future<bool> signUp({required SignUpModel model}) async {
static Future<bool> signUp({
required SignUpModel model,
required String accessToken,
}) async {
final response = await HTTPService().post(
path: ApiEndpoints.signUp,
body: model.toJson(),
showServerMessage: false,
accessToken: accessToken,
expectedResponseModel: (json) => json['statusCode'] == 201);
return response;
}
@ -63,4 +67,20 @@ class AuthenticationAPI {
expectedResponseModel: (json) => json['data']);
return response;
}
static Future<Map<String, dynamic>> fetchClientToken({
required String clientId,
required String clientSecret,
}) async {
final response = await HTTPService().post(
path: ApiEndpoints.clientLogin,
body: {
'clientId': clientId,
'clientSecret': clientSecret,
},
showServerMessage: false,
expectedResponseModel: (json) => json['data'],
);
return response;
}
}

View File

@ -1,6 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
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';
@ -8,7 +7,6 @@ import 'package:syncrow_app/features/devices/model/device_report_model.dart';
import 'package:syncrow_app/features/devices/model/function_model.dart';
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
import 'package:syncrow_app/services/api/http_service.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import '../../features/devices/model/create_temporary_password_model.dart';
class DevicesAPI {
@ -39,7 +37,7 @@ class DevicesAPI {
path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId),
body: {"deviceName": deviceName},
expectedResponseModel: (json) {
return json;
return json['data'];
},
);
return response;
@ -92,7 +90,7 @@ class DevicesAPI {
.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
return json;
return json['data'];
},
);
return response;
@ -101,7 +99,7 @@ class DevicesAPI {
static Future<Map<String, dynamic>> getPowerClampStatus(
String deviceId) async {
final response = await _httpService.get(
path: ApiEndpoints.powerClamp.replaceAll('{powerClampUuid}', deviceId),
path: ApiEndpoints.deviceFunctionsStatus.replaceAll('{powerClampUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
return json;
@ -132,7 +130,7 @@ class DevicesAPI {
path: ApiEndpoints.deviceFunctions.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
final functions = FunctionModel.fromJson(json);
final functions = FunctionModel.fromJson(json['data']);
return functions;
});
return response;
@ -188,7 +186,7 @@ class DevicesAPI {
path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
return json;
return json['data'];
});
return response;
}
@ -219,13 +217,14 @@ class DevicesAPI {
required String communityUuid,
required String spaceUuid,
required String roomId,
required String projectId,
}) async {
try {
final String path = ApiEndpoints.deviceByRoom
.replaceAll('{communityUuid}', communityUuid)
.replaceAll('{spaceUuid}', spaceUuid)
.replaceAll('{subSpaceUuid}', roomId)
.replaceAll('{projectUuid}', TempConst.projectIdDev);
.replaceAll('{projectUuid}', projectId);
final response = await _httpService.get(
path: path,
@ -263,7 +262,7 @@ class DevicesAPI {
if (json == null || json.isEmpty || json == []) {
return devices;
}
for (var device in json['devices']) {
for (var device in json['data']['devices']) {
devices.add(DeviceModel.fromJson(device));
}
return devices;
@ -490,7 +489,12 @@ class DevicesAPI {
}) async {
final response = await _httpService.post(
path: ApiEndpoints.controlBatch,
body: {"devicesUuid": devicesUuid, "code": code, "value": value},
body: {
"devicesUuid": devicesUuid,
"code": code,
"value": value,
"operationType": 'COMMAND',
},
showServerMessage: true,
expectedResponseModel: (json) {
return json;
@ -564,12 +568,13 @@ class DevicesAPI {
static Future<List<DeviceModel>> getAllDevices({
required String communityUuid,
required String spaceUuid,
required String projectId,
}) async {
try {
final String path = ApiEndpoints.getAllDevices
.replaceAll('{communityUuid}', communityUuid)
.replaceAll('{spaceUuid}', spaceUuid)
.replaceAll('{projectUuid}', TempConst.projectIdDev);
.replaceAll('{projectUuid}', projectId);
final response = await _httpService.get(
path: path,

View File

@ -145,12 +145,13 @@ class HomeCreation {
required String communityId,
required String spaceId,
required Map<String, String> body,
required String projectId
}) async {
try {
final fullPath = ApiEndpoints.addSubSpace
.replaceAll('{communityUuid}', communityId)
.replaceAll('{spaceUuid}', spaceId)
.replaceAll('{projectUuid}', TempConst.projectIdDev);
.replaceAll('{projectUuid}', projectId);
final response = await _httpService.post(
path: fullPath,
body: body,

View File

@ -27,7 +27,23 @@ class HomeManagementAPI {
return list;
}
static Future<List<DeviceModel>> fetchDevicesByUnitId() async {
static Future<List<DeviceModel>> fetchDevices(projectUuid) async {
List<DeviceModel> list = [];
await _httpService.get(
path: ApiEndpoints.devices.replaceAll("{projectUuid}", projectUuid),
showServerMessage: false,
expectedResponseModel: (json) {
json['data'].forEach((value) {
list.add(DeviceModel.fromJson(value));
});
});
return list;
}
static Future<List<DeviceModel>> fetchDevicesByUnitId(
String projectUuid) async {
List<DeviceModel> list = [];
try {
@ -40,7 +56,7 @@ class HomeManagementAPI {
final path = ApiEndpoints.spaceDevices
.replaceAll('{communityUuid}', communityUuid)
.replaceAll('{spaceUuid}', spaceUuid)
.replaceAll('{projectUuid}', TempConst.projectIdDev);
.replaceAll('{projectUuid}', projectUuid);
await _httpService.get(
path: path,
@ -62,12 +78,16 @@ class HomeManagementAPI {
return list;
}
static Future<Map<String, dynamic>> assignDeviceToRoom(String communityId,
String spaceId, String subSpaceId, String deviceId) async {
static Future<Map<String, dynamic>> assignDeviceToRoom(
String communityId,
String spaceId,
String subSpaceId,
String deviceId,
String projectId) async {
try {
final response = await _httpService.post(
path: ApiEndpoints.assignDeviceToRoom
.replaceAll('{projectUuid}', TempConst.projectIdDev)
.replaceAll('{projectUuid}', projectId)
.replaceAll('{communityUuid}', communityId)
.replaceAll('{spaceUuid}', spaceId)
.replaceAll('{subSpaceUuid}', subSpaceId)
@ -82,8 +102,12 @@ class HomeManagementAPI {
}
}
static Future<Map<String, dynamic>> unAssignDeviceToRoom(String communityId,
String spaceId, String subSpaceId, String deviceId) async {
static Future<Map<String, dynamic>> unAssignDeviceToRoom(
String communityId,
String spaceId,
String subSpaceId,
String deviceId,
String projectId) async {
try {
final response = await _httpService.delete(
path: ApiEndpoints.assignDeviceToRoom
@ -91,7 +115,7 @@ class HomeManagementAPI {
.replaceAll('{spaceUuid}', spaceId)
.replaceAll('{subSpaceUuid}', subSpaceId)
.replaceAll('{deviceUuid}', deviceId)
.replaceAll('{projectUuid}', TempConst.projectIdDev),
.replaceAll('{projectUuid}', projectId),
expectedResponseModel: (json) {
return json;
},

View File

@ -48,13 +48,26 @@ class HTTPService {
Options? options,
dynamic body,
bool showServerMessage = true,
String? accessToken,
required T Function(dynamic) expectedResponseModel}) async {
try {
final authOptions = options ??
Options(
headers: accessToken != null
? {
'Authorization': 'Bearer $accessToken',
'Content-Type': 'application/json',
}
: {
'Content-Type': 'application/json',
},
);
final response = await client.post(
path,
data: body,
queryParameters: queryParameters,
options: options,
options: authOptions,
);
return expectedResponseModel(response.data);
} catch (error) {

View File

@ -6,7 +6,6 @@ import 'package:syncrow_app/features/scene/model/scenes_model.dart';
import 'package:syncrow_app/features/scene/model/update_automation.dart';
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
import 'package:syncrow_app/services/api/http_service.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
class SceneApi {
static final HTTPService _httpService = HTTPService();
@ -31,10 +30,11 @@ class SceneApi {
// create automation
static Future<Map<String, dynamic>> createAutomation(
CreateAutomationModel createAutomationModel) async {
CreateAutomationModel createAutomationModel, String projectId) async {
try {
final response = await _httpService.post(
path: ApiEndpoints.createAutomation,
path:
ApiEndpoints.createAutomation.replaceAll('{projectId}', projectId),
body: createAutomationModel.toMap(),
showServerMessage: false,
expectedResponseModel: (json) {
@ -50,14 +50,14 @@ class SceneApi {
//get scene by unit id
static Future<List<ScenesModel>> getScenesByUnitId(
String unitId, String communityId,
String unitId, String communityId, String projectId,
{showInDevice = false}) async {
try {
final response = await _httpService.get(
path: ApiEndpoints.getUnitScenes
.replaceAll('{spaceUuid}', unitId)
.replaceAll('{communityUuid}', communityId)
.replaceAll('{projectUuid}', TempConst.projectIdDev),
.replaceAll('{projectUuid}', projectId),
queryParameters: {'showInHomePage': showInDevice},
showServerMessage: false,
expectedResponseModel: (json) {
@ -78,10 +78,17 @@ class SceneApi {
//getAutomation
static Future<List<ScenesModel>> getAutomationByUnitId(String unitId) async {
static Future<List<ScenesModel>> getAutomationByUnitId(
String unitId,
String communityId,
String projectId,
) async {
try {
final response = await _httpService.get(
path: ApiEndpoints.getUnitAutomation.replaceAll('{unitUuid}', unitId),
path: ApiEndpoints.getUnitAutomation
.replaceAll('{unitUuid}', unitId)
.replaceAll('{communityId}', communityId)
.replaceAll('{projectId}', projectId),
showServerMessage: false,
expectedResponseModel: (json) {
List<ScenesModel> scenes = [];
@ -112,11 +119,12 @@ class SceneApi {
//automation details
static Future<SceneDetailsModel> getAutomationDetails(
String automationId) async {
String automationId, String projectId) async {
try {
final response = await _httpService.get(
path: ApiEndpoints.getAutomationDetails
.replaceAll('{automationId}', automationId),
.replaceAll('{automationId}', automationId)
.replaceAll('{projectId}', projectId),
showServerMessage: false,
expectedResponseModel: (json) => SceneDetailsModel.fromJson(json),
);
@ -128,11 +136,12 @@ class SceneApi {
//updateAutomationStatus
static Future<bool> updateAutomationStatus(String automationId,
AutomationStatusUpdate createAutomationEnable) async {
AutomationStatusUpdate createAutomationEnable, String projectId) async {
try {
final response = await _httpService.put(
final response = await _httpService.patch(
path: ApiEndpoints.updateAutomationStatus
.replaceAll('{automationId}', automationId),
.replaceAll('{automationId}', automationId)
.replaceAll('{projectId}', projectId),
body: createAutomationEnable.toMap(),
expectedResponseModel: (json) => json['success'],
);
@ -194,12 +203,13 @@ class SceneApi {
}
//update automation
static updateAutomation(
CreateAutomationModel createAutomationModel, String automationId) async {
static updateAutomation(CreateAutomationModel createAutomationModel,
String automationId, String projectId) async {
try {
final response = await _httpService.put(
path: ApiEndpoints.updateAutomation
.replaceAll('{automationId}', automationId),
.replaceAll('{automationId}', automationId)
.replaceAll('{projectId}', projectId),
body: createAutomationModel
.toJson(automationId.isNotEmpty == true ? automationId : null),
expectedResponseModel: (json) {
@ -229,11 +239,14 @@ class SceneApi {
// delete automation
static Future<bool> deleteAutomation(
{required String unitUuid, required String automationId}) async {
{required String unitUuid,
required String automationId,
required String projectId}) async {
try {
final response = await _httpService.delete(
path: ApiEndpoints.deleteAutomation
.replaceAll('{automationId}', automationId),
.replaceAll('{automationId}', automationId)
.replaceAll('{projectId}', projectId),
showServerMessage: false,
expectedResponseModel: (json) => json['statusCode'] == 200,
);

View File

@ -32,13 +32,13 @@ class SpacesAPI {
}
static Future<List<SubSpaceModel>> getSubSpaceBySpaceId(
String communityId, String spaceId) async {
String communityId, String spaceId, String projectId) async {
try {
// Construct the API path
final path = ApiEndpoints.listSubspace
.replaceFirst('{communityUuid}', communityId)
.replaceFirst('{spaceUuid}', spaceId)
.replaceAll('{projectUuid}', TempConst.projectIdDev);
.replaceAll('{projectUuid}', projectId);
final response = await _httpService.get(
path: path,
@ -66,12 +66,12 @@ class SpacesAPI {
//factory/reset/{deviceUuid}
static Future<String> generateInvitationCode(
String unitId, String communityId) async {
String unitId, String communityId, String projectId) async {
final response = await _httpService.post(
path: ApiEndpoints.invitationCode
.replaceAll('{unitUuid}', unitId)
.replaceAll('{communityUuid}', communityId)
.replaceAll('{projectUuid}', TempConst.projectIdDev),
.replaceAll('{projectUuid}', projectId),
showServerMessage: false,
expectedResponseModel: (json) {
if (json != null && json['data'] != null) {

View File

@ -1,5 +1,5 @@
import 'package:flutter_dotenv/flutter_dotenv.dart';
class TempConst {
static String projectIdDev = dotenv.env['projectId'] ?? '';
static String projectIdDev = dotenv.env['PROJECT_ID'] ?? '';
}

View File

@ -5,7 +5,7 @@ description: This is the mobile application project, developed with Flutter for
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.18+55
version: 1.0.30+1
environment:
sdk: ">=3.0.6 <4.0.0"