diff --git a/android/app/build.gradle b/android/app/build.gradle index 05d473f..ec9d69e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -27,7 +27,7 @@ apply plugin: 'com.google.gms.google-services' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 30 + compileSdkVersion 31 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -36,10 +36,11 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "dev.hireflutter.starterKit" - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName + multiDexEnabled true } buildTypes { @@ -59,4 +60,5 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation platform('com.google.firebase:firebase-bom:28.2.0') implementation 'com.google.firebase:firebase-analytics-ktx' + implementation("androidx.multidex:multidex:2.0.1") } diff --git a/android/build.gradle b/android/build.gradle index a2a4cf4..0913077 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.6.10' repositories { google() jcenter() diff --git a/lib/main.dart b/lib/main.dart index cb0bf12..cb3b743 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,13 +1,15 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hf_flutter_starter_kit/src/app.dart'; +import 'package:hf_flutter_starter_kit/src/app/feature/google_authenticaiton/data/observers/app_bloc_observer.dart'; import 'src/injection/setup_locator.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); - + Bloc.observer = AppBlocObserver(); setup(); runApp(App()); } diff --git a/lib/src/app.dart b/lib/src/app.dart index bbf1a2c..06b682c 100644 --- a/lib/src/app.dart +++ b/lib/src/app.dart @@ -1,7 +1,14 @@ +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:google_sign_in/google_sign_in.dart'; +import 'package:hf_flutter_starter_kit/src/app/feature/google_authenticaiton/bloc/authentication_bloc.dart'; +import 'package:hf_flutter_starter_kit/src/app/feature/google_authenticaiton/data/domain/google_sign_in_provider.dart'; import 'package:provider/provider.dart'; import 'app/feature/authentication/presentation/viewmodel/auth_view_model.dart'; +import 'app/feature/google_authenticaiton/data/domain/authentication_firebase_provider.dart'; +import 'app/feature/google_authenticaiton/data/repositories/authenticaiton_repository.dart'; import 'app/router/router.gr.dart'; import 'config/theme_config.dart'; @@ -12,13 +19,23 @@ class App extends StatelessWidget { @override Widget build(BuildContext context) { - return ChangeNotifierProvider( + return BlocProvider(create:(context) => AuthenticationBloc( + authenticationRepository: AuthenticationRepository( + authenticationFirebaseProvider: AuthenticationFirebaseProvider( + firebaseAuth: FirebaseAuth.instance, + ), + googleSignInProvider: GoogleSignInProvider( + googleSignIn: GoogleSignIn(), + ), + ), + ), + child: ChangeNotifierProvider( create: (context) => AuthViewModel(), child: MaterialApp.router( theme: ThemeConfig.lightTheme, routerDelegate: _appRouter.delegate(), routeInformationParser: _appRouter.defaultRouteParser(), ), - ); + )); } } diff --git a/lib/src/app/feature/authentication/presentation/login_screen.dart b/lib/src/app/feature/authentication/presentation/login_screen.dart index 515b46a..1cc1918 100644 --- a/lib/src/app/feature/authentication/presentation/login_screen.dart +++ b/lib/src/app/feature/authentication/presentation/login_screen.dart @@ -1,8 +1,11 @@ import 'package:authentication_data/authentication_data.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hf_flutter_starter_kit/src/config/color_config.dart'; import 'package:provider/provider.dart'; +import '../../../router/router_constant.dart'; +import '../../google_authenticaiton/bloc/authentication_bloc.dart'; import 'viewmodel/auth_view_model.dart'; import 'widgets/widgets.dart'; import 'package:auto_route/auto_route.dart'; @@ -156,116 +159,181 @@ class _LoginScreenState extends State { } return Scaffold( - body: Padding( - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top, - left: width / 10, - right: width / 10, - ), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox( - height: height / 7, - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: width * 0.05), - child: const Logo(), - ), - SizedBox( - height: height * 0.1, - ), - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(100), - ), - height: height / 13, - width: 8 * (width / 10), - padding: const EdgeInsets.all(5), - child: Row( + body: Builder(builder: (context) { + return BlocConsumer( + buildWhen: (current, next) { + if (next is AuthenticationSuccess) { + return false; + } + return true; + }, + builder: (context, state) { + if (state is AuthenticationInitial || + state is AuthenticationFailiure) { + return Center( + child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Flexible( - flex: 2, - child: FittedBox( - child: Material( - child: InkWell( - onTap: () async { - _contryCodeDialogue(); - }, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - width: width * 0.01, - ), - Text( - '+' + - (dialCodes[_selectedDialCode]['number'] ?? - ''), - style: Theme.of(context) - .textTheme - .bodyText1 - ?.copyWith(color: Styleguide.main), - ), - const Icon(Icons.arrow_drop_down), - ], - ), - ), - ), + Padding( + padding: EdgeInsets.only( + top: MediaQuery.of(context).padding.top, + left: width / 10, + right: width / 10, ), - ), - Flexible( - flex: 7, - child: SizedBox( - height: height / 13, - child: TextFormField( - decoration: const InputDecoration( - hintText: 'Phone number', - ), - controller: _controller, - cursorWidth: 3, - style: Theme.of(context) - .textTheme - .headline3 - ?.copyWith(color: Styleguide.main), - keyboardType: TextInputType.phone, + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: height / 7, + ), + Padding( + padding: EdgeInsets.symmetric( + horizontal: width * 0.05), + child: const Logo(), + ), + SizedBox( + height: height * 0.1, + ), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100), + ), + height: height / 13, + width: 8 * (width / 10), + padding: const EdgeInsets.all(5), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Flexible( + flex: 2, + child: FittedBox( + child: Material( + child: InkWell( + onTap: () async { + _contryCodeDialogue(); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: width * 0.01, + ), + Text( + '+' + + (dialCodes[_selectedDialCode] + ['number'] ?? + ''), + style: Theme.of(context) + .textTheme + .bodyText1 + ?.copyWith( + color: Styleguide.main), + ), + const Icon(Icons.arrow_drop_down), + ], + ), + ), + ), + ), + ), + Flexible( + flex: 7, + child: SizedBox( + height: height / 13, + child: TextFormField( + decoration: const InputDecoration( + hintText: 'Phone number', + ), + controller: _controller, + cursorWidth: 3, + style: Theme.of(context) + .textTheme + .headline3 + ?.copyWith(color: Styleguide.main), + keyboardType: TextInputType.phone, + ), + ), + ), + ], + ), + ), + SizedBox( + height: height * 0.05, + ), + AppButton( + height: height / 13, + width: 8 * (width / 10), + onPressed: () { + if (_controller.text.isNotEmpty) { + /// Assign the value of [phoneNumber] + final AuthViewModel authViewModel = + Provider.of(context, listen: false); + authViewModel.setphoneNumber('+' + + dialCodes[_selectedDialCode]['number']! + + ' ' + + _controller.text); + context.router + .push(const LoginVerifyScreen()); + } + }, + child: Text( + 'SEND OTP', + style: Theme.of(context).textTheme.headline4, + ), + ), + Text("Or", style: Theme.of(context) + .textTheme + .headline5 + ?.copyWith( + color: (Styleguide.colorTransparent), + )), + AppButton( + height: height / 17, + onPressed: () => + BlocProvider.of(context) + .add( + AuthenticationGoogleStarted(), + ), + child: Text('Login with Google', + style: Theme.of(context) + .textTheme + .headline5 + ?.copyWith( + color: (Styleguide.colorTransparent), + ), + ), + ), + ], ), ), ), + ], ), - ), - SizedBox( - height: height * 0.05, - ), - AppButton( - height: height / 13, - width: 8 * (width / 10), - onPressed: () { - if (_controller.text.isNotEmpty) { - /// Assign the value of [phoneNumber] - final AuthViewModel authViewModel = - Provider.of(context, listen: false); - authViewModel.setphoneNumber('+' + - dialCodes[_selectedDialCode]['number']! + - ' ' + - _controller.text); - context.router.push(const LoginVerifyScreen()); - } - }, - child: Text( - 'SEND OTP', - style: Theme.of(context).textTheme.headline4, + ); + } else if (state is AuthenticationLoading) { + return const Center(child: CircularProgressIndicator()); + } + return Center( + child: Text('Undefined state : ${state.runtimeType}')); + }, + listener: (context, state) { + if (state is AuthenticationSuccess) { + context.router.pushNamed(RouterConstant.homescreen); + } else if (state is AuthenticationFailiure) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(state.message), ), - ), - ], - ), - ), - ), + ); + } + }, + ); + }), ); } } diff --git a/lib/src/app/feature/google_authenticaiton/bloc/authentication_bloc.dart b/lib/src/app/feature/google_authenticaiton/bloc/authentication_bloc.dart new file mode 100644 index 0000000..e64eafa --- /dev/null +++ b/lib/src/app/feature/google_authenticaiton/bloc/authentication_bloc.dart @@ -0,0 +1,81 @@ +import 'dart:async'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:hf_flutter_starter_kit/src/app/feature/google_authenticaiton/data/repositories/authenticaiton_repository.dart'; + +import '../models/authentication_detail.dart'; +part 'authentication_event.dart'; +part 'authentication_state.dart'; + +class AuthenticationBloc + extends Bloc { + final AuthenticationRepository _authenticationRepository; + + AuthenticationBloc( + {required AuthenticationRepository authenticationRepository}) + : _authenticationRepository = authenticationRepository, + super(AuthenticationInitial()); + + StreamSubscription? authStreamSub; + + @override + Future close() { + authStreamSub?.cancel(); + return super.close(); + } + + @override + Stream mapEventToState( + AuthenticationEvent event, + ) async* { + if (event is AuthenticationStarted) { + try { + yield AuthenticationLoading(); + authStreamSub = _authenticationRepository + .getAuthDetailStream() + .listen((authDetail) { + add(AuthenticationStateChanged(authenticationDetail: authDetail)); + }); + } catch (error) { + print( + 'Error occured while fetching authentication detail : ${error.toString()}'); + yield AuthenticationFailiure( + message: 'Error occrued while fetching auth detail'); + } + } else if (event is AuthenticationStateChanged) { + if (event.authenticationDetail.isValid!) { + yield AuthenticationSuccess( + authenticationDetail: event.authenticationDetail); + } else { + yield AuthenticationFailiure(message: 'User has logged out'); + } + } else if (event is AuthenticationGoogleStarted) { + try { + yield AuthenticationLoading(); + AuthenticationDetail authenticationDetail = + await _authenticationRepository.authenticateWithGoogle(); + + if (authenticationDetail.isValid!) { + yield AuthenticationSuccess( + authenticationDetail: authenticationDetail); + } else { + yield AuthenticationFailiure(message: 'User detail not found.'); + } + } catch (error) { + print('Error occured while login with Google ${error.toString()}'); + yield AuthenticationFailiure( + message: 'Unable to login with Google. Try again.', + ); + } + } else if (event is AuthenticationExited) { + try { + yield AuthenticationLoading(); + await _authenticationRepository.unAuthenticate(); + } catch (error) { + print('Error occured while logging out. : ${error.toString()}'); + yield AuthenticationFailiure( + message: 'Unable to logout. Please try again.'); + } + } + } +} diff --git a/lib/src/app/feature/google_authenticaiton/bloc/authentication_event.dart b/lib/src/app/feature/google_authenticaiton/bloc/authentication_event.dart new file mode 100644 index 0000000..a0889fd --- /dev/null +++ b/lib/src/app/feature/google_authenticaiton/bloc/authentication_event.dart @@ -0,0 +1,23 @@ +part of 'authentication_bloc.dart'; + +abstract class AuthenticationEvent extends Equatable { + const AuthenticationEvent(); + + @override + List get props => []; +} + +class AuthenticationStarted extends AuthenticationEvent {} + +class AuthenticationStateChanged extends AuthenticationEvent { + final AuthenticationDetail authenticationDetail; + AuthenticationStateChanged({ + required this.authenticationDetail, + }); + @override + List get props => [authenticationDetail]; +} + +class AuthenticationGoogleStarted extends AuthenticationEvent {} + +class AuthenticationExited extends AuthenticationEvent {} diff --git a/lib/src/app/feature/google_authenticaiton/bloc/authentication_state.dart b/lib/src/app/feature/google_authenticaiton/bloc/authentication_state.dart new file mode 100644 index 0000000..b6e275d --- /dev/null +++ b/lib/src/app/feature/google_authenticaiton/bloc/authentication_state.dart @@ -0,0 +1,30 @@ +part of 'authentication_bloc.dart'; + +abstract class AuthenticationState extends Equatable { + const AuthenticationState(); + + @override + List get props => []; +} + +class AuthenticationInitial extends AuthenticationState {} + +class AuthenticationLoading extends AuthenticationState {} + +class AuthenticationFailiure extends AuthenticationState { + final String message; + AuthenticationFailiure({ + required this.message, + }); + @override + List get props => [message]; +} + +class AuthenticationSuccess extends AuthenticationState { + final AuthenticationDetail authenticationDetail; + AuthenticationSuccess({ + required this.authenticationDetail, + }); + @override + List get props => [authenticationDetail]; +} diff --git a/lib/src/app/feature/google_authenticaiton/data/domain/authentication_firebase_provider.dart b/lib/src/app/feature/google_authenticaiton/data/domain/authentication_firebase_provider.dart new file mode 100644 index 0000000..01c775e --- /dev/null +++ b/lib/src/app/feature/google_authenticaiton/data/domain/authentication_firebase_provider.dart @@ -0,0 +1,24 @@ +import 'package:firebase_auth/firebase_auth.dart'; + +class AuthenticationFirebaseProvider { + final FirebaseAuth _firebaseAuth; + AuthenticationFirebaseProvider({ + required FirebaseAuth firebaseAuth, + }) : _firebaseAuth = firebaseAuth; + + Stream getAuthStates() { + return _firebaseAuth.authStateChanges(); + } + + Future login({ + required AuthCredential credential, + }) async { + UserCredential userCredential = + await _firebaseAuth.signInWithCredential(credential); + return userCredential.user; + } + + Future logout() async { + await _firebaseAuth.signOut(); + } +} diff --git a/lib/src/app/feature/google_authenticaiton/data/domain/google_sign_in_provider.dart b/lib/src/app/feature/google_authenticaiton/data/domain/google_sign_in_provider.dart new file mode 100644 index 0000000..8d38b33 --- /dev/null +++ b/lib/src/app/feature/google_authenticaiton/data/domain/google_sign_in_provider.dart @@ -0,0 +1,26 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:google_sign_in/google_sign_in.dart'; + +class GoogleSignInProvider { + final GoogleSignIn _googleSignIn; + GoogleSignInProvider({ + required GoogleSignIn googleSignIn, + }) : _googleSignIn = googleSignIn; + + Future login() async { + GoogleSignInAccount? googleSignInAccount = await _googleSignIn.signIn(); + GoogleSignInAuthentication googleSignInAuthentication = + await googleSignInAccount!.authentication; + AuthCredential authCredential = GoogleAuthProvider.credential( + accessToken: googleSignInAuthentication.accessToken, + idToken: googleSignInAuthentication.idToken, + ); + return authCredential; + } + + Future logout() async { + if (await _googleSignIn.isSignedIn()) { + _googleSignIn.signOut(); + } + } +} diff --git a/lib/src/app/feature/google_authenticaiton/data/observers/app_bloc_observer.dart b/lib/src/app/feature/google_authenticaiton/data/observers/app_bloc_observer.dart new file mode 100644 index 0000000..c06873e --- /dev/null +++ b/lib/src/app/feature/google_authenticaiton/data/observers/app_bloc_observer.dart @@ -0,0 +1,23 @@ +import 'dart:developer'; + +import 'package:flutter_bloc/flutter_bloc.dart'; + +class AppBlocObserver extends BlocObserver { + @override + void onChange(BlocBase bloc, Change change) { + log(' ${bloc.runtimeType} $change'); + super.onChange(bloc, change); + } + + @override + void onTransition(Bloc bloc, Transition transition) { + log('${bloc.runtimeType} $transition'); + super.onTransition(bloc, transition); + } + + @override + void onError(BlocBase bloc, Object error, StackTrace stackTrace) { + log('${bloc.runtimeType} - $error - $stackTrace'); + super.onError(bloc, error, stackTrace); + } +} diff --git a/lib/src/app/feature/google_authenticaiton/data/repositories/authenticaiton_repository.dart b/lib/src/app/feature/google_authenticaiton/data/repositories/authenticaiton_repository.dart new file mode 100644 index 0000000..d3870f4 --- /dev/null +++ b/lib/src/app/feature/google_authenticaiton/data/repositories/authenticaiton_repository.dart @@ -0,0 +1,49 @@ +import 'package:firebase_auth/firebase_auth.dart'; + +import '../../models/authentication_detail.dart'; +import '../domain/authentication_firebase_provider.dart'; +import '../domain/google_sign_in_provider.dart'; + +class AuthenticationRepository { + final AuthenticationFirebaseProvider _authenticationFirebaseProvider; + final GoogleSignInProvider _googleSignInProvider; + AuthenticationRepository( + {required AuthenticationFirebaseProvider authenticationFirebaseProvider, + required GoogleSignInProvider googleSignInProvider}) + : _googleSignInProvider = googleSignInProvider, + _authenticationFirebaseProvider = authenticationFirebaseProvider; + + Stream getAuthDetailStream() { + return _authenticationFirebaseProvider.getAuthStates().map((user) { + return _getAuthCredentialFromFirebaseUser(user: user); + }); + } + + Future authenticateWithGoogle() async { + User? user = await _authenticationFirebaseProvider.login( + credential: await _googleSignInProvider.login()); + return _getAuthCredentialFromFirebaseUser(user: user); + } + + Future unAuthenticate() async { + await _googleSignInProvider.logout(); + await _authenticationFirebaseProvider.logout(); + } + + AuthenticationDetail _getAuthCredentialFromFirebaseUser( + {required User? user}) { + AuthenticationDetail authDetail; + if (user != null) { + authDetail = AuthenticationDetail( + isValid: true, + uid: user.uid, + email: user.email, + photoUrl: user.photoURL, + name: user.displayName, + ); + } else { + authDetail = AuthenticationDetail(isValid: false); + } + return authDetail; + } +} diff --git a/lib/src/app/feature/google_authenticaiton/models/authentication_detail.dart b/lib/src/app/feature/google_authenticaiton/models/authentication_detail.dart new file mode 100644 index 0000000..62a34e2 --- /dev/null +++ b/lib/src/app/feature/google_authenticaiton/models/authentication_detail.dart @@ -0,0 +1,84 @@ +import 'dart:convert'; + +class AuthenticationDetail { + final bool? isValid; + final String? uid; + final String? photoUrl; + final String? email; + final String? name; + + AuthenticationDetail({ + required this.isValid, + this.uid, + this.photoUrl, + this.email, + this.name, + }); + + AuthenticationDetail copyWith({ + bool? isValid, + String? uid, + String? photoUrl, + String? email, + String? name, + }) { + return AuthenticationDetail( + isValid: isValid ?? this.isValid, + uid: uid ?? this.uid, + photoUrl: photoUrl ?? this.photoUrl, + email: email ?? this.email, + name: name ?? this.name, + ); + } + + Map toMap() { + return { + 'isValid': isValid, + 'uid': uid, + 'photoUrl': photoUrl, + 'email': email, + 'name': name, + }; + } + + factory AuthenticationDetail.fromMap(Map? map) { + return AuthenticationDetail( + isValid: map?['isValid'], + uid: map?['uid'], + photoUrl: map?['photoUrl'], + email: map?['email'], + name: map?['name'], + ); + } + + String toJson() => json.encode(toMap()); + + factory AuthenticationDetail.fromJson(String source) => + AuthenticationDetail.fromMap(json.decode(source)); + + @override + String toString() { + return 'AuthenticationDetail(isValid: $isValid, uid: $uid, photoUrl: $photoUrl, email: $email, name: $name)'; + } + + @override + bool operator ==(Object o) { + if (identical(this, o)) return true; + + return o is AuthenticationDetail && + o.isValid == isValid && + o.uid == uid && + o.photoUrl == photoUrl && + o.email == email && + o.name == name; + } + + @override + int get hashCode { + return isValid.hashCode ^ + uid.hashCode ^ + photoUrl.hashCode ^ + email.hashCode ^ + name.hashCode; + } +} diff --git a/lib/src/app/feature/splash/splash_screen.dart b/lib/src/app/feature/splash/splash_screen.dart index 7baedc6..fcfc66c 100644 --- a/lib/src/app/feature/splash/splash_screen.dart +++ b/lib/src/app/feature/splash/splash_screen.dart @@ -21,7 +21,7 @@ class _SplashScreenState extends State { void initState() { super.initState(); - SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { + SchedulerBinding.instance.addPostFrameCallback((timeStamp) { setState(() { _opacity = 1.0; }); diff --git a/lib/src/app/router/router.gr.dart b/lib/src/app/router/router.gr.dart index acfef6c..0f6d1c7 100644 --- a/lib/src/app/router/router.gr.dart +++ b/lib/src/app/router/router.gr.dart @@ -20,24 +20,20 @@ class AppRouter extends _i1.RootStackRouter { final Map pagesMap = { SplashScreen.name: (routeData) => _i1.MaterialPageX( routeData: routeData, - builder: (_) { - return const _i3.SplashScreen(); - }), + + child: _i3.SplashScreen()), LoginScreen.name: (routeData) => _i1.MaterialPageX( routeData: routeData, - builder: (_) { - return const _i4.LoginScreen(); - }), + child: + _i4.LoginScreen() + ), LoginVerifyScreen.name: (routeData) => _i1.MaterialPageX( routeData: routeData, - builder: (_) { - return const _i5.LoginVerifyScreen(); - }), + child:_i5.LoginVerifyScreen()), HomeScreen.name: (routeData) => _i1.MaterialPageX( routeData: routeData, - builder: (_) { - return const _i6.HomeScreen(); - }) + child: _i6.HomeScreen() + ) }; @override diff --git a/pubspec.lock b/pubspec.lock index 6670313..dfcd4ab 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "22.0.0" + version: "31.0.0" after_layout: dependency: "direct main" description: @@ -21,7 +21,7 @@ packages: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "1.7.1" + version: "2.8.0" api_client: dependency: "direct main" description: @@ -42,7 +42,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.6.1" + version: "2.8.2" authentication_data: dependency: "direct main" description: @@ -63,14 +63,14 @@ packages: name: auto_route url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "3.2.4" auto_route_generator: dependency: "direct dev" description: name: auto_route_generator url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "3.2.3" bloc: dependency: transitive description: @@ -98,7 +98,7 @@ packages: name: build url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.2.1" build_config: dependency: transitive description: @@ -119,21 +119,21 @@ packages: name: build_resolvers url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.6" build_runner: dependency: "direct dev" description: name: build_runner url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.1.7" build_runner_core: dependency: transitive description: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "7.0.0" + version: "7.2.3" built_collection: dependency: transitive description: @@ -154,14 +154,14 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" checked_yaml: dependency: transitive description: @@ -189,7 +189,7 @@ packages: name: code_builder url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.1.0" collection: dependency: transitive description: @@ -225,6 +225,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.1" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.1" cupertino_icons: dependency: "direct main" description: @@ -238,7 +245,7 @@ packages: name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.2.1" equatable: dependency: "direct main" description: @@ -344,7 +351,7 @@ packages: name: freezed url: "https://pub.dartlang.org" source: hosted - version: "0.14.2" + version: "0.14.5" freezed_annotation: dependency: "direct dev" description: @@ -373,6 +380,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + google_sign_in: + dependency: "direct main" + description: + name: google_sign_in + url: "https://pub.dartlang.org" + source: hosted + version: "5.2.4" + google_sign_in_platform_interface: + dependency: transitive + description: + name: google_sign_in_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + google_sign_in_web: + dependency: transitive + description: + name: google_sign_in_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.0+5" graphs: dependency: transitive description: @@ -380,6 +408,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.15.0" http: dependency: "direct main" description: @@ -421,21 +456,21 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3" + version: "0.6.4" json_annotation: dependency: transitive description: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "4.0.1" + version: "4.4.0" json_serializable: dependency: "direct dev" description: name: json_serializable url: "https://pub.dartlang.org" source: hosted - version: "4.1.4" + version: "6.1.4" lints: dependency: transitive description: @@ -456,14 +491,21 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.7.0" mime: dependency: transitive description: @@ -505,7 +547,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" pedantic: dependency: transitive description: @@ -548,6 +590,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1+1" shelf: dependency: transitive description: @@ -587,7 +636,14 @@ packages: name: source_gen url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.2.1" + source_helper: + dependency: transitive + description: + name: source_helper + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" source_map_stack_trace: dependency: transitive description: @@ -608,7 +664,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -650,21 +706,21 @@ packages: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.16.8" + version: "1.20.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.4.9" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.3.19" + version: "0.4.11" timing: dependency: transitive description: @@ -679,13 +735,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + universal_html: + dependency: transitive + description: + name: universal_html + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + universal_io: + dependency: transitive + description: + name: universal_io + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.2" vm_service: dependency: transitive description: @@ -722,5 +792,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.12.0 <3.0.0" - flutter: ">=1.17.0" + dart: ">=2.16.0-100.0.dev <3.0.0" + flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index eb7087a..5b4fd51 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,7 +34,7 @@ dependencies: after_layout: ^1.1.0 http: ^0.13.3 get_it: ^7.2.0 - + google_sign_in: # firebase firebase_core: ^1.4.0 firebase_auth: ^3.0.1