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