mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-11-27 13:14:55 +00:00
Merge branch 'dev' into doorlock_interface
This commit is contained in:
@ -20,8 +20,9 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
|
|
||||||
static AuthCubit get(context) => BlocProvider.of(context);
|
static AuthCubit get(context) => BlocProvider.of(context);
|
||||||
|
|
||||||
TextEditingController emailController = TextEditingController();
|
final TextEditingController emailController = TextEditingController();
|
||||||
TextEditingController passwordController = TextEditingController();
|
final TextEditingController passwordController = TextEditingController();
|
||||||
|
final loginFormKey = GlobalKey<FormState>();
|
||||||
bool isPasswordVisible = false;
|
bool isPasswordVisible = false;
|
||||||
|
|
||||||
static GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
static GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||||
@ -41,6 +42,56 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
static UserModel? user;
|
static UserModel? user;
|
||||||
|
|
||||||
static Token token = Token.emptyConstructor();
|
static Token token = Token.emptyConstructor();
|
||||||
|
|
||||||
|
/////////////////////////////////////VALIDATORS/////////////////////////////////////
|
||||||
|
String? passwordValidator(String? value) {
|
||||||
|
if (value != null) {
|
||||||
|
if (value.isNotEmpty) {
|
||||||
|
if (value.length >= 6) {
|
||||||
|
return null;
|
||||||
|
//TODO uncomment this code when the password validation is needed
|
||||||
|
// if (RegExp(
|
||||||
|
// r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$')
|
||||||
|
// .hasMatch(value)) {
|
||||||
|
// return null;
|
||||||
|
// } else {
|
||||||
|
// return 'Password must contain at least one uppercase letter, one lowercase letter, one number and one special character';
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
return 'Password must be at least 6 characters';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 'Please enter your password';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? emailAddressValidator(String? value) {
|
||||||
|
if (value != null && value.isNotEmpty && value != "") {
|
||||||
|
if (checkValidityOfEmail(value)) {
|
||||||
|
if (loginFormKey.currentState != null) {
|
||||||
|
loginFormKey.currentState!.save();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return 'Please enter a valid email';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 'Email address is required';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkValidityOfEmail(String? email) {
|
||||||
|
if (email != null) {
|
||||||
|
return RegExp(
|
||||||
|
r"^[a-zA-Z0-9]+([.!#$%&'*+/=?^_`{|}~-]?[a-zA-Z0-9]+)*@[a-zA-Z0-9]+([.-]?[a-zA-Z0-9]+)*\.[a-zA-Z0-9]{2,}$")
|
||||||
|
.hasMatch(email);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////API CALLS/////////////////////////////////////
|
/////////////////////////////////////API CALLS/////////////////////////////////////
|
||||||
login() async {
|
login() async {
|
||||||
emit(AuthLoginLoading());
|
emit(AuthLoginLoading());
|
||||||
|
|||||||
@ -13,9 +13,10 @@ class LoginForm extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var formKey = GlobalKey<FormState>();
|
var pressed = false;
|
||||||
return BlocBuilder<AuthCubit, AuthState>(
|
return BlocBuilder<AuthCubit, AuthState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
final formKey = AuthCubit.get(context).loginFormKey;
|
||||||
return Form(
|
return Form(
|
||||||
key: formKey,
|
key: formKey,
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
@ -28,30 +29,23 @@ class LoginForm extends StatelessWidget {
|
|||||||
fontColor: Colors.white,
|
fontColor: Colors.white,
|
||||||
),
|
),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
|
autovalidateMode: AutovalidateMode.disabled,
|
||||||
|
textInputAction: TextInputAction.done,
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
scrollPadding: EdgeInsets.zero,
|
||||||
|
autocorrect: false,
|
||||||
|
autofillHints: const [AutofillHints.email],
|
||||||
controller: AuthCubit.get(context).emailController,
|
controller: AuthCubit.get(context).emailController,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (state is! AuthTokenError) {
|
if (state is AuthTokenError && !pressed) {
|
||||||
if (value != null) {
|
return null;
|
||||||
if (value.isNotEmpty) {
|
|
||||||
if (RegExp(
|
|
||||||
r'^[a-zA-Z0-9._-]+@{1}[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$')
|
|
||||||
.hasMatch(value)) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return 'Please enter a valid email';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 'Please enter your email';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 'Please enter your email';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return AuthCubit.get(context).emailAddressValidator(value);
|
||||||
},
|
},
|
||||||
onTapOutside: (event) {
|
onTapOutside: (event) {
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
},
|
},
|
||||||
|
onChanged: (value) {},
|
||||||
decoration: defaultInputDecoration(context,
|
decoration: defaultInputDecoration(context,
|
||||||
hint: "Example@email.com"),
|
hint: "Example@email.com"),
|
||||||
),
|
),
|
||||||
@ -61,30 +55,18 @@ class LoginForm extends StatelessWidget {
|
|||||||
fontColor: Colors.white,
|
fontColor: Colors.white,
|
||||||
),
|
),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
|
autovalidateMode: AutovalidateMode.disabled,
|
||||||
|
textInputAction: TextInputAction.done,
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
scrollPadding: EdgeInsets.zero,
|
||||||
|
autocorrect: false,
|
||||||
|
autofillHints: const [AutofillHints.password],
|
||||||
controller: AuthCubit.get(context).passwordController,
|
controller: AuthCubit.get(context).passwordController,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (state is! AuthTokenError) {
|
if (state is AuthTokenError && !pressed) {
|
||||||
if (value != null) {
|
return null;
|
||||||
if (value.isNotEmpty) {
|
|
||||||
return null;
|
|
||||||
//TODO: uncomment this when the backend is ready
|
|
||||||
// if (value.length > 8) {
|
|
||||||
// if (RegExp(
|
|
||||||
// r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$')
|
|
||||||
// .hasMatch(value)) {
|
|
||||||
// return null;
|
|
||||||
// } else {
|
|
||||||
// return 'Password must contain at least one uppercase letter, one lowercase letter, one number and one special character';
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// return 'Password must be at least 8 characters';
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
return 'Please enter your password';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return AuthCubit.get(context).passwordValidator(value);
|
||||||
},
|
},
|
||||||
onTapOutside: (event) {
|
onTapOutside: (event) {
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
@ -116,14 +98,11 @@ class LoginForm extends StatelessWidget {
|
|||||||
'Login',
|
'Login',
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
bool isValid = formKey.currentState!.validate();
|
pressed = true;
|
||||||
if (isValid) {
|
if (formKey.currentState!.validate()) {
|
||||||
if ((state is! AuthLoading)) {
|
if ((state is! AuthLoading)) {
|
||||||
print('login');
|
|
||||||
AuthCubit.get(context).login();
|
AuthCubit.get(context).login();
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
} else {
|
|
||||||
formKey.currentState!.save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -16,16 +16,11 @@ class AuthenticationAPI {
|
|||||||
|
|
||||||
static Future<Token> loginWithEmail(
|
static Future<Token> loginWithEmail(
|
||||||
{required LoginWithEmailModel model}) async {
|
{required LoginWithEmailModel model}) async {
|
||||||
try {
|
final response = await HTTPService().post(
|
||||||
final response = await HTTPService().post(
|
path: ApiEndpoints.login,
|
||||||
path: ApiEndpoints.login,
|
body: model.toJson(),
|
||||||
body: model.toJson(),
|
showServerMessage: false,
|
||||||
showServerMessage: false,
|
expectedResponseModel: (json) => Token.fromJson(json['data']));
|
||||||
expectedResponseModel: (json) => Token.fromJson(json['data']));
|
return response;
|
||||||
// developer.log("response: $response");
|
|
||||||
return response;
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,52 +30,41 @@ class DevicesAPI {
|
|||||||
"pageSize": 100,
|
"pageSize": 100,
|
||||||
"pageNo": 1
|
"pageNo": 1
|
||||||
};
|
};
|
||||||
try {
|
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.groups,
|
path: ApiEndpoints.groups,
|
||||||
queryParameters: params,
|
queryParameters: params,
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) =>
|
expectedResponseModel: (json) =>
|
||||||
DevicesCategoryModel.fromJsonList(json['groups']),
|
DevicesCategoryModel.fromJsonList(json['groups']),
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
|
static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
|
||||||
try {
|
final response = await _httpService.get(
|
||||||
final response = await _httpService.get(
|
path: '${ApiEndpoints.deviceStatus}/$deviceId/functions/status',
|
||||||
path: '${ApiEndpoints.deviceStatus}/$deviceId/functions/status',
|
showServerMessage: false,
|
||||||
showServerMessage: false,
|
expectedResponseModel: (json) {
|
||||||
expectedResponseModel: (json) {
|
return json;
|
||||||
return json;
|
},
|
||||||
},
|
);
|
||||||
);
|
return response;
|
||||||
return response;
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<List<DeviceModel>> getDevicesByRoomId(int roomId) async {
|
static Future<List<DeviceModel>> getDevicesByRoomId(int roomId) async {
|
||||||
try {
|
final response = await _httpService.get(
|
||||||
final response = await _httpService.get(
|
path: ApiEndpoints.devicesByRoom,
|
||||||
path: ApiEndpoints.devicesByRoom,
|
queryParameters: {"roomId": roomId, "pageSize": 10},
|
||||||
queryParameters: {"roomId": roomId, "pageSize": 10},
|
showServerMessage: false,
|
||||||
showServerMessage: false,
|
expectedResponseModel: (json) {
|
||||||
expectedResponseModel: (json) {
|
List<DeviceModel> devices = [];
|
||||||
List<DeviceModel> devices = [];
|
for (var device in json['devices']) {
|
||||||
for (var device in json['devices']) {
|
devices.add(DeviceModel.fromJson(device));
|
||||||
devices.add(DeviceModel.fromJson(device));
|
}
|
||||||
}
|
return devices;
|
||||||
return devices;
|
},
|
||||||
},
|
);
|
||||||
);
|
return response;
|
||||||
return response;
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,11 +42,6 @@ class HTTPInterceptor extends InterceptorsWrapper {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onError(DioException err, ErrorInterceptorHandler handler) async {
|
void onError(DioException err, ErrorInterceptorHandler handler) async {
|
||||||
// developer.log('Error Message: ${err.message}');
|
|
||||||
// developer.log('Error res Code: ${err.response?.statusCode}');
|
|
||||||
// developer.log('Error res Data: ${err.response?.data}');
|
|
||||||
// developer.log('Error res status message: ${err.response?.statusMessage}');
|
|
||||||
|
|
||||||
ServerFailure failure = ServerFailure.fromDioError(err);
|
ServerFailure failure = ServerFailure.fromDioError(err);
|
||||||
CustomSnackBar.displaySnackBar(failure.toString());
|
CustomSnackBar.displaySnackBar(failure.toString());
|
||||||
var storage = const FlutterSecureStorage();
|
var storage = const FlutterSecureStorage();
|
||||||
|
|||||||
@ -74,11 +74,8 @@ class HTTPService {
|
|||||||
data: body,
|
data: body,
|
||||||
queryParameters: queryParameters,
|
queryParameters: queryParameters,
|
||||||
);
|
);
|
||||||
developer.log("status code is ${response.statusCode}");
|
|
||||||
return expectedResponseModel(response.data);
|
return expectedResponseModel(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
developer.log("******* Error");
|
|
||||||
developer.log(error.toString());
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,21 +86,15 @@ class HTTPService {
|
|||||||
Map<String, dynamic>? queryParameters,
|
Map<String, dynamic>? queryParameters,
|
||||||
required T Function(dynamic) expectedResponseModel}) async {
|
required T Function(dynamic) expectedResponseModel}) async {
|
||||||
try {
|
try {
|
||||||
developer.log("download begins");
|
|
||||||
final response = await client.download(
|
final response = await client.download(
|
||||||
path,
|
path,
|
||||||
savePath,
|
savePath,
|
||||||
onReceiveProgress: (current, total) {
|
onReceiveProgress: (current, total) {},
|
||||||
developer.log("current = $current, while total = $total");
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
developer.log("download ends");
|
|
||||||
return expectedResponseModel(response.data);
|
return expectedResponseModel(response.data);
|
||||||
// return expectedResponseModel(response.data);
|
// return expectedResponseModel(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
developer.log("******* Error");
|
|
||||||
developer.log("download error");
|
|
||||||
developer.log(error.toString());
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,8 +112,6 @@ class HTTPService {
|
|||||||
);
|
);
|
||||||
return expectedResponseModel(response.data);
|
return expectedResponseModel(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
developer.log("******* Error");
|
|
||||||
developer.log(error.toString());
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ class ServerFailure extends Failure {
|
|||||||
// var document = parser.parse(dioError.response!.data.toString());
|
// var document = parser.parse(dioError.response!.data.toString());
|
||||||
// var message = document.body!.text;
|
// var message = document.body!.text;
|
||||||
return ServerFailure.fromResponse(dioError.response!.statusCode!,
|
return ServerFailure.fromResponse(dioError.response!.statusCode!,
|
||||||
dioError.response!.data['message']);
|
dioError.response?.data['message'] ?? "Error");
|
||||||
}
|
}
|
||||||
case DioExceptionType.cancel:
|
case DioExceptionType.cancel:
|
||||||
return ServerFailure("The request to ApiServer was canceled");
|
return ServerFailure("The request to ApiServer was canceled");
|
||||||
@ -48,25 +48,25 @@ class ServerFailure extends Failure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
factory ServerFailure.fromResponse(int? statusCode, dynamic response) {
|
factory ServerFailure.fromResponse(int? statusCode, dynamic responseMessage) {
|
||||||
switch (statusCode) {
|
switch (statusCode) {
|
||||||
case 401:
|
case 401:
|
||||||
case 403:
|
case 403:
|
||||||
return ServerFailure(response);
|
return ServerFailure(responseMessage);
|
||||||
case 400:
|
case 400:
|
||||||
List<String> errors = [];
|
List<String> errors = [];
|
||||||
if (response['message'] is List) {
|
if (responseMessage is List) {
|
||||||
for (var error in response['message']) {
|
for (var error in responseMessage) {
|
||||||
errors.add(error);
|
errors.add(error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errors.add(response['message']);
|
return ServerFailure(responseMessage);
|
||||||
}
|
}
|
||||||
return ServerFailure(errors.join('\n'));
|
return ServerFailure(errors.join('\n'));
|
||||||
case 404:
|
case 404:
|
||||||
return ServerFailure("Your request not found, Please try later!");
|
return ServerFailure("Your request not found, Please try later!");
|
||||||
case 500:
|
case 500:
|
||||||
return ServerFailure(response);
|
return ServerFailure(responseMessage);
|
||||||
default:
|
default:
|
||||||
return ServerFailure("Opps there was an Error, Please try again!");
|
return ServerFailure("Opps there was an Error, Please try again!");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,39 +12,31 @@ class SpacesAPI {
|
|||||||
static Future<List<SpaceModel>> getSpaces() async {
|
static Future<List<SpaceModel>> getSpaces() async {
|
||||||
var uuid =
|
var uuid =
|
||||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||||
try {
|
final response = await _httpService.get(
|
||||||
final response = await _httpService.get(
|
path: ApiEndpoints.spaces,
|
||||||
path: ApiEndpoints.spaces,
|
queryParameters: {
|
||||||
queryParameters: {
|
"userUuid": uuid,
|
||||||
"userUuid": uuid,
|
},
|
||||||
},
|
showServerMessage: false,
|
||||||
showServerMessage: false,
|
expectedResponseModel: (json) => SpaceModel.fromJsonList(json),
|
||||||
expectedResponseModel: (json) => SpaceModel.fromJsonList(json),
|
);
|
||||||
);
|
return response;
|
||||||
return response;
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//get rooms by space id
|
//get rooms by space id
|
||||||
static Future<List<RoomModel>> getRoomsBySpaceId(int spaceId) async {
|
static Future<List<RoomModel>> getRoomsBySpaceId(int spaceId) async {
|
||||||
try {
|
final response = await _httpService.get(
|
||||||
final response = await _httpService.get(
|
path: ApiEndpoints.rooms,
|
||||||
path: ApiEndpoints.rooms,
|
queryParameters: {"homeId": spaceId},
|
||||||
queryParameters: {"homeId": spaceId},
|
showServerMessage: false,
|
||||||
showServerMessage: false,
|
expectedResponseModel: (json) {
|
||||||
expectedResponseModel: (json) {
|
List<RoomModel> rooms = [];
|
||||||
List<RoomModel> rooms = [];
|
for (var room in json) {
|
||||||
for (var room in json) {
|
rooms.add(RoomModel.fromJson(room));
|
||||||
rooms.add(RoomModel.fromJson(room));
|
}
|
||||||
}
|
return rooms;
|
||||||
return rooms;
|
},
|
||||||
},
|
);
|
||||||
);
|
return response;
|
||||||
return response;
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,6 @@ class StringHelpers {
|
|||||||
static String enhanceFileName(File file) {
|
static String enhanceFileName(File file) {
|
||||||
var fileName = " ";
|
var fileName = " ";
|
||||||
final filePath = file.path;
|
final filePath = file.path;
|
||||||
developer.log(filePath);
|
|
||||||
final fileStringArray = filePath.split("/");
|
final fileStringArray = filePath.split("/");
|
||||||
fileName = fileStringArray.last;
|
fileName = fileStringArray.last;
|
||||||
if (fileName.length > 20) {
|
if (fileName.length > 20) {
|
||||||
|
|||||||
Reference in New Issue
Block a user