Compare commits

..

44 Commits

Author SHA1 Message Date
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
80dd0f696f Merge pull request #75 from SyncrowIOT/SP-1245
updated endpoint for automation
2025-03-17 09:34:46 +04:00
33 changed files with 1345 additions and 673 deletions

View File

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

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

@ -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

@ -169,18 +169,20 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
}
}
_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

@ -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(
ChangeFirstWizardSwitchStatusEvent(
value: garageList[index].firstSwitch,
deviceId: garageList[index].deviceId));
},
off: 'Close',
on: 'Open',
switchValue: garageDoor.firstSwitch,
action: () => BlocProvider.of<GarageDoorBloc>(context).add(
ChangeFirstWizardSwitchStatusEvent(
value: garageDoor.firstSwitch,
deviceId: garageDoor.deviceId,
),
),
),
],
);

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,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));
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));
}
}
@ -206,7 +286,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 +364,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',
Assets.assetsIconsSensors,
'Sensitivity',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.listOfOptions,
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.listOfOptions,
isAutomation ? _createIntegerStepsOptions() : _createSensitivityOptions(),
isAutomation,
comparator,
@ -297,8 +381,8 @@ 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',
@ -351,8 +435,8 @@ 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',
@ -366,8 +450,8 @@ 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',
@ -381,8 +465,8 @@ 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',
@ -396,8 +480,8 @@ 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',
@ -411,8 +495,8 @@ 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',
@ -426,8 +510,8 @@ 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',
@ -441,8 +525,8 @@ 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',
@ -456,8 +540,8 @@ 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',
@ -471,8 +555,8 @@ 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',
@ -486,8 +570,8 @@ 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',
@ -501,8 +585,8 @@ 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',
@ -516,8 +600,8 @@ 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',
@ -531,8 +615,8 @@ 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',
@ -546,8 +630,8 @@ 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',
@ -561,8 +645,8 @@ 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',
@ -576,8 +660,8 @@ 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',
@ -591,8 +675,8 @@ 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',
@ -606,14 +690,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',
Assets.assetsIconsSensors,
'Current Distance',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.countdown,
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
_createCurrentDistanceOptions(),
isAutomation,
comparator,
@ -621,8 +707,8 @@ 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',
@ -636,8 +722,8 @@ 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',
@ -651,8 +737,8 @@ 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',
@ -666,23 +752,27 @@ 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',
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',
@ -696,8 +786,8 @@ 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',
@ -711,8 +801,8 @@ 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',
@ -726,8 +816,8 @@ 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',
@ -741,38 +831,92 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createSwitch1Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
Assets.assetsIcons3GangSwitch,
'Light 1 Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
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',
Assets.assetsIcons3GangSwitch,
'Light 1 Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
case "2G":
return _createSceneFunction(
action,
'2 Gang Button Switch L-L',
Assets.twoGang,
'Light 1 Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
default:
return _createSceneFunction(
action,
'1 Gang Button Switch L-L',
Assets.oneGang,
'Light Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
}
}
SceneStaticFunction _createSwitch2Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
Assets.assetsIcons3GangSwitch,
'Light 2 Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
SceneStaticFunction _createSwitch2Function(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
switch (action.productType) {
case "3G":
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
Assets.assetsIcons3GangSwitch,
'Light 2 Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
case "2G":
return _createSceneFunction(
action,
'2 Gang Button Switch L-L',
Assets.twoGang,
'Light 2 Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
default:
return _createSceneFunction(
action,
'1 Gang Button Switch L-L',
Assets.oneGang,
'Light Switch',
OperationDialogType.onOff,
_createOnOffOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
}
}
SceneStaticFunction _createSwitch3Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
SceneStaticFunction _createSwitch3Function(Action action, bool isAutomation,
String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
@ -786,53 +930,135 @@ mixin SceneOperationsDataHelper {
);
}
SceneStaticFunction _createCountdown1Function(
Action action, bool isAutomation, String? comparator, String? uniqueCustomId) {
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
Assets.assetsIcons3GangSwitch,
'Light 1 CountDown',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.countdown,
isAutomation ? _createAutomationCountDownOptions() : _createCountdownOptions(),
isAutomation,
comparator,
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',
Assets.assetsIcons3GangSwitch,
'Light 1 CountDown',
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
case "2G":
return _createSceneFunction(
action,
'2 Gang Button Switch L-L',
Assets.twoGang,
'Light 1 CountDown',
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
default:
return _createSceneFunction(
action,
'1 Gang Button Switch L-L',
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) {
return _createSceneFunction(
action,
'3 Gang Button Switch L-L',
Assets.assetsIcons3GangSwitch,
'Light 2 CountDown',
isAutomation ? OperationDialogType.integerSteps : OperationDialogType.countdown,
isAutomation ? _createAutomationCountDownOptions() : _createCountdownOptions(),
isAutomation,
comparator,
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',
Assets.assetsIcons3GangSwitch,
'Light 2 CountDown',
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
case "2G":
return _createSceneFunction(
action,
'2 Gang Button Switch L-L',
Assets.twoGang,
'Light 2 CountDown',
isAutomation
? OperationDialogType.integerSteps
: OperationDialogType.countdown,
isAutomation
? _createAutomationCountDownOptions()
: _createCountdownOptions(),
isAutomation,
comparator,
uniqueCustomId,
);
default:
return _createSceneFunction(
action,
'1 Gang Button Switch L-L',
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',
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',
@ -846,8 +1072,8 @@ 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',
@ -861,8 +1087,8 @@ 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',
@ -1180,8 +1406,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,

View File

@ -74,6 +74,7 @@ class Action {
ExecutorProperty? executorProperty;
String? name;
String? type;
String? productType;
Action({
required this.actionExecutor,
@ -81,6 +82,7 @@ class Action {
this.executorProperty,
this.name,
this.type,
this.productType,
});
String toRawJson() => json.encode(toJson());
@ -88,10 +90,11 @@ 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?,
);
}
if (json["executorProperty"] == null) {
@ -99,9 +102,10 @@ 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?,
);
}

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';
@ -12,6 +13,7 @@ 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';
@ -51,22 +53,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,65 +69,63 @@ class DeviceFunctionsView extends StatelessWidget
itemCount: functions.length,
padding: const EdgeInsets.only(top: 24.0),
itemBuilder: (context, index) {
return DefaultContainer(
padding: index == 0
? const EdgeInsets.only(top: 8)
: index == functions.length - 1
? const EdgeInsets.only(bottom: 8)
: EdgeInsets.zero,
margin: EdgeInsets.zero,
borderRadius: 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))
: BorderRadius.zero,
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 Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
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,
);
}
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(),
),
],
),
index != functions.length - 1
? SizedBox(
width: context.width * 0.8, child: const LightDivider())
: const SizedBox(),
],
),
),
],
);
},
),

