import 'dart:async'; import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:go_router/go_router.dart'; import 'package:google_sign_in/google_sign_in.dart'; import 'package:google_sign_in_web/web_only.dart' as web; import 'package:qpay/models/responsive_policy.dart'; import 'package:qpay/screens/onboarding/login/login_controller.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:skeletonizer/skeletonizer.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State { late SharedPreferences prefs; late GoogleSignIn googleSignIn; final _formKey = GlobalKey(); bool _loading = false; List scopes = [ 'https://www.googleapis.com/auth/contacts.readonly', ]; late LoginController _loginController; @override void initState() { super.initState(); _loginController = LoginController(context); googleSignIn = GoogleSignIn.instance; if(kIsWeb){ googleSignIn.initialize(); googleSignIn.authenticationEvents .listen(_handleAuthenticationEvent) .onError(_handleAuthenticationError); }else { unawaited(googleSignIn.initialize(serverClientId: dotenv.env['CLIENTID'])); } } Future signInWithGoogle() async { if (GoogleSignIn.instance.supportsAuthenticate()){ unawaited(GoogleSignIn.instance.authenticate().then((value) async { googleSignIn.authenticationEvents .listen(_handleAuthenticationEvent) .onError(_handleAuthenticationError); })); } } void saveUser(GoogleSignInAccount user) async { final Map data = { 'displayName': user.displayName, 'email': user.email, 'id': user.id, 'photoUrl': user.photoUrl, }; prefs = await SharedPreferences.getInstance(); if (prefs.getString("googleUser") == null) { prefs.setString("googleUser", jsonEncode(data)); } } Future _handleAuthenticationEvent( GoogleSignInAuthenticationEvent event, ) async { // #docregion CheckAuthorization final GoogleSignInAccount? user = // ... // #enddocregion CheckAuthorization switch (event) { GoogleSignInAuthenticationEventSignIn() => event.user, GoogleSignInAuthenticationEventSignOut() => null, }; // Check for existing authorization. // #docregion CheckAuthorization final GoogleSignInClientAuthorization? authorization = await user ?.authorizationClient .authorizationForScopes(scopes); // #enddocregion CheckAuthorization print(user); saveUser(user as GoogleSignInAccount); await _loginController.login(user.email, user.id); context.go('/'); } Future _handleAuthenticationError(Object e) async { print(e.toString()); } @override void dispose() { _loginController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(25), child: Form( key: _formKey, child: Center( child: LayoutBuilder( builder: (context, constraints) { final maxWidth = constraints.maxWidth > ResponsivePolicy.md ? ResponsivePolicy.md.toDouble() : constraints.maxWidth; return SizedBox( width: maxWidth, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox(height: 75), Text( 'Login', style: TextStyle( fontSize: 30, fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary, ), ), SizedBox(height: 5), Text( 'Welcome back to Velocity', style: TextStyle(fontSize: 18), textAlign: TextAlign.center, ), SizedBox(height: 30), Image.asset('assets/password.png', width: 300), Text( 'Tap on your preferred social media platform to get started', style: TextStyle(fontSize: 18), textAlign: TextAlign.center, ), // Username Field SizedBox(height: 20), // Forgot Password Link // Divider with "or" text Row( children: [ Expanded(child: Divider(color: Colors.grey.shade300)), Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: Text( 'choose from the options below to continue', style: TextStyle( color: Colors.grey.shade600, fontSize: 14, ), textAlign: TextAlign.center, ), ), Expanded(child: Divider(color: Colors.grey.shade300)), ], ), SizedBox(height: 30), // Social Login Buttons if(GoogleSignIn.instance.supportsAuthenticate()) _buildGoogleButton() else ...[ if (kIsWeb) web.renderButton() ], SizedBox(height: 40), TextButton( onPressed: () { context.go('/'); }, child: Text('Continue as guest?', style: TextStyle(fontSize: 14)), ), ], ), ); } ), ), ), ), ), ); } Widget _buildGoogleButton(){ return Skeletonizer( enabled: _loading, child: Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: () { signInWithGoogle(); }, icon: Image.asset( 'assets/google.png', width: 20, height: 20, ), label: Text('Google', style: TextStyle(fontSize: 16)), style: OutlinedButton.styleFrom( padding: EdgeInsets.symmetric(vertical: 16), side: BorderSide(color: Colors.grey.shade300), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), ), SizedBox(width: 16), ], ), ); } }