Implemented smart door animation

This commit is contained in:
Abdullah Alassaf
2024-08-26 16:45:50 +03:00
parent 611c515173
commit dcc98445d7
6 changed files with 147 additions and 159 deletions

View File

@ -6,7 +6,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/offline_password_model.dart';
import 'package:syncrow_app/features/devices/model/offline_temporary_password.dart';
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
@ -216,11 +215,13 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
void _updateLock(UpdateLockEvent event, Emitter<SmartDoorState> emit) async {
emit(LoadingNewSate(smartDoorModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: 'normal_open_switch', value: !event.value),
deviceId);
// final response = await DevicesAPI.controlDevice(
// DeviceControlModel(deviceId: deviceId, code: 'normal_open_switch', value: !event.value),
// deviceId);
if (response['success'] ?? false) {
final response = await DevicesAPI.openDoorLock(deviceId);
if (response) {
deviceStatus.normalOpenSwitch = !event.value;
}
} catch (_) {}
@ -353,7 +354,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
try {
isSavingPassword = true;
emit(LoadingSaveState());
var res = await DevicesAPI.createPassword(
await DevicesAPI.createPassword(
deviceId: deviceId,
effectiveTime: effectiveTimeTimeStamp.toString(),
invalidTime: expirationTimeTimeStamp.toString(),
@ -407,7 +408,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
Future<void> deletePassword(DeletePasswordEvent event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response =
await DevicesAPI.deletePassword(deviceId: deviceId, passwordId: event.passwordId)
.then((value) async {
add(InitialPasswordsPage());
@ -442,7 +442,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
return true;
}
if (repeat == true && (endTime == null || startTime == null || selectedDays == null)) {
if (repeat == true && (endTime == null || startTime == null)) {
CustomSnackBar.displaySnackBar('Start Time and End time and the days required ');
return true;
}

View File

@ -1,14 +1,10 @@
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/acs_bloc/acs_event.dart';
// import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
// import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
// import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
@ -37,11 +33,16 @@ class _DoorLockButtonState extends State<DoorLockButton> with SingleTickerProvid
super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
value: smartDoorModel.unlockRequest > 0 ? 1 : 0,
duration: Duration(seconds: smartDoorModel.unlockRequest),
);
_animation = Tween<double>(begin: 0, end: 1.0).animate(_animationController)
if (smartDoorModel.unlockRequest > 0) {
_animationController.reverse();
}
_animation = Tween<double>(begin: 0, end: 1).animate(_animationController)
..addListener(() {
if (_animation.status == AnimationStatus.completed) {
// if (_animation.status == AnimationStatus.completed) {
// if (widget.doorLock.status
// .firstWhere((element) => element.code == 'normal_open_switch')
// .value !=
@ -51,20 +52,22 @@ class _DoorLockButtonState extends State<DoorLockButton> with SingleTickerProvid
// deviceId: widget.doorLock.uuid, code: 'normal_open_switch', value: true),
// widget.doorLock.uuid ?? "");
// }
BlocProvider.of<SmartDoorBloc>(context)
.add(UpdateLockEvent(value: smartDoorModel.normalOpenSwitch));
_animationController.reverse();
} else if (_animation.status == AnimationStatus.dismissed) {
// if (widget.doorLock.status
// .firstWhere((element) => element.code == 'normal_open_switch')
// .value !=
// false) {
// BlocProvider.of<SmartDoorBloc>(context)
// .add(UpdateLockEvent(value: smartDoorModel.normalOpenSwitch));
// _animationController.reverse();
// }
// } else if (_animation.status == AnimationStatus.dismissed) {
// // if (widget.doorLock.status
// // .firstWhere((element) => element.code == 'normal_open_switch')
// // .value !=
// // false) {
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: widget.doorLock.uuid, code: 'normal_open_switch', value: false),
// widget.doorLock.uuid ?? "");
// // }
// _animationController.forward();
// }
}
setState(() {});
});
}
@ -88,14 +91,18 @@ class _DoorLockButtonState extends State<DoorLockButton> with SingleTickerProvid
WidgetStateProperty.all(ColorsManager.primaryColorWithOpacity.withOpacity(0.1)),
borderRadius: BorderRadius.circular(999),
onTapDown: (details) {
if (_animationController.status == AnimationStatus.dismissed) {
_animationController.forward();
} else if (_animationController.status == AnimationStatus.completed) {
_animationController.reverse();
} else if (_animationController.status == AnimationStatus.forward) {
_animationController.reverse();
} else if (_animationController.status == AnimationStatus.reverse) {
_animationController.forward();
// if (_animationController.status == AnimationStatus.dismissed) {
// _animationController.forward();
// } else if (_animationController.status == AnimationStatus.completed) {
// _animationController.reverse();
// } else if (_animationController.status == AnimationStatus.forward) {
// _animationController.reverse();
// } else if (_animationController.status == AnimationStatus.reverse) {
// _animationController.forward();
// }
if (smartDoorModel.unlockRequest > 0) {
BlocProvider.of<SmartDoorBloc>(context)
.add(UpdateLockEvent(value: smartDoorModel.normalOpenSwitch));
}
},
onTapUp: (details) {

View File

@ -7,27 +7,22 @@ import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_sta
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
import 'package:syncrow_app/features/devices/view/widgets/popup_menu_widget.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_button.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_grid.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class DoorInterface extends StatelessWidget {
DoorInterface({super.key, required this.doorLock});
const DoorInterface({super.key, required this.doorLock});
final DeviceModel doorLock;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => SmartDoorBloc(deviceId: doorLock.uuid ?? '')..add(InitialEvent()),
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
listener: (context, state) {
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
if (state is FailedState) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
@ -98,14 +93,11 @@ class DoorInterface extends StatelessWidget {
? const Center(
child: RefreshProgressIndicator(),
)
:
RefreshIndicator(
: RefreshIndicator(
onRefresh: () async {
BlocProvider.of<SmartDoorBloc>(context).add(InitialEvent());
},
child:
ListView(
child: ListView(
children: [
DoorLockStatusBar(
smartDoorModel: smartDoorModel,
@ -118,8 +110,9 @@ class DoorInterface extends StatelessWidget {
doorLock: doorLock,
smartDoorModel: smartDoorModel,
),
DoorLockGrid( uuid: doorLock.uuid!, ),
DoorLockGrid(
uuid: doorLock.uuid!,
),
],
)
],
@ -132,4 +125,3 @@ class DoorInterface extends StatelessWidget {
);
}
}

View File

@ -18,7 +18,7 @@ class ManageHomeView extends StatelessWidget {
title: 'Manage Your Home',
child: spaces == null
? const Center(
child: CircularProgressIndicator(),
child: BodyMedium(text: 'No spaces found'),
)
: Column(
children: [
@ -30,8 +30,7 @@ class ManageHomeView extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children:
List.generate(
children: List.generate(
spaces.length,
(index) {
if (index == spaces.length - 1) {
@ -43,12 +42,10 @@ class ManageHomeView extends StatelessWidget {
)));
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyMedium(
text: StringHelpers.toTitleCase(
spaces[index].name ?? "")),
text: StringHelpers.toTitleCase(spaces[index].name ?? "")),
const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
@ -76,14 +73,10 @@ class ManageHomeView extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyMedium(
text: HomeCubit.getInstance()
.spaces![index]
.name ??
""),
text: HomeCubit.getInstance().spaces![index].name ?? ""),
const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
@ -92,8 +85,7 @@ class ManageHomeView extends StatelessWidget {
],
),
Container(
margin:
const EdgeInsets.symmetric(vertical: 15),
margin: const EdgeInsets.symmetric(vertical: 15),
height: 1,
color: ColorsManager.greyColor,
),

View File

@ -81,8 +81,7 @@ abstract class ApiEndpoints {
static const String controlGroup = '/group/control';
//GET
static const String groupBySpace = '/group/{unitUuid}';
static const String devicesByGroupName =
'/group/{unitUuid}/devices/{groupName}';
static const String devicesByGroupName = '/group/{unitUuid}/devices/{groupName}';
static const String groupByUuid = '/group/{groupUuid}';
//DELETE
@ -94,18 +93,17 @@ abstract class ApiEndpoints {
static const String addDeviceToRoom = '/device/room';
static const String addDeviceToGroup = '/device/group';
static const String controlDevice = '/device/{deviceUuid}/control';
static const String firmwareDevice =
'/device/{deviceUuid}/firmware/{firmwareVersion}';
static const String firmwareDevice = '/device/{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}';
//GET
static const String deviceByRoom = '/device/room';
static const String deviceByUuid = '/device/{deviceUuid}';
static const String deviceFunctions = '/device/{deviceUuid}/functions';
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices';
static const String deviceFunctionsStatus =
'/device/{deviceUuid}/functions/status';
static const String deviceFunctionsStatus = '/device/{deviceUuid}/functions/status';
///Device Permission Module
//POST
@ -130,29 +128,24 @@ abstract class ApiEndpoints {
static const String getUnitAutomation = '/automation/{unitUuid}';
static const String getAutomationDetails =
'/automation/details/{automationId}';
static const String getAutomationDetails = '/automation/details/{automationId}';
/// PUT
static const String updateScene = '/scene/tap-to-run/{sceneId}';
static const String updateAutomation = '/automation/{automationId}';
static const String updateAutomationStatus =
'/automation/status/{automationId}';
static const String updateAutomationStatus = '/automation/status/{automationId}';
/// DELETE
static const String deleteScene = '/scene/tap-to-run/{unitUuid}/{sceneId}';
static const String deleteAutomation =
'/automation/{unitUuid}/{automationId}';
static const String deleteAutomation = '/automation/{unitUuid}/{automationId}';
//////////////////////Door Lock //////////////////////
//online
static const String addTemporaryPassword =
'/door-lock/temporary-password/online/{doorLockUuid}';
static const String getTemporaryPassword =
'/door-lock/temporary-password/online/{doorLockUuid}';
static const String addTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
static const String getTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
//one-time offline
static const String addOneTimeTemporaryPassword =
@ -160,8 +153,6 @@ abstract class ApiEndpoints {
static const String getOneTimeTemporaryPassword =
'/door-lock/temporary-password/offline/one-time/{doorLockUuid}';
//user
static const String getUser = '/user/{userUuid}';

View File

@ -46,6 +46,17 @@ class DevicesAPI {
}
}
static Future<bool> openDoorLock(String deviceId) async {
final response = await _httpService.post(
path: ApiEndpoints.openDoorLock.replaceAll('{doorLockUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
return json['success'] ?? false;
},
);
return response;
}
static Future<List<DevicesCategoryModel>> fetchGroups(String spaceId) async {
// Map<String, dynamic> params = {"homeId": spaceId, "pageSize": 100, "pageNo": 1};
@ -69,17 +80,13 @@ class DevicesAPI {
return response;
}
static Future<Map<String, dynamic>> renamePass({
required String name,
required String doorLockUuid,
required String passwordId}) async {
static Future<Map<String, dynamic>> renamePass(
{required String name, required String doorLockUuid, required String passwordId}) async {
final response = await _httpService.put(
path: ApiEndpoints.renamePassword
.replaceAll('{doorLockUuid}', doorLockUuid)
.replaceAll('{passwordId}', passwordId),
body: {
"name": name
},
body: {"name": name},
expectedResponseModel: (json) {
return json;
},
@ -156,7 +163,9 @@ class DevicesAPI {
return response;
}
static Future getTemporaryPasswords(String deviceId, ) async {
static Future getTemporaryPasswords(
String deviceId,
) async {
final response = await _httpService.get(
path: ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
showServerMessage: false,
@ -196,7 +205,8 @@ class DevicesAPI {
required String effectiveTime,
required String invalidTime,
required String deviceId,
List<Schedule>? scheduleList,}) async {
List<Schedule>? scheduleList,
}) async {
Map<String, dynamic> body = {
"name": name,
"password": password,
@ -236,10 +246,7 @@ class DevicesAPI {
final response = await _httpService.post(
path: ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
showServerMessage: true,
body: {
"effectiveTime": effectiveTime,
"invalidTime": invalidTime
},
body: {"effectiveTime": effectiveTime, "invalidTime": invalidTime},
expectedResponseModel: (json) {
return json;
},
@ -263,5 +270,4 @@ class DevicesAPI {
);
return response;
}
}