View File

@ -20,82 +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();
WidgetsBinding.instance.addPostFrameCallback((_) {
selectedSpace = HomeCubit.getInstance().selectedSpace!;
selectedSpace = HomeCubit.getInstance().selectedSpace!;
rooms = List.from(selectedSpace.subspaces ?? []);
rooms = List.from(selectedSpace.subspaces);
final defaultSubSpaceModel = SubSpaceModel(
name: 'All Devices',
devices: context.read<DevicesCubit>().allDevices,
id: '-1',
);
if (rooms != null && rooms!.isNotEmpty) {
if (rooms![0].id != '-1') {
rooms?.insert(
0,
SubSpaceModel(
name: 'All Devices',
devices: context.read<DevicesCubit>().allDevices,
id: '-1',
),
);
}
} else {
rooms = [
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);
}
_tabController = TabController(length: rooms!.length, vsync: this);
_tabController.addListener(_handleTabSwitched);
setState(() {});
});
}
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;
} else {
rooms = [defaultSubSpaceModel];
}
_tabController = TabController(length: rooms.length, vsync: this);
_tabController.addListener(_handleTabSwitched);
}
@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,108 +1,70 @@
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 ?? '',
HomeCubit.getInstance().selectedSpace?.community.uuid ?? ''));
}
},
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,
HomeCubit.getInstance().selectedSpace!.community.uuid));
}
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,
HomeCubit.getInstance().selectedSpace!.community.uuid));
context
.read<SmartSceneSelectBloc>()
.add(const SmartSceneClearEvent());
if (state.success) {
_loadScenesAndAutomations(context, selectedSpace);
context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent());
}
}
return BlocListener<SceneBloc, SceneState>(
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
? 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(
@ -112,90 +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(
child: SceneListview(
scenes: scenes,
loadingSceneId: state.loadingSceneId,
))
: Expanded(
child: ListView(
if (pageType) {
return SizedBox(
height: context.height * 0.1,
child: SceneListview(
scenes: scenes,
loadingSceneId: state.loadingSceneId,
),
);
}
return Theme(
data: Theme.of(context).copyWith(
dividerColor: Colors.transparent,
),
child: Expanded(
child: ListView(
children: [
ExpansionTile(
tilePadding: const EdgeInsets.symmetric(
horizontal: 6,
),
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
title: const BodyMedium(
text: 'Tap to run routines',
),
children: [
Theme(
data: ThemeData().copyWith(
dividerColor: Colors.transparent),
child: ExpansionTile(
tilePadding:
const EdgeInsets.symmetric(
horizontal: 6),
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
title: const BodyMedium(
text: 'Tap to run routines'),
children: [
scenes.isNotEmpty
? SceneGrid(
scenes: scenes,
loadingSceneId:
state.loadingSceneId,
disablePlayButton: false,
loadingStates: state
.loadingStates, // Add this line
)
: const Center(
child: BodyMedium(
text:
'No scenes have been added yet',
),
),
const SizedBox(
height: 10,
),
],
if (scenes.isNotEmpty)
SceneGrid(
scenes: scenes,
loadingSceneId: state.loadingSceneId,
disablePlayButton: false,
loadingStates: state.loadingStates,
)
else
const Center(
child: BodyMedium(
text: 'No scenes have been added yet',
),
),
),
Theme(
data: ThemeData().copyWith(
dividerColor: Colors.transparent),
child: ExpansionTile(
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
tilePadding:
const EdgeInsets.symmetric(
horizontal: 6),
title: const BodyMedium(
text: 'Automation'),
children: [
automationList.isNotEmpty
? SceneGrid(
scenes: automationList,
loadingSceneId:
state.loadingSceneId,
disablePlayButton: true,
loadingStates: state
.loadingStates, // Add this line
)
: const Center(
child: BodyMedium(
text:
'No automations have been added yet',
),
),
const SizedBox(
height: 10,
),
],
),
),
const SizedBox(
height: 15,
),
const SizedBox(height: 10),
],
),
);
ExpansionTile(
initiallyExpanded: true,
iconColor: ColorsManager.grayColor,
tilePadding: const EdgeInsets.symmetric(
horizontal: 6,
),
title: const BodyMedium(text: 'Automation'),
children: [
if (automationList.isNotEmpty)
SceneGrid(
scenes: automationList,
loadingSceneId: state.loadingSceneId,
disablePlayButton: true,
loadingStates: state.loadingStates,
)
else
const Center(
child: BodyMedium(
text:
'No automations have been added yet',
),
),
const SizedBox(height: 10),
],
),
const SizedBox(height: 15),
],
),
),
);
}
return const SizedBox();
return const SizedBox.shrink();
},
),
],
@ -205,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

