326 lines
8.8 KiB
Dart
326 lines
8.8 KiB
Dart
|
// ignore_for_file: unnecessary_overrides, prefer_typing_uninitialized_variables
|
||
|
|
||
|
import 'dart:convert';
|
||
|
import 'dart:io';
|
||
|
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||
|
import 'package:form_builder_validators/form_builder_validators.dart';
|
||
|
import 'package:get/get.dart';
|
||
|
import 'package:logger/logger.dart';
|
||
|
import 'package:IQ/app/global/login_snackbar.dart';
|
||
|
import 'package:IQ/app/global/snono_encrypt.dart';
|
||
|
import 'package:IQ/app/global/static_informs.dart';
|
||
|
import 'package:IQ/app/global/text_field.dart';
|
||
|
import 'package:IQ/app/global/text_widget.dart';
|
||
|
import 'package:IQ/app/modules/home/providers/language_currency.dart';
|
||
|
import 'package:IQ/app/modules/service/api_service.dart';
|
||
|
import 'package:IQ/app/routes/app_pages.dart';
|
||
|
import 'package:IQ/main.dart';
|
||
|
import 'package:url_launcher/url_launcher.dart';
|
||
|
import 'package:uuid/uuid.dart';
|
||
|
|
||
|
String? uuid = const Uuid().v1();
|
||
|
|
||
|
class LoginController extends GetxController with WidgetsBindingObserver {
|
||
|
bool inputsEntered = false;
|
||
|
|
||
|
var encryptedText, decryptedText;
|
||
|
var formKey = GlobalKey<FormBuilderState>();
|
||
|
String? enteredName;
|
||
|
TextEditingController nameController = TextEditingController(
|
||
|
text: storage.read('username') ?? '',
|
||
|
);
|
||
|
String? enteredPassword;
|
||
|
String? enteredCaptcha;
|
||
|
TextEditingController passwordController = TextEditingController(
|
||
|
text: storage.read('password') ?? '',
|
||
|
);
|
||
|
bool? checkedCheckbox = false;
|
||
|
resetCaptcha() async {
|
||
|
uuid = null;
|
||
|
captcha = null;
|
||
|
enteredCaptcha = null;
|
||
|
if (isCaptcha == 1) {
|
||
|
uuid = const Uuid().v1();
|
||
|
await getcaptcha(uuid.toString());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
onChangedCheckbox(val) {
|
||
|
checkedCheckbox = val;
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
onPressedCallCenter() async {
|
||
|
const url = "tel:+93787204545";
|
||
|
await launchUrl(Uri.parse(url));
|
||
|
}
|
||
|
|
||
|
onChangedEnteredName(val) {
|
||
|
enteredName = val;
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
onChangedPassword(val) {
|
||
|
enteredPassword = val;
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
bool isObscure = true;
|
||
|
onPressedEye() {
|
||
|
isObscure = !isObscure;
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
Future login() async {
|
||
|
String payload = AES.encrypt(
|
||
|
data: jsonEncode({
|
||
|
"username": enteredName,
|
||
|
"password": enteredPassword,
|
||
|
"language": "en",
|
||
|
"captcha_text": enteredCaptcha,
|
||
|
"session_id": uuid,
|
||
|
"device_id": deviceId,
|
||
|
}),
|
||
|
passpharse: 'abcdefghijuklmno0123456789012345',
|
||
|
);
|
||
|
|
||
|
var value = await APIService.post('auth/login', payload, false).timeout(
|
||
|
const Duration(seconds: 6),
|
||
|
onTimeout: () {
|
||
|
inputsEntered = false;
|
||
|
update();
|
||
|
snack('provider_unreachable'.tr);
|
||
|
},
|
||
|
);
|
||
|
Logger().d("login $value");
|
||
|
if (value.runtimeType == int) {
|
||
|
inputsEntered = false;
|
||
|
update();
|
||
|
|
||
|
switch (value) {
|
||
|
case 0:
|
||
|
snack('no_connect'.tr);
|
||
|
break;
|
||
|
case -2:
|
||
|
snack('provider_unreachable'.tr);
|
||
|
break;
|
||
|
case -1:
|
||
|
snack('ip_address_invalid'.tr);
|
||
|
break;
|
||
|
case 401:
|
||
|
snack('login_failed'.tr);
|
||
|
break;
|
||
|
case 403:
|
||
|
snack('login_failed'.tr);
|
||
|
break;
|
||
|
case -3:
|
||
|
snack('unknown_error'.tr);
|
||
|
break;
|
||
|
default:
|
||
|
snack('unknown_error'.tr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
await resetCaptcha();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (value == null) {
|
||
|
snack('login_failed'.tr);
|
||
|
inputsEntered = false;
|
||
|
update();
|
||
|
await resetCaptcha();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var data = jsonDecode(value);
|
||
|
if (data['status'] == -3) {
|
||
|
snack('unknown_error'.tr);
|
||
|
inputsEntered = false;
|
||
|
update();
|
||
|
} else {
|
||
|
if (data['status'] == 200) {
|
||
|
token = data["token"];
|
||
|
storage.write('token', token);
|
||
|
await resetCaptcha();
|
||
|
if (checkedCheckbox == true) {
|
||
|
storage.write('username', enteredName);
|
||
|
storage.write('password', enteredPassword);
|
||
|
storage.write('remember', checkedCheckbox);
|
||
|
update();
|
||
|
}
|
||
|
Future.delayed(
|
||
|
const Duration(seconds: 2),
|
||
|
() {
|
||
|
inputsEntered = false;
|
||
|
update();
|
||
|
Get.offNamed(Routes.HOME);
|
||
|
},
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
onPressedEnter() {
|
||
|
if (checkedCheckbox == false) {
|
||
|
storage.remove('username');
|
||
|
storage.remove('password');
|
||
|
storage.remove('remember');
|
||
|
}
|
||
|
enteredName = nameController.text;
|
||
|
enteredPassword = passwordController.text;
|
||
|
|
||
|
if (enteredName == null ||
|
||
|
enteredPassword == null ||
|
||
|
(enteredName?.isEmpty)! ||
|
||
|
(enteredPassword?.isEmpty)!) {
|
||
|
snack('unentered_login_credentials'.tr);
|
||
|
return;
|
||
|
}
|
||
|
if (isCaptcha == 1) {
|
||
|
Get.defaultDialog(
|
||
|
title: 'enter_captcha'.tr,
|
||
|
backgroundColor: brandColor,
|
||
|
titlePadding: const EdgeInsets.only(top: 15),
|
||
|
titleStyle: buildTextStyle(
|
||
|
color: Colors.white,
|
||
|
fontSize: 20,
|
||
|
fontWeight: FontWeight.w600,
|
||
|
),
|
||
|
content: SizedBox(
|
||
|
width: Get.width,
|
||
|
child: Column(
|
||
|
children: [
|
||
|
Container(
|
||
|
width: 200,
|
||
|
decoration: BoxDecoration(
|
||
|
border: Border.all(
|
||
|
color: Colors.white.withOpacity(0.5),
|
||
|
width: 1,
|
||
|
),
|
||
|
),
|
||
|
child: Image.memory(
|
||
|
captcha!,
|
||
|
width: 200,
|
||
|
frameBuilder:
|
||
|
(context, child, frame, wasSynchronouslyLoaded) {
|
||
|
if (wasSynchronouslyLoaded) {
|
||
|
return child;
|
||
|
}
|
||
|
return AnimatedOpacity(
|
||
|
child: child,
|
||
|
opacity: frame == null ? 0 : 1,
|
||
|
duration: const Duration(milliseconds: 500),
|
||
|
);
|
||
|
},
|
||
|
),
|
||
|
),
|
||
|
FormBuilder(
|
||
|
key: formKey,
|
||
|
child: Directionality(
|
||
|
textDirection: TextDirection.rtl,
|
||
|
child: BuildTextField(
|
||
|
name: 'captcha',
|
||
|
hintText: 'captcha_hint'.tr,
|
||
|
margin: const EdgeInsets.all(30),
|
||
|
textDirection: TextDirection.rtl,
|
||
|
onChanged: (val) {
|
||
|
enteredCaptcha = val;
|
||
|
update();
|
||
|
},
|
||
|
onEditingComplete: () {
|
||
|
FocusScope.of(Get.context!).unfocus();
|
||
|
},
|
||
|
validator: FormBuilderValidators.compose(
|
||
|
[
|
||
|
FormBuilderValidators.required(
|
||
|
errorText: 'captcha_validation'.tr,
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
contentPadding: const EdgeInsets.all(10),
|
||
|
onWillPop: () async {
|
||
|
await resetCaptcha();
|
||
|
return true;
|
||
|
},
|
||
|
actions: [
|
||
|
TextButton(
|
||
|
child: TextWidget(
|
||
|
text: 'captcha_dialog_cancel_button'.tr,
|
||
|
color: Colors.white,
|
||
|
),
|
||
|
onPressed: () async {
|
||
|
Get.back();
|
||
|
await resetCaptcha();
|
||
|
},
|
||
|
),
|
||
|
ElevatedButton(
|
||
|
child: TextWidget(
|
||
|
text: 'captcha_dialog_ok_button'.tr,
|
||
|
color: brandColor,
|
||
|
),
|
||
|
style: ButtonStyle(
|
||
|
backgroundColor: MaterialStateProperty.all(Colors.white),
|
||
|
),
|
||
|
onPressed: () {
|
||
|
if ((formKey.currentState?.validate())!) {
|
||
|
inputsEntered = true;
|
||
|
update();
|
||
|
Get.back();
|
||
|
login();
|
||
|
}
|
||
|
},
|
||
|
),
|
||
|
],
|
||
|
);
|
||
|
} else {
|
||
|
inputsEntered = true;
|
||
|
update();
|
||
|
login();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||
|
super.didChangeAppLifecycleState(state);
|
||
|
if (state == AppLifecycleState.inactive ||
|
||
|
state == AppLifecycleState.detached ||
|
||
|
state == AppLifecycleState.paused) return;
|
||
|
if (state == AppLifecycleState.resumed) {
|
||
|
defaultLocale = Platform.localeName.split('_')[0];
|
||
|
textDirection =
|
||
|
defaultLocale == "en" ? TextDirection.ltr : TextDirection.rtl;
|
||
|
snackBarText = 'back_twice'.tr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void onInit() async {
|
||
|
WidgetsBinding.instance.addObserver(this);
|
||
|
if (storage.read('remember') != null) {
|
||
|
checkedCheckbox =
|
||
|
storage.read('remember').toString().toLowerCase() == 'true';
|
||
|
}
|
||
|
|
||
|
super.onInit();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void onReady() {
|
||
|
super.onReady();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void onClose() {
|
||
|
WidgetsBinding.instance.removeObserver(this);
|
||
|
}
|
||
|
}
|