flagged bugs fix
This commit is contained in:
@@ -34,32 +34,12 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
await state.initiateLogin(_phone.text);
|
||||
if (!mounted) return;
|
||||
|
||||
state.isLoginFlow = true;
|
||||
|
||||
// Bypass OTP for Easter Egg
|
||||
if (_phone.text.replaceAll(' ', '') == '9876543210') {
|
||||
setState(() => _loading = false);
|
||||
Navigator.pushNamed(context, Routes.enterPin);
|
||||
return;
|
||||
}
|
||||
|
||||
await state.sendOtp(
|
||||
_phone.text,
|
||||
onSuccess: () {
|
||||
if (!mounted) return;
|
||||
setState(() => _loading = false);
|
||||
Navigator.pushNamed(context, Routes.otp);
|
||||
},
|
||||
onError: (err) {
|
||||
if (!mounted) return;
|
||||
state.isLoginFlow = false;
|
||||
setState(() => _loading = false);
|
||||
SnackbarUtils.showError(context, err);
|
||||
},
|
||||
);
|
||||
// Backend already gates login behind the PIN check, so no separate
|
||||
// OTP possession-of-phone step is needed for returning users.
|
||||
setState(() => _loading = false);
|
||||
Navigator.pushNamed(context, Routes.enterPin);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
state.isLoginFlow = false;
|
||||
setState(() => _loading = false);
|
||||
SnackbarUtils.showError(context, e.toString());
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:sms_autofill/sms_autofill.dart';
|
||||
|
||||
import 'package:doormile/main.dart';
|
||||
import 'package:doormile/shared/state/app_state.dart';
|
||||
@@ -18,7 +21,7 @@ class OtpScreen extends StatefulWidget {
|
||||
State<OtpScreen> createState() => _OtpScreenState();
|
||||
}
|
||||
|
||||
class _OtpScreenState extends State<OtpScreen> {
|
||||
class _OtpScreenState extends State<OtpScreen> with CodeAutoFill {
|
||||
final List<TextEditingController> _controllers =
|
||||
List.generate(6, (_) => TextEditingController());
|
||||
final List<FocusNode> _nodes = List.generate(6, (_) => FocusNode());
|
||||
@@ -30,9 +33,40 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_startTimer();
|
||||
listenForCode();
|
||||
_prefillDebugBypass();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _nodes[0].requestFocus());
|
||||
}
|
||||
|
||||
/// Debug-only tester shortcut, see [AppState.verifyOtp]. Compiled out of
|
||||
/// release builds via kDebugMode.
|
||||
Future<void> _prefillDebugBypass() async {
|
||||
if (!kDebugMode) return;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final provider = prefs.getInt('smsDefaultProvider') ?? 0;
|
||||
final passKey = prefs.getInt('smsPassKey');
|
||||
if (provider != 1 || passKey == null) return;
|
||||
if (!mounted || _controllers.any((c) => c.text.isNotEmpty)) return;
|
||||
|
||||
final passKeyStr = passKey.toString().padLeft(6, '0');
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_controllers[i].text = passKeyStr[i];
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void codeUpdated() {
|
||||
if (!mounted) return;
|
||||
final digits = (code ?? '').replaceAll(RegExp(r'[^0-9]'), '');
|
||||
if (digits.length < 6) return;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_controllers[i].text = digits[i];
|
||||
}
|
||||
setState(() {});
|
||||
_verify();
|
||||
}
|
||||
|
||||
void _startTimer() {
|
||||
_seconds = 28;
|
||||
_timer?.cancel();
|
||||
@@ -59,8 +93,6 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
final state = context.read<AppState>();
|
||||
if (state.isResettingPin) {
|
||||
Navigator.pushReplacementNamed(context, Routes.resetPin);
|
||||
} else if (state.isLoginFlow) {
|
||||
Navigator.pushReplacementNamed(context, Routes.enterPin);
|
||||
} else {
|
||||
Navigator.pushReplacementNamed(context, Routes.setPin);
|
||||
}
|
||||
@@ -115,6 +147,7 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
cancel();
|
||||
for (final c in _controllers) {
|
||||
c.dispose();
|
||||
}
|
||||
@@ -137,8 +170,10 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: AppCard(
|
||||
padding: const EdgeInsets.all(28),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 400),
|
||||
child: AppCard(
|
||||
padding: const EdgeInsets.all(28),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -147,10 +182,10 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
height: 88,
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColors.primaryFixed, shape: BoxShape.circle),
|
||||
child: const Icon(Icons.mark_email_read_rounded, size: 40, color: AppColors.primary),
|
||||
child: const Icon(Icons.sms_rounded, size: 40, color: AppColors.primary),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Text('Verify your email',
|
||||
Text('Verify your number',
|
||||
textAlign: TextAlign.center, style: AppTheme.headlineLg),
|
||||
const SizedBox(height: 8),
|
||||
Text.rich(
|
||||
@@ -159,7 +194,7 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
children: [
|
||||
const TextSpan(text: 'We sent a 6-digit code to '),
|
||||
TextSpan(
|
||||
text: context.read<AppState>().pendingEmail ?? 'your email',
|
||||
text: '+91 $phone',
|
||||
style: AppTheme.labelMd,
|
||||
),
|
||||
],
|
||||
@@ -168,12 +203,19 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
),
|
||||
const SizedBox(height: 28),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: List.generate(6, (i) => _OtpBox(
|
||||
controller: _controllers[i],
|
||||
node: _nodes[i],
|
||||
onChanged: (v) => _onChanged(i, v),
|
||||
)),
|
||||
children: List.generate(
|
||||
6,
|
||||
(i) => Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3),
|
||||
child: _OtpBox(
|
||||
controller: _controllers[i],
|
||||
node: _nodes[i],
|
||||
onChanged: (v) => _onChanged(i, v),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 28),
|
||||
if (_seconds > 0)
|
||||
@@ -198,6 +240,7 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -213,7 +256,6 @@ class _OtpBox extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final filled = controller.text.isNotEmpty;
|
||||
return SizedBox(
|
||||
width: 46,
|
||||
height: 56,
|
||||
child: TextField(
|
||||
controller: controller,
|
||||
|
||||
Reference in New Issue
Block a user