Compare commits
	
		
			No commits in common. "31ad460757e9b199922a4d24f20f352f2f8cf6b2" and "6eb40de72c97910dcd6ef4e809f140a904d10e9e" have entirely different histories.
		
	
	
		
			31ad460757
			...
			6eb40de72c
		
	
		
@ -1,4 +1 @@
 | 
				
			|||||||
include: package:wyatt_analysis/analysis_options.flutter.yaml
 | 
					include: package:wyatt_analysis/analysis_options.flutter.yaml
 | 
				
			||||||
 | 
					 | 
				
			||||||
analyzer:
 | 
					 | 
				
			||||||
  exclude: "!example/**"
 | 
					 | 
				
			||||||
@ -8,7 +8,6 @@
 | 
				
			|||||||
.buildlog/
 | 
					.buildlog/
 | 
				
			||||||
.history
 | 
					.history
 | 
				
			||||||
.svn/
 | 
					.svn/
 | 
				
			||||||
migrate_working_dir/
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# IntelliJ related
 | 
					# IntelliJ related
 | 
				
			||||||
*.iml
 | 
					*.iml
 | 
				
			||||||
@ -46,4 +45,4 @@ app.*.map.json
 | 
				
			|||||||
/android/app/profile
 | 
					/android/app/profile
 | 
				
			||||||
/android/app/release
 | 
					/android/app/release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
firebase_options.dart
 | 
					lib/firebase_options.dart
 | 
				
			||||||
@ -1,30 +1,10 @@
 | 
				
			|||||||
# This file tracks properties of this Flutter project.
 | 
					# This file tracks properties of this Flutter project.
 | 
				
			||||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
 | 
					# Used by Flutter tool to assess capabilities and perform upgrades etc.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# This file should be version controlled.
 | 
					# This file should be version controlled and should not be manually edited.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
version:
 | 
					version:
 | 
				
			||||||
  revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
					  revision: 5464c5bac742001448fe4fc0597be939379f88ea
 | 
				
			||||||
  channel: stable
 | 
					  channel: stable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
project_type: app
 | 
					project_type: app
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Tracks metadata for the flutter migrate command
 | 
					 | 
				
			||||||
migration:
 | 
					 | 
				
			||||||
  platforms:
 | 
					 | 
				
			||||||
    - platform: root
 | 
					 | 
				
			||||||
      create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
					 | 
				
			||||||
      base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
					 | 
				
			||||||
    - platform: ios
 | 
					 | 
				
			||||||
      create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
					 | 
				
			||||||
      base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # User provided section
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # List of Local paths (relative to this file) that should be
 | 
					 | 
				
			||||||
  # ignored by the migrate tool.
 | 
					 | 
				
			||||||
  #
 | 
					 | 
				
			||||||
  # Files that are not part of the templates will be ignored by default.
 | 
					 | 
				
			||||||
  unmanaged_files:
 | 
					 | 
				
			||||||
    - 'lib/main.dart'
 | 
					 | 
				
			||||||
    - 'ios/Runner.xcodeproj/project.pbxproj'
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								packages/wyatt_authentication_bloc/example/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					## 1.0.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - Update a dependency to the latest release.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
# example_router
 | 
					# authentication_bloc_example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
A new Flutter project.
 | 
					A new Flutter project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -8,9 +8,9 @@ This project is a starting point for a Flutter application.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