@ -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,
),
),
trailingWidget: const Icon(
Icons.arrow_forward_ios_rounded,
color: ColorsManager.greyColor,
size: 16,
),
onPressed: () {
Navigator.pushNamed(
context,
Routes.deviceFunctionsRoute,
arguments: {
"device": device,
"isAutomationDeviceStatus": isAutomationDeviceStatus
},
);
},
),
);
},
);
} else if (state.error != null) {
return const Center(child: Text('Something went wrong'));
} else {
return const SizedBox();
}
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,
),
};
final invalidWidgetEntry = MapEntry(
true,
Center(child: Text('This subspace has no devices')),
);
final validWidgetEntry = widgets.entries.firstWhere(
(entry) => entry.key == true,
orElse: () => invalidWidgetEntry,
);
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

@ -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
@ -111,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}';
@ -121,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
@ -153,7 +153,8 @@ abstract class ApiEndpoints {
static const String getScene = '/scene/tap-to-run/{sceneId}';
static const String getIconScene = '/scene/icon';
static const String getUnitAutomation = '/projects/{projectId}/communities/{communityId}/spaces/{unitUuid}/automations';
static const String getUnitAutomation =
'/projects/{projectId}/communities/{communityId}/spaces/{unitUuid}/automations';
static const String getAutomationDetails =
'/projects/{projectId}/automations/{automationId}';
@ -161,7 +162,8 @@ abstract class ApiEndpoints {
/// PUT
static const String updateScene = '/scene/tap-to-run/{sceneId}';
static const String updateAutomation = '/projects/{projectId}/automations/{automationId}';
static const String updateAutomation =
'/projects/{projectId}/automations/{automationId}';
static const String updateAutomationStatus =
'/projects/{projectId}/automations/{automationId}';
@ -169,7 +171,8 @@ abstract class ApiEndpoints {
/// DELETE
static const String deleteScene = '/scene/tap-to-run/{sceneId}';
static const String deleteAutomation = '/projects/{projectId}/automations/{automationId}';
static const String deleteAutomation =
'/projects/{projectId}/automations/{automationId}';
//////////////////////Door Lock //////////////////////
//online
@ -213,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;
}
@ -264,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;
@ -491,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;

View File

@ -34,7 +34,7 @@ class HomeManagementAPI {
path: ApiEndpoints.devices.replaceAll("{projectUuid}", projectUuid),
showServerMessage: false,
expectedResponseModel: (json) {
json.forEach((value) {
json['data'].forEach((value) {
list.add(DeviceModel.fromJson(value));
});
});

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) {