1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
/// A screen that provides a button to trigger Google Sign-In and handles the
/// entire authentication flow with Firebase.
class SignInDemo extends StatefulWidget {
const SignInDemo({super.key});
@override
State<SignInDemo> createState() => _SignInDemoState();
}
class _SignInDemoState extends State<SignInDemo> {
// A single, reusable instance of the GoogleSignIn client.
final GoogleSignIn _googleSignIn = GoogleSignIn();
// State to manage the loading indicator on the button.
bool _isSigningIn = false;
/// Performs the entire Google Sign-In flow and authenticates with Firebase.
Future<void> _signInWithGoogle() async {
// Prevent multiple sign-in attempts.
if (_isSigningIn) return;
setState(() {
_isSigningIn = true;
});
try {
// 1. Initiate the Google Sign-In flow.
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
// If the user canceled the process, stop here.
if (googleUser == null) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Sign-in canceled by user.')),
);
}
return; // Early exit
}
// 2. Obtain the authentication details from the Google user account.
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
// 3. Create a new Firebase credential using the Google tokens.
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
// 4. Sign in to Firebase with the new credential.
// This action will be picked up by the StreamBuilder in AuthWrapper,
// which will then navigate to the main application screen.
await FirebaseAuth.instance.signInWithCredential(credential);
} catch (e) {
// Handle any errors that occur during the process.
print('Error during Google sign-in: $e');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.toString()}')),
);
}
} finally {
// Ensure the loading state is always reset, even if an error occurs.
if (mounted) {
setState(() {
_isSigningIn = false;
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sign In'),
elevation: 2,
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Welcome to Mesh Masks',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 16),
const Text(
'Please sign in with your Google account to continue.',
textAlign: TextAlign.center,
),
const SizedBox(height: 48),
_isSigningIn
? const CircularProgressIndicator()
: ElevatedButton.icon(
icon: const Icon(Icons.login), // Example icon
onPressed: _signInWithGoogle,
label: const Text('Sign In with Google'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 50), // Make button wider
),
),
],
),
),
),
);
}
} |
Partager