Compare commits
	
		
			2 Commits
		
	
	
		
			6eb40de72c
			...
			31ad460757
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 31ad460757 | |||
| 4fd2a2a16c | 
@ -1 +1,4 @@
 | 
				
			|||||||
include: package:wyatt_analysis/analysis_options.flutter.yaml
 | 
					include: package:wyatt_analysis/analysis_options.flutter.yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					analyzer:
 | 
				
			||||||
 | 
					  exclude: "!example/**"
 | 
				
			||||||
@ -8,6 +8,7 @@
 | 
				
			|||||||
.buildlog/
 | 
					.buildlog/
 | 
				
			||||||
.history
 | 
					.history
 | 
				
			||||||
.svn/
 | 
					.svn/
 | 
				
			||||||
 | 
					migrate_working_dir/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# IntelliJ related
 | 
					# IntelliJ related
 | 
				
			||||||
*.iml
 | 
					*.iml
 | 
				
			||||||
@ -45,4 +46,4 @@ app.*.map.json
 | 
				
			|||||||
/android/app/profile
 | 
					/android/app/profile
 | 
				
			||||||
/android/app/release
 | 
					/android/app/release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lib/firebase_options.dart
 | 
					firebase_options.dart
 | 
				
			||||||
@ -1,10 +1,30 @@
 | 
				
			|||||||
# 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 and should not be manually edited.
 | 
					# This file should be version controlled.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
version:
 | 
					version:
 | 
				
			||||||
  revision: 5464c5bac742001448fe4fc0597be939379f88ea
 | 
					  revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
 | 
				
			||||||
  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'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +0,0 @@
 | 
				
			|||||||
## 1.0.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 - Update a dependency to the latest release.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
# authentication_bloc_example
 | 
					# example_router
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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://flutter.dev/docs/get-started/codelab)
 | 
					- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
 | 
				
			||||||
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
 | 
					- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For help getting started with Flutter, view our
 | 
					For help getting started with Flutter development, view the
 | 
				
			||||||
