You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HMG_Patient_App/lib/widgets/otp/sms-popup.dart

372 lines
11 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:hmg_patient_app/config/size_config.dart';
import 'package:hmg_patient_app/core/viewModels/project_view_model.dart';
import 'package:hmg_patient_app/theme/colors.dart';
import 'package:hmg_patient_app/uitl/font_utils.dart';
import 'package:hmg_patient_app/uitl/translations_delegate_base.dart';
import 'package:hmg_patient_app/uitl/utils.dart';
import 'package:hmg_patient_app/uitl/whatsapp_method_channel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:hmg_patient_app/widgets/others/app_scaffold_widget.dart';
import 'package:provider/provider.dart';
import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart';
import '../otp_widget.dart';
class SMSOTP {
final type;
final mobileNo;
final Function onSuccess;
final Function onFailure;
final context;
int remainingTime = 120;
Timer? _timer; // Changed from Future<dynamic>? to Timer?
bool _isDisposed = false; // Add disposal flag
static BuildContext? _context;
static bool? _loading;
SMSOTP(
this.context,
this.type,
this.mobileNo,
this.onSuccess,
this.onFailure,
);
final verifyAccountForm = GlobalKey<FormState>();
final TextEditingController _pinPutController = TextEditingController();
TextEditingController digit1 = TextEditingController(text: "");
TextEditingController digit2 = TextEditingController(text: "");
TextEditingController digit3 = TextEditingController(text: "");
TextEditingController digit4 = TextEditingController(text: "");
Map verifyAccountFormValue = {
'digit1': '',
'digit2': '',
'digit3': '',
'digit4': '',
};
final focusD1 = FocusNode();
final focusD2 = FocusNode();
final focusD3 = FocusNode();
final focusD4 = FocusNode();
String? errorMsg;
ProjectViewModel? projectProvider;
String? displayTime = '';
String? _code;
dynamic setState;
static String? signature;
displayDialog(BuildContext context) async {
return showGeneralDialog(
context: context,
barrierColor: Colors.black.withOpacity(0.63),
barrierDismissible: false,
transitionDuration: Duration(milliseconds: 300),
pageBuilder: (context, animation1, animation2) {
projectProvider = Provider.of(context);
return StatefulBuilder(builder: (context, setState) {
if (displayTime == '') {
startTimer(setState);
if (Platform.isAndroid) {
if (type == 1)
checkSignature();
else if (type == 4) _listenWhatsAppCode();
}
}
return AppScaffold(
appBarTitle: TranslationBase.of(context).otpVerfication,
isShowDecPage: false,
isShowAppBar: true,
isshowBackButton: true,
showNewAppBar: true,
backgroundColor: Color(0xffF8F8F8),
showNewAppBarTitle: true,
showDropDown: false,
isShowLanguageChanger: false,
showHomeAppBarIcon: false,
resizeToAvoidBottomInset: true,
appBarIcons: [],
dropDownIndexChange: (value) {
Utils.changeAppLanguage(context: context);
},
body: SafeArea(
top: false,
bottom: Platform.isIOS ? false : true,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 21, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 22),
Text(
TranslationBase.of(context).pleaseEnterTheVerificationCode + ' xxxxxxxx' + mobileNo.toString().substring(mobileNo.toString().length - 3),
style: context.dynamicTextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xff2B353E),
letterSpacing: -0.48,
),
),
SizedBox(height: 18),
Directionality(
textDirection: TextDirection.ltr,
child: OTPWidget(
autoFocus: true,
controller: _pinPutController,
defaultBorderColor: Color(0xffE0E0E0), // Changed from white to light gray
maxLength: 4,
onTextChanged: (text) {},
pinBoxColor: Colors.white,
onDone: (code) => _onOtpCallBack(code, false),
textBorderColor: Color(0xffffff),
pinBoxWidth: 76,
pinBoxHeight: 94,
pinTextStyle: TextStyle(fontSize: 24.0, color: Color(0xff2B353E)),
pinTextAnimatedSwitcherTransition: ProvidedPinBoxTextAnimation.scalingTransition,
pinTextAnimatedSwitcherDuration: Duration(milliseconds: 300),
pinBoxRadius: 18,
keyboardType: TextInputType.number,
),
),
SizedBox(height: 30),
RichText(
text: TextSpan(
text: TranslationBase.of(context).validationMessage + '\n',
style: context.dynamicTextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xff2B353E),
letterSpacing: -0.48,
),
children: <TextSpan>[
TextSpan(
text: displayTime,
style: context.dynamicTextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xffD02127),
letterSpacing: -0.48,
),
),
],
),
),
],
),
),
),
);
});
},
);
}
TextStyle buildTextStyle() {
return TextStyle(
fontSize: SizeConfig.textMultiplier! * 3,
);
}
InputDecoration buildInputDecoration(BuildContext context) {
return InputDecoration(
counterText: " ",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide(color: Theme.of(context).primaryColor),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide(color: CustomColors.accentColor),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide(color: CustomColors.accentColor),
),
);
}
String? validateCodeDigit(value) {
if (value.isEmpty) {
return ' ';
} else if (value.length == 3) {
print(value);
} else {
return null;
}
}
checkValue() {
//print(verifyAccountFormValue);
if (verifyAccountForm.currentState!.validate()) {
onSuccess(digit1.text.toString() + digit2.text.toString() + digit3.text.toString() + digit4.text.toString());
}
}
getSecondsAsDigitalClock(int inputSeconds) {
var sec_num = int.parse(inputSeconds.toString()); // don't forget the second param
var hours = (sec_num / 3600).floor();
var minutes = ((sec_num - hours * 3600) / 60).floor();
var seconds = sec_num - hours * 3600 - minutes * 60;
var minutesString = "";
var secondsString = "";
minutesString = minutes < 10 ? "0" + minutes.toString() : minutes.toString();
secondsString = seconds < 10 ? "0" + seconds.toString() : seconds.toString();
return minutesString + ":" + secondsString;
}
startTimer(setState) {
// Cancel any existing timer
_timer?.cancel();
this.remainingTime--;
// Check if widget is still mounted before calling setState
if (!_isDisposed) {
setState(() {
displayTime = this.getSecondsAsDigitalClock(this.remainingTime);
});
_timer = Timer(Duration(seconds: 1), () {
if (!_isDisposed && this.remainingTime > 0) {
startTimer(setState);
} else if (!_isDisposed && this.remainingTime <= 0) {
Navigator.pop(context);
}
});
}
}
// Add method to dispose the timer properly
void dispose() {
_isDisposed = true;
_timer?.cancel();
_timer = null;
}
// New method for flexible timer handling - pause timer without disposing
void pauseTimer() {
_timer?.cancel();
_timer = null;
}
// Method to resume the timer from current remaining time
void resumeTimer(setState) {
if (!_isDisposed && remainingTime > 0) {
startTimer(setState);
}
}
// Method to reset timer to original time and restart
void resetTimer(setState, {int? newTime}) {
_timer?.cancel();
if (newTime != null) {
remainingTime = newTime;
} else {
remainingTime = 120; // Reset to original 2 minutes
}
if (!_isDisposed) {
startTimer(setState);
}
}
// Method to check if timer is currently running
bool isTimerRunning() {
return _timer != null && _timer!.isActive;
}
// Method to get current remaining time
int getCurrentRemainingTime() {
return remainingTime;
}
// Method to clear the OTP input
void clearOTPInput() {
_pinPutController.clear();
digit1.clear();
digit2.clear();
digit3.clear();
digit4.clear();
}
checkSignature() async {
SmsVerification.startListeningSms().then((message) {
// setState(() {
final intRegex = RegExp(r'\d+', multiLine: true);
var otp = SmsVerification.getCode(message, intRegex);
_pinPutController.text = otp;
onSuccess(otp);
SmsVerification.stopListening();
// });
});
}
void _listenWhatsAppCode() {
WhatsappMethodChannel().startListening().then((message) {
final intRegex = RegExp(r'\d+', multiLine: true);
var otp = SmsVerification.getCode(message, intRegex);
_pinPutController.text = otp;
onSuccess(otp);
});
}
// startLister() {
// var signature = checkSignature();
//
// print(signature);
// }
static getSignature() async {
if (Platform.isAndroid) {
return await SmsVerification.getAppSignature();
} else {
return null;
}
}
static void hideSMSBox(context) {
Navigator.pop(context);
}
_onOtpCallBack(String otpCode, bool isAutofill) {
if (otpCode.length == 4) {
onSuccess(otpCode);
}
}
}