mirror of
https://github.com/Dvorinka/1356.git
synced 2026-06-05 04:22:55 +00:00
small fix, don't worry about it
This commit is contained in:
@@ -3,10 +3,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../application/auth_controller.dart';
|
||||
import '../../../data/services/biometric_service.dart';
|
||||
import '../../../core/widgets/app_scaffold.dart';
|
||||
import '../../../core/widgets/primary_button.dart';
|
||||
import '../../../core/utils/validators.dart';
|
||||
import '../application/auth_controller.dart';
|
||||
|
||||
class SignInScreen extends ConsumerStatefulWidget {
|
||||
const SignInScreen({super.key});
|
||||
@@ -19,8 +21,86 @@ class _SignInScreenState extends ConsumerState<SignInScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _emailController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
final BiometricService _biometricService = BiometricService();
|
||||
bool _isLoading = false;
|
||||
bool _obscurePassword = true;
|
||||
bool _isBiometricAvailable = false;
|
||||
bool _isBiometricEnabled = false;
|
||||
bool _isBiometricLoading = false;
|
||||
bool _showEmailVerificationMessage = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_checkBiometricStatus();
|
||||
_checkIfComingFromRegistration();
|
||||
}
|
||||
|
||||
void _checkIfComingFromRegistration() async {
|
||||
// Check if user navigated from registration by checking shared preferences
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final justRegistered = prefs.getBool('just_registered') ?? false;
|
||||
final registrationTime = prefs.getInt('registration_time') ?? 0;
|
||||
|
||||
if (mounted) {
|
||||
// Show message if registration happened in the last 5 minutes
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
final fiveMinutesAgo = now - (5 * 60 * 1000);
|
||||
|
||||
if (justRegistered && registrationTime > fiveMinutesAgo) {
|
||||
setState(() {
|
||||
_showEmailVerificationMessage = true;
|
||||
});
|
||||
// Clear the flag so it doesn't show again
|
||||
await prefs.remove('just_registered');
|
||||
await prefs.remove('registration_time');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _checkBiometricStatus() async {
|
||||
try {
|
||||
final availability = await _biometricService.checkAvailability();
|
||||
final isEnabled = await _biometricService.isBiometricEnabled();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isBiometricAvailable = availability == BiometricAvailability.available;
|
||||
_isBiometricEnabled = isEnabled;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// Biometric not available, ignore
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handleBiometricSignIn() async {
|
||||
setState(() => _isBiometricLoading = true);
|
||||
try {
|
||||
final authController = ref.read(authControllerProvider.notifier);
|
||||
final success = await authController.signInWithBiometric();
|
||||
|
||||
if (success) {
|
||||
// Navigation will be handled by AuthGate
|
||||
} else {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Biometric login failed')),
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Biometric login error: ${e.toString()}')),
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() => _isBiometricLoading = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handleSignIn() async {
|
||||
if (!_formKey.currentState!.validate()) return;
|
||||
@@ -172,6 +252,45 @@ class _SignInScreenState extends ConsumerState<SignInScreen> {
|
||||
.withOpacity(0.7),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Email verification reminder message
|
||||
if (_showEmailVerificationMessage)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: Colors.blue.withOpacity(0.3)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.info_outline, color: Colors.blue.shade700, size: 20),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Please verify your email before signing in. Check your inbox for the verification link.',
|
||||
style: TextStyle(
|
||||
color: Colors.blue.shade700,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close, size: 16),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_showEmailVerificationMessage = false;
|
||||
});
|
||||
},
|
||||
color: Colors.blue.shade700,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
if (_showEmailVerificationMessage)
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: 24),
|
||||
Semantics(
|
||||
label: 'Email address field',
|
||||
@@ -240,6 +359,39 @@ class _SignInScreenState extends ConsumerState<SignInScreen> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Biometric Login Button
|
||||
if (_isBiometricAvailable && _isBiometricEnabled)
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 48,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: _isBiometricLoading ? null : _handleBiometricSignIn,
|
||||
icon: _isBiometricLoading
|
||||
? const SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
: const Icon(Icons.fingerprint),
|
||||
label: Text(_isBiometricLoading ? 'Authenticating...' : 'Sign in with Biometric'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
foregroundColor: Theme.of(context).colorScheme.onSurface,
|
||||
elevation: 0,
|
||||
side: BorderSide(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
if (_isBiometricAvailable && _isBiometricEnabled)
|
||||
const SizedBox(height: 12),
|
||||
|
||||
PrimaryButton(
|
||||
onPressed: _handleSignIn,
|
||||
text: _isLoading ? 'Signing in...' : 'Sign In',
|
||||
|
||||
Reference in New Issue
Block a user