A few resources to get you started if this is your first Flutter project:
 | 
					A few resources to get you started if this is your first Flutter project:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
 | 
					- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
 | 
				
			||||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
 | 
					- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For help getting started with Flutter development, view the
 | 
					For help getting started with Flutter, view our
 | 
				
			||||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
 | 
					[online documentation](https://flutter.dev/docs), which offers tutorials,
 | 
				
			||||||
samples, guidance on mobile development, and a full API reference.
 | 
					samples, guidance on mobile development, and a full API reference.
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,6 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
android {
 | 
					android {
 | 
				
			||||||
    compileSdkVersion flutter.compileSdkVersion
 | 
					    compileSdkVersion flutter.compileSdkVersion
 | 
				
			||||||
    ndkVersion flutter.ndkVersion
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    compileOptions {
 | 
					    compileOptions {
 | 
				
			||||||
        sourceCompatibility JavaVersion.VERSION_1_8
 | 
					        sourceCompatibility JavaVersion.VERSION_1_8
 | 
				
			||||||
@ -47,9 +46,7 @@ android {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    defaultConfig {
 | 
					    defaultConfig {
 | 
				
			||||||
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
 | 
					        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
 | 
				
			||||||
        applicationId "com.example.example_router"
 | 
					        applicationId "com.example.authentication_bloc_example"
 | 
				
			||||||
        // You can update the following values to match your application needs.
 | 
					 | 
				
			||||||
        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
 | 
					 | 
				
			||||||
        minSdkVersion 21
 | 
					        minSdkVersion 21
 | 
				
			||||||
        targetSdkVersion flutter.targetSdkVersion
 | 
					        targetSdkVersion flutter.targetSdkVersion
 | 
				
			||||||
        versionCode flutterVersionCode.toInteger()
 | 
					        versionCode flutterVersionCode.toInteger()
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,6 @@
 | 
				
			|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
    package="com.example.example_router">
 | 
					    package="com.example.authentication_bloc_example">
 | 
				
			||||||
    <!-- The INTERNET permission is required for development. Specifically,
 | 
					    <!-- Flutter needs it to communicate with the running application
 | 
				
			||||||
         the Flutter tool needs it to communicate with the running application
 | 
					 | 
				
			||||||
         to allow setting breakpoints, to provide hot reload, etc.
 | 
					         to allow setting breakpoints, to provide hot reload, etc.
 | 
				
			||||||
    -->
 | 
					    -->
 | 
				
			||||||
    <uses-permission android:name="android.permission.INTERNET"/>
 | 
					    <uses-permission android:name="android.permission.INTERNET"/>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
    package="com.example.example_router">
 | 
					    package="com.example.authentication_bloc_example">
 | 
				
			||||||
   <application
 | 
					   <application
 | 
				
			||||||
        android:label="example_router"
 | 
					        android:label="authentication_bloc_example"
 | 
				
			||||||
        android:name="${applicationName}"
 | 
					        android:name="${applicationName}"
 | 
				
			||||||
        android:icon="@mipmap/ic_launcher">
 | 
					        android:icon="@mipmap/ic_launcher">
 | 
				
			||||||
        <activity
 | 
					        <activity
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package com.example.authentication_bloc_example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import io.flutter.embedding.android.FlutterActivity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MainActivity: FlutterActivity() {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
 | 
					    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
 | 
				
			||||||
    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
 | 
					    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
 | 
				
			||||||
        <!-- Show a splash screen on the activity. Automatically removed when
 | 
					        <!-- Show a splash screen on the activity. Automatically removed when
 | 
				
			||||||
             the Flutter engine draws its first frame -->
 | 
					             Flutter draws its first frame -->
 | 
				
			||||||
        <item name="android:windowBackground">@drawable/launch_background</item>
 | 
					        <item name="android:windowBackground">@drawable/launch_background</item>
 | 
				
			||||||
    </style>
 | 
					    </style>
 | 
				
			||||||
    <!-- Theme applied to the Android Window as soon as the process has started.
 | 
					    <!-- Theme applied to the Android Window as soon as the process has started.
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
 | 
					    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
 | 
				
			||||||
    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
 | 
					    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
 | 
				
			||||||
        <!-- Show a splash screen on the activity. Automatically removed when
 | 
					        <!-- Show a splash screen on the activity. Automatically removed when
 | 
				
			||||||
             the Flutter engine draws its first frame -->
 | 
					             Flutter draws its first frame -->
 | 
				
			||||||
        <item name="android:windowBackground">@drawable/launch_background</item>
 | 
					        <item name="android:windowBackground">@drawable/launch_background</item>
 | 
				
			||||||
    </style>
 | 
					    </style>
 | 
				
			||||||
    <!-- Theme applied to the Android Window as soon as the process has started.
 | 
					    <!-- Theme applied to the Android Window as soon as the process has started.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,6 @@
 | 
				
			|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
    package="com.example.example_router">
 | 
					    package="com.example.authentication_bloc_example">
 | 
				
			||||||
    <!-- The INTERNET permission is required for development. Specifically,
 | 
					    <!-- Flutter needs it to communicate with the running application
 | 
				
			||||||
         the Flutter tool needs it to communicate with the running application
 | 
					 | 
				
			||||||
         to allow setting breakpoints, to provide hot reload, etc.
 | 
					         to allow setting breakpoints, to provide hot reload, etc.
 | 
				
			||||||
    -->
 | 
					    -->
 | 
				
			||||||
    <uses-permission android:name="android.permission.INTERNET"/>
 | 
					    <uses-permission android:name="android.permission.INTERNET"/>
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ buildscript {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dependencies {
 | 
					    dependencies {
 | 
				
			||||||
        classpath 'com.android.tools.build:gradle:7.1.2'
 | 
					        classpath 'com.android.tools.build:gradle:4.1.0'
 | 
				
			||||||
        // START: FlutterFire Configuration
 | 
					        // START: FlutterFire Configuration
 | 
				
			||||||
        classpath 'com.google.gms:google-services:4.3.10'
 | 
					        classpath 'com.google.gms:google-services:4.3.10'
 | 
				
			||||||
        // END: FlutterFire Configuration
 | 
					        // END: FlutterFire Configuration
 | 
				
			||||||
 | 
				
			|||||||
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 | 
				
			|||||||
distributionPath=wrapper/dists
 | 
					distributionPath=wrapper/dists
 | 
				
			||||||
zipStoreBase=GRADLE_USER_HOME
 | 
					zipStoreBase=GRADLE_USER_HOME
 | 
				
			||||||
zipStorePath=wrapper/dists
 | 
					zipStorePath=wrapper/dists
 | 
				
			||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
 | 
					distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										182
									
								
								packages/wyatt_authentication_bloc/example/lib/app/app.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,182 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'dart:developer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/constants.dart';
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/home/home_page.dart';
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/login/login_page.dart';
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/model.dart';
 | 
				
			||||||
 | 
					import 'package:cloud_firestore/cloud_firestore.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_bloc/flutter_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class App extends StatelessWidget {
 | 
				
			||||||
 | 
					  const App({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static FormData getNormalFormData() {
 | 
				
			||||||
 | 
					    return const FormData([
 | 
				
			||||||
 | 
					      FormInput(formFieldName, Name.pure()),
 | 
				
			||||||
 | 
					      FormInput(formFieldPhone, Phone.pure()),
 | 
				
			||||||
 | 
					      FormInput(formFieldPro, Boolean.pure()),
 | 
				
			||||||
 | 
					      FormInput(
 | 
				
			||||||
 | 
					        formFieldConfirmedPassword,
 | 
				
			||||||
 | 
					        ConfirmedPassword.pure(),
 | 
				
			||||||
 | 
					        metadata: FormInputMetadata(export: false),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static FormData getProFormData() {
 | 
				
			||||||
 | 
					    return const FormData([
 | 
				
			||||||
 | 
					      FormInput(formFieldName, Name.pure()),
 | 
				
			||||||
 | 
					      FormInput(formFieldPhone, Phone.pure()),
 | 
				
			||||||
 | 
					      FormInput(formFieldPro, Boolean.pure()),
 | 
				
			||||||
 | 
					      FormInput(formFieldSiren, Siren.pure()),
 | 
				
			||||||
 | 
					      FormInput(formFieldIban, Iban.pure()),
 | 
				
			||||||
 | 
					      FormInput(
 | 
				
			||||||
 | 
					        formFieldConfirmedPassword,
 | 
				
			||||||
 | 
					        ConfirmedPassword.pure(),
 | 
				
			||||||
 | 
					        metadata: FormInputMetadata(export: false),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // On Authentication Success. (Authenticated or Anonymous)
 | 
				
			||||||
 | 
					  // User callback.
 | 
				
			||||||
 | 
					  Future<Map<String, dynamic>> onAuthSuccess(UserInterface user) async {
 | 
				
			||||||
 | 
					    if (user.isNotEmpty && !user.isAnonymous) {
 | 
				
			||||||
 | 
					      // Check if user is register in Firesore.
 | 
				
			||||||
 | 
					      DocumentSnapshot firestoreUser = await FirebaseFirestore.instance
 | 
				
			||||||
 | 
					          .collection(firestoreCollectionUsers)
 | 
				
			||||||
 | 
					          .doc(user.uid)
 | 
				
			||||||
 | 
					          .get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (!firestoreUser.exists) {
 | 
				
			||||||
 | 
					        // Register user in Firestore when sign in with social account.
 | 
				
			||||||
 | 
					        final uid = user.uid;
 | 
				
			||||||
 | 
					        final u = {'uid': uid, 'email': user.email};
 | 
				
			||||||
 | 
					        await FirebaseFirestore.instance
 | 
				
			||||||
 | 
					            .collection(firestoreCollectionUsers)
 | 
				
			||||||
 | 
					            .doc(uid)
 | 
				
			||||||
 | 
					            .set(u);
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          'user': UserFirestore(
 | 
				
			||||||
 | 
					              uid: uid,
 | 
				
			||||||
 | 
					              email: user.email ?? '',
 | 
				
			||||||
 | 
					              name: user.displayName ?? '',
 | 
				
			||||||
 | 
					              phone: user.phoneNumber ?? ''),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          'user': UserFirestore.fromMap(
 | 
				
			||||||
 | 
					              firestoreUser.data() as Map<String, dynamic>),
 | 
				
			||||||
 | 
					          ...firestoreUser.data() as Map<String, dynamic>? ?? {}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return {};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // On Sign Up Success.
 | 
				
			||||||
 | 
					  Future<void> onSignUpSuccess(SignUpState state, String? uid) async {
 | 
				
			||||||
 | 
					    if (uid != null) {
 | 
				
			||||||
 | 
					      final data = state.data.toMap();
 | 
				
			||||||
 | 
					      final user = {'uid': uid, 'email': state.email.value, ...data};
 | 
				
			||||||
 | 
					      log('onSignUpSuccess: $user');
 | 
				
			||||||
 | 
					      await FirebaseFirestore.instance
 | 
				
			||||||
 | 
					          .collection(firestoreCollectionUsers)
 | 
				
			||||||
 | 
					          .doc(uid)
 | 
				
			||||||
 | 
					          .set(user);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    AuthenticationRepositoryInterface authenticationRepository =
 | 
				
			||||||
 | 
					        AuthenticationRepositoryFirebase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AuthenticationCubit authenticationCubit = AuthenticationCubit(
 | 
				
			||||||
 | 
					      authenticationRepository: authenticationRepository,
 | 
				
			||||||
 | 
					      onAuthSuccess: onAuthSuccess,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SignUpCubit signUpCubit = SignUpCubit(
 | 
				
			||||||
 | 
					      authenticationRepository: authenticationRepository,
 | 
				
			||||||
 | 
					      authenticationCubit: authenticationCubit,
 | 
				
			||||||
 | 
					      entries: getNormalFormData(),
 | 
				
			||||||
 | 
					      onSignUpSuccess: onSignUpSuccess,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SignInCubit signInCubit = SignInCubit(
 | 
				
			||||||
 | 
					      authenticationRepository: authenticationRepository,
 | 
				
			||||||
 | 
					      authenticationCubit: authenticationCubit,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return MultiRepositoryProvider(
 | 
				
			||||||
 | 
					      providers: [
 | 
				
			||||||
 | 
					        RepositoryProvider<AuthenticationRepositoryInterface>(
 | 
				
			||||||
 | 
					          create: (context) => authenticationRepository,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      child: MultiBlocProvider(
 | 
				
			||||||
 | 
					        providers: [
 | 
				
			||||||
 | 
					          BlocProvider<AuthenticationCubit>(
 | 
				
			||||||
 | 
					            create: (context) => authenticationCubit..init(),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          BlocProvider<SignUpCubit>(
 | 
				
			||||||
 | 
					            create: (context) => signUpCubit,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          BlocProvider<SignInCubit>(
 | 
				
			||||||
 | 
					            create: (context) => signInCubit,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        child: const AppView(),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AppView extends StatelessWidget {
 | 
				
			||||||
 | 
					  const AppView({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return MaterialApp(
 | 
				
			||||||
 | 
					      theme: ThemeData(
 | 
				
			||||||
 | 
					        primarySwatch: Colors.blue,
 | 
				
			||||||
 | 
					        buttonTheme: const ButtonThemeData(
 | 
				
			||||||
 | 
					          buttonColor: Colors.blue,
 | 
				
			||||||
 | 
					          textTheme: ButtonTextTheme.primary,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      home: AuthenticationBuilder(
 | 
				
			||||||
 | 
					        unknown: (context) {
 | 
				
			||||||
 | 
					          return const Scaffold(
 | 
				
			||||||
 | 
					            body: Center(
 | 
				
			||||||
 | 
					              child: CircularProgressIndicator(),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        authenticated: (context, user, userData) => const HomePage(),
 | 
				
			||||||
 | 
					        unauthenticated: (context) => const LoginPage(),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:bloc/bloc.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/foundation.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AppBlocObserver extends BlocObserver {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void onEvent(Bloc bloc, Object? event) {
 | 
				
			||||||
 | 
					    super.onEvent(bloc, event);
 | 
				
			||||||
 | 
					    debugPrint(event.toString());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
 | 
				
			||||||
 | 
					    debugPrint(error.toString());
 | 
				
			||||||
 | 
					    super.onError(bloc, error, stackTrace);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void onChange(BlocBase bloc, Change change) {
 | 
				
			||||||
 | 
					    super.onChange(bloc, change);
 | 
				
			||||||
 | 
					    debugPrint('curr:\t${change.currentState}\nnext:\t${change.nextState}');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void onTransition(Bloc bloc, Transition transition) {
 | 
				
			||||||
 | 
					    super.onTransition(bloc, transition);
 | 
				
			||||||
 | 
					    debugPrint(transition.toString());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					// 
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					// 
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					// 
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const String formFieldName = 'name';
 | 
				
			||||||
 | 
					const String formFieldPhone = 'phone';
 | 
				
			||||||
 | 
					const String formFieldPro = 'isPro';
 | 
				
			||||||
 | 
					const String formFieldConfirmedPassword = 'confirmedPassword';
 | 
				
			||||||
 | 
					const String formFieldSiren = 'siren';
 | 
				
			||||||
 | 
					const String formFieldIban = 'iban';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const String firestoreCollectionUsers = 'authentication_bloc_users';
 | 
				
			||||||
@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/forgot_password/widgets/forgot_password_form.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_bloc/flutter_bloc.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ForgotPasswordPage extends StatelessWidget {
 | 
				
			||||||
 | 
					  const ForgotPasswordPage({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Route route() {
 | 
				
			||||||
 | 
					    return MaterialPageRoute<void>(builder: (_) => const ForgotPasswordPage());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Scaffold(
 | 
				
			||||||
 | 
					      appBar: AppBar(title: const Text('Forgot Password')),
 | 
				
			||||||
 | 
					      body: Padding(
 | 
				
			||||||
 | 
					        padding: const EdgeInsets.all(8),
 | 
				
			||||||
 | 
					        child: BlocProvider(
 | 
				
			||||||
 | 
					          create: (_) => PasswordResetCubit(
 | 
				
			||||||
 | 
					            context.read<AuthenticationRepositoryInterface>(),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          child: const ForgotPasswordForm(),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_bloc/flutter_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _EmailInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<PasswordResetCubit, PasswordResetState>(
 | 
				
			||||||
 | 
					      buildWhen: (previous, current) => previous.email != current.email,
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (email) =>
 | 
				
			||||||
 | 
					              context.read<PasswordResetCubit>().emailChanged(email),
 | 
				
			||||||
 | 
					          keyboardType: TextInputType.emailAddress,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'email',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText: state.email.invalid ? 'invalid email' : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _ResetButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<PasswordResetCubit, PasswordResetState>(
 | 
				
			||||||
 | 
					      buildWhen: (previous, current) => previous.status != current.status,
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return state.status.isSubmissionInProgress
 | 
				
			||||||
 | 
					            ? const CircularProgressIndicator()
 | 
				
			||||||
 | 
					            : ElevatedButton(
 | 
				
			||||||
 | 
					                onPressed: state.status.isValidated
 | 
				
			||||||
 | 
					                    ? () => context
 | 
				
			||||||
 | 
					                        .read<PasswordResetCubit>()
 | 
				
			||||||
 | 
					                        .sendPasswordResetEmail()
 | 
				
			||||||
 | 
					                    : null,
 | 
				
			||||||
 | 
					                child: const Text('SEND EMAIL'),
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ForgotPasswordForm extends StatelessWidget {
 | 
				
			||||||
 | 
					  const ForgotPasswordForm({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocListener<PasswordResetCubit, PasswordResetState>(
 | 
				
			||||||
 | 
					      listener: (context, state) {
 | 
				
			||||||
 | 
					        if (state.status.isSubmissionSuccess) {
 | 
				
			||||||
 | 
					          Navigator.of(context).pop();
 | 
				
			||||||
 | 
					        } else if (state.status.isSubmissionFailure) {
 | 
				
			||||||
 | 
					          ScaffoldMessenger.of(context)
 | 
				
			||||||
 | 
					            ..hideCurrentSnackBar()
 | 
				
			||||||
 | 
					            ..showSnackBar(
 | 
				
			||||||
 | 
					              SnackBar(
 | 
				
			||||||
 | 
					                content: Text(state.errorMessage ?? 'Password reset Failure'),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      child: Align(
 | 
				
			||||||
 | 
					        alignment: const Alignment(0, -1 / 3),
 | 
				
			||||||
 | 
					        child: Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					          children: [_EmailInput(), const SizedBox(height: 8), _ResetButton()],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/home/widgets/infos.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_bloc/flutter_bloc.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/home/widgets/email_verification.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class HomePage extends StatelessWidget {
 | 
				
			||||||
 | 
					  const HomePage({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Route route() {
 | 
				
			||||||
 | 
					    return MaterialPageRoute<void>(builder: (_) => const HomePage());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final user = context.select((AuthenticationCubit cubit) => cubit.state.user);
 | 
				
			||||||
 | 
					    return Scaffold(
 | 
				
			||||||
 | 
					      appBar: AppBar(
 | 
				
			||||||
 | 
					        title: const Text('Home'),
 | 
				
			||||||
 | 
					        actions: <Widget>[
 | 
				
			||||||
 | 
					          IconButton(
 | 
				
			||||||
 | 
					            icon: const Icon(Icons.exit_to_app),
 | 
				
			||||||
 | 
					            onPressed: () => context
 | 
				
			||||||
 | 
					                .read<AuthenticationCubit>()
 | 
				
			||||||
 | 
					                .logOut(),
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      body: Padding(
 | 
				
			||||||
 | 
					        padding: const EdgeInsets.all(8),
 | 
				
			||||||
 | 
					        child: BlocProvider(
 | 
				
			||||||
 | 
					          create: (_) => EmailVerificationCubit(
 | 
				
			||||||
 | 
					            context.read<AuthenticationRepositoryInterface>(),
 | 
				
			||||||
 | 
					          )..checkEmailVerification(),
 | 
				
			||||||
 | 
					          child: BlocBuilder<EmailVerificationCubit, EmailVerificationState>(
 | 
				
			||||||
 | 
					            builder: (context, state) {
 | 
				
			||||||
 | 
					              if (state.isVerified || user!.isAnonymous) {
 | 
				
			||||||
 | 
					                return const UserInfo();
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                return const EmailVerification();
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const _avatarSize = 48.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Avatar extends StatelessWidget {
 | 
				
			||||||
 | 
					  const Avatar({Key? key, this.photo}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final String? photo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final photo = this.photo;
 | 
				
			||||||
 | 
					    return CircleAvatar(
 | 
				
			||||||
 | 
					      radius: _avatarSize,
 | 
				
			||||||
 | 
					      backgroundImage: photo != null ? NetworkImage(photo) : null,
 | 
				
			||||||
 | 
					      child: photo == null
 | 
				
			||||||
 | 
					          ? const Icon(Icons.person_outline, size: _avatarSize)
 | 
				
			||||||
 | 
					          : null,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_bloc/flutter_bloc.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EmailVerification extends StatelessWidget {
 | 
				
			||||||
 | 
					  const EmailVerification({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final user = context.select((AuthenticationCubit cubit) => cubit.state.user);
 | 
				
			||||||
 | 
					    final userData = context.select((AuthenticationCubit cubit) => cubit.state.userData);
 | 
				
			||||||
 | 
					    return Align(
 | 
				
			||||||
 | 
					      alignment: const Alignment(0, -1 / 3),
 | 
				
			||||||
 | 
					      child: Column(
 | 
				
			||||||
 | 
					        mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					        children: <Widget>[
 | 
				
			||||||
 | 
					          Text("Hello ${userData!['name'] ?? 'null'}!"),
 | 
				
			||||||
 | 
					          const SizedBox(height: 4),
 | 
				
			||||||
 | 
					          Text("Email '${user?.email ?? 'null'}' is not verified"),
 | 
				
			||||||
 | 
					          const SizedBox(height: 4),
 | 
				
			||||||
 | 
					          ElevatedButton(
 | 
				
			||||||
 | 
					            onPressed: () {
 | 
				
			||||||
 | 
					              context.read<EmailVerificationCubit>().sendEmailVerification();
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            child: const Text('(Re)send email'),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          ElevatedButton(
 | 
				
			||||||
 | 
					            onPressed: () {
 | 
				
			||||||
 | 
					              context.read<EmailVerificationCubit>().checkEmailVerification();
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            child: const Text('Refresh'),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/home/widgets/avatar.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_bloc/flutter_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/constants.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UserInfo extends StatelessWidget {
 | 
				
			||||||
 | 
					  const UserInfo({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final textTheme = Theme.of(context).textTheme;
 | 
				
			||||||
 | 
					    final user = context.select((AuthenticationCubit cubit) => cubit.state.user);
 | 
				
			||||||
 | 
					    final userData = context.select((AuthenticationCubit cubit) => cubit.state.userData);
 | 
				
			||||||
 | 
					    return Align(
 | 
				
			||||||
 | 
					      alignment: const Alignment(0, -1 / 3),
 | 
				
			||||||
 | 
					      child: Column(
 | 
				
			||||||
 | 
					        mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					        children: <Widget>[
 | 
				
			||||||
 | 
					          Avatar(photo: user?.photoURL),
 | 
				
			||||||
 | 
					          const SizedBox(height: 4),
 | 
				
			||||||
 | 
					          Text("Email: ${user?.email ?? 'null'}", style: textTheme.headline6),
 | 
				
			||||||
 | 
					          const SizedBox(height: 4),
 | 
				
			||||||
 | 
					          Text("Name: ${userData![formFieldName] ?? 'null'}",
 | 
				
			||||||
 | 
					              style: textTheme.headline6),
 | 
				
			||||||
 | 
					          const SizedBox(height: 4),
 | 
				
			||||||
 | 
					          Text("Phone: ${userData[formFieldPhone] ?? 'null'}",
 | 
				
			||||||
 | 
					              style: textTheme.headline6),
 | 
				
			||||||
 | 
					          const SizedBox(height: 4),
 | 
				
			||||||
 | 
					          Text("IsPro: ${userData[formFieldPro] ?? 'null'}",
 | 
				
			||||||
 | 
					              style: textTheme.headline6),
 | 
				
			||||||
 | 
					          const SizedBox(height: 4),
 | 
				
			||||||
 | 
					          Text("IsAnonymous: ${user?.isAnonymous.toString() ?? 'null'}",
 | 
				
			||||||
 | 
					              style: textTheme.headline6),
 | 
				
			||||||
 | 
					          const SizedBox(height: 4),
 | 
				
			||||||
 | 
					          Text("IsEmailVerified: ${user?.emailVerified.toString() ?? 'null'}",
 | 
				
			||||||
 | 
					              style: textTheme.headline6),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/login/widgets/login_form.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LoginPage extends StatelessWidget {
 | 
				
			||||||
 | 
					  const LoginPage({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Route route() {
 | 
				
			||||||
 | 
					    return MaterialPageRoute<void>(builder: (_) => const LoginPage());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Scaffold(
 | 
				
			||||||
 | 
					      appBar: AppBar(title: const Text('Login')),
 | 
				
			||||||
 | 
					      body: const Padding(
 | 
				
			||||||
 | 
					        padding: EdgeInsets.all(8),
 | 
				
			||||||
 | 
					        child: LoginForm(),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,214 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/app/app.dart';
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/constants.dart';
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/forgot_password/forgot_password_page.dart';
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/sign_up/sign_up_page.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_bloc/flutter_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _EmailInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignInCubit, SignInState>(
 | 
				
			||||||
 | 
					      buildWhen: (previous, current) => previous.email != current.email,
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (email) => context.read<SignInCubit>().emailChanged(email),
 | 
				
			||||||
 | 
					          keyboardType: TextInputType.emailAddress,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'email',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText: state.email.invalid ? 'invalid email' : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _PasswordInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignInCubit, SignInState>(
 | 
				
			||||||
 | 
					      buildWhen: (previous, current) => previous.password != current.password,
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (password) =>
 | 
				
			||||||
 | 
					              context.read<SignInCubit>().passwordChanged(password),
 | 
				
			||||||
 | 
					          obscureText: true,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'password',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText: state.password.invalid ? 'invalid password' : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _LoginAnonButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignInCubit, SignInState>(
 | 
				
			||||||
 | 
					      buildWhen: (previous, current) => previous.status != current.status,
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return state.status.isSubmissionInProgress
 | 
				
			||||||
 | 
					            ? const CircularProgressIndicator()
 | 
				
			||||||
 | 
					            : ElevatedButton(
 | 
				
			||||||
 | 
					                onPressed: () =>
 | 
				
			||||||
 | 
					                    context.read<SignInCubit>().signInAnonymously(),
 | 
				
			||||||
 | 
					                child: const Text('LOGIN ANONYMOUSLY'),
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _LoginWithPasswordButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignInCubit, SignInState>(
 | 
				
			||||||
 | 
					      buildWhen: (previous, current) => previous.status != current.status,
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return state.status.isSubmissionInProgress
 | 
				
			||||||
 | 
					            ? const CircularProgressIndicator()
 | 
				
			||||||
 | 
					            : ElevatedButton(
 | 
				
			||||||
 | 
					                onPressed: state.status.isValidated
 | 
				
			||||||
 | 
					                    ? () =>
 | 
				
			||||||
 | 
					                        context.read<SignInCubit>().signInWithEmailAndPassword()
 | 
				
			||||||
 | 
					                    : null,
 | 
				
			||||||
 | 
					                child: const Text('LOGIN WITH PASSWORD'),
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _LoginWithGoogleButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignInCubit, SignInState>(
 | 
				
			||||||
 | 
					      buildWhen: (previous, current) => previous.status != current.status,
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return state.status.isSubmissionInProgress
 | 
				
			||||||
 | 
					            ? const CircularProgressIndicator()
 | 
				
			||||||
 | 
					            : ElevatedButton(
 | 
				
			||||||
 | 
					                onPressed: () =>
 | 
				
			||||||
 | 
					                    context.read<SignInCubit>().signInWithGoogle(),
 | 
				
			||||||
 | 
					                child: const Text('LOGIN GOOGLE'),
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _SignUpButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final theme = Theme.of(context);
 | 
				
			||||||
 | 
					    return TextButton(
 | 
				
			||||||
 | 
					      onPressed: () {
 | 
				
			||||||
 | 
					        context.read<SignUpCubit>().updateFormData(App.getNormalFormData());
 | 
				
			||||||
 | 
					        Navigator.of(context).push<void>(SignUpPage.route());
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      child: Text(
 | 
				
			||||||
 | 
					        'CREATE ACCOUNT',
 | 
				
			||||||
 | 
					        style: TextStyle(color: theme.primaryColor),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _SignUpAsProButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final theme = Theme.of(context);
 | 
				
			||||||
 | 
					    return TextButton(
 | 
				
			||||||
 | 
					      onPressed: () {
 | 
				
			||||||
 | 
					        context.read<SignUpCubit>().updateFormData(App.getProFormData());
 | 
				
			||||||
 | 
					        context.read<SignUpCubit>().dataChanged(
 | 
				
			||||||
 | 
					              formFieldPro,
 | 
				
			||||||
 | 
					              const Boolean.dirty(value: true),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        Navigator.of(context).push<void>(SignUpPage.route());
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      child: Text(
 | 
				
			||||||
 | 
					        'CREATE PRO ACCOUNT',
 | 
				
			||||||
 | 
					        style: TextStyle(color: theme.primaryColor),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LoginForm extends StatelessWidget {
 | 
				
			||||||
 | 
					  const LoginForm({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocListener<SignInCubit, SignInState>(
 | 
				
			||||||
 | 
					      listener: (context, state) {
 | 
				
			||||||
 | 
					        if (state.status.isSubmissionFailure) {
 | 
				
			||||||
 | 
					          ScaffoldMessenger.of(context)
 | 
				
			||||||
 | 
					            ..hideCurrentSnackBar()
 | 
				
			||||||
 | 
					            ..showSnackBar(
 | 
				
			||||||
 | 
					              SnackBar(
 | 
				
			||||||
 | 
					                content: Text(state.errorMessage ?? 'Authentication Failure'),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      child: Align(
 | 
				
			||||||
 | 
					        alignment: const Alignment(0, -1 / 3),
 | 
				
			||||||
 | 
					        child: SingleChildScrollView(
 | 
				
			||||||
 | 
					          child: Column(
 | 
				
			||||||
 | 
					            mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					            children: [
 | 
				
			||||||
 | 
					              const SizedBox(height: 120),
 | 
				
			||||||
 | 
					              _EmailInput(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _PasswordInput(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              GestureDetector(
 | 
				
			||||||
 | 
					                onTap: () {
 | 
				
			||||||
 | 
					                  Navigator.of(context).push(ForgotPasswordPage.route());
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                child: Text(
 | 
				
			||||||
 | 
					                  'Forgot password ?',
 | 
				
			||||||
 | 
					                  style: Theme.of(context).textTheme.bodyText2,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _LoginWithPasswordButton(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _LoginAnonButton(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _LoginWithGoogleButton(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _SignUpButton(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _SignUpAsProButton(),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,6 +1,35 @@
 | 
				
			|||||||
import 'package:example_router/bootstrap.dart';
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
import 'package:example_router/presentation/features/app/app.dart';
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void main() {
 | 
					import 'package:authentication_bloc_example/app/app.dart';
 | 
				
			||||||
  bootstrap(App.new);
 | 
					import 'package:authentication_bloc_example/app/bloc_observer.dart';
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/firebase_options.dart';
 | 
				
			||||||
 | 
					import 'package:firebase_core/firebase_core.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_bloc/flutter_bloc.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Future<void> main() async {
 | 
				
			||||||
 | 
					  WidgetsFlutterBinding.ensureInitialized();
 | 
				
			||||||
 | 
					  await Firebase.initializeApp(
 | 
				
			||||||
 | 
					    options: DefaultFirebaseOptions.currentPlatform,
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  BlocOverrides.runZoned(
 | 
				
			||||||
 | 
					    () => runApp(
 | 
				
			||||||
 | 
					      const App(),
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    blocObserver: AppBlocObserver(),
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										52
									
								
								packages/wyatt_authentication_bloc/example/lib/model.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UserFirestore {
 | 
				
			||||||
 | 
					  final String email;
 | 
				
			||||||
 | 
					  final String name;
 | 
				
			||||||
 | 
					  final String phone;
 | 
				
			||||||
 | 
					  final String uid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  UserFirestore({
 | 
				
			||||||
 | 
					    required this.email,
 | 
				
			||||||
 | 
					    required this.name,
 | 
				
			||||||
 | 
					    required this.phone,
 | 
				
			||||||
 | 
					    required this.uid,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  factory UserFirestore.fromMap(Map<String, dynamic> map) {
 | 
				
			||||||
 | 
					    return UserFirestore(
 | 
				
			||||||
 | 
					      uid: map['uid'],
 | 
				
			||||||
 | 
					      email: map['email'],
 | 
				
			||||||
 | 
					      name: map['name'],
 | 
				
			||||||
 | 
					      phone: map['phone'],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Map<String, dynamic> toMap() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      'uid': uid,
 | 
				
			||||||
 | 
					      'email': email,
 | 
				
			||||||
 | 
					      'name': name,
 | 
				
			||||||
 | 
					      'phone': phone,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'UserFirestore(email: $email, name: $name, phone: $phone, uid: $uid)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/sign_up/widgets/sign_up_form.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SignUpPage extends StatelessWidget {
 | 
				
			||||||
 | 
					  const SignUpPage({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Route route() {
 | 
				
			||||||
 | 
					    return MaterialPageRoute<void>(builder: (_) => const SignUpPage());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Scaffold(
 | 
				
			||||||
 | 
					      appBar: AppBar(title: const Text('Sign Up')),
 | 
				
			||||||
 | 
					      body: const Padding(
 | 
				
			||||||
 | 
					        padding: EdgeInsets.all(8),
 | 
				
			||||||
 | 
					        child: SingleChildScrollView(
 | 
				
			||||||
 | 
					          child: SignUpForm(),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,325 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2022 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'dart:developer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/app/app.dart';
 | 
				
			||||||
 | 
					import 'package:authentication_bloc_example/constants.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_bloc/flutter_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _NameInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (name) => context
 | 
				
			||||||
 | 
					              .read<SignUpCubit>()
 | 
				
			||||||
 | 
					              .dataChanged(formFieldName, Name.dirty(name)),
 | 
				
			||||||
 | 
					          keyboardType: TextInputType.name,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'name',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText:
 | 
				
			||||||
 | 
					                state.data.isNotValid(formFieldName) ? 'invalid name' : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _PhoneInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (phone) => context
 | 
				
			||||||
 | 
					              .read<SignUpCubit>()
 | 
				
			||||||
 | 
					              .dataChanged(formFieldPhone, Phone.dirty(phone)),
 | 
				
			||||||
 | 
					          keyboardType: TextInputType.phone,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'phone',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText: state.data.isNotValid(formFieldPhone)
 | 
				
			||||||
 | 
					                ? 'invalid phone'
 | 
				
			||||||
 | 
					                : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _SirenInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (siren) => context
 | 
				
			||||||
 | 
					              .read<SignUpCubit>()
 | 
				
			||||||
 | 
					              .dataChanged(formFieldSiren, Siren.dirty(siren)),
 | 
				
			||||||
 | 
					          keyboardType: TextInputType.number,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'siren',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText: state.data.isNotValid(formFieldSiren)
 | 
				
			||||||
 | 
					                ? 'invalid SIREN'
 | 
				
			||||||
 | 
					                : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _IbanInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (iban) => context
 | 
				
			||||||
 | 
					              .read<SignUpCubit>()
 | 
				
			||||||
 | 
					              .dataChanged(formFieldIban, Iban.dirty(iban)),
 | 
				
			||||||
 | 
					          keyboardType: TextInputType.text,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'iban',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText:
 | 
				
			||||||
 | 
					                state.data.isNotValid(formFieldIban) ? 'invalid IBAN' : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _EmailInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      buildWhen: (previous, current) => previous.email != current.email,
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (email) => context.read<SignUpCubit>().emailChanged(email),
 | 
				
			||||||
 | 
					          keyboardType: TextInputType.emailAddress,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'email',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText: state.email.invalid ? 'invalid email' : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _PasswordInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (password) {
 | 
				
			||||||
 | 
					            context.read<SignUpCubit>().passwordChanged(password);
 | 
				
			||||||
 | 
					            context.read<SignUpCubit>().dataChanged(
 | 
				
			||||||
 | 
					                  formFieldConfirmedPassword,
 | 
				
			||||||
 | 
					                  ConfirmedPassword.dirty(
 | 
				
			||||||
 | 
					                    password: password,
 | 
				
			||||||
 | 
					                    value: context
 | 
				
			||||||
 | 
					                        .read<SignUpCubit>()
 | 
				
			||||||
 | 
					                        .state
 | 
				
			||||||
 | 
					                        .data
 | 
				
			||||||
 | 
					                        .valueOf<String>(formFieldConfirmedPassword),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          obscureText: true,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'password',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText: state.password.invalid ? 'invalid password' : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _ConfirmPasswordInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return TextField(
 | 
				
			||||||
 | 
					          onChanged: (confirmPassword) => context
 | 
				
			||||||
 | 
					              .read<SignUpCubit>()
 | 
				
			||||||
 | 
					              .dataChanged(
 | 
				
			||||||
 | 
					                formFieldConfirmedPassword,
 | 
				
			||||||
 | 
					                ConfirmedPassword.dirty(
 | 
				
			||||||
 | 
					                  password: context.read<SignUpCubit>().state.password.value,
 | 
				
			||||||
 | 
					                  value: confirmPassword,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					          obscureText: true,
 | 
				
			||||||
 | 
					          decoration: InputDecoration(
 | 
				
			||||||
 | 
					            labelText: 'confirm password',
 | 
				
			||||||
 | 
					            helperText: '',
 | 
				
			||||||
 | 
					            errorText: state.data.isNotValid(formFieldConfirmedPassword)
 | 
				
			||||||
 | 
					                ? 'passwords do not match'
 | 
				
			||||||
 | 
					                : null,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _CheckIsProInput extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return ListTile(
 | 
				
			||||||
 | 
					      title: const Text('Are you a pro?'),
 | 
				
			||||||
 | 
					      trailing: BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					        builder: (context, state) {
 | 
				
			||||||
 | 
					          return Checkbox(
 | 
				
			||||||
 | 
					              value: state.data.valueOf<bool>(formFieldPro),
 | 
				
			||||||
 | 
					              onChanged: (isPro) {
 | 
				
			||||||
 | 
					                final value =
 | 
				
			||||||
 | 
					                    isPro!; // tristate is false, so value can't be null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                context.read<SignUpCubit>().dataChanged(
 | 
				
			||||||
 | 
					                      formFieldPro,
 | 
				
			||||||
 | 
					                      Boolean.dirty(value: value),
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (value) {
 | 
				
			||||||
 | 
					                  context.read<SignUpCubit>().updateFormData(
 | 
				
			||||||
 | 
					                      App.getProFormData(),
 | 
				
			||||||
 | 
					                      operation: SetOperation.union);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                  context.read<SignUpCubit>().updateFormData(
 | 
				
			||||||
 | 
					                      App.getNormalFormData(),
 | 
				
			||||||
 | 
					                      operation: SetOperation.intersection);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _SignUpButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      buildWhen: (previous, current) => previous.status != current.status,
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return state.status.isSubmissionInProgress
 | 
				
			||||||
 | 
					            ? const CircularProgressIndicator()
 | 
				
			||||||
 | 
					            : ElevatedButton(
 | 
				
			||||||
 | 
					                onPressed: state.status.isValidated
 | 
				
			||||||
 | 
					                    ? () => context.read<SignUpCubit>().signUpFormSubmitted()
 | 
				
			||||||
 | 
					                    : null,
 | 
				
			||||||
 | 
					                child: const Text('SIGN UP'),
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _DebugButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      builder: (context, state) {
 | 
				
			||||||
 | 
					        return ElevatedButton(
 | 
				
			||||||
 | 
					          onPressed: () {
 | 
				
			||||||
 | 
					            // log(state.toString());
 | 
				
			||||||
 | 
					            log(state.data.toMap().toString());
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          child: const Text('DEBUG'),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SignUpForm extends StatelessWidget {
 | 
				
			||||||
 | 
					  const SignUpForm({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return BlocListener<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					      listener: (context, state) {
 | 
				
			||||||
 | 
					        if (state.status.isSubmissionSuccess) {
 | 
				
			||||||
 | 
					          Navigator.of(context).pop();
 | 
				
			||||||
 | 
					        } else if (state.status.isSubmissionFailure) {
 | 
				
			||||||
 | 
					          ScaffoldMessenger.of(context)
 | 
				
			||||||
 | 
					            ..hideCurrentSnackBar()
 | 
				
			||||||
 | 
					            ..showSnackBar(
 | 
				
			||||||
 | 
					              SnackBar(content: Text(state.errorMessage ?? 'Sign Up Failure')),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      child: SizedBox(
 | 
				
			||||||
 | 
					        height: MediaQuery.of(context).size.height,
 | 
				
			||||||
 | 
					        child: Align(
 | 
				
			||||||
 | 
					          alignment: const Alignment(0, -1 / 3),
 | 
				
			||||||
 | 
					          child: Column(
 | 
				
			||||||
 | 
					            mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					            children: [
 | 
				
			||||||
 | 
					              _NameInput(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _PhoneInput(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _CheckIsProInput(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              BlocBuilder<SignUpCubit, SignUpState>(
 | 
				
			||||||
 | 
					                builder: (context, state) {
 | 
				
			||||||
 | 
					                  if (state.data.valueOf<bool>(formFieldPro)) {
 | 
				
			||||||
 | 
					                    return Column(children: [
 | 
				
			||||||
 | 
					                      _SirenInput(),
 | 
				
			||||||
 | 
					                      const SizedBox(height: 8),
 | 
				
			||||||
 | 
					                      _IbanInput(),
 | 
				
			||||||
 | 
					                      const SizedBox(height: 8),
 | 
				
			||||||
 | 
					                    ]);
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                  return const SizedBox.shrink();
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              _EmailInput(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _PasswordInput(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _ConfirmPasswordInput(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _SignUpButton(),
 | 
				
			||||||
 | 
					              const SizedBox(height: 8),
 | 
				
			||||||
 | 
					              _DebugButton(),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
name: example_router
 | 
					name: authentication_bloc_example
 | 
				
			||||||
description: A new Flutter project.
 | 
					description: A new Flutter project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The following line prevents the package from being accidentally published to
 | 
					# The following line prevents the package from being accidentally published to
 | 
				
			||||||
@ -15,10 +15,10 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 | 
				
			|||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
 | 
					# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
 | 
				
			||||||
# Read more about iOS versioning at
 | 
					# Read more about iOS versioning at
 | 
				
			||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
					# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
				
			||||||
version: 1.0.0+1
 | 
					version: 1.0.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  sdk: ">=2.17.6 <3.0.0"
 | 
					  sdk: ">=2.16.2 <3.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Dependencies specify other packages that your package needs in order to work.
 | 
					# Dependencies specify other packages that your package needs in order to work.
 | 
				
			||||||
# To automatically upgrade your package dependencies to the latest versions
 | 
					# To automatically upgrade your package dependencies to the latest versions
 | 
				
			||||||
@ -29,30 +29,22 @@ environment:
 | 
				
			|||||||
dependencies:
 | 
					dependencies:
 | 
				
			||||||
  flutter:
 | 
					  flutter:
 | 
				
			||||||
    sdk: flutter
 | 
					    sdk: flutter
 | 
				
			||||||
 | 
					 | 
				
			||||||
  go_router: ^5.1.5
 | 
					 | 
				
			||||||
  firebase_core: ^2.1.1
 | 
					 | 
				
			||||||
  flutter_bloc: ^8.1.1
 | 
					 | 
				
			||||||
  get_it: ^7.2.0
 | 
					 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					  firebase_core: ^1.14.1
 | 
				
			||||||
 | 
					  flutter_bloc: ^8.0.1
 | 
				
			||||||
  wyatt_authentication_bloc:
 | 
					  wyatt_authentication_bloc:
 | 
				
			||||||
    path: "../"
 | 
					    path: "../"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  wyatt_form_bloc:
 | 
					  wyatt_form_bloc:
 | 
				
			||||||
    hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
 | 
					    git:
 | 
				
			||||||
    version: 0.1.0+1
 | 
					      url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
 | 
				
			||||||
 | 
					      ref: wyatt_form_bloc-v0.1.0+1
 | 
				
			||||||
  wyatt_architecture:
 | 
					      path: packages/wyatt_form_bloc
 | 
				
			||||||
    hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
 | 
					 | 
				
			||||||
    version: 0.0.2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  wyatt_type_utils:
 | 
					 | 
				
			||||||
    hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
 | 
					 | 
				
			||||||
    version: 0.0.3+1
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # The following adds the Cupertino Icons font to your application.
 | 
					  # The following adds the Cupertino Icons font to your application.
 | 
				
			||||||
  # Use with the CupertinoIcons class for iOS style icons.
 | 
					  # Use with the CupertinoIcons class for iOS style icons.
 | 
				
			||||||
  cupertino_icons: ^1.0.5
 | 
					  cupertino_icons: ^1.0.4
 | 
				
			||||||
 | 
					  cloud_firestore: ^3.1.12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev_dependencies:
 | 
					dev_dependencies:
 | 
				
			||||||
  flutter_test:
 | 
					  flutter_test:
 | 
				
			||||||
@ -68,7 +60,7 @@ dev_dependencies:
 | 
				
			|||||||
# For information on the generic Dart part of this file, see the
 | 
					# For information on the generic Dart part of this file, see the
 | 
				
			||||||
# following page: https://dart.dev/tools/pub/pubspec
 | 
					# following page: https://dart.dev/tools/pub/pubspec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The following section is specific to Flutter packages.
 | 
					# The following section is specific to Flutter.
 | 
				
			||||||
flutter:
 | 
					flutter:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # The following line ensures that the Material Icons font is
 | 
					  # The following line ensures that the Material Icons font is
 | 
				
			||||||
@ -82,7 +74,7 @@ flutter:
 | 
				
			|||||||
  #   - images/a_dot_ham.jpeg
 | 
					  #   - images/a_dot_ham.jpeg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # An image asset can refer to one or more resolution-specific "variants", see
 | 
					  # An image asset can refer to one or more resolution-specific "variants", see
 | 
				
			||||||
  # https://flutter.dev/assets-and-images/#resolution-aware
 | 
					  # https://flutter.dev/assets-and-images/#resolution-aware.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # For details regarding adding assets from package dependencies, see
 | 
					  # For details regarding adding assets from package dependencies, see
 | 
				
			||||||
  # https://flutter.dev/assets-and-images/#from-packages
 | 
					  # https://flutter.dev/assets-and-images/#from-packages
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										49
									
								
								packages/wyatt_authentication_bloc/example_router/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					# Miscellaneous
 | 
				
			||||||
 | 
					*.class
 | 
				
			||||||
 | 
					*.log
 | 
				
			||||||
 | 
					*.pyc
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					.atom/
 | 
				
			||||||
 | 
					.buildlog/
 | 
				
			||||||
 | 
					.history
 | 
				
			||||||
 | 
					.svn/
 | 
				
			||||||
 | 
					migrate_working_dir/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# IntelliJ related
 | 
				
			||||||
 | 
					*.iml
 | 
				
			||||||
 | 
					*.ipr
 | 
				
			||||||
 | 
					*.iws
 | 
				
			||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The .vscode folder contains launch configuration and tasks you configure in
 | 
				
			||||||
 | 
					# VS Code which you may wish to be included in version control, so this line
 | 
				
			||||||
 | 
					# is commented out by default.
 | 
				
			||||||
 | 
					#.vscode/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Flutter/Dart/Pub related
 | 
				
			||||||
 | 
					**/doc/api/
 | 
				
			||||||
 | 
					**/ios/Flutter/.last_build_id
 | 
				
			||||||
 | 
					.dart_tool/
 | 
				
			||||||
 | 
					.flutter-plugins
 | 
				
			||||||
 | 
					.flutter-plugins-dependencies
 | 
				
			||||||
 | 
					.packages
 | 
				
			||||||
 | 
					.pub-cache/
 | 
				
			||||||
 | 
					.pub/
 | 
				
			||||||
 | 
					/build/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Web related
 | 
				
			||||||
 | 
					lib/generated_plugin_registrant.dart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Symbolication related
 | 
				
			||||||
 | 
					app.*.symbols
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Obfuscation related
 | 
				
			||||||
 | 
					app.*.map.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Android Studio will place build artifacts here
 | 
				
			||||||
 | 
					/android/app/debug
 | 
				
			||||||
 | 
					/android/app/profile
 | 
				
			||||||
 | 
					/android/app/release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					firebase_options.dart
 | 
				
			||||||
							
								
								
									
										30
									
								
								packages/wyatt_authentication_bloc/example_router/.metadata
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					# This file tracks properties of this Flutter project.
 | 
				
			||||||
 | 
					# Used by Flutter tool to assess capabilities and perform upgrades etc.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This file should be version controlled.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					version:
 | 
				
			||||||
 | 
					  revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
				
			||||||
 | 
					  channel: stable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project_type: app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Tracks metadata for the flutter migrate command
 | 
				
			||||||
 | 
					migration:
 | 
				
			||||||
 | 
					  platforms:
 | 
				
			||||||
 | 
					    - platform: root
 | 
				
			||||||
 | 
					      create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
				
			||||||
 | 
					      base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
				
			||||||
 | 
					    - platform: ios
 | 
				
			||||||
 | 
					      create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
				
			||||||
 | 
					      base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # User provided section
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # List of Local paths (relative to this file) that should be
 | 
				
			||||||
 | 
					  # ignored by the migrate tool.
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # Files that are not part of the templates will be ignored by default.
 | 
				
			||||||
 | 
					  unmanaged_files:
 | 
				
			||||||
 | 
					    - 'lib/main.dart'
 | 
				
			||||||
 | 
					    - 'ios/Runner.xcodeproj/project.pbxproj'
 | 
				
			||||||
							
								
								
									
										16
									
								
								packages/wyatt_authentication_bloc/example_router/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					# example_router
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A new Flutter project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Getting Started
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This project is a starting point for a Flutter application.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A few resources to get you started if this is your first Flutter project:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
 | 
				
			||||||
 | 
					- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For help getting started with Flutter development, view the
 | 
				
			||||||
 | 
					[online documentation](https://docs.flutter.dev/), which offers tutorials,
 | 
				
			||||||
 | 
					samples, guidance on mobile development, and a full API reference.
 | 
				
			||||||
@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					# This file configures the analyzer, which statically analyzes Dart code to
 | 
				
			||||||
 | 
					# check for errors, warnings, and lints.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
 | 
				
			||||||
 | 
					# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
 | 
				
			||||||
 | 
					# invoked from the command line by running `flutter analyze`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The following line activates a set of recommended lints for Flutter apps,
 | 
				
			||||||
 | 
					# packages, and plugins designed to encourage good coding practices.
 | 
				
			||||||
 | 
					include: package:flutter_lints/flutter.yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					linter:
 | 
				
			||||||
 | 
					  # The lint rules applied to this project can be customized in the
 | 
				
			||||||
 | 
					  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
 | 
				
			||||||
 | 
					  # included above or to enable additional rules. A list of all available lints
 | 
				
			||||||
 | 
					  # and their documentation is published at
 | 
				
			||||||
 | 
					  # https://dart-lang.github.io/linter/lints/index.html.
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # Instead of disabling a lint rule for the entire project in the
 | 
				
			||||||
 | 
					  # section below, it can also be suppressed for a single line of code
 | 
				
			||||||
 | 
					  # or a specific dart file by using the `// ignore: name_of_lint` and
 | 
				
			||||||
 | 
					  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
 | 
				
			||||||
 | 
					  # producing the lint.
 | 
				
			||||||
 | 
					  rules:
 | 
				
			||||||
 | 
					    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
 | 
				
			||||||
 | 
					    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Additional information about this file can be found at
 | 
				
			||||||
 | 
					# https://dart.dev/guides/language/analysis-options
 | 
				
			||||||
							
								
								
									
										13
									
								
								packages/wyatt_authentication_bloc/example_router/android/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					gradle-wrapper.jar
 | 
				
			||||||
 | 
					/.gradle
 | 
				
			||||||
 | 
					/captures/
 | 
				
			||||||
 | 
					/gradlew
 | 
				
			||||||
 | 
					/gradlew.bat
 | 
				
			||||||
 | 
					/local.properties
 | 
				
			||||||
 | 
					GeneratedPluginRegistrant.java
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Remember to never publicly share your keystore.
 | 
				
			||||||
 | 
					# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
 | 
				
			||||||
 | 
					key.properties
 | 
				
			||||||
 | 
					**/*.keystore
 | 
				
			||||||
 | 
					**/*.jks
 | 
				
			||||||
@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					def localProperties = new Properties()
 | 
				
			||||||
 | 
					def localPropertiesFile = rootProject.file('local.properties')
 | 
				
			||||||
 | 
					if (localPropertiesFile.exists()) {
 | 
				
			||||||
 | 
					    localPropertiesFile.withReader('UTF-8') { reader ->
 | 
				
			||||||
 | 
					        localProperties.load(reader)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def flutterRoot = localProperties.getProperty('flutter.sdk')
 | 
				
			||||||
 | 
					if (flutterRoot == null) {
 | 
				
			||||||
 | 
					    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
 | 
				
			||||||
 | 
					if (flutterVersionCode == null) {
 | 
				
			||||||
 | 
					    flutterVersionCode = '1'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def flutterVersionName = localProperties.getProperty('flutter.versionName')
 | 
				
			||||||
 | 
					if (flutterVersionName == null) {
 | 
				
			||||||
 | 
					    flutterVersionName = '1.0'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					apply plugin: 'com.android.application'
 | 
				
			||||||
 | 
					// START: FlutterFire Configuration
 | 
				
			||||||
 | 
					apply plugin: 'com.google.gms.google-services'
 | 
				
			||||||
 | 
					// END: FlutterFire Configuration
 | 
				
			||||||
 | 
					apply plugin: 'kotlin-android'
 | 
				
			||||||
 | 
					apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					android {
 | 
				
			||||||
 | 
					    compileSdkVersion flutter.compileSdkVersion
 | 
				
			||||||
 | 
					    ndkVersion flutter.ndkVersion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    compileOptions {
 | 
				
			||||||
 | 
					        sourceCompatibility JavaVersion.VERSION_1_8
 | 
				
			||||||
 | 
					        targetCompatibility JavaVersion.VERSION_1_8
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    kotlinOptions {
 | 
				
			||||||
 | 
					        jvmTarget = '1.8'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sourceSets {
 | 
				
			||||||
 | 
					        main.java.srcDirs += 'src/main/kotlin'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    defaultConfig {
 | 
				
			||||||
 | 
					        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
 | 
				
			||||||
 | 
					        applicationId "com.example.example_router"
 | 
				
			||||||
 | 
					        // You can update the following values to match your application needs.
 | 
				
			||||||
 | 
					        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
 | 
				
			||||||
 | 
					        minSdkVersion 21
 | 
				
			||||||
 | 
					        targetSdkVersion flutter.targetSdkVersion
 | 
				
			||||||
 | 
					        versionCode flutterVersionCode.toInteger()
 | 
				
			||||||
 | 
					        versionName flutterVersionName
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    buildTypes {
 | 
				
			||||||
 | 
					        release {
 | 
				
			||||||
 | 
					            // TODO: Add your own signing config for the release build.
 | 
				
			||||||
 | 
					            // Signing with the debug keys for now, so `flutter run --release` works.
 | 
				
			||||||
 | 
					            signingConfig signingConfigs.debug
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					flutter {
 | 
				
			||||||
 | 
					    source '../..'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dependencies {
 | 
				
			||||||
 | 
					    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    package="com.example.example_router">
 | 
				
			||||||
 | 
					    <!-- The INTERNET permission is required for development. Specifically,
 | 
				
			||||||
 | 
					         the Flutter tool needs it to communicate with the running application
 | 
				
			||||||
 | 
					         to allow setting breakpoints, to provide hot reload, etc.
 | 
				
			||||||
 | 
					    -->
 | 
				
			||||||
 | 
					    <uses-permission android:name="android.permission.INTERNET"/>
 | 
				
			||||||
 | 
					</manifest>
 | 
				
			||||||
@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    package="com.example.example_router">
 | 
				
			||||||
 | 
					   <application
 | 
				
			||||||
 | 
					        android:label="example_router"
 | 
				
			||||||
 | 
					        android:name="${applicationName}"
 | 
				
			||||||
 | 
					        android:icon="@mipmap/ic_launcher">
 | 
				
			||||||
 | 
					        <activity
 | 
				
			||||||
 | 
					            android:name=".MainActivity"
 | 
				
			||||||
 | 
					            android:exported="true"
 | 
				
			||||||
 | 
					            android:launchMode="singleTop"
 | 
				
			||||||
 | 
					            android:theme="@style/LaunchTheme"
 | 
				
			||||||
 | 
					            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
 | 
				
			||||||
 | 
					            android:hardwareAccelerated="true"
 | 
				
			||||||
 | 
					            android:windowSoftInputMode="adjustResize">
 | 
				
			||||||
 | 
					            <!-- Specifies an Android theme to apply to this Activity as soon as
 | 
				
			||||||
 | 
					                 the Android process has started. This theme is visible to the user
 | 
				
			||||||
 | 
					                 while the Flutter UI initializes. After that, this theme continues
 | 
				
			||||||
 | 
					                 to determine the Window background behind the Flutter UI. -->
 | 
				
			||||||
 | 
					            <meta-data
 | 
				
			||||||
 | 
					              android:name="io.flutter.embedding.android.NormalTheme"
 | 
				
			||||||
 | 
					              android:resource="@style/NormalTheme"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            <intent-filter>
 | 
				
			||||||
 | 
					                <action android:name="android.intent.action.MAIN"/>
 | 
				
			||||||
 | 
					                <category android:name="android.intent.category.LAUNCHER"/>
 | 
				
			||||||
 | 
					            </intent-filter>
 | 
				
			||||||
 | 
					        </activity>
 | 
				
			||||||
 | 
					        <!-- Don't delete the meta-data below.
 | 
				
			||||||
 | 
					             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
 | 
				
			||||||
 | 
					        <meta-data
 | 
				
			||||||
 | 
					            android:name="flutterEmbedding"
 | 
				
			||||||
 | 
					            android:value="2" />
 | 
				
			||||||
 | 
					    </application>
 | 
				
			||||||
 | 
					</manifest>
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<!-- Modify this file to customize your launch splash screen -->
 | 
				
			||||||
 | 
					<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 | 
				
			||||||
 | 
					    <item android:drawable="?android:colorBackground" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- You can insert your own image assets here -->
 | 
				
			||||||
 | 
					    <!-- <item>
 | 
				
			||||||
 | 
					        <bitmap
 | 
				
			||||||
 | 
					            android:gravity="center"
 | 
				
			||||||
 | 
					            android:src="@mipmap/launch_image" />
 | 
				
			||||||
 | 
					    </item> -->
 | 
				
			||||||
 | 
					</layer-list>
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<!-- Modify this file to customize your launch splash screen -->
 | 
				
			||||||
 | 
					<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 | 
				
			||||||
 | 
					    <item android:drawable="@android:color/white" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- You can insert your own image assets here -->
 | 
				
			||||||
 | 
					    <!-- <item>
 | 
				
			||||||
 | 
					        <bitmap
 | 
				
			||||||
 | 
					            android:gravity="center"
 | 
				
			||||||
 | 
					            android:src="@mipmap/launch_image" />
 | 
				
			||||||
 | 
					    </item> -->
 | 
				
			||||||
 | 
					</layer-list>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 544 B  | 
| 
		 After Width: | Height: | Size: 442 B  | 
| 
		 After Width: | Height: | Size: 721 B  | 
| 
		 After Width: | Height: | Size: 1.0 KiB  | 
| 
		 After Width: | Height: | Size: 1.4 KiB  | 
@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<resources>
 | 
				
			||||||
 | 
					    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
 | 
				
			||||||
 | 
					    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
 | 
				
			||||||
 | 
					        <!-- Show a splash screen on the activity. Automatically removed when
 | 
				
			||||||
 | 
					             the Flutter engine draws its first frame -->
 | 
				
			||||||
 | 
					        <item name="android:windowBackground">@drawable/launch_background</item>
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					    <!-- Theme applied to the Android Window as soon as the process has started.
 | 
				
			||||||
 | 
					         This theme determines the color of the Android Window while your
 | 
				
			||||||
 | 
					         Flutter UI initializes, as well as behind your Flutter UI while its
 | 
				
			||||||
 | 
					         running.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					         This Theme is only used starting with V2 of Flutter's Android embedding. -->
 | 
				
			||||||
 | 
					    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
 | 
				
			||||||
 | 
					        <item name="android:windowBackground">?android:colorBackground</item>
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</resources>
 | 
				
			||||||
@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<resources>
 | 
				
			||||||
 | 
					    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
 | 
				
			||||||
 | 
					    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
 | 
				
			||||||
 | 
					        <!-- Show a splash screen on the activity. Automatically removed when
 | 
				
			||||||
 | 
					             the Flutter engine draws its first frame -->
 | 
				
			||||||
 | 
					        <item name="android:windowBackground">@drawable/launch_background</item>
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					    <!-- Theme applied to the Android Window as soon as the process has started.
 | 
				
			||||||
 | 
					         This theme determines the color of the Android Window while your
 | 
				
			||||||
 | 
					         Flutter UI initializes, as well as behind your Flutter UI while its
 | 
				
			||||||
 | 
					         running.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					         This Theme is only used starting with V2 of Flutter's Android embedding. -->
 | 
				
			||||||
 | 
					    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
 | 
				
			||||||
 | 
					        <item name="android:windowBackground">?android:colorBackground</item>
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</resources>
 | 
				
			||||||
@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    package="com.example.example_router">
 | 
				
			||||||
 | 
					    <!-- The INTERNET permission is required for development. Specifically,
 | 
				
			||||||
 | 
					         the Flutter tool needs it to communicate with the running application
 | 
				
			||||||
 | 
					         to allow setting breakpoints, to provide hot reload, etc.
 | 
				
			||||||
 | 
					    -->
 | 
				
			||||||
 | 
					    <uses-permission android:name="android.permission.INTERNET"/>
 | 
				
			||||||
 | 
					</manifest>
 | 
				
			||||||
@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					buildscript {
 | 
				
			||||||
 | 
					    ext.kotlin_version = '1.6.10'
 | 
				
			||||||
 | 
					    repositories {
 | 
				
			||||||
 | 
					        google()
 | 
				
			||||||
 | 
					        mavenCentral()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies {
 | 
				
			||||||
 | 
					        classpath 'com.android.tools.build:gradle:7.1.2'
 | 
				
			||||||
 | 
					        // START: FlutterFire Configuration
 | 
				
			||||||
 | 
					        classpath 'com.google.gms:google-services:4.3.10'
 | 
				
			||||||
 | 
					        // END: FlutterFire Configuration
 | 
				
			||||||
 | 
					        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					allprojects {
 | 
				
			||||||
 | 
					    repositories {
 | 
				
			||||||
 | 
					        google()
 | 
				
			||||||
 | 
					        mavenCentral()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rootProject.buildDir = '../build'
 | 
				
			||||||
 | 
					subprojects {
 | 
				
			||||||
 | 
					    project.buildDir = "${rootProject.buildDir}/${project.name}"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					subprojects {
 | 
				
			||||||
 | 
					    project.evaluationDependsOn(':app')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					task clean(type: Delete) {
 | 
				
			||||||
 | 
					    delete rootProject.buildDir
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					org.gradle.jvmargs=-Xmx1536M
 | 
				
			||||||
 | 
					android.useAndroidX=true
 | 
				
			||||||
 | 
					android.enableJetifier=true
 | 
				
			||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					#Fri Jun 23 08:50:38 CEST 2017
 | 
				
			||||||
 | 
					distributionBase=GRADLE_USER_HOME
 | 
				
			||||||
 | 
					distributionPath=wrapper/dists
 | 
				
			||||||
 | 
					zipStoreBase=GRADLE_USER_HOME
 | 
				
			||||||
 | 
					zipStorePath=wrapper/dists
 | 
				
			||||||
 | 
					distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
 | 
				
			||||||
@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					include ':app'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
 | 
				
			||||||
 | 
					def properties = new Properties()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					assert localPropertiesFile.exists()
 | 
				
			||||||
 | 
					localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def flutterSdkPath = properties.getProperty("flutter.sdk")
 | 
				
			||||||
 | 
					assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
 | 
				
			||||||
 | 
					apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB  | 
| 
		 Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 564 B  | 
| 
		 Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB  | 
| 
		 Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB  | 
| 
		 Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB  | 
| 
		 Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB  | 
| 
		 Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB  | 
| 
		 Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB  | 
| 
		 Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB  | 
| 
		 Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB  | 
| 
		 Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB  | 
| 
		 Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB  | 
| 
		 Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB  | 
| 
		 Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB  | 
| 
		 Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB  | 
| 
		 Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B  | 
| 
		 Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B  | 
| 
		 Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B  |