[online documentation](https://flutter.dev/docs), which offers tutorials,
 | 
					[online documentation](https://docs.flutter.dev/), which offers tutorials,
 | 
				
			||||||
samples, guidance on mobile development, and a full API reference.
 | 
					samples, guidance on mobile development, and a full API reference.
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@ 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
 | 
				
			||||||
@ -46,7 +47,9 @@ 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.authentication_bloc_example"
 | 
					        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
 | 
					        minSdkVersion 21
 | 
				
			||||||
        targetSdkVersion flutter.targetSdkVersion
 | 
					        targetSdkVersion flutter.targetSdkVersion
 | 
				
			||||||
        versionCode flutterVersionCode.toInteger()
 | 
					        versionCode flutterVersionCode.toInteger()
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +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.authentication_bloc_example">
 | 
					    package="com.example.example_router">
 | 
				
			||||||
    <!-- Flutter needs it to communicate with the running application
 | 
					    <!-- 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.
 | 
					         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.authentication_bloc_example">
 | 
					    package="com.example.example_router">
 | 
				
			||||||
   <application
 | 
					   <application
 | 
				
			||||||
        android:label="authentication_bloc_example"
 | 
					        android:label="example_router"
 | 
				
			||||||
        android:name="${applicationName}"
 | 
					        android:name="${applicationName}"
 | 
				
			||||||
        android:icon="@mipmap/ic_launcher">
 | 
					        android:icon="@mipmap/ic_launcher">
 | 
				
			||||||
        <activity
 | 
					        <activity
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +0,0 @@
 | 
				
			|||||||
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
 | 
				
			||||||
             Flutter draws its first frame -->
 | 
					             the Flutter engine 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
 | 
				
			||||||
             Flutter draws its first frame -->
 | 
					             the Flutter engine 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,6 +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.authentication_bloc_example">
 | 
					    package="com.example.example_router">
 | 
				
			||||||
    <!-- Flutter needs it to communicate with the running application
 | 
					    <!-- 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.
 | 
					         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:4.1.0'
 | 
					        classpath 'com.android.tools.build:gradle:7.1.2'
 | 
				
			||||||
        // 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-6.7-all.zip
 | 
					distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
 | 
				
			||||||
 | 
				
			|||||||
| 
		 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  | 
@ -1,182 +0,0 @@
 | 
				
			|||||||
// 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(),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,44 +0,0 @@
 | 
				
			|||||||
// 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());
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,24 +0,0 @@
 | 
				
			|||||||
// 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';
 | 
					 | 
				
			||||||
@ -1,44 +0,0 @@
 | 
				
			|||||||
// 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(),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,92 +0,0 @@
 | 
				
			|||||||
// 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()],
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,65 +0,0 @@
 | 
				
			|||||||
// 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();
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,37 +0,0 @@
 | 
				
			|||||||
// 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,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,53 +0,0 @@
 | 
				
			|||||||
// 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'),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,58 +0,0 @@
 | 
				
			|||||||
// 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),
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,37 +0,0 @@
 | 
				
			|||||||
// 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(),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,214 +0,0 @@
 | 
				
			|||||||
// 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,35 +1,6 @@
 | 
				
			|||||||
// Copyright (C) 2022 WYATT GROUP
 | 
					import 'package:example_router/bootstrap.dart';
 | 
				
			||||||
// Please see the AUTHORS file for details.
 | 
					import 'package:example_router/presentation/features/app/app.dart';
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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';
 | 
					void main() {
 | 
				
			||||||
import 'package:authentication_bloc_example/app/bloc_observer.dart';
 | 
					  bootstrap(App.new);
 | 
				
			||||||
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(),
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,52 +0,0 @@
 | 
				
			|||||||
// 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)';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
// -----
 | 
					// -----
 | 
				
			||||||
// File: sign_in_form.dart
 | 
					// File: sign_in_form.dart
 | 
				
			||||||
// Created Date: 19/08/2022 15:24:37
 | 
					// Created Date: 19/08/2022 15:24:37
 | 
				
			||||||
// Last Modified: Fri Nov 11 2022
 | 
					// Last Modified: Tue Nov 15 2022
 | 
				
			||||||
// -----
 | 
					// -----
 | 
				
			||||||
// Copyright (c) 2022
 | 
					// Copyright (c) 2022
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,8 +59,24 @@ class _SignInButton extends StatelessWidget {
 | 
				
			|||||||
        return status.isSubmissionInProgress
 | 
					        return status.isSubmissionInProgress
 | 
				
			||||||
            ? const CircularProgressIndicator()
 | 
					            ? const CircularProgressIndicator()
 | 
				
			||||||
            : ElevatedButton(
 | 
					            : ElevatedButton(
 | 
				
			||||||
                onPressed: status.isValidated ? () => cubit.submit() : null,
 | 
					                onPressed: status.isValidated ? () => cubit.signInWithEmailAndPassword() : null,
 | 
				
			||||||
                child: const Text('Sign in'),
 | 
					                child: const Text('Sign in with credentials'),
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _SignInAnonymouslyButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return SubmitBuilder<SignInCubit<int>>(
 | 
				
			||||||
 | 
					      builder: ((context, cubit, status) {
 | 
				
			||||||
 | 
					        return status.isSubmissionInProgress
 | 
				
			||||||
 | 
					            ? const CircularProgressIndicator()
 | 
				
			||||||
 | 
					            : ElevatedButton(
 | 
				
			||||||
 | 
					                onPressed: () => cubit.signInAnonymously(),
 | 
				
			||||||
 | 
					                child: const Text('Sign in anonymously'),
 | 
				
			||||||
              );
 | 
					              );
 | 
				
			||||||
      }),
 | 
					      }),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
@ -80,12 +96,15 @@ class SignInForm extends StatelessWidget {
 | 
				
			|||||||
        ),
 | 
					        ),
 | 
				
			||||||
      child: SingleChildScrollView(
 | 
					      child: SingleChildScrollView(
 | 
				
			||||||
        child: Column(
 | 
					        child: Column(
 | 
				
			||||||
 | 
					          crossAxisAlignment: CrossAxisAlignment.center,
 | 
				
			||||||
          children: [
 | 
					          children: [
 | 
				
			||||||
            _EmailInput(),
 | 
					            _EmailInput(),
 | 
				
			||||||
            const SizedBox(height: 8),
 | 
					            const SizedBox(height: 8),
 | 
				
			||||||
            _PasswordInput(),
 | 
					            _PasswordInput(),
 | 
				
			||||||
            const SizedBox(height: 16),
 | 
					            const SizedBox(height: 16),
 | 
				
			||||||
            _SignInButton(),
 | 
					            _SignInButton(),
 | 
				
			||||||
 | 
					            const SizedBox(height: 16),
 | 
				
			||||||
 | 
					            _SignInAnonymouslyButton(),
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
@ -1,39 +0,0 @@
 | 
				
			|||||||
// 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(),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,325 +0,0 @@
 | 
				
			|||||||
// 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: authentication_bloc_example
 | 
					name: example_router
 | 
				
			||||||
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.1
 | 
					version: 1.0.0+1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  sdk: ">=2.16.2 <3.0.0"
 | 
					  sdk: ">=2.17.6 <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
 | 
				
			||||||
@ -30,21 +30,29 @@ dependencies:
 | 
				
			|||||||
  flutter:
 | 
					  flutter:
 | 
				
			||||||
    sdk: flutter
 | 
					    sdk: flutter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  firebase_core: ^1.14.1
 | 
					  go_router: ^5.1.5
 | 
				
			||||||
  flutter_bloc: ^8.0.1
 | 
					  firebase_core: ^2.1.1
 | 
				
			||||||
 | 
					  flutter_bloc: ^8.1.1
 | 
				
			||||||
 | 
					  get_it: ^7.2.0
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  wyatt_authentication_bloc:
 | 
					  wyatt_authentication_bloc:
 | 
				
			||||||
    path: "../"
 | 
					    path: "../"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  wyatt_form_bloc:
 | 
					  wyatt_form_bloc:
 | 
				
			||||||
    git:
 | 
					    hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
 | 
				
			||||||
      url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
 | 
					    version: 0.1.0+1
 | 
				
			||||||
      ref: wyatt_form_bloc-v0.1.0+1
 | 
					
 | 
				
			||||||
      path: packages/wyatt_form_bloc
 | 
					  wyatt_architecture:
 | 
				
			||||||
 | 
					    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.4
 | 
					  cupertino_icons: ^1.0.5
 | 
				
			||||||
  cloud_firestore: ^3.1.12
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev_dependencies:
 | 
					dev_dependencies:
 | 
				
			||||||
  flutter_test:
 | 
					  flutter_test:
 | 
				
			||||||
@ -60,7 +68,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.
 | 
					# The following section is specific to Flutter packages.
 | 
				
			||||||
flutter:
 | 
					flutter:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # The following line ensures that the Material Icons font is
 | 
					  # The following line ensures that the Material Icons font is
 | 
				
			||||||
@ -74,7 +82,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
 | 
				
			||||||
 | 
				
			|||||||
@ -1,49 +0,0 @@
 | 
				
			|||||||
# 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
 | 
					 | 
				
			||||||
@ -1,30 +0,0 @@
 | 
				
			|||||||
# 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'
 | 
					 | 
				
			||||||
@ -1,16 +0,0 @@
 | 
				
			|||||||
# 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.
 | 
					 | 
				
			||||||
@ -1,29 +0,0 @@
 | 
				
			|||||||
# 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
 | 
					 | 
				
			||||||
@ -1,13 +0,0 @@
 | 
				
			|||||||
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
 | 
					 | 
				
			||||||
@ -1,74 +0,0 @@
 | 
				
			|||||||
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"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,8 +0,0 @@
 | 
				
			|||||||
<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>
 | 
					 | 
				
			||||||
@ -1,34 +0,0 @@
 | 
				
			|||||||
<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>
 | 
					 | 
				
			||||||
@ -1,12 +0,0 @@
 | 
				
			|||||||
<?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>
 | 
					 | 
				
			||||||
@ -1,12 +0,0 @@
 | 
				
			|||||||
<?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>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 544 B  | 
| 
		 Before Width: | Height: | Size: 442 B  | 
| 
		 Before Width: | Height: | Size: 721 B  | 
| 
		 Before Width: | Height: | Size: 1.0 KiB  |