feat(sms): автоподстановка кода из sms
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import 'dart:io';
|
||||
import 'package:smart_auth/smart_auth.dart';
|
||||
|
||||
typedef SmsCodeCallback = void Function(String code);
|
||||
|
||||
class SmsCodeListener {
|
||||
static const String _matcher = r'\d{6}';
|
||||
|
||||
final SmartAuth _smartAuth = SmartAuth.instance;
|
||||
bool _listening = false;
|
||||
bool _disposed = false;
|
||||
|
||||
bool get _supported => Platform.isAndroid;
|
||||
|
||||
Future<void> start(SmsCodeCallback onCode) async {
|
||||
if (!_supported || _listening || _disposed) return;
|
||||
_listening = true;
|
||||
|
||||
final result = await _smartAuth.getSmsWithUserConsentApi(matcher: _matcher);
|
||||
|
||||
_listening = false;
|
||||
if (_disposed) return;
|
||||
|
||||
final code = result.hasData ? result.requireData.code : null;
|
||||
if (code != null) onCode(code);
|
||||
}
|
||||
|
||||
Future<void> cancel() async {
|
||||
if (!_supported) return;
|
||||
await _smartAuth.removeUserConsentApiListener();
|
||||
_listening = false;
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import 'password_2fa_screen.dart';
|
||||
import 'registration_screen.dart';
|
||||
import '../../../backend/api.dart';
|
||||
import '../../../core/protocol/packet.dart';
|
||||
import '../../../core/utils/sms_code_listener.dart';
|
||||
import '../../../main.dart';
|
||||
import '../../widgets/custom_notification.dart';
|
||||
import '../../widgets/login_success_screen.dart';
|
||||
@@ -30,6 +31,7 @@ class _CodeConfirmationScreenState extends State<CodeConfirmationScreen>
|
||||
with TickerProviderStateMixin {
|
||||
final TextEditingController _codeController = TextEditingController();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
final SmsCodeListener _smsListener = SmsCodeListener();
|
||||
int _timerSeconds = 30;
|
||||
Timer? _timer;
|
||||
Timer? _errorTimer;
|
||||
@@ -59,6 +61,7 @@ class _CodeConfirmationScreenState extends State<CodeConfirmationScreen>
|
||||
_epoch = api.sessionEpoch;
|
||||
_stateSub = api.stateStream.listen(_onSessionState);
|
||||
_startTimer();
|
||||
_listenForSmsCode();
|
||||
|
||||
_shakeController = AnimationController(
|
||||
vsync: this,
|
||||
@@ -85,6 +88,7 @@ class _CodeConfirmationScreenState extends State<CodeConfirmationScreen>
|
||||
if (_routeAnimationListener != null) {
|
||||
_routeAnimation?.removeStatusListener(_routeAnimationListener!);
|
||||
}
|
||||
_smsListener.dispose();
|
||||
_stateSub?.cancel();
|
||||
_timer?.cancel();
|
||||
_errorTimer?.cancel();
|
||||
@@ -137,6 +141,7 @@ class _CodeConfirmationScreenState extends State<CodeConfirmationScreen>
|
||||
_errorMessage = null;
|
||||
});
|
||||
_startTimer();
|
||||
_listenForSmsCode();
|
||||
showCustomNotification(
|
||||
context,
|
||||
'Соединение восстановлено — выслали новый код',
|
||||
@@ -194,6 +199,23 @@ class _CodeConfirmationScreenState extends State<CodeConfirmationScreen>
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _listenForSmsCode() async {
|
||||
await _smsListener.start((code) {
|
||||
if (!mounted) return;
|
||||
_applyAutoCode(code);
|
||||
});
|
||||
}
|
||||
|
||||
void _applyAutoCode(String code) {
|
||||
if (_verifying || _recovering) return;
|
||||
if (_codeController.text == code) return;
|
||||
_codeController.text = code;
|
||||
_codeController.selection = TextSelection.collapsed(offset: code.length);
|
||||
if (_errorMessage != null) _errorMessage = null;
|
||||
setState(() {});
|
||||
if (code.length == 6) _verifyCode();
|
||||
}
|
||||
|
||||
void _showError(String message) {
|
||||
_errorTimer?.cancel();
|
||||
_shakeController.forward(from: 0);
|
||||
|
||||
@@ -1322,6 +1322,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.1"
|
||||
smart_auth:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: smart_auth
|
||||
sha256: a536423c50d71e9a311d16027346634d0deadd07dafc5b5606b46719cf6fb2b6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -80,6 +80,7 @@ dependencies:
|
||||
media_kit_libs_linux: ^1.2.1
|
||||
media_kit_libs_macos_video: ^1.1.4
|
||||
sensors_plus: ^7.1.0
|
||||
smart_auth: ^3.2.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in New Issue
Block a user