我正在尝试循环显示“没有互联网连接。请检查您的互联网连接并重试。”的 AlertDialog。如果没有互联网连接,我希望当我按“重试”按钮时继续显示该对话框,但一旦它已经连接到互联网,警报对话框将停止并继续登录。
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:namer_app/Passenger_Widgets/GuestRegistration.dart';
import 'package:namer_app/login_auth/login_method.dart';
import 'package:namer_app/login_auth/resetpass_method.dart';
import 'package:namer_app/Passenger_Widgets/ScheduleWindow.dart';
import 'package:namer_app/prf_login/my_buttons.dart';
import 'package:namer_app/prf_login/my_textfields.dart';
import 'package:namer_app/prf_login/snackbar_ext.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Supabase.initialize(
url: 'https://',
anonKey:
'0000',
);
final prefs = await SharedPreferences.getInstance();
final bool isLoggedIn = prefs.getBool('isLoggedIn') ?? false;
List<ConnectivityResult> connectivityResults = await (Connectivity().checkConnectivity());
ConnectivityResult connectivityResult = connectivityResults.first;
runApp(
MaterialApp(
home: MyApp(connectivityResult, prefs, isLoggedIn),
),
);
}
class MyApp extends StatelessWidget {
final ConnectivityResult connectivityResult;
final SharedPreferences prefs;
final bool isLoggedIn;
MyApp(this.connectivityResult, this.prefs, this.isLoggedIn);
@override
Widget build(BuildContext context) {
if (connectivityResult == ConnectivityResult.none) {
// Show a popup to inform the user that there's no internet connection
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('No Internet Connection'),
content: Text('Please check your internet connection and try again.'),
actions: [
ElevatedButton(
child: Text('Retry'),
onPressed: () => Navigator.pop(context),
),
],
),
);
});
}
return MaterialApp(
theme: ThemeData(
appBarTheme: AppBarTheme(
iconTheme: IconThemeData(
color: Colors.white,
), // Set back button color to white
),
),
home: isLoggedIn ? ScheduleWindow(prefs: prefs) : LOGIN_passenger(),
);
}
}
class LOGIN_passenger extends StatefulWidget {
LOGIN_passenger({super.key});
@override
State<LOGIN_passenger> createState() => _LOGIN_passengerState();
}
class _LOGIN_passengerState extends State<LOGIN_passenger> {
GlobalKey<FormState> _formkey = GlobalKey();
bool _isLoading = false;
late TextEditingController emailController;
late TextEditingController passController;
//LOGIN ATTEMPTS TIMER
int _loginAttempts = 0;
bool _isCooldown = false;
Timer? _cooldownTimer;
int _cooldownTime = 60; // Cooldown time in seconds
@override
void initState() {
super.initState();
emailController = TextEditingController();
passController = TextEditingController();
}
@override
void dispose() {
emailController.dispose();
passController.dispose();
_cooldownTimer?.cancel();
super.dispose();
}
bool isValidEmail(String input) {
final emailRegex = RegExp(r'^[^@]+@[^@]+\.[^@]+');
return emailRegex.hasMatch(input);
}
bool isValidPhoneNumber(String input) {
final phoneWithPrefix = '63$input';
final phoneRegex = RegExp(r'^63\d{10}$');
return phoneRegex.hasMatch(phoneWithPrefix);
}
void insertPrefs(AuthResponse response) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
if (response.user != null) {
final user = response.user?.id;
final selectQuery = await Supabase.instance.client
.from('registered_passenger')
.select()
.eq('user_id', user.toString());
if (selectQuery.isNotEmpty) {
prefs.setBool('isLoggedIn', true);
prefs.setString('userId', selectQuery[0]['user_id']);
prefs.setString('lastName', selectQuery[0]['last_name']);
prefs.setString('firstName', selectQuery[0]['first_name']);
prefs.setString('middleInitial', selectQuery[0]['middle_initial']);
prefs.setString('email', selectQuery[0]['email']);
prefs.setString('password', selectQuery[0]['password']);
prefs.setString('profession', selectQuery[0]['profession']);
String contactNumber = selectQuery[0]['phone'];
prefs.setString('contactNumber', contactNumber.substring(2));
prefs.setString('age', selectQuery[0]['age']);
prefs.setString('gender', selectQuery[0]['gender']);
prefs.setString('region', selectQuery[0]['region']);
prefs.setString('province', selectQuery[0]['province']);
prefs.setString('municipality', selectQuery[0]['municipality']);
prefs.setString('barangay', selectQuery[0]['barangay']);
prefs.setString('titlePage', 'Schedule');
navigatetoSched(prefs);
}
}
}
void _login() async {
final connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.none) {
context.showSnackbar(
message: 'No internet connection. Please check your internet connection and try again.',
backgroundColor: Colors.red,
);
setState(() {
_isLoading = false; // Reset _isLoading so the button can be clicked again
});
return;
}
if (_isCooldown) {
context.showSnackbar(
message: 'Too many attempts. Please wait $_cooldownTime seconds.',
backgroundColor: Colors.red,
);
return;
}
final isValid = _formkey.currentState?.validate();
if (isValid != null && isValid) {
setState(() {
_isLoading = true;
});
try {
final input = emailController.text;
final password = passController.text;
final response;
if (isValidEmail(input)) {
response = await Supabase.instance.client.auth.signInWithPassword(
email: input,
password: password,
);
insertPrefs(response);
} else if (isValidPhoneNumber(input)) {
response = await Supabase.instance.client.auth.signInWithPassword(
phone: '63$input',
password: password,
);
insertPrefs(response);
} else {
throw AuthException('Invalid email or phone number');
}
setState(() {
_isLoading = false;
});
context.showSnackbar(
message: 'LOGIN SUCCESSFUL',
backgroundColor: Colors.green,
);
} on AuthException catch (e) {
if (e.message.contains('SocketException')) {
context.showSnackbar(
message: 'No internet connection. Please check your internet connection and try again.',
backgroundColor: Colors.red,
);
} else {
context.showSnackbar(
message: e.message,
backgroundColor: Colors.red,
);
}
setState(() {
_isLoading = false; // Reset _isLoading in case of an error
});
} catch (e) {
context.showSnackbar(
message: e.toString(),
backgroundColor: Colors.red,
);
setState(() {
_isLoading = false; // Reset _isLoading for other types of errors
});
}
}
}
/*Future<void> _logout() async {
if (selectedFerry != null) {
await _supabaseClient
.from('boats')
.update({'is_active': false}) // Set ferry as inactive
.eq('boat_name', selectedFerry!)
}
// Continue with logout process
}*/
void _handleLoginFailure(String errorMessage) {
context.showSnackbar(message: errorMessage, backgroundColor: Colors.red);
setState(() {
_isLoading = false;
_loginAttempts++;
});
if (_loginAttempts >= 3) {
_startCooldown();
}
}
void _startCooldown() {
setState(() {
_isCooldown = true;
});
_cooldownTimer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
_cooldownTime--;
});
if (_cooldownTime == 0) {
timer.cancel();
setState(() {
_isCooldown = false;
_loginAttempts = 0;
_cooldownTime = 60; // Reset cooldown time
});
}
});
}
void navigatetoSched(SharedPreferences prefs) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (_) => ScheduleWindow(prefs: prefs)),
(route) => false);
}
void _forgotPassword() {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => ResetpassMethod()),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(270.0),
child: AppBar(
centerTitle: true,
flexibleSpace: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/bgprf1.png'),
fit: BoxFit.fill,
),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'images/prf_logo.png',
width: 155.0,
height: 155.0,
),
SizedBox(height: 10.0),
Text(
'PASIG RIVER FERRY PORTAL',
style: TextStyle(
color: Color(0xFF33385F),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
),
backgroundColor: Colors.white,
body: Container(
padding: EdgeInsets.all(20.0),
child: SingleChildScrollView(
child: Form(
key: _formkey, // Associate the Form with the GlobalKey
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(height: 30.0),
Text(
'WELCOME',
style: TextStyle(
color: Color(0xFF33385F),
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
Text(
'Please, Login to your account!',
style: TextStyle(
color: Color(0xFF666666),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 20.0),
// Textfield for Email/Username
Textfield_auth(
controller: emailController,
prefixIcon: Icon(Icons.person),
hintText: 'Enter Email/Username',
labelText: 'Email/Username',
obscureText: false,
),
const SizedBox(height: 15.0),
// Textfield for Password
Textfield_authpass(
controller: passController,
prefixIcon: Icon(Icons.lock),
hintText: 'Enter Password',
labelText: 'Password',
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
onTap: _forgotPassword,
child: Text(
'Forgot Password?',
style: TextStyle(
color: Color(0xFF666666),
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
),
],
),
SizedBox(height: 30.0),
LoginButton(
onTap: _isLoading || _isCooldown ? null : _login,
),
if (_isCooldown)
Center(
child: Text(
'Please wait $_cooldownTime seconds to try again.',
style: TextStyle(
color: Colors.red,
fontSize: 16,
),
),
),
const SizedBox(height: 20.0),
// Continue with Google account
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: Row(
children: [
Expanded(
child: Divider(
thickness: 1,
color: Colors.grey,
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Text(
'OR',
style: TextStyle(color: Colors.grey),
),
),
Expanded(
child: Divider(
thickness: 1,
color: Colors.grey,
),
),
],
),
),
SizedBox(height: 30.0),
// GOOGLE SIGN IN
Center(
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
const SizedBox(height: 5),
GuestButton(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PrfGuestRegistration(),
),
);
},
),
SignUpButton(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChooseLoginMethod(),
),
);
},
),
],
),
),
],
),
),
),
),
);
}
}
我已经尝试在重试逻辑上使用
Connectivity().checkConnectivity()
和 ConnectivityResult.none
。
要循环
AlertDialog
直到有互联网连接,您可以修改代码以在按下“重试”按钮时持续检查互联网连接。如果仍然没有互联网,该对话框将再次显示;否则,它将关闭并允许进一步的操作。
以下是实现此方法的方法:
这是更新后的代码:
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Supabase.initialize(
url: 'https://',
anonKey: '0000',
);
final prefs = await SharedPreferences.getInstance();
final bool isLoggedIn = prefs.getBool('isLoggedIn') ?? false;
runApp(MyApp(prefs, isLoggedIn));
}
class MyApp extends StatelessWidget {
final SharedPreferences prefs;
final bool isLoggedIn;
MyApp(this.prefs, this.isLoggedIn);
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(),
home: isLoggedIn ? ScheduleWindow(prefs: prefs) : LOGIN_passenger(),
);
}
}
class LOGIN_passenger extends StatefulWidget {
@override
State<LOGIN_passenger> createState() => _LOGIN_passengerState();
}
class _LOGIN_passengerState extends State<LOGIN_passenger> {
bool _isLoading = false;
late TextEditingController emailController;
late TextEditingController passController;
@override
void initState() {
super.initState();
emailController = TextEditingController();
passController = TextEditingController();
_checkInternetConnection();
}
@override
void dispose() {
emailController.dispose();
passController.dispose();
super.dispose();
}
Future<void> _checkInternetConnection() async {
var connectivityResult = await Connectivity().checkConnectivity();
if (connectivityResult == ConnectivityResult.none) {
_showNoInternetDialog();
}
}
void _showNoInternetDialog() {
showDialog(
context: context,
barrierDismissible: false, // Prevent dismissing the dialog by tapping outside
builder: (context) => AlertDialog(
title: Text('No Internet Connection'),
content: Text('Please check your internet connection and try again.'),
actions: [
ElevatedButton(
child: Text('Retry'),
onPressed: () async {
Navigator.of(context).pop(); // Close the dialog
_retryConnection();
},
),
],
),
);
}
Future<void> _retryConnection() async {
var connectivityResult = await Connectivity().checkConnectivity();
if (connectivityResult == ConnectivityResult.none) {
// Still no internet, show the dialog again
_showNoInternetDialog();
} else {
// Internet is available, proceed with login or further actions
_login();
}
}
void _login() {
// Login logic here
print("Proceed to login.");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Center(
child: ElevatedButton(
onPressed: _checkInternetConnection,
child: Text('Check Connection and Login'),
),
),
);
}
}
initState()
中,应用程序使用 Connectivity().checkConnectivity()
检查互联网连接。_showNoInternetDialog()
方法会显示警报对话框。此对话框将保留在屏幕上,直到用户按“重试”。此方法可确保警报对话框一直显示,直到检测到有效的互联网连接。