From 0bc2aa35125b6106692377c323ee37d80d39df4d Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Wed, 9 Nov 2022 01:44:52 -0500 Subject: [PATCH 01/18] feat: update dependencies --- .../wyatt_authentication_bloc/pubspec.yaml | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/wyatt_authentication_bloc/pubspec.yaml b/packages/wyatt_authentication_bloc/pubspec.yaml index a64ff634..a70feec4 100644 --- a/packages/wyatt_authentication_bloc/pubspec.yaml +++ b/packages/wyatt_authentication_bloc/pubspec.yaml @@ -3,6 +3,8 @@ description: Authentication BLoC for Flutter repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_authentication_bloc version: 0.2.1+4 +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + environment: sdk: ">=2.17.0 <3.0.0" flutter: ">=1.17.0" @@ -12,9 +14,9 @@ dependencies: sdk: flutter crypto: ^3.0.2 - flutter_bloc: ^8.0.1 - equatable: ^2.0.3 - firebase_auth: ^3.3.17 + flutter_bloc: ^8.1.1 + equatable: ^2.0.5 + firebase_auth: ^4.1.1 google_sign_in: ^5.3.0 flutter_facebook_auth: ^4.3.0 sign_in_with_apple: ^3.3.0 @@ -25,12 +27,24 @@ dependencies: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages ref: wyatt_form_bloc-v0.0.6 path: packages/wyatt_form_bloc + + wyatt_architecture: + git: + url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages + ref: wyatt_architecture-v0.0.2-dev.0 + path: packages/wyatt_architecture + + wyatt_type_utils: + git: + url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages + ref: wyatt_type_utils-v0.0.3+1 + path: packages/wyatt_type_utils dev_dependencies: flutter_test: sdk: flutter - bloc_test: ^9.0.3 + bloc_test: ^9.1.0 mocktail: ^0.3.0 wyatt_analysis: From 3972c56e5598d55b15a66de99a5241128a6b2ec0 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Wed, 9 Nov 2022 01:46:28 -0500 Subject: [PATCH 02/18] feat: rewrite authentication repository --- .../authentication_repository_firebase.dart | 338 ------------------ .../authentication_repository_impl.dart | 156 ++++++++ .../src/data/repositories/repositories.dart | 17 + .../authentication_repository.dart | 130 +------ .../src/domain/repositories/repositories.dart | 17 + 5 files changed, 209 insertions(+), 449 deletions(-) delete mode 100644 packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart deleted file mode 100644 index 0cf6d5dc..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'dart:async'; - -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; -import 'package:google_sign_in/google_sign_in.dart'; -import 'package:sign_in_with_apple/sign_in_with_apple.dart'; -import 'package:twitter_login/twitter_login.dart'; -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions_firebase.dart'; -import 'package:wyatt_authentication_bloc/src/core/extensions/firebase_auth_user_x.dart'; -import 'package:wyatt_authentication_bloc/src/core/utils/cryptography.dart'; -import 'package:wyatt_authentication_bloc/src/data/models/user_firebase.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart' - as wyatt; -import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; - -class AuthenticationRepositoryFirebase implements AuthenticationRepository { - final _controller = StreamController(); - final FirebaseAuth _firebaseAuth; - final TwitterLogin? _twitterLogin; - - UserFirebase _userCache = const UserFirebase.empty(); - - AuthenticationRepositoryFirebase({ - FirebaseAuth? firebaseAuth, - TwitterLogin? twitterLogin, - }) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance, - _twitterLogin = twitterLogin { - _controller.sink.add(AuthCubitStatus.stoped); - } - - @override - Stream get cubitStatus => - _controller.stream.asBroadcastStream(); - - @override - void changeCubitStatus(AuthCubitStatus status) => - _controller.sink.add(status); - - @override - Stream get user => - _firebaseAuth.userChanges().map((firebaseUser) { - final UserFirebase user = (firebaseUser == null) - ? const UserFirebase.empty() - : firebaseUser.model; - _userCache = user; - return user; - }); - - @override - wyatt.User get currentUser => _userCache; - - @override - Future applyActionCode(String code) async { - try { - await _firebaseAuth.applyActionCode(code); - } on FirebaseAuthException catch (e) { - throw ApplyActionCodeFailureFirebase.fromCode(e.code); - } catch (_) { - throw ApplyActionCodeFailureFirebase(); - } - } - - @override - Future signUp({ - required String email, - required String password, - }) async { - try { - final creds = await _firebaseAuth.createUserWithEmailAndPassword( - email: email, - password: password, - ); - return creds.user?.uid; - } on FirebaseAuthException catch (e) { - throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignUpWithEmailAndPasswordFailureFirebase(); - } - } - - @override - Future> fetchSignInMethodsForEmail({ - required String email, - }) async { - try { - return await _firebaseAuth.fetchSignInMethodsForEmail(email); - } on FirebaseAuthException catch (e) { - throw FetchSignInMethodsForEmailFailureFirebase.fromCode(e.code); - } catch (_) { - throw FetchSignInMethodsForEmailFailureFirebase(); - } - } - - @override - Future signInAnonymously() async { - try { - await _firebaseAuth.signInAnonymously(); - } on FirebaseAuthException catch (e) { - throw SignInAnonymouslyFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInAnonymouslyFailureFirebase(); - } - } - - @override - Future signInWithGoogle() async { - // Trigger the authentication flow - final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn(); - - // Obtain the auth details from the request - final GoogleSignInAuthentication? googleAuth = - await googleUser?.authentication; - - // Create a new credential - final credential = GoogleAuthProvider.credential( - accessToken: googleAuth?.accessToken, - idToken: googleAuth?.idToken, - ); - - try { - await _firebaseAuth.signInWithCredential(credential); - } on FirebaseAuthException catch (e) { - throw SignInWithGoogleFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithGoogleFailureFirebase(); - } - } - - @override - Future signInWithFacebook() async { - // Trigger the sign-in flow - final LoginResult loginResult = await FacebookAuth.instance.login(); - - // Create a credential from the access token - final OAuthCredential credential = - FacebookAuthProvider.credential(loginResult.accessToken?.token ?? ''); - - try { - await _firebaseAuth.signInWithCredential(credential); - } on FirebaseAuthException catch (e) { - throw SignInWithFacebookFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithFacebookFailureFirebase(); - } - } - - @override - Future signInWithApple() async { - // To prevent replay attacks with the credential returned from Apple, we - // include a nonce in the credential request. When signing in with - // Firebase, the nonce in the id token returned by Apple, is expected to - // match the sha256 hash of `rawNonce`. - final rawNonce = Cryptography.generateNonce(); - final nonce = Cryptography.sha256ofString(rawNonce); - - // Request credential for the currently signed in Apple account. - final appleCredential = await SignInWithApple.getAppleIDCredential( - scopes: [ - AppleIDAuthorizationScopes.email, - AppleIDAuthorizationScopes.fullName, - ], - nonce: nonce, - ); - - // Create an `OAuthCredential` from the credential returned by Apple. - final credential = OAuthProvider('apple.com').credential( - idToken: appleCredential.identityToken, - rawNonce: rawNonce, - ); - - // Sign in the user with Firebase. If the nonce we generated earlier does - // not match the nonce in `appleCredential.identityToken`, - // sign in will fail. - try { - await _firebaseAuth.signInWithCredential(credential); - } on FirebaseAuthException catch (e) { - throw SignInWithAppleFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithAppleFailureFirebase(); - } - } - - @override - Future signInWithTwitter() async { - final twitterLogin = _twitterLogin; - if (twitterLogin == null) { - throw SignInWithTwitterFailureFirebase(); - } - - // Trigger the sign-in flow - final authResult = await twitterLogin.login(); - - // Create a credential from the access token - final credential = TwitterAuthProvider.credential( - accessToken: authResult.authToken!, - secret: authResult.authTokenSecret!, - ); - - try { - await _firebaseAuth.signInWithCredential(credential); - } on FirebaseAuthException catch (e) { - throw SignInWithCredentialFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithCredentialFailureFirebase(); - } - } - - @override - Future signInWithEmailLink(String email, String emailLink) async { - try { - await _firebaseAuth.signInWithEmailLink( - email: email, - emailLink: emailLink, - ); - } on FirebaseAuthException catch (e) { - throw SignInWithEmailLinkFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithEmailLinkFailureFirebase(); - } - } - - @override - Future signInWithEmailAndPassword({ - required String email, - required String password, - }) async { - try { - await _firebaseAuth.signInWithEmailAndPassword( - email: email, - password: password, - ); - } on FirebaseAuthException catch (e) { - throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithEmailAndPasswordFailureFirebase(); - } - } - - @override - Future sendEmailVerification() async { - try { - await _userCache.inner!.sendEmailVerification(); - } catch (e) { - throw SendEmailVerificationFailureFirebase(); - } - } - - @override - Future sendPasswordResetEmail({required String email}) async { - try { - await _firebaseAuth.sendPasswordResetEmail(email: email); - } on FirebaseAuthException catch (e) { - throw SendPasswordResetEmailFailureFirebase.fromCode(e.code); - } catch (_) { - throw SendPasswordResetEmailFailureFirebase(); - } - } - - @override - Future sendSignInLinkEmail({required String email}) async { - try { - // TODO(hpcl): implement sendSignInLinkEmail - } on FirebaseAuthException catch (e) { - throw SendSignInLinkEmailFailureFirebase.fromCode(e.code); - } catch (_) { - throw SendSignInLinkEmailFailureFirebase(); - } - } - - @override - Future confirmPasswordReset({ - required String code, - required String newPassword, - }) async { - try { - await _firebaseAuth.confirmPasswordReset( - code: code, - newPassword: newPassword, - ); - } on FirebaseAuthException catch (e) { - throw ConfirmPasswordResetFailureFirebase.fromCode(e.code); - } catch (_) { - throw ConfirmPasswordResetFailureFirebase(); - } - throw UnimplementedError(); - } - - @override - Future verifyPasswordResetCode({required String code}) async { - try { - await _firebaseAuth.verifyPasswordResetCode(code); - } on FirebaseAuthException catch (e) { - throw VerifyPasswordResetCodeFailureFirebase.fromCode(e.code); - } catch (_) { - throw VerifyPasswordResetCodeFailureFirebase(); - } - } - - @override - Future signOut() async { - try { - await Future.wait([ - _firebaseAuth.signOut(), - ]); - _userCache = const UserFirebase.empty(); - } catch (_) { - throw SignOutFailureFirebase(); - } - } - - @override - Future refresh() async { - try { - await _userCache.inner!.reload(); - } on FirebaseAuthException catch (e) { - throw RefreshFailureFirebase.fromCode(e.code); - } catch (_) { - throw RefreshFailureFirebase(); - } - } -} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart new file mode 100644 index 00000000..e5526ea8 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart @@ -0,0 +1,156 @@ +// 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 . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/data/models/account_wrapper_model.dart'; +import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_local_data_source.dart'; +import 'package:wyatt_authentication_bloc/src/domain/data_sources/remote/authentication_remote_data_source.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; +import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class AuthenticationRepositoryImpl + extends AuthenticationRepository { + final AuthenticationLocalDataSource _authenticationLocalDataSource; + final AuthenticationRemoteDataSource _authenticationRemoteDataSource; + + final FutureResult Function(Account? account)? _onSignUpSuccess; + final FutureResult Function(Account? account)? _onAccountChanges; + + AuthenticationRepositoryImpl( + this._authenticationLocalDataSource, + this._authenticationRemoteDataSource, + this._onSignUpSuccess, + this._onAccountChanges, + ); + + @override + FutureResult signInWithEmailAndPassword({ + required String email, + required String password, + }) => + Result.tryCatchAsync( + () async { + final account = + await _authenticationRemoteDataSource.signInWithEmailAndPassword( + email: email, + password: password, + ); + _authenticationLocalDataSource.storeAccount(account); + return account; + }, + (error) => error, + ); + + @override + FutureResult signOut() => + Result.tryCatchAsync( + () async { + await _authenticationRemoteDataSource.signOut(); + _authenticationLocalDataSource.destroy(); + }, + (error) => error, + ); + + @override + FutureResult signUp({ + required String email, + required String password, + }) => + Result.tryCatchAsync( + () async { + final account = await _authenticationRemoteDataSource.signUp( + email: email, + password: password, + ); + _authenticationLocalDataSource.storeAccount(account); + if (_onSignUpSuccess.isNotNull) { + final dataResult = await _onSignUpSuccess!.call(account); + dataResult.fold( + _authenticationLocalDataSource.storeData, + (error) => throw error, + ); + } + return account; + }, + (error) => error, + ); + + @override + Result destroyCache() => + Result.tryCatch( + _authenticationLocalDataSource.destroy, + (error) => error, + ); + + @override + Result getAccount() => + Result.tryCatch( + _authenticationLocalDataSource.loadAccount, + (error) => error, + ); + + @override + Result setAccount( + Account account, + ) => + Result.tryCatch( + () { + _authenticationLocalDataSource.storeAccount(account); + return account; + }, + (error) => error, + ); + + @override + Result getData() => + Result.tryCatch( + _authenticationLocalDataSource.loadData, + (error) => error, + ); + + @override + Result setData( + T data, + ) => + Result.tryCatch( + () { + _authenticationLocalDataSource.storeData(data); + return data; + }, + (error) => error, + ); + + @override + FutureResult getIdentityToken() => + Result.tryCatchAsync( + _authenticationRemoteDataSource.getIdentityToken, + (error) => error, + ); + + @override + Stream>> streamAccount() => + _authenticationRemoteDataSource.streamAccount().map((account) async { + if (_onAccountChanges.isNotNull) { + final dataResult = await _onAccountChanges!.call(account); + return dataResult.map((data) => AccountWrapperModel(account, data)); + } + return Ok, AppException>( + AccountWrapperModel(account, null), + ); + }); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart new file mode 100644 index 00000000..7858c9e7 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart @@ -0,0 +1,17 @@ +// 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 . + +export 'authentication_repository_impl.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart index 35c80a72..432b1de6 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart @@ -14,126 +14,34 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; -/// {@template authentication_repository} -/// Repository which manages user authentication. -/// {@endtemplate} -abstract class AuthenticationRepository { - /// Stream of [AuthCubitStatus] wich will emit the current cubit status. - Stream get cubitStatus; +abstract class AuthenticationRepository extends BaseRepository { + FutureResult signUp({ + required String email, + required String password, + + }); - /// Changes cubit status.(Useful to start or stop the engine.) - void changeCubitStatus(AuthCubitStatus status); - - /// Stream of [User] which will emit the current user when - /// the authentication state changes. - /// - /// Emits [User.empty] if the user is not authenticated. - Stream get user; - - /// Returns the current cached account. - /// Defaults to [User.empty] if there is no cached user. - User get currentUser; - - /// Applies action code - /// - /// [code] - The action code sent to the user's email address. - /// Throw [ApplyActionCodeFailureInterface] if an exception occurs. - Future applyActionCode(String code); - - /// Creates a new user with the provided [email] and [password]. - /// - /// Returns the newly created user's unique identifier. - /// - /// Throws a [SignUpWithEmailAndPasswordFailureInterface] if - /// an exception occurs. - Future signUp({required String email, required String password}); - - /// Fetches sign in methods for [email]. - /// - /// Throws a [FetchSignInMethodsForEmailFailureInterface] if - /// an exception occurs. - Future> fetchSignInMethodsForEmail({required String email}); - - /// Sign in anonimously. - /// - /// Throws a [SignInAnonymouslyFailureInterface] if an exception occurs. - Future signInAnonymously(); - - /// Starts the Sign In with Google Flow. - /// - /// Throws a [SignInWithGoogleFailureInterface] if an exception occurs. - Future signInWithGoogle(); - - /// Starts the Sign In with Facebook Flow. - /// - /// Throws a [SignInWithFacebookFailureInterface] if an exception occurs. - Future signInWithFacebook(); - - /// Starts the Sign In with Apple Flow. - /// - /// Throws a [SignInWithAppleFailureInterface] if an exception occurs. - Future signInWithApple(); - - /// Starts the Sign In with Twitter Flow. - /// - /// Throws a [SignInWithTwitterFailureInterface] if an exception occurs. - Future signInWithTwitter(); - - /// Signs in using an email address and email sign-in link. - /// - /// Throws a [SignInWithEmailLinkFailureInterface] if an exception occurs. - Future signInWithEmailLink( - String email, - String emailLink, - ); - - /// Signs in with the provided [email] and [password]. - /// - /// Throws a [SignInWithEmailAndPasswordFailureInterface] if - /// an exception occurs. - Future signInWithEmailAndPassword({ + FutureResult signInWithEmailAndPassword({ required String email, required String password, }); - /// Sends verification email to the provided [user]. - /// - /// Throws a [SendEmailVerificationFailureInterface] if an exception occurs. - Future sendEmailVerification(); + FutureResult signOut(); - /// Sends a password reset email to the provided [email]. - /// - /// Throws a [SendPasswordResetEmailFailureInterface] if an exception occurs. - Future sendPasswordResetEmail({required String email}); + Stream>> streamAccount(); - /// Sends link to login. - /// - /// Throws a [SendSignInLinkEmailFailureInterface] if an exception occurs. - Future sendSignInLinkEmail({required String email}); + FutureResult getIdentityToken(); - /// Confirms the password reset with the provided [newPassword] and [code]. - /// - /// Throws a [ConfirmPasswordResetFailureInterface] if an exception occurs. - Future confirmPasswordReset({ - required String code, - required String newPassword, - }); + Result getAccount(); + Result setAccount(Account account); - /// Verify password reset code. - /// - /// Throws a [VerifyPasswordResetCodeFailureInterface] if an exception occurs. - Future verifyPasswordResetCode({required String code}); + Result getData(); + Result setData(T data); - /// Signs out the current user which will emit - /// [User.empty] from the [user] Stream. - Future signOut(); - - /// Refreshes the current user. - /// - /// Throws a [RefreshFailureInterface] if an exception occurs. - Future refresh(); + Result destroyCache(); } diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart new file mode 100644 index 00000000..85f8ae88 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart @@ -0,0 +1,17 @@ +// 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 . + +export 'authentication_repository.dart'; From 2f572db4a4e12fc1175bc2d33a185fdc1e8cbdb2 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Wed, 9 Nov 2022 01:47:09 -0500 Subject: [PATCH 03/18] feat: add data sources --- .../lib/src/data/data.dart | 19 +++ .../src/data/data_sources/data_sources.dart | 18 +++ ...authentication_cache_data_source_impl.dart | 60 ++++++++++ ...hentication_firebase_data_source_impl.dart | 110 ++++++++++++++++++ .../lib/src/data/models/account_model.dart | 27 +++++ .../data/models/account_wrapper_model.dart | 27 +++++ .../lib/src/data/models/models.dart | 18 +++ .../lib/src/data/models/user_firebase.dart | 82 ------------- .../src/domain/data_sources/data_sources.dart | 19 +++ ...authentication_biometrics_data_source.dart | 19 +++ .../authentication_local_data_source.dart | 27 +++++ .../authentication_remote_data_source.dart | 36 ++++++ 12 files changed, 380 insertions(+), 82 deletions(-) create mode 100644 packages/wyatt_authentication_bloc/lib/src/data/data.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/data/models/models.dart delete mode 100644 packages/wyatt_authentication_bloc/lib/src/data/models/user_firebase.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_biometrics_data_source.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_local_data_source.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data.dart b/packages/wyatt_authentication_bloc/lib/src/data/data.dart new file mode 100644 index 00000000..42218c55 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data.dart @@ -0,0 +1,19 @@ +// 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 . + +export 'data_sources/data_sources.dart'; +export 'models/models.dart'; +export 'repositories/repositories.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart new file mode 100644 index 00000000..346c8fa7 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart @@ -0,0 +1,18 @@ +// 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 . + +export 'local/authentication_cache_data_source_impl.dart'; +export 'remote/authentication_firebase_data_source_impl.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart new file mode 100644 index 00000000..363ee51d --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart @@ -0,0 +1,60 @@ +// 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 . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_local_data_source.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class AuthenticationCacheDataSourceImpl + extends AuthenticationLocalDataSource { + Account? _account; + T? _data; + + AuthenticationCacheDataSourceImpl(); + + @override + void storeAccount(Account? account) { + _account = account; + } + + @override + void storeData(T? data) { + _data = data; + } + + @override + Account loadAccount() { + if (_account.isNotNull) { + return _account!; + } + throw ClientException('Cached account is invalid'); + } + + @override + T loadData() { + if (_data.isNotNull) { + return _data!; + } + throw ClientException('Cached data is invalid'); + } + + @override + void destroy() { + _data = null; + _account = null; + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart new file mode 100644 index 00000000..f0c55b8d --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart @@ -0,0 +1,110 @@ +// 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 . + +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class AuthenticationFirebaseDataSourceImpl + extends AuthenticationRemoteDataSource { + final FirebaseAuth _firebaseAuth; + + AuthenticationFirebaseDataSourceImpl({FirebaseAuth? firebaseAuth}) + : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance; + + Account _mapper(User user) => AccountModel( + uid: user.uid, + email: user.email, + ); + + @override + Future signInWithEmailAndPassword({ + required String email, + required String password, + }) async { + try { + final userCredential = await _firebaseAuth.signInWithEmailAndPassword( + email: email, + password: password, + ); + final user = userCredential.user; + if (user.isNotNull) { + return _mapper(user!); + } else { + throw Exception(); // Get caught just after. + } + } on FirebaseAuthException catch (e) { + throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code); + } catch (_) { + throw SignInWithEmailAndPasswordFailureFirebase(); + } + } + + @override + Future signUp({ + required String email, + required String password, + }) async { + try { + final userCredential = await _firebaseAuth.createUserWithEmailAndPassword( + email: email, + password: password, + ); + final user = userCredential.user; + if (user.isNotNull) { + return _mapper(user!); + } else { + throw Exception(); // Get caught just after. + } + } on FirebaseAuthException catch (e) { + throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code); + } catch (_) { + throw SignUpWithEmailAndPasswordFailureFirebase(); + } + } + + @override + Future signOut() async { + try { + await _firebaseAuth.signOut(); + } catch (_) { + throw SignOutFailureFirebase(); + } + } + + @override + Future getIdentityToken() async { + try { + final token = await _firebaseAuth.currentUser?.getIdToken(); + if (token.isNotNull) { + return token!; + } else { + throw Exception(); // Get caught just after. + } + } catch (_) { + // TODO(hpcl): implement a non ambiguous exception for this case + throw ServerException(); + } + } + + @override + Stream streamAccount() => + _firebaseAuth.userChanges().map((user) { + final Account? account = (user.isNotNull) ? _mapper(user!) : null; + return account; + }); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart new file mode 100644 index 00000000..0d1d6b65 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart @@ -0,0 +1,27 @@ +// 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 . + +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; + +class AccountModel implements Account { + @override + final String uid; + + @override + final String? email; + + AccountModel({required this.uid, required this.email}); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart new file mode 100644 index 00000000..69bffd98 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart @@ -0,0 +1,27 @@ +// 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 . + +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; + +class AccountWrapperModel extends AccountWrapper { + @override + final Account? account; + @override + final T? data; + + AccountWrapperModel(this.account, this.data); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart new file mode 100644 index 00000000..09cc76bf --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart @@ -0,0 +1,18 @@ +// 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 . + +export 'account_model.dart'; +export 'account_wrapper_model.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/user_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/user_firebase.dart deleted file mode 100644 index 31139cf3..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/data/models/user_firebase.dart +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart' as wyatt; - -class UserFirebase implements wyatt.User { - final User? _user; - - const UserFirebase(User user) : _user = user; - - User? get inner => _user; - - @override - const UserFirebase.empty() : _user = null; - - @override - DateTime? get creationTime => _user?.metadata.creationTime; - - @override - String? get displayName => _user?.displayName; - - @override - String? get email => _user?.email; - - @override - bool get emailVerified => _user?.emailVerified ?? false; - - @override - bool get isAnonymous => _user?.isAnonymous ?? false; - - @override - bool get isEmpty => _user == null; - - @override - bool get isNotEmpty => _user != null; - - @override - DateTime? get lastSignInTime => _user?.metadata.lastSignInTime; - - @override - String? get phoneNumber => _user?.phoneNumber; - - @override - String? get photoURL => _user?.photoURL; - - @override - String? get refreshToken => _user?.refreshToken; - - @override - String get uid => _user?.uid ?? ''; - - @override - String? get providerId => _user?.providerData.first.providerId; - - @override - bool? get isNewUser { - if (_user?.metadata.lastSignInTime == null || - _user?.metadata.creationTime == null) { - return null; - } else { - return _user?.metadata.lastSignInTime == _user?.metadata.creationTime; - } - } - - @override - // ignore: lines_longer_than_80_chars - String toString() => 'UserFirebase(creationTime: $creationTime, displayName: $displayName, email: $email, emailVerified: $emailVerified, isAnonymous: $isAnonymous, lastSignInTime: $lastSignInTime, phoneNumber: $phoneNumber, photoURL: $photoURL, refreshToken: $refreshToken, uid: $uid)'; -} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart new file mode 100644 index 00000000..1e726386 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart @@ -0,0 +1,19 @@ +// 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 . + +export 'local/authentication_biometrics_data_source.dart'; +export 'local/authentication_local_data_source.dart'; +export 'remote/authentication_remote_data_source.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_biometrics_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_biometrics_data_source.dart new file mode 100644 index 00000000..489c9919 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_biometrics_data_source.dart @@ -0,0 +1,19 @@ +// 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 . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; + +abstract class AuthenticationBiometricsDataSource extends BaseLocalDataSource {} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_local_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_local_data_source.dart new file mode 100644 index 00000000..cd47d32e --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_local_data_source.dart @@ -0,0 +1,27 @@ +// 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 . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; + +abstract class AuthenticationLocalDataSource + extends BaseLocalDataSource { + void storeAccount(Account? account); + void storeData(T? data); + Account loadAccount(); + T loadData(); + void destroy(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart new file mode 100644 index 00000000..3bd615e1 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart @@ -0,0 +1,36 @@ +// 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 . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; + +abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource { + Future signUp({ + required String email, + required String password, + }); + + Future signInWithEmailAndPassword({ + required String email, + required String password, + }); + + Future signOut(); + + Stream streamAccount(); + + Future getIdentityToken(); +} From d2d8acdafb1eb05588d2474e19721dbcb5c3b995 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Wed, 9 Nov 2022 01:47:37 -0500 Subject: [PATCH 04/18] fix: rework core and entities --- .../lib/src/core/core.dart | 19 +++ .../src/core/enums/authentication_status.dart | 21 +++ .../enums.dart} | 11 +- .../lib/src/core/exceptions/exceptions.dart | 51 ++++--- .../core/exceptions/exceptions_firebase.dart | 137 +++++++++--------- .../lib/src/core/utils/utils.dart | 17 +++ .../lib/src/domain/domain.dart | 19 +++ .../lib/src/domain/entities/account.dart | 27 ++++ .../entities/account_wrapper.dart} | 9 +- .../lib/src/domain/entities/entities.dart | 18 +++ .../lib/src/domain/entities/user.dart | 85 ----------- 11 files changed, 224 insertions(+), 190 deletions(-) create mode 100644 packages/wyatt_authentication_bloc/lib/src/core/core.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart rename packages/wyatt_authentication_bloc/lib/src/core/{enum/auth_cubit_status.dart => enums/enums.dart} (92%) create mode 100644 packages/wyatt_authentication_bloc/lib/src/core/utils/utils.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/domain.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart rename packages/wyatt_authentication_bloc/lib/src/{core/extensions/firebase_auth_user_x.dart => domain/entities/account_wrapper.dart} (75%) create mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart delete mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/entities/user.dart diff --git a/packages/wyatt_authentication_bloc/lib/src/core/core.dart b/packages/wyatt_authentication_bloc/lib/src/core/core.dart new file mode 100644 index 00000000..658cbca0 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/core.dart @@ -0,0 +1,19 @@ +// 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 . + +export 'enums/enums.dart'; +export 'exceptions/exceptions.dart'; +export 'utils/utils.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart b/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart new file mode 100644 index 00000000..af10ceae --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart @@ -0,0 +1,21 @@ +// 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 . + +enum AuthenticationStatus { + unknown, + authenticated, + unauthenticated, +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/enum/auth_cubit_status.dart b/packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart similarity index 92% rename from packages/wyatt_authentication_bloc/lib/src/core/enum/auth_cubit_status.dart rename to packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart index 37448fa1..67d107d6 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/enum/auth_cubit_status.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart @@ -1,20 +1,17 @@ // 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 . -enum AuthCubitStatus { - started, - stoped, -} +export 'authentication_status.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart index 44f258f7..11e7835d 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart @@ -14,13 +14,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -abstract class AuthenticationFailureInterface implements Exception { - String code; - String message; +import 'package:wyatt_architecture/wyatt_architecture.dart'; - AuthenticationFailureInterface(this.code, this.message); +part 'exceptions_firebase.dart'; + +abstract class AuthenticationFailureInterface extends AppException + implements Exception { + String code; + String msg; + + AuthenticationFailureInterface(this.code, this.msg); AuthenticationFailureInterface.fromCode(this.code) - : message = 'An unknown error occurred.'; + : msg = 'An unknown error occurred.'; } /// {@template apply_action_code_failure} @@ -29,7 +34,7 @@ abstract class AuthenticationFailureInterface implements Exception { abstract class ApplyActionCodeFailureInterface extends AuthenticationFailureInterface { /// {@macro apply_action_code_failure} - ApplyActionCodeFailureInterface(super.code, super.message); + ApplyActionCodeFailureInterface(super.code, super.msg); /// {@macro apply_action_code_failure} ApplyActionCodeFailureInterface.fromCode(super.code) : super.fromCode(); @@ -41,7 +46,7 @@ abstract class ApplyActionCodeFailureInterface abstract class SignUpWithEmailAndPasswordFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_up_with_email_and_password_failure} - SignUpWithEmailAndPasswordFailureInterface(super.code, super.message); + SignUpWithEmailAndPasswordFailureInterface(super.code, super.msg); /// {@macro sign_up_with_email_and_password_failure} SignUpWithEmailAndPasswordFailureInterface.fromCode(super.code) @@ -54,7 +59,7 @@ abstract class SignUpWithEmailAndPasswordFailureInterface abstract class FetchSignInMethodsForEmailFailureInterface extends AuthenticationFailureInterface { /// {@macro fetch_sign_in_methods_failure} - FetchSignInMethodsForEmailFailureInterface(super.code, super.message); + FetchSignInMethodsForEmailFailureInterface(super.code, super.msg); /// {@macro fetch_sign_in_methods_failure} FetchSignInMethodsForEmailFailureInterface.fromCode(super.code) @@ -67,7 +72,7 @@ abstract class FetchSignInMethodsForEmailFailureInterface abstract class SignInWithCredentialFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_credential_failure} - SignInWithCredentialFailureInterface(super.code, super.message); + SignInWithCredentialFailureInterface(super.code, super.msg); /// {@macro sign_in_with_credential_failure} SignInWithCredentialFailureInterface.fromCode(super.code) : super.fromCode(); @@ -79,7 +84,7 @@ abstract class SignInWithCredentialFailureInterface abstract class SignInAnonymouslyFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_anonymously_failure} - SignInAnonymouslyFailureInterface(super.code, super.message); + SignInAnonymouslyFailureInterface(super.code, super.msg); /// {@macro sign_in_anonymously_failure} SignInAnonymouslyFailureInterface.fromCode(super.code) : super.fromCode(); @@ -91,7 +96,7 @@ abstract class SignInAnonymouslyFailureInterface abstract class SignInWithGoogleFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_google_failure} - SignInWithGoogleFailureInterface(super.code, super.message); + SignInWithGoogleFailureInterface(super.code, super.msg); /// {@macro sign_in_with_google_failure} SignInWithGoogleFailureInterface.fromCode(super.code) : super.fromCode(); @@ -103,7 +108,7 @@ abstract class SignInWithGoogleFailureInterface abstract class SignInWithFacebookFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_facebook_failure} - SignInWithFacebookFailureInterface(super.code, super.message); + SignInWithFacebookFailureInterface(super.code, super.msg); /// {@macro sign_in_with_facebook_failure} SignInWithFacebookFailureInterface.fromCode(super.code) : super.fromCode(); @@ -115,7 +120,7 @@ abstract class SignInWithFacebookFailureInterface abstract class SignInWithAppleFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_apple_failure} - SignInWithAppleFailureInterface(super.code, super.message); + SignInWithAppleFailureInterface(super.code, super.msg); /// {@macro sign_in_with_apple_failure} SignInWithAppleFailureInterface.fromCode(super.code) : super.fromCode(); @@ -127,7 +132,7 @@ abstract class SignInWithAppleFailureInterface abstract class SignInWithTwitterFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_twitter_failure} - SignInWithTwitterFailureInterface(super.code, super.message); + SignInWithTwitterFailureInterface(super.code, super.msg); /// {@macro sign_in_with_twitter_failure} SignInWithTwitterFailureInterface.fromCode(super.code) : super.fromCode(); @@ -139,7 +144,7 @@ abstract class SignInWithTwitterFailureInterface abstract class SignInWithEmailLinkFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_email_link_failure} - SignInWithEmailLinkFailureInterface(super.code, super.message); + SignInWithEmailLinkFailureInterface(super.code, super.msg); /// {@macro sign_in_with_email_link_failure} SignInWithEmailLinkFailureInterface.fromCode(super.code) : super.fromCode(); @@ -151,7 +156,7 @@ abstract class SignInWithEmailLinkFailureInterface abstract class SignInWithEmailAndPasswordFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_email_and_password_failure} - SignInWithEmailAndPasswordFailureInterface(super.code, super.message); + SignInWithEmailAndPasswordFailureInterface(super.code, super.msg); /// {@macro sign_in_with_email_and_password_failure} SignInWithEmailAndPasswordFailureInterface.fromCode(super.code) @@ -164,7 +169,7 @@ abstract class SignInWithEmailAndPasswordFailureInterface abstract class SendEmailVerificationFailureInterface extends AuthenticationFailureInterface { /// {@macro send_email_verification_failure} - SendEmailVerificationFailureInterface(super.code, super.message); + SendEmailVerificationFailureInterface(super.code, super.msg); /// {@macro send_email_verification_failure} SendEmailVerificationFailureInterface.fromCode(super.code) : super.fromCode(); @@ -176,7 +181,7 @@ abstract class SendEmailVerificationFailureInterface abstract class SendPasswordResetEmailFailureInterface extends AuthenticationFailureInterface { /// {@macro send_password_reset_email_failure} - SendPasswordResetEmailFailureInterface(super.code, super.message); + SendPasswordResetEmailFailureInterface(super.code, super.msg); /// {@macro send_password_reset_email_failure} SendPasswordResetEmailFailureInterface.fromCode(super.code) @@ -189,7 +194,7 @@ abstract class SendPasswordResetEmailFailureInterface abstract class SendSignInLinkEmailFailureInterface extends AuthenticationFailureInterface { /// {@macro send_sign_in_link_email_failure} - SendSignInLinkEmailFailureInterface(super.code, super.message); + SendSignInLinkEmailFailureInterface(super.code, super.msg); /// {@macro send_sign_in_link_email_failure} SendSignInLinkEmailFailureInterface.fromCode(super.code) : super.fromCode(); @@ -201,7 +206,7 @@ abstract class SendSignInLinkEmailFailureInterface abstract class ConfirmPasswordResetFailureInterface extends AuthenticationFailureInterface { /// {@macro confirm_password_reset_failure} - ConfirmPasswordResetFailureInterface(super.code, super.message); + ConfirmPasswordResetFailureInterface(super.code, super.msg); /// {@macro confirm_password_reset_failure} ConfirmPasswordResetFailureInterface.fromCode(super.code) : super.fromCode(); @@ -213,7 +218,7 @@ abstract class ConfirmPasswordResetFailureInterface abstract class VerifyPasswordResetCodeFailureInterface extends AuthenticationFailureInterface { /// {@macro verify_password_reset_code_failure} - VerifyPasswordResetCodeFailureInterface(super.code, super.message); + VerifyPasswordResetCodeFailureInterface(super.code, super.msg); /// {@macro verify_password_reset_code_failure} VerifyPasswordResetCodeFailureInterface.fromCode(super.code) @@ -225,7 +230,7 @@ abstract class VerifyPasswordResetCodeFailureInterface /// {@endtemplate} abstract class RefreshFailureInterface extends AuthenticationFailureInterface { /// {@macro refresh_failure} - RefreshFailureInterface(super.code, super.message); + RefreshFailureInterface(super.code, super.msg); /// {@macro refresh_failure} RefreshFailureInterface.fromCode(super.code) : super.fromCode(); @@ -236,7 +241,7 @@ abstract class RefreshFailureInterface extends AuthenticationFailureInterface { /// {@endtemplate} abstract class SignOutFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_out_failure} - SignOutFailureInterface(super.code, super.message); + SignOutFailureInterface(super.code, super.msg); /// {@macro sign_out_failure} SignOutFailureInterface.fromCode(super.code) : super.fromCode(); diff --git a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart index a2d2c108..42f410a2 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart @@ -14,133 +14,130 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; +part of 'exceptions.dart'; class ApplyActionCodeFailureFirebase extends ApplyActionCodeFailureInterface { - ApplyActionCodeFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + ApplyActionCodeFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); ApplyActionCodeFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'expired-action-code': - message = 'Action code has expired.'; + msg = 'Action code has expired.'; break; case 'invalid-action-code': - message = 'Action code is invalid.'; + msg = 'Action code is invalid.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; case 'user-not-found': - message = 'Email is not found, please create an account.'; + msg = 'Email is not found, please create an account.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SignUpWithEmailAndPasswordFailureFirebase extends SignUpWithEmailAndPasswordFailureInterface { - SignUpWithEmailAndPasswordFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignUpWithEmailAndPasswordFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignUpWithEmailAndPasswordFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'invalid-email': - message = 'The email address is badly formatted.'; + msg = 'The email address is badly formatted.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; case 'email-already-in-use': - message = 'An account already exists for that email.'; + msg = 'An account already exists for that email.'; break; case 'operation-not-allowed': - message = 'Operation is not allowed. Please contact support.'; + msg = 'Operation is not allowed. Please contact support.'; break; case 'weak-password': - message = 'Please enter a stronger password.'; + msg = 'Please enter a stronger password.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class FetchSignInMethodsForEmailFailureFirebase extends FetchSignInMethodsForEmailFailureInterface { - FetchSignInMethodsForEmailFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + FetchSignInMethodsForEmailFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); FetchSignInMethodsForEmailFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'invalid-email': - message = 'The email address is badly formatted.'; + msg = 'The email address is badly formatted.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SignInAnonymouslyFailureFirebase extends SignInAnonymouslyFailureInterface { - SignInAnonymouslyFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignInAnonymouslyFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignInAnonymouslyFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'operation-not-allowed': - message = 'Operation is not allowed. Please contact support.'; + msg = 'Operation is not allowed. Please contact support.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SignInWithCredentialFailureFirebase extends SignInWithCredentialFailureInterface { - SignInWithCredentialFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignInWithCredentialFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignInWithCredentialFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'account-exists-with-different-credential': - message = 'Account exists with different credentials.'; + msg = 'Account exists with different credentials.'; break; case 'invalid-credential': - message = 'The credential received is malformed or has expired.'; + msg = 'The credential received is malformed or has expired.'; break; case 'operation-not-allowed': - message = 'Operation is not allowed. Please contact support.'; + msg = 'Operation is not allowed. Please contact support.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; case 'user-not-found': - message = 'Email is not found, please create an account.'; + msg = 'Email is not found, please create an account.'; break; case 'wrong-password': - message = 'Incorrect password, please try again.'; + msg = 'Incorrect password, please try again.'; break; case 'invalid-verification-code': - message = 'The credential verification code received is invalid.'; + msg = 'The credential verification code received is invalid.'; break; case 'invalid-verification-id': - message = 'The credential verification ID received is invalid.'; + msg = 'The credential verification ID received is invalid.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } @@ -148,130 +145,128 @@ class SignInWithCredentialFailureFirebase class SignInWithGoogleFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithGoogleFailureInterface { - SignInWithGoogleFailureFirebase([super.code, super.message]); + SignInWithGoogleFailureFirebase([super.code, super.msg]); SignInWithGoogleFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignInWithFacebookFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithFacebookFailureInterface { - SignInWithFacebookFailureFirebase([super.code, super.message]); + SignInWithFacebookFailureFirebase([super.code, super.msg]); SignInWithFacebookFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignInWithAppleFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithAppleFailureInterface { - SignInWithAppleFailureFirebase([super.code, super.message]); + SignInWithAppleFailureFirebase([super.code, super.msg]); SignInWithAppleFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignInWithTwitterFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithAppleFailureInterface { - SignInWithTwitterFailureFirebase([super.code, super.message]); + SignInWithTwitterFailureFirebase([super.code, super.msg]); SignInWithTwitterFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignInWithEmailLinkFailureFirebase extends SignInWithEmailLinkFailureInterface { - SignInWithEmailLinkFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignInWithEmailLinkFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignInWithEmailLinkFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'expired-action-code': - message = 'Action code has expired.'; + msg = 'Action code has expired.'; break; case 'invalid-email': - message = 'Email is not valid or badly formatted.'; + msg = 'Email is not valid or badly formatted.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SignInWithEmailAndPasswordFailureFirebase extends SignInWithEmailAndPasswordFailureInterface { - SignInWithEmailAndPasswordFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignInWithEmailAndPasswordFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignInWithEmailAndPasswordFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'invalid-email': - message = 'Email is not valid or badly formatted.'; + msg = 'Email is not valid or badly formatted.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; case 'user-not-found': - message = 'Email is not found, please create an account.'; + msg = 'Email is not found, please create an account.'; break; case 'wrong-password': - message = 'Incorrect password, please try again.'; + msg = 'Incorrect password, please try again.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SendEmailVerificationFailureFirebase extends SendEmailVerificationFailureInterface { - SendEmailVerificationFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SendEmailVerificationFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SendEmailVerificationFailureFirebase.fromCode(super.code) : super.fromCode(); } class SendPasswordResetEmailFailureFirebase extends SendPasswordResetEmailFailureInterface { - SendPasswordResetEmailFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SendPasswordResetEmailFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SendPasswordResetEmailFailureFirebase.fromCode(super.code) : super.fromCode(); } class SendSignInLinkEmailFailureFirebase extends SendSignInLinkEmailFailureInterface { - SendSignInLinkEmailFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SendSignInLinkEmailFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SendSignInLinkEmailFailureFirebase.fromCode(super.code) : super.fromCode(); } class ConfirmPasswordResetFailureFirebase extends ConfirmPasswordResetFailureInterface { - ConfirmPasswordResetFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + ConfirmPasswordResetFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); ConfirmPasswordResetFailureFirebase.fromCode(super.code) : super.fromCode(); } class VerifyPasswordResetCodeFailureFirebase extends VerifyPasswordResetCodeFailureInterface { - VerifyPasswordResetCodeFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + VerifyPasswordResetCodeFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); VerifyPasswordResetCodeFailureFirebase.fromCode(super.code) : super.fromCode(); } class RefreshFailureFirebase extends RefreshFailureInterface { - RefreshFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + RefreshFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); RefreshFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignOutFailureFirebase extends SignOutFailureInterface { - SignOutFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignOutFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignOutFailureFirebase.fromCode(super.code) : super.fromCode(); } diff --git a/packages/wyatt_authentication_bloc/lib/src/core/utils/utils.dart b/packages/wyatt_authentication_bloc/lib/src/core/utils/utils.dart new file mode 100644 index 00000000..81005a25 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/utils/utils.dart @@ -0,0 +1,17 @@ +// 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 . + +export 'cryptography.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart b/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart new file mode 100644 index 00000000..7727f7ee --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart @@ -0,0 +1,19 @@ +// 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 . + +export 'data_sources/data_sources.dart'; +export 'entities/entities.dart'; +export 'repositories/repositories.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart new file mode 100644 index 00000000..97d5deeb --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart @@ -0,0 +1,27 @@ +// 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 . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; + +abstract class Account extends Entity { + /// The user's unique ID. + String get uid; + + /// The users email address. + /// + /// Will be `null` if signing in anonymously. + String? get email; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/extensions/firebase_auth_user_x.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account_wrapper.dart similarity index 75% rename from packages/wyatt_authentication_bloc/lib/src/core/extensions/firebase_auth_user_x.dart rename to packages/wyatt_authentication_bloc/lib/src/domain/entities/account_wrapper.dart index 70b870c3..1e1f0034 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/extensions/firebase_auth_user_x.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account_wrapper.dart @@ -14,9 +14,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:wyatt_authentication_bloc/src/data/models/user_firebase.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; -extension FirebaseAuthUserX on User { - UserFirebase get model => UserFirebase(this); +abstract class AccountWrapper extends Entity { + Account? get account; + T? get data; } diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart new file mode 100644 index 00000000..8ecf9215 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart @@ -0,0 +1,18 @@ +// 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 . + +export 'account.dart'; +export 'account_wrapper.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/user.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/user.dart deleted file mode 100644 index 40c0c7b9..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/domain/entities/user.dart +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -abstract class User { - /// The empty user constructor. - const User.empty(); - - /// The users display name. - /// - /// Will be `null` if signing in anonymously or via password authentication. - String? get displayName; - - /// The users email address. - /// - /// Will be `null` if signing in anonymously. - String? get email; - - /// Returns whether the users email address has been verified. - /// - /// To send a verification email, see `SendEmailVerification`. - /// - /// Once verified, call `reload` to ensure the latest user information is - /// retrieved from Firebase. - bool get emailVerified; - - /// Returns whether the user is a anonymous. - bool get isAnonymous; - - /// Returns the users account creation time. - /// - /// When this account was created as dictated by the server clock. - DateTime? get creationTime; - - /// When the user last signed in as dictated by the server clock. - /// - /// This is only accurate up to a granularity of 2 minutes for consecutive - /// sign-in attempts. - DateTime? get lastSignInTime; - - /// Returns the users phone number. - /// - /// This property will be `null` if the user has not signed in or been has - /// their phone number linked. - String? get phoneNumber; - - /// Returns a photo URL for the user. - /// - /// This property will be populated if the user has signed in or been linked - /// with a 3rd party OAuth provider (such as Google). - String? get photoURL; - - /// Returns a JWT refresh token for the user. - /// - /// This property maybe `null` or empty if the underlying platform does not - /// support providing refresh tokens. - String? get refreshToken; - - /// The user's unique ID. - String get uid; - - /// The provider ID for the user. - String? get providerId; - - /// Whether the user account has been recently created. - bool? get isNewUser; - - /// Convenience getter to determine whether the current user is empty. - bool get isEmpty; - - /// Convenience getter to determine whether the current user is not empty. - bool get isNotEmpty; -} From 0d00a67b7c369f8540476c5a7aa5c68e53aca9e8 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Wed, 9 Nov 2022 01:47:57 -0500 Subject: [PATCH 05/18] fix: rework presentation features --- .../builder/authentication_builder.dart | 10 +-- .../cubit/authentication_cubit.dart | 87 ++++++------------- .../cubit/authentication_state.dart | 28 ++---- .../cubit/email_verification_cubit.dart | 71 --------------- .../cubit/email_verification_state.dart | 42 --------- .../email_verification.dart => features.dart} | 10 ++- .../cubit/password_reset_cubit.dart | 68 --------------- .../cubit/password_reset_state.dart | 42 --------- .../password_reset/password_reset.dart | 17 ---- .../features/sign_in/cubit/sign_in_cubit.dart | 81 ++++------------- .../lib/src/features/sign_in/sign_in.dart | 6 +- .../features/sign_up/cubit/sign_up_cubit.dart | 42 ++++----- .../lib/src/features/sign_up/sign_up.dart | 6 +- .../lib/src/src.dart | 24 ++--- 14 files changed, 89 insertions(+), 445 deletions(-) delete mode 100644 packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart delete mode 100644 packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart rename packages/wyatt_authentication_bloc/lib/src/features/{email_verification/email_verification.dart => features.dart} (85%) delete mode 100644 packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart delete mode 100644 packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart delete mode 100644 packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart index f10c88c3..4a19e6a9 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart @@ -16,7 +16,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart'; +import 'package:wyatt_authentication_bloc/src/core/enums/authentication_status.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; import 'package:wyatt_authentication_bloc/src/features/authentication/cubit/authentication_cubit.dart'; class AuthenticationBuilder extends StatelessWidget { @@ -29,8 +30,7 @@ class AuthenticationBuilder extends StatelessWidget { final Widget Function( BuildContext context, - User user, - Extra? extra, + AccountWrapper accountWrapper, ) authenticated; final Widget Function(BuildContext context) unauthenticated; final Widget Function(BuildContext context) unknown; @@ -40,8 +40,8 @@ class AuthenticationBuilder extends StatelessWidget { BlocBuilder, AuthenticationState>( builder: (context, state) { if (state.status == AuthenticationStatus.authenticated) { - if (state.user != null) { - return authenticated(context, state.user!, state.extra); + if (state.accountWrapper != null) { + return authenticated(context, state.accountWrapper!); } else { return unauthenticated(context); } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart index 95ae5a59..af9cb0b0 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart @@ -18,83 +18,46 @@ import 'dart:async'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart'; +import 'package:wyatt_authentication_bloc/src/core/enums/authentication_status.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; part 'authentication_state.dart'; class AuthenticationCubit extends Cubit> { - final AuthenticationRepository _authenticationRepository; - late final StreamSubscription _statusSubscription; - - StreamSubscription? _userSubscription; - - final Future Function(User user)? _onAuthSuccess; + final AuthenticationRepository _authenticationRepository; AuthenticationCubit({ - required AuthenticationRepository authenticationRepository, - Future Function(User user)? onAuthSuccess, + required AuthenticationRepository authenticationRepository, }) : _authenticationRepository = authenticationRepository, - _onAuthSuccess = onAuthSuccess, super(const AuthenticationState.unknown()) { - _subscribeStatus(); + _listenForAuthenticationChanges(); } - Future get status async => - _authenticationRepository.cubitStatus.last; - - void _subscribeStatus() { - try { - _statusSubscription = _authenticationRepository.cubitStatus.listen( - (status) { - switch (status) { - case AuthCubitStatus.started: - start(); - break; - case AuthCubitStatus.stoped: - stop(); - break; + void _listenForAuthenticationChanges() { + _authenticationRepository.streamAccount().listen((accountFutureResult) { + accountFutureResult.fold( + (value) { + if (value.account.isNotNull) { + emit(AuthenticationState.authenticated(value)); + return; } + _authenticationRepository.destroyCache(); + emit(const AuthenticationState.unauthenticated()); + return; + }, + (error) { + _authenticationRepository.destroyCache(); + emit(const AuthenticationState.unauthenticated()); + return; }, ); - } catch (_) {} + }); } - Future init() async { - final firstUser = await _authenticationRepository.user.first; - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - return changeStatus(firstUser); - } - - bool start() { - _userSubscription = _authenticationRepository.user.listen(changeStatus); - return true; - } - - bool stop() { - _userSubscription?.cancel(); - return true; - } - - Future changeStatus(User user) async { - if (user.isNotEmpty) { - final Extra? extra = await _onAuthSuccess?.call(user); - emit(AuthenticationState.authenticated(user, extra)); - } else { - _authenticationRepository.changeCubitStatus(AuthCubitStatus.stoped); - emit(const AuthenticationState.unauthenticated()); - } - } - - void logOut() { - unawaited(_authenticationRepository.signOut()); - } - - @override - Future close() { - _userSubscription?.cancel(); - _statusSubscription.cancel(); - return super.close(); + FutureOr signOut() { + // TODO(hpcl): maybe force unauthenticated by emitting an event + _authenticationRepository.signOut(); } } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart index d01fdfb7..0a3bc98e 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart @@ -16,42 +16,28 @@ part of 'authentication_cubit.dart'; -enum AuthenticationStatus { - unknown, - authenticated, - unauthenticated, -} - class AuthenticationState extends Equatable { final AuthenticationStatus status; - final User? user; - final Extra? extra; + final AccountWrapper? accountWrapper; - const AuthenticationState._({ - required this.status, - this.user, - this.extra, - }); + const AuthenticationState._({required this.status, this.accountWrapper}); const AuthenticationState.unknown() : this._(status: AuthenticationStatus.unknown); - const AuthenticationState.authenticated( - User user, - Extra? extra, - ) : this._( + const AuthenticationState.authenticated(AccountWrapper accountWrapper) + : this._( status: AuthenticationStatus.authenticated, - user: user, - extra: extra, + accountWrapper: accountWrapper, ); const AuthenticationState.unauthenticated() : this._(status: AuthenticationStatus.unauthenticated); @override - List get props => [status, user, extra]; + List get props => [status]; @override String toString() => - 'AuthenticationState(status: $status, user: $user, extra: $extra)'; + 'AuthenticationState(status: $status, accountWrapper: $accountWrapper)'; } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart deleted file mode 100644 index 2ef607a0..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:equatable/equatable.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; -import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart' show FormStatus; - -part 'email_verification_state.dart'; - -class EmailVerificationCubit extends Cubit { - final AuthenticationRepository _authenticationRepository; - - EmailVerificationCubit({ - required AuthenticationRepository authenticationRepository, - }) : _authenticationRepository = authenticationRepository, - super(const EmailVerificationState()); - - Future sendEmailVerification() async { - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.sendEmailVerification(); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SendEmailVerificationFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } - } - - Future checkEmailVerification() async { - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.refresh(); - emit( - state.copyWith( - isVerified: _authenticationRepository.currentUser.emailVerified, - status: FormStatus.submissionSuccess, - ), - ); - } on RefreshFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } - } -} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart deleted file mode 100644 index f05f2caf..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -part of 'email_verification_cubit.dart'; - -class EmailVerificationState extends Equatable { - final bool isVerified; - final FormStatus status; - final String? errorMessage; - - const EmailVerificationState({ - this.isVerified = false, - this.status = FormStatus.pure, - this.errorMessage, - }); - - EmailVerificationState copyWith({ - bool? isVerified, - FormStatus? status, - String? errorMessage, - }) => EmailVerificationState( - isVerified: isVerified ?? this.isVerified, - status: status ?? this.status, - errorMessage: errorMessage ?? this.errorMessage, - ); - - @override - List get props => [isVerified, status]; -} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart b/packages/wyatt_authentication_bloc/lib/src/features/features.dart similarity index 85% rename from packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart rename to packages/wyatt_authentication_bloc/lib/src/features/features.dart index 59beab8e..e1b478e9 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/features.dart @@ -1,17 +1,19 @@ // 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 . -export 'cubit/email_verification_cubit.dart'; +export 'authentication/authentication.dart'; +export 'sign_in/sign_in.dart'; +export 'sign_up/sign_up.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart deleted file mode 100644 index 66ab6545..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:equatable/equatable.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; -import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; - -part 'password_reset_state.dart'; - -class PasswordResetCubit extends Cubit { - final AuthenticationRepository _authenticationRepository; - - final FormValidator _validationStrategy; - - PasswordResetCubit({ - required AuthenticationRepository authenticationRepository, - FormValidator validationStrategy = const EveryInputValidator(), - }) : _authenticationRepository = authenticationRepository, - _validationStrategy = validationStrategy, - super(const PasswordResetState()); - - void emailChanged(String value) { - final Email email = Email.dirty(value); - emit( - state.copyWith( - email: email, - status: _validationStrategy.rawValidate([email]), - ), - ); - } - - Future sendPasswordResetEmail() async { - if (!state.status.isValidated) { - return; - } - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.sendPasswordResetEmail( - email: state.email.value, - ); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SendPasswordResetEmailFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } - } -} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart deleted file mode 100644 index e8100c8e..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -part of 'password_reset_cubit.dart'; - -class PasswordResetState extends Equatable { - final Email email; - final FormStatus status; - final String? errorMessage; - - const PasswordResetState({ - this.email = const Email.pure(), - this.status = FormStatus.pure, - this.errorMessage, - }); - - PasswordResetState copyWith({ - Email? email, - FormStatus? status, - String? errorMessage, - }) => PasswordResetState( - email: email ?? this.email, - status: status ?? this.status, - errorMessage: errorMessage ?? this.errorMessage, - ); - - @override - List get props => [email, status]; -} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart deleted file mode 100644 index 43919e02..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -export 'cubit/password_reset_cubit.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart index 2891dc57..531c94b4 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart @@ -16,20 +16,18 @@ import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; part 'sign_in_state.dart'; -class SignInCubit extends Cubit { - final AuthenticationRepository _authenticationRepository; +class SignInCubit extends Cubit { + final AuthenticationRepository _authenticationRepository; final FormValidator _validationStrategy; SignInCubit({ - required AuthenticationRepository authenticationRepository, + required AuthenticationRepository authenticationRepository, FormValidator validationStrategy = const EveryInputValidator(), }) : _authenticationRepository = authenticationRepository, _validationStrategy = validationStrategy, @@ -55,71 +53,26 @@ class SignInCubit extends Cubit { ); } - Future signInAnonymously() async { - if (state.status.isSubmissionInProgress) { - return; - } - - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.signInAnonymously(); - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SignInAnonymouslyFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } - } - - Future signInWithGoogle() async { - if (state.status.isSubmissionInProgress) { - return; - } - - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.signInWithGoogle(); - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SignInWithGoogleFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } - } - Future signInWithEmailAndPassword() async { if (!state.status.isValidated) { return; } + emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.signInWithEmailAndPassword( - email: state.email.value, - password: state.password.value, - ); - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SignInWithEmailAndPasswordFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, + + final uid = await _authenticationRepository.signInWithEmailAndPassword( + email: state.email.value, + password: state.password.value, + ); + + emit( + uid.fold( + (value) => state.copyWith(status: FormStatus.submissionSuccess), + (error) => state.copyWith( + errorMessage: error.message, status: FormStatus.submissionFailure, ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } + ), + ); } } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart index 77700ab6..ea803529 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart @@ -1,16 +1,16 @@ // 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 . diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart index 3e79b7a8..5d338498 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart @@ -17,28 +17,22 @@ import 'dart:async'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; part 'sign_up_state.dart'; -class SignUpCubit extends Cubit { - final AuthenticationRepository _authenticationRepository; +class SignUpCubit extends Cubit { + final AuthenticationRepository _authenticationRepository; - final Future Function(SignUpState state, String? uid)? _onSignUpSuccess; final FormValidator _validationStrategy; SignUpCubit({ - required AuthenticationRepository authenticationRepository, + required AuthenticationRepository authenticationRepository, required FormData formData, FormValidator validationStrategy = const EveryInputValidator(), - Future Function(SignUpState state, String? uid)? onSignUpSuccess, }) : _authenticationRepository = authenticationRepository, - _onSignUpSuccess = onSignUpSuccess, _validationStrategy = validationStrategy, super(SignUpState(data: formData)); @@ -144,24 +138,20 @@ class SignUpCubit extends Cubit { return; } emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - final uid = await _authenticationRepository.signUp( - email: state.email.value, - password: state.password.value, - ); - await _onSignUpSuccess?.call(state, uid); - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SignUpWithEmailAndPasswordFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, + + final uid = await _authenticationRepository.signUp( + email: state.email.value, + password: state.password.value, + ); + + emit( + uid.fold( + (value) => state.copyWith(status: FormStatus.submissionSuccess), + (error) => state.copyWith( + errorMessage: error.message, status: FormStatus.submissionFailure, ), - ); - } catch (e) { - debugPrint(e.toString()); - emit(state.copyWith(status: FormStatus.submissionFailure)); - } + ), + ); } } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart index 798c644d..d03bdb75 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart @@ -1,16 +1,16 @@ // 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 . diff --git a/packages/wyatt_authentication_bloc/lib/src/src.dart b/packages/wyatt_authentication_bloc/lib/src/src.dart index 62ba6ef9..e5a07de0 100644 --- a/packages/wyatt_authentication_bloc/lib/src/src.dart +++ b/packages/wyatt_authentication_bloc/lib/src/src.dart @@ -1,30 +1,20 @@ // 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 . -export 'core/enum/auth_cubit_status.dart'; -export 'core/exceptions/exceptions.dart'; -export 'core/exceptions/exceptions_firebase.dart'; -export 'core/extensions/firebase_auth_user_x.dart'; -export 'core/utils/cryptography.dart'; -export 'data/models/user_firebase.dart'; -export 'data/repositories/authentication_repository_firebase.dart'; -export 'domain/entities/user.dart'; -export 'domain/repositories/authentication_repository.dart'; -export 'features/authentication/authentication.dart'; -export 'features/email_verification/email_verification.dart'; -export 'features/password_reset/password_reset.dart'; -export 'features/sign_in/sign_in.dart'; -export 'features/sign_up/sign_up.dart'; +export 'core/core.dart'; +export 'data/data.dart'; +export 'domain/domain.dart'; +export 'features/features.dart'; From 79fdd3c83751d0507512504bfc8a3e13a8e2c750 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Wed, 9 Nov 2022 01:48:32 -0500 Subject: [PATCH 06/18] doc(auth): update example --- .../example_router/.metadata | 12 +- .../example_router/ios/.gitignore | 34 ++ .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../example_router/ios/Flutter/Debug.xcconfig | 2 + .../ios/Flutter/Release.xcconfig | 2 + .../example_router/ios/Podfile | 41 ++ .../example_router/ios/Podfile.lock | 142 +++++ .../ios/Runner.xcodeproj/project.pbxproj | 552 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 87 +++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 ++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 ++ .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../example_router/ios/Runner/Info.plist | 51 ++ .../ios/Runner/Runner-Bridging-Header.h | 1 + .../ios/firebase_app_id_file.json | 7 + .../example_router/lib/bootstrap.dart | 9 +- .../lib/core/dependency_injection/get_it.dart | 34 ++ .../example_router/lib/firebase_options.dart | 15 +- .../lib/presentation/features/app/app.dart | 56 +- .../presentation/features/home/home_page.dart | 15 +- .../sign_in/widgets/sign_in_form.dart | 6 +- .../presentation/features/sub/sub_page.dart | 4 +- .../features/welcome/welcome_page.dart | 10 +- .../example_router/pubspec.yaml | 7 +- 51 files changed, 1327 insertions(+), 61 deletions(-) create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/.gitignore create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Flutter/Debug.xcconfig create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Flutter/Release.xcconfig create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Podfile create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Podfile.lock create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/AppDelegate.swift create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Info.plist create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/Runner/Runner-Bridging-Header.h create mode 100644 packages/wyatt_authentication_bloc/example_router/ios/firebase_app_id_file.json create mode 100644 packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart diff --git a/packages/wyatt_authentication_bloc/example_router/.metadata b/packages/wyatt_authentication_bloc/example_router/.metadata index 2544bab1..8c2e2e3d 100644 --- a/packages/wyatt_authentication_bloc/example_router/.metadata +++ b/packages/wyatt_authentication_bloc/example_router/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled. version: - revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 channel: stable project_type: app @@ -13,11 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 - base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 - - platform: android - create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 - base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 + base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 + - platform: ios + create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 + base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 # User provided section diff --git a/packages/wyatt_authentication_bloc/example_router/ios/.gitignore b/packages/wyatt_authentication_bloc/example_router/ios/.gitignore new file mode 100644 index 00000000..7a7f9873 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Flutter/AppFrameworkInfo.plist b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..9625e105 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Debug.xcconfig b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..ec97fc6f --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Release.xcconfig b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..c4855bfe --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Podfile b/packages/wyatt_authentication_bloc/example_router/ios/Podfile new file mode 100644 index 00000000..88359b22 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '11.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Podfile.lock b/packages/wyatt_authentication_bloc/example_router/ios/Podfile.lock new file mode 100644 index 00000000..1a4d1789 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Podfile.lock @@ -0,0 +1,142 @@ +PODS: + - AppAuth (1.6.0): + - AppAuth/Core (= 1.6.0) + - AppAuth/ExternalUserAgent (= 1.6.0) + - AppAuth/Core (1.6.0) + - AppAuth/ExternalUserAgent (1.6.0): + - AppAuth/Core + - FBAEMKit (14.1.0): + - FBSDKCoreKit_Basics (= 14.1.0) + - FBSDKCoreKit (14.1.0): + - FBAEMKit (= 14.1.0) + - FBSDKCoreKit_Basics (= 14.1.0) + - FBSDKCoreKit_Basics (14.1.0) + - FBSDKLoginKit (14.1.0): + - FBSDKCoreKit (= 14.1.0) + - Firebase/Auth (10.0.0): + - Firebase/CoreOnly + - FirebaseAuth (~> 10.0.0) + - Firebase/CoreOnly (10.0.0): + - FirebaseCore (= 10.0.0) + - firebase_auth (4.1.1): + - Firebase/Auth (= 10.0.0) + - firebase_core + - Flutter + - firebase_core (2.1.1): + - Firebase/CoreOnly (= 10.0.0) + - Flutter + - FirebaseAuth (10.0.0): + - FirebaseCore (~> 10.0) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GTMSessionFetcher/Core (~> 2.1) + - FirebaseCore (10.0.0): + - FirebaseCoreInternal (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Logger (~> 7.8) + - FirebaseCoreInternal (10.1.0): + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - Flutter (1.0.0) + - flutter_facebook_auth (4.4.1): + - FBSDKLoginKit (= 14.1.0) + - Flutter + - google_sign_in_ios (0.0.1): + - Flutter + - GoogleSignIn (~> 6.2) + - GoogleSignIn (6.2.4): + - AppAuth (~> 1.5) + - GTMAppAuth (~> 1.3) + - GTMSessionFetcher/Core (< 3.0, >= 1.1) + - GoogleUtilities/AppDelegateSwizzler (7.8.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (7.8.0): + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.8.0): + - GoogleUtilities/Environment + - GoogleUtilities/Network (7.8.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (7.8.0)" + - GoogleUtilities/Reachability (7.8.0): + - GoogleUtilities/Logger + - GTMAppAuth (1.3.1): + - AppAuth/Core (~> 1.6) + - GTMSessionFetcher/Core (< 3.0, >= 1.5) + - GTMSessionFetcher/Core (2.1.0) + - PromisesObjC (2.1.1) + - sign_in_with_apple (0.0.1): + - Flutter + - twitter_login (0.0.1): + - Flutter + +DEPENDENCIES: + - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - Flutter (from `Flutter`) + - flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`) + - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`) + - sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`) + - twitter_login (from `.symlinks/plugins/twitter_login/ios`) + +SPEC REPOS: + trunk: + - AppAuth + - FBAEMKit + - FBSDKCoreKit + - FBSDKCoreKit_Basics + - FBSDKLoginKit + - Firebase + - FirebaseAuth + - FirebaseCore + - FirebaseCoreInternal + - GoogleSignIn + - GoogleUtilities + - GTMAppAuth + - GTMSessionFetcher + - PromisesObjC + +EXTERNAL SOURCES: + firebase_auth: + :path: ".symlinks/plugins/firebase_auth/ios" + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + Flutter: + :path: Flutter + flutter_facebook_auth: + :path: ".symlinks/plugins/flutter_facebook_auth/ios" + google_sign_in_ios: + :path: ".symlinks/plugins/google_sign_in_ios/ios" + sign_in_with_apple: + :path: ".symlinks/plugins/sign_in_with_apple/ios" + twitter_login: + :path: ".symlinks/plugins/twitter_login/ios" + +SPEC CHECKSUMS: + AppAuth: 8fca6b5563a5baef2c04bee27538025e4ceb2add + FBAEMKit: a899515e45476027f73aef377b5cffadcd56ca3a + FBSDKCoreKit: 24f8bc8d3b5b2a8c5c656a1329492a12e8efa792 + FBSDKCoreKit_Basics: 6e578c9bdc7aa1365dbbbde633c9ebb536bcaa98 + FBSDKLoginKit: 787de205d524c3a4b17d527916f1d066e4361660 + Firebase: 1b810f3d0c0532e27a48f1961f8c0400a668a2cf + firebase_auth: dd33e93fce72a1c72040f7380dacf06e89db5705 + firebase_core: 5c0bb0ca7d0e70480a68a6e9ad9bf55d1edd5305 + FirebaseAuth: 493382cf533cc45e2862b00e9aa4cfe4c98daf71 + FirebaseCore: 97f48a3a567a72b8d4daa0f03c3aadb78df4e995 + FirebaseCoreInternal: 96d75228e10fd369564da51bd898414eb0f54df5 + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + flutter_facebook_auth: 361ac7a57263ebf327f26089507ead0d66558ee8 + google_sign_in_ios: 4f85eb9f937450765c8573bb85fd8cd6a5af675c + GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a + GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7 + GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd + GTMSessionFetcher: ffbb25ec00ebcb5201adab0a56d808f6f1902d9f + PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb + sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440 + twitter_login: 2794db69b7640681171b17b3c2c84ad9dfb4a57f + +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 + +COCOAPODS: 1.11.3 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.pbxproj b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..11d0d0ad --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,552 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 69F3BBCD5DEB05A456F6B74F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0A061B2E527F311149C3581 /* Pods_Runner.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 07E343497E760D6A90A105C5 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B0A061B2E527F311149C3581 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F0D7945BAE0BEA457137ED73 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + F9340E3A859C31E59380BD0F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 69F3BBCD5DEB05A456F6B74F /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 66B357379C2757D2844F12BB /* Pods */ = { + isa = PBXGroup; + children = ( + F0D7945BAE0BEA457137ED73 /* Pods-Runner.debug.xcconfig */, + F9340E3A859C31E59380BD0F /* Pods-Runner.release.xcconfig */, + 07E343497E760D6A90A105C5 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 66B357379C2757D2844F12BB /* Pods */, + BC1E25CE0DADDF7B7201CCF8 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + BC1E25CE0DADDF7B7201CCF8 /* Frameworks */ = { + isa = PBXGroup; + children = ( + B0A061B2E527F311149C3581 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 92D20EC4971D81AAB7475BDB /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + DEBBE8DDE939288865FFA279 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 92D20EC4971D81AAB7475BDB /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + DEBBE8DDE939288865FFA279 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 6Z5P8GG96U; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleRouter; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 6Z5P8GG96U; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleRouter; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 6Z5P8GG96U; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleRouter; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..c87d15a3 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/AppDelegate.swift b/packages/wyatt_authentication_bloc/example_router/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 zcmeHN2~<R zh`|8`A_PQ1nSu(UMFx?8j8PC!!VDphaL#`F42fd#7Vlc`zIE4n%Y~eiz4y1j|NDpi z?<@|pSJ-HM`qifhf@m%MamgwK83`XpBA<+azdF#2QsT{X@z0A9Bq>~TVErigKH1~P zRX-!h-f0NJ4Mh++{D}J+K>~~rq}d%o%+4dogzXp7RxX4C>Km5XEI|PAFDmo;DFm6G zzjVoB`@qW98Yl0Kvc-9w09^PrsobmG*Eju^=3f?0o-t$U)TL1B3;sZ^!++3&bGZ!o-*6w?;oOhf z=A+Qb$scV5!RbG+&2S}BQ6YH!FKb0``VVX~T$dzzeSZ$&9=X$3)_7Z{SspSYJ!lGE z7yig_41zpQ)%5dr4ff0rh$@ky3-JLRk&DK)NEIHecf9c*?Z1bUB4%pZjQ7hD!A0r-@NF(^WKdr(LXj|=UE7?gBYGgGQV zidf2`ZT@pzXf7}!NH4q(0IMcxsUGDih(0{kRSez&z?CFA0RVXsVFw3^u=^KMtt95q z43q$b*6#uQDLoiCAF_{RFc{!H^moH_cmll#Fc^KXi{9GDl{>%+3qyfOE5;Zq|6#Hb zp^#1G+z^AXfRKaa9HK;%b3Ux~U@q?xg<2DXP%6k!3E)PA<#4$ui8eDy5|9hA5&{?v z(-;*1%(1~-NTQ`Is1_MGdQ{+i*ccd96ab$R$T3=% zw_KuNF@vI!A>>Y_2pl9L{9h1-C6H8<)J4gKI6{WzGBi<@u3P6hNsXG=bRq5c+z;Gc3VUCe;LIIFDmQAGy+=mRyF++u=drBWV8-^>0yE9N&*05XHZpPlE zxu@?8(ZNy7rm?|<+UNe0Vs6&o?l`Pt>P&WaL~M&#Eh%`rg@Mbb)J&@DA-wheQ>hRV z<(XhigZAT z>=M;URcdCaiO3d^?H<^EiEMDV+7HsTiOhoaMX%P65E<(5xMPJKxf!0u>U~uVqnPN7T!X!o@_gs3Ct1 zlZ_$5QXP4{Aj645wG_SNT&6m|O6~Tsl$q?nK*)(`{J4b=(yb^nOATtF1_aS978$x3 zx>Q@s4i3~IT*+l{@dx~Hst21fR*+5}S1@cf>&8*uLw-0^zK(+OpW?cS-YG1QBZ5q! zgTAgivzoF#`cSz&HL>Ti!!v#?36I1*l^mkrx7Y|K6L#n!-~5=d3;K<;Zqi|gpNUn_ z_^GaQDEQ*jfzh;`j&KXb66fWEk1K7vxQIMQ_#Wu_%3 z4Oeb7FJ`8I>Px;^S?)}2+4D_83gHEq>8qSQY0PVP?o)zAv3K~;R$fnwTmI-=ZLK`= zTm+0h*e+Yfr(IlH3i7gUclNH^!MU>id$Jw>O?2i0Cila#v|twub21@e{S2v}8Z13( zNDrTXZVgris|qYm<0NU(tAPouG!QF4ZNpZPkX~{tVf8xY690JqY1NVdiTtW+NqyRP zZ&;T0ikb8V{wxmFhlLTQ&?OP7 z;(z*<+?J2~z*6asSe7h`$8~Se(@t(#%?BGLVs$p``;CyvcT?7Y!{tIPva$LxCQ&4W z6v#F*);|RXvI%qnoOY&i4S*EL&h%hP3O zLsrFZhv&Hu5tF$Lx!8(hs&?!Kx5&L(fdu}UI5d*wn~A`nPUhG&Rv z2#ixiJdhSF-K2tpVL=)5UkXRuPAFrEW}7mW=uAmtVQ&pGE-&az6@#-(Te^n*lrH^m@X-ftVcwO_#7{WI)5v(?>uC9GG{lcGXYJ~Q8q zbMFl7;t+kV;|;KkBW2!P_o%Czhw&Q(nXlxK9ak&6r5t_KH8#1Mr-*0}2h8R9XNkr zto5-b7P_auqTJb(TJlmJ9xreA=6d=d)CVbYP-r4$hDn5|TIhB>SReMfh&OVLkMk-T zYf%$taLF0OqYF?V{+6Xkn>iX@TuqQ?&cN6UjC9YF&%q{Ut3zv{U2)~$>-3;Dp)*(? zg*$mu8^i=-e#acaj*T$pNowo{xiGEk$%DusaQiS!KjJH96XZ-hXv+jk%ard#fu=@Q z$AM)YWvE^{%tDfK%nD49=PI|wYu}lYVbB#a7wtN^Nml@CE@{Gv7+jo{_V?I*jkdLD zJE|jfdrmVbkfS>rN*+`#l%ZUi5_bMS<>=MBDNlpiSb_tAF|Zy`K7kcp@|d?yaTmB^ zo?(vg;B$vxS|SszusORgDg-*Uitzdi{dUV+glA~R8V(?`3GZIl^egW{a919!j#>f` znL1o_^-b`}xnU0+~KIFLQ)$Q6#ym%)(GYC`^XM*{g zv3AM5$+TtDRs%`2TyR^$(hqE7Y1b&`Jd6dS6B#hDVbJlUXcG3y*439D8MrK!2D~6gn>UD4Imctb z+IvAt0iaW73Iq$K?4}H`7wq6YkTMm`tcktXgK0lKPmh=>h+l}Y+pDtvHnG>uqBA)l zAH6BV4F}v$(o$8Gfo*PB>IuaY1*^*`OTx4|hM8jZ?B6HY;F6p4{`OcZZ(us-RVwDx zUzJrCQlp@mz1ZFiSZ*$yX3c_#h9J;yBE$2g%xjmGF4ca z&yL`nGVs!Zxsh^j6i%$a*I3ZD2SoNT`{D%mU=LKaEwbN(_J5%i-6Va?@*>=3(dQy` zOv%$_9lcy9+(t>qohkuU4r_P=R^6ME+wFu&LA9tw9RA?azGhjrVJKy&8=*qZT5Dr8g--d+S8zAyJ$1HlW3Olryt`yE zFIph~Z6oF&o64rw{>lgZISC6p^CBer9C5G6yq%?8tC+)7*d+ib^?fU!JRFxynRLEZ zj;?PwtS}Ao#9whV@KEmwQgM0TVP{hs>dg(1*DiMUOKHdQGIqa0`yZnHk9mtbPfoLx zo;^V6pKUJ!5#n`w2D&381#5#_t}AlTGEgDz$^;u;-vxDN?^#5!zN9ngytY@oTv!nc zp1Xn8uR$1Z;7vY`-<*?DfPHB;x|GUi_fI9@I9SVRv1)qETbNU_8{5U|(>Du84qP#7 z*l9Y$SgA&wGbj>R1YeT9vYjZuC@|{rajTL0f%N@>3$DFU=`lSPl=Iv;EjuGjBa$Gw zHD-;%YOE@<-!7-Mn`0WuO3oWuL6tB2cpPw~Nvuj|KM@))ixuDK`9;jGMe2d)7gHin zS<>k@!x;!TJEc#HdL#RF(`|4W+H88d4V%zlh(7#{q2d0OQX9*FW^`^_<3r$kabWAB z$9BONo5}*(%kx zOXi-yM_cmB3>inPpI~)duvZykJ@^^aWzQ=eQ&STUa}2uT@lV&WoRzkUoE`rR0)`=l zFT%f|LA9fCw>`enm$p7W^E@U7RNBtsh{_-7vVz3DtB*y#*~(L9+x9*wn8VjWw|Q~q zKFsj1Yl>;}%MG3=PY`$g$_mnyhuV&~O~u~)968$0b2!Jkd;2MtAP#ZDYw9hmK_+M$ zb3pxyYC&|CuAbtiG8HZjj?MZJBFbt`ryf+c1dXFuC z0*ZQhBzNBd*}s6K_G}(|Z_9NDV162#y%WSNe|FTDDhx)K!c(mMJh@h87@8(^YdK$&d*^WQe8Z53 z(|@MRJ$Lk-&ii74MPIs80WsOFZ(NX23oR-?As+*aq6b?~62@fSVmM-_*cb1RzZ)`5$agEiL`-E9s7{GM2?(KNPgK1(+c*|-FKoy}X(D_b#etO|YR z(BGZ)0Ntfv-7R4GHoXp?l5g#*={S1{u-QzxCGng*oWr~@X-5f~RA14b8~B+pLKvr4 zfgL|7I>jlak9>D4=(i(cqYf7#318!OSR=^`xxvI!bBlS??`xxWeg?+|>MxaIdH1U~#1tHu zB{QMR?EGRmQ_l4p6YXJ{o(hh-7Tdm>TAX380TZZZyVkqHNzjUn*_|cb?T? zt;d2s-?B#Mc>T-gvBmQZx(y_cfkXZO~{N zT6rP7SD6g~n9QJ)8F*8uHxTLCAZ{l1Y&?6v)BOJZ)=R-pY=Y=&1}jE7fQ>USS}xP#exo57uND0i*rEk@$;nLvRB@u~s^dwRf?G?_enN@$t* zbL%JO=rV(3Ju8#GqUpeE3l_Wu1lN9Y{D4uaUe`g>zlj$1ER$6S6@{m1!~V|bYkhZA z%CvrDRTkHuajMU8;&RZ&itnC~iYLW4DVkP<$}>#&(`UO>!n)Po;Mt(SY8Yb`AS9lt znbX^i?Oe9r_o=?})IHKHoQGKXsps_SE{hwrg?6dMI|^+$CeC&z@*LuF+P`7LfZ*yr+KN8B4{Nzv<`A(wyR@!|gw{zB6Ha ziwPAYh)oJ(nlqSknu(8g9N&1hu0$vFK$W#mp%>X~AU1ay+EKWcFdif{% z#4!4aoVVJ;ULmkQf!ke2}3hqxLK>eq|-d7Ly7-J9zMpT`?dxo6HdfJA|t)?qPEVBDv z{y_b?4^|YA4%WW0VZd8C(ZgQzRI5(I^)=Ub`Y#MHc@nv0w-DaJAqsbEHDWG8Ia6ju zo-iyr*sq((gEwCC&^TYBWt4_@|81?=B-?#P6NMff(*^re zYqvDuO`K@`mjm_Jd;mW_tP`3$cS?R$jR1ZN09$YO%_iBqh5ftzSpMQQtxKFU=FYmP zeY^jph+g<4>YO;U^O>-NFLn~-RqlHvnZl2yd2A{Yc1G@Ga$d+Q&(f^tnPf+Z7serIU};17+2DU_f4Z z@GaPFut27d?!YiD+QP@)T=77cR9~MK@bd~pY%X(h%L={{OIb8IQmf-!xmZkm8A0Ga zQSWONI17_ru5wpHg3jI@i9D+_Y|pCqVuHJNdHUauTD=R$JcD2K_liQisqG$(sm=k9;L* z!L?*4B~ql7uioSX$zWJ?;q-SWXRFhz2Jt4%fOHA=Bwf|RzhwqdXGr78y$J)LR7&3T zE1WWz*>GPWKZ0%|@%6=fyx)5rzUpI;bCj>3RKzNG_1w$fIFCZ&UR0(7S?g}`&Pg$M zf`SLsz8wK82Vyj7;RyKmY{a8G{2BHG%w!^T|Njr!h9TO2LaP^_f22Q1=l$QiU84ao zHe_#{S6;qrC6w~7{y(hs-?-j?lbOfgH^E=XcSgnwW*eEz{_Z<_Px$?ny*JR5%f>l)FnDQ543{x%ZCiu33$Wg!pQFfT_}?5Q|_VSlIbLC`dpoMXL}9 zHfd9&47Mo(7D231gb+kjFxZHS4-m~7WurTH&doVX2KI5sU4v(sJ1@T9eCIKPjsqSr z)C01LsCxk=72-vXmX}CQD#BD;Cthymh&~=f$Q8nn0J<}ZrusBy4PvRNE}+1ceuj8u z0mW5k8fmgeLnTbWHGwfKA3@PdZxhn|PypR&^p?weGftrtCbjF#+zk_5BJh7;0`#Wr zgDpM_;Ax{jO##IrT`Oz;MvfwGfV$zD#c2xckpcXC6oou4ML~ezCc2EtnsQTB4tWNg z?4bkf;hG7IMfhgNI(FV5Gs4|*GyMTIY0$B=_*mso9Ityq$m^S>15>-?0(zQ<8Qy<_TjHE33(?_M8oaM zyc;NxzRVK@DL6RJnX%U^xW0Gpg(lXp(!uK1v0YgHjs^ZXSQ|m#lV7ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/Main.storyboard b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Info.plist b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Info.plist new file mode 100644 index 00000000..e2987027 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Example Router + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + example_router + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Runner-Bridging-Header.h b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/wyatt_authentication_bloc/example_router/ios/firebase_app_id_file.json b/packages/wyatt_authentication_bloc/example_router/ios/firebase_app_id_file.json new file mode 100644 index 00000000..17445d1d --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:136771801992:ios:bcdca68d2b7d227097203d", + "FIREBASE_PROJECT_ID": "tchat-beta", + "GCM_SENDER_ID": "136771801992" +} \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/example_router/lib/bootstrap.dart b/packages/wyatt_authentication_bloc/example_router/lib/bootstrap.dart index cc0ab97e..f5fd03eb 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/bootstrap.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/bootstrap.dart @@ -3,23 +3,24 @@ // ----- // File: bootstrap.dart // Created Date: 19/08/2022 15:05:17 -// Last Modified: 19/08/2022 15:21:47 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 import 'dart:async'; +import 'package:example_router/core/dependency_injection/get_it.dart'; import 'package:example_router/core/utils/app_bloc_observer.dart'; import 'package:example_router/firebase_options.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:go_router/go_router.dart'; Future bootstrap(FutureOr Function() builder) async { await runZonedGuarded( () async { WidgetsFlutterBinding.ensureInitialized(); + Bloc.observer = AppBlocObserver(); FlutterError.onError = (details) { debugPrint(details.toString()); @@ -29,9 +30,7 @@ Future bootstrap(FutureOr Function() builder) async { options: DefaultFirebaseOptions.currentPlatform, ); - GoRouter.setUrlPathStrategy(UrlPathStrategy.path); - - Bloc.observer = AppBlocObserver(); + await GetItInitializer.init(); runApp(await builder()); }, diff --git a/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart b/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart new file mode 100644 index 00000000..0466f831 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart @@ -0,0 +1,34 @@ +// 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 . + +import 'package:get_it/get_it.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; + +final getIt = GetIt.I; + +abstract class GetItInitializer { + static Future init() async { + getIt + ..registerLazySingleton( + () => AuthenticationFirebaseDataSourceImpl(), + ) + ..registerLazySingleton>( + () => AuthenticationCacheDataSourceImpl(), + ); + + await getIt.allReady(); + } +} diff --git a/packages/wyatt_authentication_bloc/example_router/lib/firebase_options.dart b/packages/wyatt_authentication_bloc/example_router/lib/firebase_options.dart index 20a9ebf6..f0198262 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/firebase_options.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/firebase_options.dart @@ -24,12 +24,12 @@ class DefaultFirebaseOptions { } switch (defaultTargetPlatform) { case TargetPlatform.android: - return android; - case TargetPlatform.iOS: throw UnsupportedError( - 'DefaultFirebaseOptions have not been configured for ios - ' + 'DefaultFirebaseOptions have not been configured for android - ' 'you can reconfigure this by running the FlutterFire CLI again.', ); + case TargetPlatform.iOS: + return ios; case TargetPlatform.macOS: throw UnsupportedError( 'DefaultFirebaseOptions have not been configured for macos - ' @@ -52,12 +52,15 @@ class DefaultFirebaseOptions { } } - static const FirebaseOptions android = FirebaseOptions( - apiKey: 'AIzaSyAYS14uXupkS158Q5QAFP1864UrUN_yDSk', - appId: '1:136771801992:android:ac3cfeb99fb0763e97203d', + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyCDbbhjbFrQwLXuIANdJzjkDk8uOETnn7w', + appId: '1:136771801992:ios:bcdca68d2b7d227097203d', messagingSenderId: '136771801992', projectId: 'tchat-beta', databaseURL: 'https://tchat-beta.firebaseio.com', storageBucket: 'tchat-beta.appspot.com', + androidClientId: '136771801992-n2pq8oqutvrqj58e05hbavvc7n1jdfjb.apps.googleusercontent.com', + iosClientId: '136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9.apps.googleusercontent.com', + iosBundleId: 'com.example.exampleRouter', ); } diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart index 291387e7..0f503aa6 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart @@ -3,10 +3,13 @@ // ----- // File: app.dart // Created Date: 19/08/2022 12:05:38 -// Last Modified: Fri Aug 26 2022 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 +import 'dart:async'; + +import 'package:example_router/core/dependency_injection/get_it.dart'; import 'package:example_router/core/routes/router.dart'; import 'package:example_router/core/utils/forms.dart'; import 'package:example_router/presentation/features/home/home_page.dart'; @@ -15,10 +18,18 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; class App extends StatelessWidget { - final AuthenticationRepository authenticationRepository = - AuthenticationRepositoryFirebase(); + final AuthenticationRepository authenticationRepository = + AuthenticationRepositoryImpl(getIt>(), + getIt(), (account) async { + debugPrint('onSignUpSuccess: $account'); + return const Ok(null); + }, (account) async { + debugPrint('onAccountChanges: $account'); + return const Ok(null); + }); App({Key? key}) : super(key: key); @@ -26,13 +37,8 @@ class App extends StatelessWidget { Widget build(BuildContext context) { AuthenticationState? previous; - final AuthenticationCubit authenticationCubit = AuthenticationCubit( - authenticationRepository: authenticationRepository, - onAuthSuccess: (user) async { - debugPrint(user.toString()); - return {}; - }, - ); + final AuthenticationCubit authenticationCubit = + AuthenticationCubit(authenticationRepository: authenticationRepository); final GoRouter router = GoRouter( initialLocation: '/', @@ -42,7 +48,7 @@ class App extends StatelessWidget { color: Colors.red, ), refreshListenable: GoRouterRefreshStream(authenticationCubit.stream), - redirect: (state) { + redirect: (context, state) { final authState = authenticationCubit.state; if (authState != previous) { @@ -62,8 +68,7 @@ class App extends StatelessWidget { return state.namedLocation(WelcomePage.pageName); } } else { - final email = authState.user?.email; - debugPrint('Logged as: $email'); + debugPrint('Logged'); if (isOnboarding) { return state.namedLocation(HomePage.pageName); } else { @@ -83,17 +88,13 @@ class App extends StatelessWidget { ], child: MultiBlocProvider( providers: [ - BlocProvider.value( - value: authenticationCubit..init(), + BlocProvider>.value( + value: authenticationCubit, ), BlocProvider( create: (_) => SignUpCubit( authenticationRepository: authenticationRepository, formData: Forms.getNormalData(), - onSignUpSuccess: (state, uid) async { - debugPrint(state.toString()); - debugPrint(uid); - }, ), ), BlocProvider( @@ -113,3 +114,20 @@ class App extends StatelessWidget { ); } } + +class GoRouterRefreshStream extends ChangeNotifier { + GoRouterRefreshStream(Stream stream) { + notifyListeners(); + _subscription = stream.asBroadcastStream().listen( + (dynamic _) => notifyListeners(), + ); + } + + late final StreamSubscription _subscription; + + @override + void dispose() { + _subscription.cancel(); + super.dispose(); + } +} diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart index 316598cb..bc980cd3 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart @@ -3,7 +3,7 @@ // ----- // File: home_page.dart // Created Date: 19/08/2022 14:38:24 -// Last Modified: 19/08/2022 16:12:22 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 @@ -25,7 +25,7 @@ class HomePage extends StatelessWidget { title: const Text('Home'), actions: [ IconButton( - onPressed: () => context.read().logOut(), + onPressed: () => context.read>().signOut(), icon: const Icon(Icons.logout_rounded)) ], ), @@ -34,11 +34,12 @@ class HomePage extends StatelessWidget { child: SingleChildScrollView( child: Column( children: [ - BlocBuilder( - builder: (context, state) { - final email = state.user?.email; - return Text('Logged as $email'); - }, + AuthenticationBuilder( + authenticated: (context, accountWrapper) => + Text('Logged as ${accountWrapper.account?.email}'), + unauthenticated: (context) => + const Text('Not logged (unauthenticated)'), + unknown: (context) => const Text('Not logged (unknown)'), ), const SizedBox( height: 8, diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart index ea785177..3f729ad1 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart @@ -3,7 +3,7 @@ // ----- // File: sign_in_form.dart // Created Date: 19/08/2022 15:24:37 -// Last Modified: 19/08/2022 16:35:01 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 @@ -79,9 +79,7 @@ class SignInForm extends StatelessWidget { Widget build(BuildContext context) { return BlocListener( listener: (context, state) { - if (state.status.isSubmissionSuccess) { - Navigator.of(context).pop(); - } else if (state.status.isSubmissionFailure) { + if (state.status.isSubmissionFailure) { ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar( diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sub/sub_page.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sub/sub_page.dart index 34f4558f..14b340b8 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sub/sub_page.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sub/sub_page.dart @@ -3,7 +3,7 @@ // ----- // File: sub_page.dart // Created Date: 19/08/2022 16:10:05 -// Last Modified: 19/08/2022 16:10:44 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 @@ -23,7 +23,7 @@ class SubPage extends StatelessWidget { title: const Text('Sub'), actions: [ IconButton( - onPressed: () => context.read().logOut(), + onPressed: () => context.read>().signOut(), icon: const Icon(Icons.logout_rounded)) ], ), diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/welcome/welcome_page.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/welcome/welcome_page.dart index aa3a10c4..3794f971 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/welcome/welcome_page.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/welcome/welcome_page.dart @@ -3,16 +3,14 @@ // ----- // File: welcome_page.dart // Created Date: 19/08/2022 12:33:21 -// Last Modified: 19/08/2022 15:56:05 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 import 'package:example_router/presentation/features/sign_in/sign_in_page.dart'; import 'package:example_router/presentation/features/sign_up/sign_up_page.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; class WelcomePage extends StatelessWidget { const WelcomePage({Key? key}) : super(key: key); @@ -24,12 +22,6 @@ class WelcomePage extends StatelessWidget { return Scaffold( appBar: AppBar( title: const Text('Welcome'), - actions: [ - IconButton( - onPressed: () => context.read().changeStatus( - context.read().state.user!), - icon: const Icon(Icons.refresh_rounded)) - ], ), body: SingleChildScrollView( child: Column( diff --git a/packages/wyatt_authentication_bloc/example_router/pubspec.yaml b/packages/wyatt_authentication_bloc/example_router/pubspec.yaml index 5f6dec50..98e04304 100644 --- a/packages/wyatt_authentication_bloc/example_router/pubspec.yaml +++ b/packages/wyatt_authentication_bloc/example_router/pubspec.yaml @@ -30,8 +30,8 @@ dependencies: flutter: sdk: flutter - go_router: ^4.2.8 - firebase_core: ^1.21.0 + go_router: ^5.1.5 + firebase_core: ^2.1.1 flutter_bloc: ^8.1.1 wyatt_authentication_bloc: path: "../" @@ -44,7 +44,8 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 + cupertino_icons: ^1.0.5 + get_it: ^7.2.0 dev_dependencies: flutter_test: From b89ef3de8a068bd097d90b621ce51e9cdad3e944 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Wed, 9 Nov 2022 22:35:41 -0500 Subject: [PATCH 07/18] feat!(form): migrate to wyatt architecture --- packages/wyatt_form_bloc/README.md | 6 +- .../wyatt_form_bloc/analysis_options.yaml | 2 +- .../ios/Flutter/AppFrameworkInfo.plist | 2 +- .../ios/Runner.xcodeproj/project.pbxproj | 6 +- .../example/ios/Runner/Info.plist | 2 + .../wyatt_form_bloc/example/lib/app/app.dart | 44 ++- .../example/lib/app/metadata.dart | 4 +- .../example/lib/constants.dart | 2 - .../lib/sign_up/widgets/sign_up_form.dart | 374 +++++++----------- .../simple_custom_form_cubit.dart} | 9 +- .../validators.dart => core/core.dart} | 15 +- .../lib/src/{ => core}/enums/enums.dart | 0 .../{ => core}/enums/form_input_status.dart | 0 .../lib/src/{ => core}/enums/form_status.dart | 0 .../lib/src/core/enums/set_operations.dart | 39 ++ .../{ => core}/enums/validation_error.dart | 3 +- .../lib/src/cubit/form_data_cubit.dart | 110 ------ .../wyatt_form_bloc/lib/src/data/data.dart | 34 ++ .../lib/src/data/form/wyatt_form_impl.dart | 136 +++++++ .../data/form_encoders/form_json_encoder.dart | 30 ++ .../data/form_encoders/form_map_encoder.dart | 32 ++ .../data/form_operations/form_difference.dart | 50 +++ .../form_operations/form_intersection.dart | 44 +++ .../form_operations/form_replace.dart} | 17 +- .../src/data/form_operations/form_union.dart | 48 +++ .../every_input_validator.dart | 14 +- .../only_required_input_validator.dart | 29 ++ .../input_validators}/boolean.dart | 12 +- .../input_validators}/confirmed_password.dart | 20 +- .../input_validators}/email.dart | 6 +- .../input_validators/enum_option.dart} | 31 +- .../data/input_validators/list_option.dart | 40 ++ .../input_validators}/name.dart | 6 +- .../input_validators}/password.dart | 8 +- .../input_validators}/phone.dart | 6 +- .../input_validators}/text_string.dart | 6 +- .../lib/src/domain/domain.dart | 23 ++ .../{form => domain/entities}/form_input.dart | 32 +- .../entities}/form_input_metadata.dart | 28 +- .../lib/src/domain/form/wyatt_form.dart | 60 +++ .../form_encoders/form_encoder.dart} | 17 +- .../form_operations/form_operation.dart | 23 ++ .../form_validators}/form_validator.dart | 14 +- .../input_validators/any_validator.dart | 45 +++ .../input_validators/equality_validator.dart | 45 +++ .../form_input_validator.dart | 22 +- .../input_validators/nullable_validator.dart} | 27 +- .../input_validators}/regex_validator.dart | 11 +- .../input_validators}/text_validator.dart | 9 +- .../lib/src/form/form_data.dart | 184 --------- .../features/form_data/form_data_cubit.dart | 47 +++ .../features/form_data}/form_data_state.dart | 24 +- .../form_data_impl/form_data_cubit_impl.dart | 86 ++++ .../form_data_impl/form_data_state_impl.dart | 42 ++ .../features/widgets/input_builder.dart | 43 ++ .../widgets/input_builder_metadata.dart | 57 +++ .../features/widgets/submit_builder.dart | 37 ++ .../lib/src/presentation/presentation.dart | 21 + packages/wyatt_form_bloc/lib/src/src.dart | 8 +- .../lib/src/validators/inputs/iban.dart | 39 -- .../src/validators/inputs/list_option.dart | 50 --- packages/wyatt_form_bloc/pubspec.yaml | 24 +- 62 files changed, 1387 insertions(+), 818 deletions(-) rename packages/wyatt_form_bloc/example/lib/{cubit/custom_form_cubit.dart => simple_custom_form_cubit/simple_custom_form_cubit.dart} (80%) rename packages/wyatt_form_bloc/lib/src/{validators/validators.dart => core/core.dart} (60%) rename packages/wyatt_form_bloc/lib/src/{ => core}/enums/enums.dart (100%) rename packages/wyatt_form_bloc/lib/src/{ => core}/enums/form_input_status.dart (100%) rename packages/wyatt_form_bloc/lib/src/{ => core}/enums/form_status.dart (100%) create mode 100644 packages/wyatt_form_bloc/lib/src/core/enums/set_operations.dart rename packages/wyatt_form_bloc/lib/src/{ => core}/enums/validation_error.dart (97%) delete mode 100644 packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart create mode 100644 packages/wyatt_form_bloc/lib/src/data/data.dart create mode 100644 packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart create mode 100644 packages/wyatt_form_bloc/lib/src/data/form_encoders/form_json_encoder.dart create mode 100644 packages/wyatt_form_bloc/lib/src/data/form_encoders/form_map_encoder.dart create mode 100644 packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart create mode 100644 packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart rename packages/wyatt_form_bloc/lib/src/{form/form.dart => data/form_operations/form_replace.dart} (64%) create mode 100644 packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart rename packages/wyatt_form_bloc/lib/src/{validators/form => data/form_validators}/every_input_validator.dart (73%) create mode 100644 packages/wyatt_form_bloc/lib/src/data/form_validators/only_required_input_validator.dart rename packages/wyatt_form_bloc/lib/src/{validators/inputs => data/input_validators}/boolean.dart (74%) rename packages/wyatt_form_bloc/lib/src/{validators/inputs => data/input_validators}/confirmed_password.dart (61%) rename packages/wyatt_form_bloc/lib/src/{validators/inputs => data/input_validators}/email.dart (85%) rename packages/wyatt_form_bloc/lib/src/{validators/inputs/siren.dart => data/input_validators/enum_option.dart} (52%) create mode 100644 packages/wyatt_form_bloc/lib/src/data/input_validators/list_option.dart rename packages/wyatt_form_bloc/lib/src/{validators/inputs => data/input_validators}/name.dart (85%) rename packages/wyatt_form_bloc/lib/src/{validators/inputs => data/input_validators}/password.dart (81%) rename packages/wyatt_form_bloc/lib/src/{validators/inputs => data/input_validators}/phone.dart (85%) rename packages/wyatt_form_bloc/lib/src/{validators/inputs => data/input_validators}/text_string.dart (84%) create mode 100644 packages/wyatt_form_bloc/lib/src/domain/domain.dart rename packages/wyatt_form_bloc/lib/src/{form => domain/entities}/form_input.dart (59%) rename packages/wyatt_form_bloc/lib/src/{form => domain/entities}/form_input_metadata.dart (69%) create mode 100644 packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart rename packages/wyatt_form_bloc/lib/src/{enums/set_operations.dart => domain/form_encoders/form_encoder.dart} (75%) create mode 100644 packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart rename packages/wyatt_form_bloc/lib/src/{form => domain/form_validators}/form_validator.dart (74%) create mode 100644 packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart create mode 100644 packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart rename packages/wyatt_form_bloc/lib/src/{form => domain/input_validators}/form_input_validator.dart (85%) rename packages/wyatt_form_bloc/lib/src/{validators/inputs/enum_validator.dart => domain/input_validators/nullable_validator.dart} (57%) rename packages/wyatt_form_bloc/lib/src/{validators/inputs/base => domain/input_validators}/regex_validator.dart (80%) rename packages/wyatt_form_bloc/lib/src/{validators/inputs/base => domain/input_validators}/text_validator.dart (78%) delete mode 100644 packages/wyatt_form_bloc/lib/src/form/form_data.dart create mode 100644 packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart rename packages/wyatt_form_bloc/lib/src/{cubit => presentation/features/form_data}/form_data_state.dart (68%) create mode 100644 packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart create mode 100644 packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart create mode 100644 packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart create mode 100644 packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_metadata.dart create mode 100644 packages/wyatt_form_bloc/lib/src/presentation/features/widgets/submit_builder.dart create mode 100644 packages/wyatt_form_bloc/lib/src/presentation/presentation.dart delete mode 100644 packages/wyatt_form_bloc/lib/src/validators/inputs/iban.dart delete mode 100644 packages/wyatt_form_bloc/lib/src/validators/inputs/list_option.dart diff --git a/packages/wyatt_form_bloc/README.md b/packages/wyatt_form_bloc/README.md index 74a53324..82fb439a 100644 --- a/packages/wyatt_form_bloc/README.md +++ b/packages/wyatt_form_bloc/README.md @@ -16,16 +16,16 @@ * along with this program. If not, see . --> -# Dart - Form BLoC +# Flutter - Form BLoC

Style: Wyatt Analysis - SDK: Dart & Flutter + SDK: Flutter

-Form Bloc for Dart & Flutter. +Form Bloc for Flutter. ## Features diff --git a/packages/wyatt_form_bloc/analysis_options.yaml b/packages/wyatt_form_bloc/analysis_options.yaml index cc27c8ca..b0c6aced 100644 --- a/packages/wyatt_form_bloc/analysis_options.yaml +++ b/packages/wyatt_form_bloc/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:wyatt_analysis/analysis_options.yaml +include: package:wyatt_analysis/analysis_options.flutter.yaml analyzer: exclude: "!example/**" \ No newline at end of file diff --git a/packages/wyatt_form_bloc/example/ios/Flutter/AppFrameworkInfo.plist b/packages/wyatt_form_bloc/example/ios/Flutter/AppFrameworkInfo.plist index 8d4492f9..9625e105 100644 --- a/packages/wyatt_form_bloc/example/ios/Flutter/AppFrameworkInfo.plist +++ b/packages/wyatt_form_bloc/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 11.0 diff --git a/packages/wyatt_form_bloc/example/ios/Runner.xcodeproj/project.pbxproj b/packages/wyatt_form_bloc/example/ios/Runner.xcodeproj/project.pbxproj index abeae7fe..8a34f9c6 100644 --- a/packages/wyatt_form_bloc/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/wyatt_form_bloc/example/ios/Runner.xcodeproj/project.pbxproj @@ -272,7 +272,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -349,7 +349,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -398,7 +398,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/packages/wyatt_form_bloc/example/ios/Runner/Info.plist b/packages/wyatt_form_bloc/example/ios/Runner/Info.plist index 7f67e595..18f4a4be 100644 --- a/packages/wyatt_form_bloc/example/ios/Runner/Info.plist +++ b/packages/wyatt_form_bloc/example/ios/Runner/Info.plist @@ -43,5 +43,7 @@ UIViewControllerBasedStatusBarAppearance + CADisableMinimumFrameDurationOnPhone + diff --git a/packages/wyatt_form_bloc/example/lib/app/app.dart b/packages/wyatt_form_bloc/example/lib/app/app.dart index 611f20ac..f9000f08 100644 --- a/packages/wyatt_form_bloc/example/lib/app/app.dart +++ b/packages/wyatt_form_bloc/example/lib/app/app.dart @@ -18,7 +18,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:form_bloc_example/app/metadata.dart'; import 'package:form_bloc_example/constants.dart'; -import 'package:form_bloc_example/cubit/custom_form_cubit.dart'; +import 'package:form_bloc_example/simple_custom_form_cubit/simple_custom_form_cubit.dart'; import 'package:form_bloc_example/sign_up/sign_up_page.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; @@ -29,41 +29,43 @@ class App extends StatelessWidget { const App({Key? key}) : super(key: key); static List getNormalEntries() { - return const [ - FormInput(formFieldName, Name.pure(), metadata: FormInputMetadata(extra: blue)), - FormInput(formFieldEmail, Email.pure(), metadata: FormInputMetadata(extra: blue)), - FormInput(formFieldPhone, Phone.pure(), metadata: FormInputMetadata(extra: red)), - FormInput( - formFieldList, ListOption.pure(defaultValue: ['checkbox3'])), - FormInput(formFieldRadio, TextString.pure()), - FormInput(formFieldPro, Boolean.pure(), - metadata: FormInputMetadata(name: 'business')), - FormInput(formFieldHidden, Boolean.pure(), - metadata: FormInputMetadata(export: false, extra: blue)), + return [ + FormInput(formFieldName, const Name.pure(), + metadata: const FormInputMetadata(extra: blue)), + FormInput(formFieldEmail, const Email.pure(), + metadata: const FormInputMetadata(extra: blue)), + FormInput(formFieldList, + const ListOption.pure(defaultValue: 'c3')), + FormInput(formFieldRadio, const TextString.pure()), + FormInput(formFieldPro, const Boolean.pure(), + metadata: const FormInputMetadata(name: 'business')), + FormInput(formFieldHidden, const Boolean.pure(), + metadata: + const FormInputMetadata(export: false, extra: blue)), ]; } static List getBusinessEntries() { - const entries = [ - FormInput(formFieldSiren, Siren.pure()), - FormInput(formFieldIban, Iban.pure()), + final entries = [ + FormInput(formFieldPhone, const Phone.pure(), + metadata: const FormInputMetadata(extra: red)), ]; return getNormalEntries() + entries; } - static FormData getNormalFormData() { - return FormData(getNormalEntries()); + static WyattForm getNormalFormData() { + return WyattFormImpl(getNormalEntries()); } - static FormData getProFormData() { - return FormData(getBusinessEntries()); + static WyattForm getProFormData() { + return WyattFormImpl(getBusinessEntries()); } @override Widget build(BuildContext context) { - FormDataCubit formCubit = CustomFormCubit(inputs: getNormalFormData()); + SimpleCustomFormCubit formCubit = SimpleCustomFormCubit(getNormalFormData()); - return BlocProvider( + return BlocProvider( create: (context) => formCubit, child: const WidgetTree(), ); diff --git a/packages/wyatt_form_bloc/example/lib/app/metadata.dart b/packages/wyatt_form_bloc/example/lib/app/metadata.dart index b4e68725..6d66f961 100644 --- a/packages/wyatt_form_bloc/example/lib/app/metadata.dart +++ b/packages/wyatt_form_bloc/example/lib/app/metadata.dart @@ -28,7 +28,5 @@ class Metadata { }); @override - String toString() { - return category.toString(); - } + String toString() => 'Metadata(category: $category)'; } diff --git a/packages/wyatt_form_bloc/example/lib/constants.dart b/packages/wyatt_form_bloc/example/lib/constants.dart index c1c52795..573b5ef6 100644 --- a/packages/wyatt_form_bloc/example/lib/constants.dart +++ b/packages/wyatt_form_bloc/example/lib/constants.dart @@ -17,8 +17,6 @@ const String formFieldName = 'name'; const String formFieldPhone = 'phone'; const String formFieldEmail = 'email'; -const String formFieldSiren = 'siren'; -const String formFieldIban = 'iban'; const String formFieldList = 'list'; const String formFieldRadio = 'radio'; const String formFieldHidden = 'hidden'; diff --git a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart index 947faf6d..14ac7fbc 100644 --- a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart +++ b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart @@ -14,39 +14,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:form_bloc_example/app/app.dart'; import 'package:form_bloc_example/app/metadata.dart'; import 'package:form_bloc_example/constants.dart'; +import 'package:form_bloc_example/simple_custom_form_cubit/simple_custom_form_cubit.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -class CategoryIndicator extends StatelessWidget { - const CategoryIndicator( - {Key? key, required this.field, required this.builder}) - : super(key: key); - - final String field; - final Function(BuildContext context, FormDataState state) builder; - - Color computeColor(Metadata meta) { - switch (meta.category) { - case Category.perso: - return Colors.blue; - case Category.business: - return Colors.red; - } +Color computeColor(Metadata? meta) { + switch (meta?.category) { + case Category.perso: + return Colors.blue; + case Category.business: + return Colors.red; + case null: + return Colors.green; } +} +class _NameInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: ((context, state) { - final meta = state.data.metadataOf(field).extra as Metadata; + return InputBuilderMetadata( + field: formFieldName, + builder: (context, cubit, state, field, inputValid, metadata) { + final meta = state.form.metadataOf(field).extra; final color = computeColor(meta); - return Row( children: [ Container( @@ -57,58 +51,24 @@ class CategoryIndicator extends StatelessWidget { borderRadius: BorderRadius.circular(8), ), ), - const SizedBox(width: 20,), + const SizedBox( + width: 20, + ), SizedBox( width: MediaQuery.of(context).size.width - 45, - child: builder(context, state), + child: TextField( + onChanged: (value) => + cubit.dataChanged(field, Name.dirty(value)), + keyboardType: TextInputType.name, + decoration: InputDecoration( + labelText: 'name', + helperText: '', + errorText: !inputValid ? 'invalid name' : null, + ), + ), ) ], ); - }), - ); - } -} - -class _NameInput extends StatelessWidget { - @override - Widget build(BuildContext context) { - return CategoryIndicator( - field: formFieldName, - builder: (context, state) { - return TextField( - onChanged: (name) => context - .read() - .dataChanged(formFieldName, Name.dirty(name)), - keyboardType: TextInputType.name, - decoration: InputDecoration( - labelText: 'name', - helperText: '', - errorText: - state.data.isNotValid(formFieldName) ? 'invalid name' : null, - ), - ); - }); - } -} - -class _EmailInput extends StatelessWidget { - @override - Widget build(BuildContext context) { - return CategoryIndicator( - field: formFieldEmail, - builder: (context, state) { - return TextField( - onChanged: (email) => context - .read() - .dataChanged(formFieldEmail, Email.dirty(email)), - keyboardType: TextInputType.emailAddress, - decoration: InputDecoration( - labelText: 'email', - helperText: '', - errorText: - state.data.isNotValid(formFieldEmail) ? 'invalid email' : null, - ), - ); }, ); } @@ -117,67 +77,58 @@ class _EmailInput extends StatelessWidget { class _PhoneInput extends StatelessWidget { @override Widget build(BuildContext context) { - return CategoryIndicator( - field: formFieldPhone, - builder: (context, state) { - return TextField( - onChanged: (phone) => context - .read() - .dataChanged(formFieldPhone, Phone.dirty(phone)), - keyboardType: TextInputType.phone, - decoration: InputDecoration( - labelText: 'phone', - helperText: '', - errorText: - state.data.isNotValid(formFieldPhone) ? 'invalid phone' : null, - ), + return InputBuilderMetadata( + field: formFieldPhone, + builder: (context, cubit, state, field, inputValid, metadata) { + final meta = state.form.metadataOf(field).extra; + final color = computeColor(meta); + return Row( + children: [ + Container( + height: 8, + width: 8, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(8), + ), + ), + const SizedBox( + width: 20, + ), + SizedBox( + width: MediaQuery.of(context).size.width - 45, + child: TextField( + onChanged: (value) => + cubit.dataChanged(field, Phone.dirty(value)), + keyboardType: TextInputType.phone, + decoration: InputDecoration( + labelText: 'phone', + helperText: '', + errorText: !inputValid ? 'invalid phone' : null, + ), + ), + ) + ], ); }, ); } } -class _SirenInput extends StatelessWidget { +class _EmailInput extends StatelessWidget { @override Widget build(BuildContext context) { - return CategoryIndicator( - field: formFieldName, - builder: (context, state) { - return TextField( - onChanged: (siren) => context - .read() - .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( - builder: (context, state) { - return TextField( - onChanged: (iban) => context - .read() - .dataChanged(formFieldIban, Iban.dirty(iban)), - keyboardType: TextInputType.text, - decoration: InputDecoration( - labelText: 'iban', - helperText: '', - errorText: - state.data.isNotValid(formFieldIban) ? 'invalid IBAN' : null, - ), - ); - }, + return InputBuilder( + field: formFieldEmail, + builder: (context, cubit, state, field, inputValid) => TextField( + onChanged: (value) => cubit.dataChanged(field, Email.dirty(value)), + keyboardType: TextInputType.emailAddress, + decoration: InputDecoration( + labelText: 'email', + helperText: '', + errorText: !inputValid ? 'invalid email' : null, + ), + ), ); } } @@ -185,11 +136,11 @@ class _IbanInput extends StatelessWidget { class _CheckListInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - final input = - state.data.validatorOf>(formFieldList); - final options = input.value; + return InputBuilder( + field: formFieldList, + builder: (context, cubit, state, field, inputValid) { + final input = state.form.validatorOf>(field); + final choices = ['c1', 'c2', 'c3']; return Column( mainAxisSize: MainAxisSize.min, @@ -197,34 +148,34 @@ class _CheckListInput extends StatelessWidget { ListTile( title: const Text('Checkbox1'), trailing: Checkbox( - value: options.contains('checkbox1'), + value: input.value == choices[0], onChanged: (_) { - context.read().dataChanged( - formFieldList, - input.select('checkbox1'), - ); + cubit.dataChanged( + field, + ListOption.dirty(choices: choices, value: choices[0]), + ); }), ), ListTile( title: const Text('Checkbox2'), trailing: Checkbox( - value: options.contains('checkbox2'), + value: input.value == choices[1], onChanged: (_) { - context.read().dataChanged( - formFieldList, - input.select('checkbox2'), - ); + cubit.dataChanged( + field, + ListOption.dirty(choices: choices, value: choices[1]), + ); }), ), ListTile( title: const Text('Checkbox3 (default)'), trailing: Checkbox( - value: options.contains('checkbox3'), + value: input.value == choices[2], onChanged: (_) { - context.read().dataChanged( - formFieldList, - input.select('checkbox3'), - ); + cubit.dataChanged( + field, + ListOption.dirty(choices: choices, value: choices[2]), + ); }), ), ], @@ -237,9 +188,10 @@ class _CheckListInput extends StatelessWidget { class _RadioListInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - final input = state.data.validatorOf(formFieldRadio); + return InputBuilder( + field: formFieldRadio, + builder: ((context, cubit, state, field, inputValid) { + final input = state.form.validatorOf(field); return Column( mainAxisSize: MainAxisSize.min, @@ -250,10 +202,10 @@ class _RadioListInput extends StatelessWidget { groupValue: true, value: input.value == 'radio1', onChanged: (_) { - context.read().dataChanged( - formFieldRadio, - const TextString.dirty('radio1'), - ); + cubit.dataChanged( + field, + const TextString.dirty('radio1'), + ); }), ), ListTile( @@ -262,10 +214,10 @@ class _RadioListInput extends StatelessWidget { groupValue: true, value: input.value == 'radio2', onChanged: (_) { - context.read().dataChanged( - formFieldRadio, - const TextString.dirty('radio2'), - ); + cubit.dataChanged( + field, + const TextString.dirty('radio2'), + ); }), ), ListTile( @@ -274,15 +226,15 @@ class _RadioListInput extends StatelessWidget { groupValue: true, value: input.value == 'radio3', onChanged: (_) { - context.read().dataChanged( - formFieldRadio, - const TextString.dirty('radio3'), - ); + cubit.dataChanged( + field, + const TextString.dirty('radio3'), + ); }), ), ], ); - }, + }), ); } } @@ -292,17 +244,18 @@ class _CheckHiddenInput extends StatelessWidget { Widget build(BuildContext context) { return ListTile( title: const Text('This input is not exported'), - trailing: BlocBuilder( - builder: (context, state) { + trailing: InputBuilder( + field: formFieldHidden, + builder: (context, cubit, state, field, inputValid) { return Checkbox( - value: state.data.validatorOf(formFieldHidden).value, + value: state.form.validatorOf(field).value, onChanged: (v) { final value = v!; // state is false, so value can't be null - context.read().dataChanged( - formFieldHidden, - Boolean.dirty(value: value), - ); + cubit.dataChanged( + field, + Boolean.dirty(value: value), + ); }); }, ), @@ -315,25 +268,24 @@ class _CheckIsProInput extends StatelessWidget { Widget build(BuildContext context) { return ListTile( title: const Text('Are you a pro?'), - trailing: BlocBuilder( - builder: (context, state) { + trailing: InputBuilder( + field: formFieldPro, + builder: (context, cubit, state, field, inputValid) { return Checkbox( - value: state.data.validatorOf(formFieldPro).value, - onChanged: (isPro) { - final value = isPro!; // state is false, so value can't be null + value: state.form.validatorOf(field).value, + onChanged: (v) { + final value = v!; // state is false, so value can't be null - context.read().dataChanged( - formFieldPro, - Boolean.dirty(value: value), - ); + cubit.dataChanged( + field, + Boolean.dirty(value: value), + ); if (value) { - context.read().updateFormData( - App.getProFormData(), + cubit.update(App.getProFormData(), operation: SetOperation.union); } else { - context.read().updateFormData( - App.getNormalFormData(), + cubit.update(App.getNormalFormData(), operation: SetOperation.intersection); } }); @@ -346,49 +298,28 @@ class _CheckIsProInput extends StatelessWidget { class _SignUpButton extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.status != current.status, - builder: (context, state) { - return state.status.isSubmissionInProgress - ? const CircularProgressIndicator() - : ElevatedButton( - onPressed: state.status.isValidated - ? () => context.read().submitForm() - : null, - child: const Text('SIGN UP'), - ); - }, - ); - } -} - -class _DebugButton extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return ElevatedButton( - onPressed: () { - log(state.toString()); - }, - child: const Text('DEBUG'), - ); - }, - ); + return SubmitBuilder( + builder: (context, cubit, status) { + return status.isSubmissionInProgress + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: status.isValidated ? () => cubit.submit() : null, + child: const Text('SIGN UP'), + ); + }); } } class _ResetButton extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return ElevatedButton( - onPressed: () => context.read().resetForm(), - child: const Text('RESET'), - ); - }, - ); + return SubmitBuilder( + builder: (context, cubit, status) { + return ElevatedButton( + onPressed: () => cubit.reset(), + child: const Text('RESET'), + ); + }); } } @@ -397,7 +328,7 @@ class SignUpForm extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocListener( + return BlocListener( listener: (context, state) { if (state.status.isSubmissionSuccess) { Navigator.of(context).pop(); // Never happens here @@ -418,8 +349,6 @@ class SignUpForm extends StatelessWidget { const SizedBox(height: 8), _EmailInput(), const SizedBox(height: 8), - _PhoneInput(), - const SizedBox(height: 8), _CheckListInput(), const SizedBox(height: 8), _RadioListInput(), @@ -428,13 +357,12 @@ class SignUpForm extends StatelessWidget { const SizedBox(height: 8), _CheckIsProInput(), const SizedBox(height: 8), - BlocBuilder( + BlocBuilder( builder: (context, state) { - if (state.data.validatorOf(formFieldPro).value) { + if (state.form.validatorOf(formFieldPro).value ?? + false) { return Column(children: [ - _SirenInput(), - const SizedBox(height: 8), - _IbanInput(), + _PhoneInput(), const SizedBox(height: 8), ]); } @@ -444,8 +372,6 @@ class SignUpForm extends StatelessWidget { const SizedBox(height: 8), _SignUpButton(), const SizedBox(height: 8), - _DebugButton(), - const SizedBox(height: 8), _ResetButton(), ], ), diff --git a/packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart b/packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart similarity index 80% rename from packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart rename to packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart index 3f211c60..b8b0dfca 100644 --- a/packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart +++ b/packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart @@ -18,12 +18,13 @@ import 'dart:developer'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -class CustomFormCubit extends FormDataCubit { - CustomFormCubit({required FormData inputs}) : super(inputs: inputs); +class SimpleCustomFormCubit extends FormDataCubitImpl { + SimpleCustomFormCubit(super.form) : super(); @override - Future submitForm() { - log(state.data.toMap().toString()); + Future submit() { + final value = FormJsonEncoder().encode(state.form); + log(value); return Future.value(); } diff --git a/packages/wyatt_form_bloc/lib/src/validators/validators.dart b/packages/wyatt_form_bloc/lib/src/core/core.dart similarity index 60% rename from packages/wyatt_form_bloc/lib/src/validators/validators.dart rename to packages/wyatt_form_bloc/lib/src/core/core.dart index b9eaa4b6..9d6c64d8 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/validators.dart +++ b/packages/wyatt_form_bloc/lib/src/core/core.dart @@ -14,17 +14,4 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'form/every_input_validator.dart'; -export 'inputs/base/regex_validator.dart'; -export 'inputs/base/text_validator.dart'; -export 'inputs/boolean.dart'; -export 'inputs/confirmed_password.dart'; -export 'inputs/email.dart'; -export 'inputs/enum_validator.dart'; -export 'inputs/iban.dart'; -export 'inputs/list_option.dart'; -export 'inputs/name.dart'; -export 'inputs/password.dart'; -export 'inputs/phone.dart'; -export 'inputs/siren.dart'; -export 'inputs/text_string.dart'; +export 'enums/enums.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/enums/enums.dart b/packages/wyatt_form_bloc/lib/src/core/enums/enums.dart similarity index 100% rename from packages/wyatt_form_bloc/lib/src/enums/enums.dart rename to packages/wyatt_form_bloc/lib/src/core/enums/enums.dart diff --git a/packages/wyatt_form_bloc/lib/src/enums/form_input_status.dart b/packages/wyatt_form_bloc/lib/src/core/enums/form_input_status.dart similarity index 100% rename from packages/wyatt_form_bloc/lib/src/enums/form_input_status.dart rename to packages/wyatt_form_bloc/lib/src/core/enums/form_input_status.dart diff --git a/packages/wyatt_form_bloc/lib/src/enums/form_status.dart b/packages/wyatt_form_bloc/lib/src/core/enums/form_status.dart similarity index 100% rename from packages/wyatt_form_bloc/lib/src/enums/form_status.dart rename to packages/wyatt_form_bloc/lib/src/core/enums/form_status.dart diff --git a/packages/wyatt_form_bloc/lib/src/core/enums/set_operations.dart b/packages/wyatt_form_bloc/lib/src/core/enums/set_operations.dart new file mode 100644 index 00000000..3e27f437 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/core/enums/set_operations.dart @@ -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 . + +import 'package:wyatt_form_bloc/src/data/form_operations/form_difference.dart'; +import 'package:wyatt_form_bloc/src/data/form_operations/form_intersection.dart'; +import 'package:wyatt_form_bloc/src/data/form_operations/form_replace.dart'; +import 'package:wyatt_form_bloc/src/data/form_operations/form_union.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; + +enum SetOperation { + /// Replace entire set with new set. + replace(FormReplace()), + + /// Keep common elements between sets. + intersection(FormIntersection()), + + /// Remove common elements between sets. + difference(FormDifference()), + + /// Add new elements to set. + union(FormUnion()); + + final FormOperation operation; + + const SetOperation(this.operation); +} diff --git a/packages/wyatt_form_bloc/lib/src/enums/validation_error.dart b/packages/wyatt_form_bloc/lib/src/core/enums/validation_error.dart similarity index 97% rename from packages/wyatt_form_bloc/lib/src/enums/validation_error.dart rename to packages/wyatt_form_bloc/lib/src/core/enums/validation_error.dart index 5a0b436e..4966b6b8 100644 --- a/packages/wyatt_form_bloc/lib/src/enums/validation_error.dart +++ b/packages/wyatt_form_bloc/lib/src/core/enums/validation_error.dart @@ -23,5 +23,6 @@ abstract class ValidationError {} enum ValidationStandardError implements ValidationError { invalid, - empty + empty, + notEqual, } diff --git a/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart b/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart deleted file mode 100644 index 5434acac..00000000 --- a/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:equatable/equatable.dart'; -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; -import 'package:wyatt_form_bloc/src/validators/form/every_input_validator.dart'; - -part 'form_data_state.dart'; - -abstract class FormDataCubit extends Cubit { - FormValidator validationStrategy; - FormData formCopy; - - FormDataCubit({ - required FormData inputs, - FormValidator validator = const EveryInputValidator(), - }) : formCopy = inputs.clone(), - validationStrategy = validator, - super(FormDataState(data: inputs)); - - /// Change value of a field. - /// - /// Inputs: - /// - `field`: The key of the field to change. - /// - `dirtyValue`: The new value of the field. (Wrapped in a dirty validator) - void dataChanged( - String field, - FormInputValidator dirtyValue, - ) { - final form = state.data.clone(); - - if (form.contains(field)) { - form.updateValidator(field, dirtyValue); - } else { - throw Exception('Form field $field not found'); - } - - emit( - state.copyWith( - data: form, - status: validationStrategy.validate(form), - ), - ); - } - - /// Just validate the form manually. (Useful if you just update the strategy) - void validate() { - final form = state.data; - emit(state.copyWith(status: validationStrategy.validate(form))); - } - - /// Update entries list. - /// - /// Inputs: - /// - `data`: The new entries list. - /// - `operation`: The operation to perform on the entries set. - void updateFormData( - FormData data, { - SetOperation operation = SetOperation.replace, - }) { - FormData form = data; - - switch (operation) { - case SetOperation.replace: - form = data; - break; - case SetOperation.difference: - form = state.data.difference(data); - break; - case SetOperation.intersection: - form = state.data.intersection(data); - break; - case SetOperation.union: - form = state.data.union(data); - break; - } - - emit( - state.copyWith( - data: form, - status: validationStrategy.validate(form), - ), - ); - } - - /// Reset all form inputs - void resetForm() { - emit(FormDataState(data: formCopy)); - } - - /// Submit the form. - Future submitForm(); -} diff --git a/packages/wyatt_form_bloc/lib/src/data/data.dart b/packages/wyatt_form_bloc/lib/src/data/data.dart new file mode 100644 index 00000000..743bef59 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/data.dart @@ -0,0 +1,34 @@ +// 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 . + +export 'form/wyatt_form_impl.dart'; +export 'form_encoders/form_json_encoder.dart'; +export 'form_encoders/form_map_encoder.dart'; +export 'form_operations/form_difference.dart'; +export 'form_operations/form_intersection.dart'; +export 'form_operations/form_replace.dart'; +export 'form_operations/form_union.dart'; +export 'form_validators/every_input_validator.dart'; +export 'form_validators/only_required_input_validator.dart'; +export 'input_validators/boolean.dart'; +export 'input_validators/confirmed_password.dart'; +export 'input_validators/email.dart'; +export 'input_validators/enum_option.dart'; +export 'input_validators/list_option.dart'; +export 'input_validators/name.dart'; +export 'input_validators/password.dart'; +export 'input_validators/phone.dart'; +export 'input_validators/text_string.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart new file mode 100644 index 00000000..235ce5c8 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart @@ -0,0 +1,136 @@ +// 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 . + +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form_validators/every_input_validator.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +// ignore: must_be_immutable +class WyattFormImpl extends WyattForm { + final List< + FormInput, + dynamic>> _inputs; + final FormValidator _validator; + + late List< + FormInput, + dynamic>> _inputsInitial; + + WyattFormImpl( + this._inputs, { + FormValidator validationStrategy = const EveryInputValidator(), + }) : _validator = validationStrategy { + _inputsInitial = _inputs.map((input) => input.clone()).toList(); + } + + @override + List< + FormInput, + dynamic>> get inputs => _inputs; + + @override + FormValidator get formValidationStrategy => _validator; + + @override + bool containsKey(String key) => inputs.any((input) => input.key == key); + + @override + List> + asValidatorList() => inputs + .map>( + (input) => input.validator as FormInputValidator, + ) + .toList(); + + @override + FormInput, dynamic> + inputOf(String key) { + if (containsKey(key)) { + return inputs.firstWhere((input) => input.key == key); + } else { + throw Exception('FormInput with key `$key` does not exist in form'); + } + } + + @override + Error? errorOf(String key) => + (inputOf(key).validator as FormInputValidator).error; + + @override + FormInputMetadata metadataOf(String key) => + inputOf(key).metadata as FormInputMetadata; + + @override + Validator validatorOf< + Validator extends FormInputValidator>( + String key, + ) => + inputOf(key).validator as Validator; + + @override + Value? valueOf(String key) => + (inputOf(key).validator as FormInputValidator).value; + + @override + FormStatus validate() => formValidationStrategy.validate(this); + + @override + WyattForm clone() => WyattFormImpl( + _inputs.map((input) => input.clone()).toList(), + validationStrategy: formValidationStrategy, + ); + + @override + WyattForm reset() => WyattFormImpl( + _inputsInitial, + validationStrategy: formValidationStrategy, + ); + + @override + bool? get stringify => true; + + @override + List get props => _inputs; + + @override + void updateMetadata(String key, FormInputMetadata metadata) { + final index = _inputs.indexOf( + inputOf(key), + ); + _inputs[index] = _inputs[index].copyWith(metadata: metadata); + } + + @override + void updateValidator( + String key, + FormInputValidator dirtyValue, + ) { + final index = _inputs.indexOf( + inputOf(key), + ); + _inputs[index] = _inputs[index].copyWith(validator: dirtyValue); + } + + @override + WyattForm operationWith(FormOperation operation, WyattForm other) => + operation.call(this, other); +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_json_encoder.dart b/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_json_encoder.dart new file mode 100644 index 00000000..a4d3d636 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_json_encoder.dart @@ -0,0 +1,30 @@ +// 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 . + +import 'dart:convert'; + +import 'package:wyatt_form_bloc/src/data/form_encoders/form_map_encoder.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_encoders/form_encoder.dart'; + +class FormJsonEncoder extends FormEncoder { + @override + String encode(WyattForm form) { + final mapEncoder = FormMapEncoder(); + final map = mapEncoder.encode(form); + return jsonEncode(map); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_map_encoder.dart b/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_map_encoder.dart new file mode 100644 index 00000000..9d682976 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_map_encoder.dart @@ -0,0 +1,32 @@ +// 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 . + +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_encoders/form_encoder.dart'; + +class FormMapEncoder extends FormEncoder> { + @override + Map encode(WyattForm form) { + final inputs = form.inputs; + final map = {}; + for (final input in inputs) { + if (input.metadata.export) { + map[input.name] = input.validator.value; + } + } + return map; + } +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart new file mode 100644 index 00000000..20a5fee4 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart @@ -0,0 +1,50 @@ +// 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 . + +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +class FormDifference extends FormOperation { + const FormDifference(); + + @override + WyattForm call(WyattForm a, WyattForm b) { + final inputs = < + FormInput, + dynamic>>[]; + + for (final i in b.inputs) { + if (!a.containsKey(i.key)) { + inputs.add(i); + } + } + + for (final i in a.inputs) { + if (!b.containsKey(i.key)) { + inputs.add(i); + } + } + + return WyattFormImpl( + inputs, + validationStrategy: a.formValidationStrategy, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart new file mode 100644 index 00000000..1a5d75bb --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart @@ -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 . + +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +class FormIntersection extends FormOperation { + const FormIntersection(); + + @override + WyattForm call(WyattForm a, WyattForm b) { + final inputs = < + FormInput, + dynamic>>[]; + + for (final i in a.inputs) { + if (b.containsKey(i.key)) { + inputs.add(i); + } + } + + return WyattFormImpl( + inputs, + validationStrategy: a.formValidationStrategy, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/form/form.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_replace.dart similarity index 64% rename from packages/wyatt_form_bloc/lib/src/form/form.dart rename to packages/wyatt_form_bloc/lib/src/data/form_operations/form_replace.dart index 041263fc..9c5ab986 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_replace.dart @@ -14,15 +14,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'dart:convert'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; -import 'package:equatable/equatable.dart'; -import 'package:wyatt_form_bloc/src/enums/form_input_status.dart'; -import 'package:wyatt_form_bloc/src/enums/form_status.dart'; -import 'package:wyatt_form_bloc/src/enums/validation_error.dart'; +class FormReplace extends FormOperation { + const FormReplace(); -part 'form_data.dart'; -part 'form_input.dart'; -part 'form_input_metadata.dart'; -part 'form_input_validator.dart'; -part 'form_validator.dart'; + @override + WyattForm call(WyattForm a, WyattForm b) => b; +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart new file mode 100644 index 00000000..06d0c067 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart @@ -0,0 +1,48 @@ +// 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 . + +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +class FormUnion extends FormOperation { + const FormUnion(); + + @override + WyattForm call(WyattForm a, WyattForm b) { + final inputs = < + FormInput, + dynamic>>[]; + + for (final i in a.inputs) { + inputs.add(i); + } + + for (final i in b.inputs) { + if (!a.containsKey(i.key)) { + inputs.add(i); + } + } + + return WyattFormImpl( + inputs, + validationStrategy: a.formValidationStrategy, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/validators/form/every_input_validator.dart b/packages/wyatt_form_bloc/lib/src/data/form_validators/every_input_validator.dart similarity index 73% rename from packages/wyatt_form_bloc/lib/src/validators/form/every_input_validator.dart rename to packages/wyatt_form_bloc/lib/src/data/form_validators/every_input_validator.dart index fba42286..adfd60bc 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/form/every_input_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_validators/every_input_validator.dart @@ -14,7 +14,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart'; /// {@template every} /// Check and validate every input of a form @@ -24,18 +27,13 @@ class EveryInputValidator extends FormValidator { const EveryInputValidator() : super(); @override - FormStatus validate(FormData form) { + FormStatus validate(WyattForm form) { if (isPure(form)) { return FormStatus.pure; } - return rawValidate(form.validators()); - } + final validators = form.asValidatorList(); - @override - FormStatus rawValidate( - List> validators, - ) { if (validators.any((validator) => validator.valid == false)) { return FormStatus.invalid; } diff --git a/packages/wyatt_form_bloc/lib/src/data/form_validators/only_required_input_validator.dart b/packages/wyatt_form_bloc/lib/src/data/form_validators/only_required_input_validator.dart new file mode 100644 index 00000000..bd83d295 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_validators/only_required_input_validator.dart @@ -0,0 +1,29 @@ +// 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 . + +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart'; + +class OnlyRequiredInputValidator extends FormValidator { + const OnlyRequiredInputValidator() : super(); + + @override + FormStatus validate(WyattForm form) { + // TODO(hpcl): use metadata to check if input is required or not. + return FormStatus.valid; + } +} diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/boolean.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/boolean.dart similarity index 74% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/boolean.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/boolean.dart index e28f5ad1..71f470ca 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/boolean.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/boolean.dart @@ -14,21 +14,25 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template boolean} /// Form input for a bool input /// {@endtemplate} -class Boolean extends FormInputValidator { +class Boolean extends NullableValidator { /// {@macro boolean} const Boolean.pure({bool? defaultValue = false}) : super.pure(defaultValue ?? false); /// {@macro boolean} const Boolean.dirty({bool value = false}) : super.dirty(value); + + @override + ValidationStandardError get onNull => ValidationStandardError.invalid; @override ValidationStandardError? validator(bool? value) => - value != null ? null : ValidationStandardError.invalid; + value != null ? null : onNull; + } diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/confirmed_password.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart similarity index 61% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/confirmed_password.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart index 54899cf2..448efba2 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/confirmed_password.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart @@ -14,25 +14,31 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template confirmed_password} /// Form input for a confirmed password input. /// {@endtemplate} class ConfirmedPassword - extends FormInputValidator { + extends EqualityValidator { /// {@macro confirmed_password} - const ConfirmedPassword.pure({this.password = ''}) : super.pure(''); + const ConfirmedPassword.pure({this.password = '', String? defaultValue}) + : super.pure(defaultValue); /// {@macro confirmed_password} - const ConfirmedPassword.dirty({required this.password, String value = ''}) + const ConfirmedPassword.dirty({required this.password, String? value}) : super.dirty(value); /// The original password. final String password; @override - ValidationStandardError? validator(String? value) => - password == value ? null : ValidationStandardError.invalid; + String get another => password; + + @override + ValidationStandardError get onNotEqual => ValidationStandardError.notEqual; + + @override + ValidationStandardError get onNull => ValidationStandardError.invalid; } diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/email.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/email.dart similarity index 85% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/email.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/email.dart index 4961c672..c718dfdb 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/email.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/email.dart @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template email} /// Form input for an email input. /// {@endtemplate} class Email extends RegexValidator { /// {@macro email} - const Email.pure() : super.pure(); + const Email.pure([super.value]) : super.pure(); /// {@macro email} const Email.dirty([super.value = '']) : super.dirty(); diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/siren.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/enum_option.dart similarity index 52% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/siren.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/enum_option.dart index 798c33f4..8a939fba 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/siren.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/enum_option.dart @@ -14,24 +14,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; -/// {@template siren} -/// Form input for a SIREN input. -/// {@endtemplate} -class Siren extends RegexValidator { - /// {@macro siren} - const Siren.pure() : super.pure(); +class EnumOption extends AnyValidator, ValidationError> { + const EnumOption.pure({this.enums = const [], T? defaultValue}) + : super.pure(defaultValue); - /// {@macro siren} - const Siren.dirty([super.value = '']) : super.dirty(); + const EnumOption.dirty({required this.enums, T? value}) + : super.dirty(value); + + final List enums; @override - ValidationStandardError get onEmpty => ValidationStandardError.empty; - @override - ValidationStandardError get onError => ValidationStandardError.invalid; + List get allChoices => enums; @override - RegExp get regex => RegExp(r'(\d{9}|\d{3}[ ]\d{3}[ ]\d{3})$'); + ValidationError get onError => ValidationStandardError.invalid; + + @override + ValidationError get onNull => ValidationStandardError.invalid; + + @override + bool test(T? element, T value) => element == value; } diff --git a/packages/wyatt_form_bloc/lib/src/data/input_validators/list_option.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/list_option.dart new file mode 100644 index 00000000..13f28986 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/list_option.dart @@ -0,0 +1,40 @@ +// 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 . + +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +class ListOption extends AnyValidator, ValidationError> { + const ListOption.pure({this.choices = const [], T? defaultValue}) + : super.pure(defaultValue); + + const ListOption.dirty({required this.choices, T? value}) + : super.dirty(value); + + final Iterable choices; + + @override + Iterable get allChoices => choices; + + @override + ValidationError get onError => ValidationStandardError.invalid; + + @override + ValidationError get onNull => ValidationStandardError.invalid; + + @override + bool test(T? element, T value) => element == value; +} diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/name.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/name.dart similarity index 85% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/name.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/name.dart index cf3b6558..6ade3e21 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/name.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/name.dart @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template name} /// Form input for a name input. /// {@endtemplate} class Name extends RegexValidator { /// {@macro name} - const Name.pure() : super.pure(); + const Name.pure([super.value]) : super.pure(); /// {@macro name} const Name.dirty([super.value = '']) : super.dirty(); diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/password.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/password.dart similarity index 81% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/password.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/password.dart index 8a6beab0..5ec35d91 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/password.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/password.dart @@ -14,18 +14,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template password} /// Form input for a password input. /// {@endtemplate} class Password extends RegexValidator { /// {@macro password} - const Password.pure() : super.pure(); + const Password.pure([super.value]) : super.pure(); /// {@macro password} - const Password.dirty([super.value = '']) : super.dirty(); + const Password.dirty([super.value]) : super.dirty(); @override ValidationStandardError get onEmpty => ValidationStandardError.empty; diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/phone.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/phone.dart similarity index 85% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/phone.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/phone.dart index 9f4dd1af..74c93c2e 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/phone.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/phone.dart @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template phone} /// Form input for a phone input. /// {@endtemplate} class Phone extends RegexValidator { /// {@macro phone} - const Phone.pure() : super.pure(); + const Phone.pure([super.value]) : super.pure(); /// {@macro phone} const Phone.dirty([super.value = '']) : super.dirty(); diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/text_string.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/text_string.dart similarity index 84% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/text_string.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/text_string.dart index 61d0def3..9bf9e0be 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/text_string.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/text_string.dart @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/text_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template text_string} /// Form input for a text input /// {@endtemplate} class TextString extends TextValidator { /// {@macro text_string} - const TextString.pure() : super.pure(); + const TextString.pure([super.value]) : super.pure(); /// {@macro text_string} const TextString.dirty([super.value = '']) : super.dirty(); diff --git a/packages/wyatt_form_bloc/lib/src/domain/domain.dart b/packages/wyatt_form_bloc/lib/src/domain/domain.dart new file mode 100644 index 00000000..9eada269 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/domain.dart @@ -0,0 +1,23 @@ +// 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 . + +export 'entities/form_input.dart'; +export 'entities/form_input_metadata.dart'; +export 'form/wyatt_form.dart'; +export 'form_encoders/form_encoder.dart'; +export 'form_operations/form_operation.dart'; +export 'form_validators/form_validator.dart'; +export 'input_validators/form_input_validator.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/form/form_input.dart b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart similarity index 59% rename from packages/wyatt_form_bloc/lib/src/form/form_input.dart rename to packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart index 6ab60d99..41eb70aa 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_input.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart @@ -15,27 +15,36 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'form.dart'; +import 'package:equatable/equatable.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; -class FormInput> - extends Equatable { +// ignore: must_be_immutable +class FormInput< + Value, + Validator extends FormInputValidator, + Extra> extends Equatable implements Entity { final String key; final Validator validator; - final FormInputMetadata metadata; + late FormInputMetadata metadata; - String get name => metadata._name ?? key; + String get name => metadata.name ?? key; - const FormInput( + FormInput( this.key, this.validator, { // ignore: avoid_redundant_argument_values - this.metadata = const FormInputMetadata(export: true), - }); + FormInputMetadata? metadata, + }) { + this.metadata = metadata ?? FormInputMetadata(); + } - FormInput copyWith({ + FormInput copyWith({ String? key, Validator? validator, - FormInputMetadata? metadata, + FormInputMetadata? metadata, }) => FormInput( key ?? this.key, @@ -43,11 +52,12 @@ class FormInput> metadata: metadata ?? this.metadata, ); - FormInput clone() => copyWith( + FormInput clone() => copyWith( key: key, validator: validator, metadata: metadata, ); + @override bool? get stringify => true; diff --git a/packages/wyatt_form_bloc/lib/src/form/form_input_metadata.dart b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input_metadata.dart similarity index 69% rename from packages/wyatt_form_bloc/lib/src/form/form_input_metadata.dart rename to packages/wyatt_form_bloc/lib/src/domain/entities/form_input_metadata.dart index bed46368..df21c950 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_input_metadata.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input_metadata.dart @@ -15,33 +15,35 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'form.dart'; +import 'package:equatable/equatable.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; -class FormInputMetadata extends Equatable { +class FormInputMetadata extends Equatable + implements Entity { final bool export; - final String? _name; - final T? extra; + final String? name; + final Extra? extra; const FormInputMetadata({ this.export = true, + this.name, this.extra, - String? name, - }) : _name = name; + }); - FormInputMetadata copyWith({ + FormInputMetadata copyWith({ bool? export, String? name, - T? extra, + Extra? extra, }) => - FormInputMetadata( + FormInputMetadata( export: export ?? this.export, - name: name ?? _name, + name: name ?? this.name, extra: extra ?? this.extra, ); - FormInputMetadata clone() => copyWith( + FormInputMetadata clone() => copyWith( export: export, - name: _name, + name: name, extra: extra, ); @@ -49,5 +51,5 @@ class FormInputMetadata extends Equatable { bool? get stringify => true; @override - List get props => [export, _name, extra]; + List get props => [export, name, extra]; } diff --git a/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart b/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart new file mode 100644 index 00000000..718e5be5 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart @@ -0,0 +1,60 @@ +// 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 . + +// ignore_for_file: strict_raw_type + +import 'package:equatable/equatable.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +abstract class WyattForm extends Equatable { + List get inputs; + FormValidator get formValidationStrategy; + + bool containsKey(String key); + + FormInput inputOf(String key); + Validator validatorOf< + Validator extends FormInputValidator>( + String key, + ); + Error? errorOf(String key); + Value? valueOf(String key); + FormInputMetadata metadataOf(String key); + + List> + asValidatorList(); + + void updateValidator( + String key, + FormInputValidator dirtyValue, + ); + + void updateMetadata( + String key, + FormInputMetadata metadata, + ); + + FormStatus validate(); + WyattForm clone(); + WyattForm operationWith(FormOperation operation, WyattForm other); + WyattForm reset(); +} diff --git a/packages/wyatt_form_bloc/lib/src/enums/set_operations.dart b/packages/wyatt_form_bloc/lib/src/domain/form_encoders/form_encoder.dart similarity index 75% rename from packages/wyatt_form_bloc/lib/src/enums/set_operations.dart rename to packages/wyatt_form_bloc/lib/src/domain/form_encoders/form_encoder.dart index fa203b98..c69c226d 100644 --- a/packages/wyatt_form_bloc/lib/src/enums/set_operations.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/form_encoders/form_encoder.dart @@ -14,16 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -enum SetOperation { - /// Replace entire set with new set. - replace, - - /// Keep common elements between sets. - intersection, - - /// Remove common elements between sets. - difference, - - /// Add new elements to set. - union +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; + +// ignore: one_member_abstracts +abstract class FormEncoder { + Output encode(WyattForm form); } diff --git a/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart b/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart new file mode 100644 index 00000000..ab5f34de --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart @@ -0,0 +1,23 @@ +// 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 . + +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; + +// ignore: one_member_abstracts +abstract class FormOperation { + const FormOperation(); + WyattForm call(WyattForm a, WyattForm b); +} diff --git a/packages/wyatt_form_bloc/lib/src/form/form_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/form_validators/form_validator.dart similarity index 74% rename from packages/wyatt_form_bloc/lib/src/form/form_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/form_validators/form_validator.dart index 958d4e3e..45137ab7 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/form_validators/form_validator.dart @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'form.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; /// {@template form_validator} /// A [FormValidator] represents the global validaton state of a Form. @@ -23,13 +25,9 @@ abstract class FormValidator { /// {@macro form_validator} const FormValidator(); - bool isPure(FormData form) => form - .validators() + bool isPure(WyattForm form) => form + .asValidatorList() .every((validator) => validator.pure); - FormStatus validate(FormData form); - - FormStatus rawValidate( - List> validators, - ); + FormStatus validate(WyattForm form); } diff --git a/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart new file mode 100644 index 00000000..0869d8b5 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart @@ -0,0 +1,45 @@ +// 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 . + +part of 'form_input_validator.dart'; + +abstract class AnyValidator, + E extends ValidationError> extends FormInputValidator { + const AnyValidator.pure(super.value) : super.pure(); + const AnyValidator.dirty(super.value) : super.dirty(); + + I get allChoices; + + bool test(O? element, O value); + + E get onError; + + /// If value is null. + E get onNull; + + @override + E? validator(O? value) { + if (value == null) { + return onNull; + } + if (allChoices.any( + (element) => test(element, value), + )) { + return null; + } + return onError; + } +} diff --git a/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart new file mode 100644 index 00000000..531d55ab --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart @@ -0,0 +1,45 @@ +// 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 . + +part of 'form_input_validator.dart'; + +/// {@template equality_validator} +/// Abstract equality validator validating a value when equals to another. +/// {@endtemplate} +abstract class EqualityValidator + extends FormInputValidator { + const EqualityValidator.pure(super.value) : super.pure(); + const EqualityValidator.dirty(super.value) : super.dirty(); + + O get another; + + /// If values are different. + E get onNotEqual; + + /// If value is null. + E get onNull; + + @override + E? validator(O? value) { + if (value == null) { + return onNull; + } + if (value != another) { + return onNotEqual; + } + return null; + } +} diff --git a/packages/wyatt_form_bloc/lib/src/form/form_input_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart similarity index 85% rename from packages/wyatt_form_bloc/lib/src/form/form_input_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart index 61f47cf3..16d2e21a 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_input_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart @@ -14,7 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'form.dart'; +import 'package:equatable/equatable.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_input_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; + +part 'regex_validator.dart'; +part 'text_validator.dart'; +part 'nullable_validator.dart'; +part 'equality_validator.dart'; +part 'any_validator.dart'; /// {@template form_input_validator} /// A [FormInputValidator] represents the value of a single form input field. @@ -39,21 +47,21 @@ part of 'form.dart'; /// } /// ``` /// {@endtemplate} -abstract class FormInputValidator +abstract class FormInputValidator extends Equatable { const FormInputValidator._(this.value, [this.pure = true]); /// Constructor which create a `pure` [FormInputValidator] with a given value. - const FormInputValidator.pure(V value) : this._(value); + const FormInputValidator.pure(Value value) : this._(value); /// Constructor which create a `dirty` [FormInputValidator] with a /// given value. - const FormInputValidator.dirty(V value) : this._(value, false); + const FormInputValidator.dirty(Value value) : this._(value, false); /// The value of the given [FormInputValidator]. /// For example, if you have a `FormInputValidator` for `FirstName`, /// the value could be 'Joe'. - final V value; + final Value? value; /// If the [FormInputValidator] is pure (has been touched/modified). /// Typically when the `FormInputValidator` is initially created, @@ -80,7 +88,7 @@ abstract class FormInputValidator /// Returns a validation error if the [FormInputValidator] is invalid. /// Returns `null` if the [FormInputValidator] is valid. - E? get error => validator(value); + Error? get error => validator(value); /// Whether the [FormInputValidator] value is valid according to the /// overridden `validator`. @@ -96,7 +104,7 @@ abstract class FormInputValidator /// A function that must return a validation error if the provided /// [value] is invalid and `null` otherwise. - E? validator(V value); + Error? validator(Value? value); @override bool? get stringify => true; diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/enum_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/nullable_validator.dart similarity index 57% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/enum_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/input_validators/nullable_validator.dart index 63c3ef60..e478e2ec 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/enum_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/nullable_validator.dart @@ -14,19 +14,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/validation_error.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/text_validator.dart'; +part of 'form_input_validator.dart'; -class EnumValidator extends TextValidator { - /// {@macro text_string} - const EnumValidator.pure() : super.pure(); +/// {@template nullable_validator} +/// Abstract nullable validator not validating null values. +/// {@endtemplate} +abstract class NullableValidator + extends FormInputValidator { + const NullableValidator.pure(super.value) : super.pure(); + const NullableValidator.dirty(super.value) : super.dirty(); - /// {@macro text_string} - EnumValidator.dirty(E value) : super.dirty(value.toString()); + /// If value is null. + E get onNull; @override - ValidationStandardError get onEmpty => ValidationStandardError.empty; - - @override - ValidationStandardError get onNull => ValidationStandardError.invalid; + E? validator(O? value) { + if (value == null) { + return onNull; + } + return null; + } } diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/base/regex_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/regex_validator.dart similarity index 80% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/base/regex_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/input_validators/regex_validator.dart index 16d41ab2..971e9566 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/base/regex_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/regex_validator.dart @@ -14,20 +14,21 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/validation_error.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; +part of 'form_input_validator.dart'; /// {@template regex_validator} /// Abstract regex validator for form input. /// {@endtemplate} abstract class RegexValidator - extends FormInputValidator { - const RegexValidator.pure() : super.pure(''); - const RegexValidator.dirty([super.value = '']) : super.dirty(); + extends FormInputValidator { + const RegexValidator.pure(super.value) : super.pure(); + const RegexValidator.dirty(super.value) : super.dirty(); RegExp get regex; + /// If the value is **not** null, but empty. E get onEmpty; + /// If value does not conform to regex. E get onError; diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/base/text_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/text_validator.dart similarity index 78% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/base/text_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/input_validators/text_validator.dart index c57697f1..6e70e027 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/base/text_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/text_validator.dart @@ -14,13 +14,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/validation_error.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; +part of 'form_input_validator.dart'; abstract class TextValidator - extends FormInputValidator { - const TextValidator.pure() : super.pure(''); - const TextValidator.dirty([super.value = '']) : super.dirty(); + extends FormInputValidator { + const TextValidator.pure(super.value) : super.pure(); + const TextValidator.dirty(super.value) : super.dirty(); /// If the value is **not** null, but empty. E get onEmpty; diff --git a/packages/wyatt_form_bloc/lib/src/form/form_data.dart b/packages/wyatt_form_bloc/lib/src/form/form_data.dart deleted file mode 100644 index 86e67940..00000000 --- a/packages/wyatt_form_bloc/lib/src/form/form_data.dart +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -part of 'form.dart'; - -class FormData extends Equatable { - final List _inputs; - - const FormData(this._inputs); - const FormData.empty() : this(const []); - - /// Returns all inputs as a list - List inputs() => _inputs; - - /// Returns the input for the associated key - FormInput inputOf(String key) { - if (contains(key)) { - return _inputs.firstWhere((input) => input.key == key); - } else { - throw Exception('FormInput with key `$key` does not exist in form'); - } - } - - /// Updates a input (perform a replace at index). - void updateInput(String key, FormInput input) { - if (contains(key)) { - final index = _inputs.indexOf( - inputOf(key), - ); - _inputs[index] = input; - } - } - - /// Returns all associated validators as a list - List> validators() => - _inputs - .map>( - (input) => input.validator as FormInputValidator, - ) - .toList(); - - /// A [FormInputValidator] represents the value of a single form input field. - /// It contains information about the [FormInputStatus], value, as well - /// as validation status. - T validatorOf(String key) => inputOf(key).validator as T; - - /// Updates validator of a given input. (perform copyWith) - void updateValidator( - String key, - FormInputValidator dirtyValue, - ) { - if (contains(key)) { - final index = _inputs.indexOf( - inputOf(key), - ); - _inputs[index] = _inputs[index].copyWith(validator: dirtyValue); - } - } - - /// Returns a validation error if the [FormInputValidator] is invalid. - /// Returns null if the [FormInputValidator] is valid. - E? errorOf(String key) => - (inputOf(key).validator as FormInputValidator).error; - - /// The value of the associated [FormInputValidator]. For example, - /// if you have a FormInputValidator for FirstName, the value could be 'Joe'. - V valueOf(String key) => - (inputOf(key).validator as FormInputValidator).value; - - /// Returns `true` if the [FormInputValidator] is not valid. - /// Same as `E? errorOf(String key) != null` - bool isNotValid(String key) => !inputOf(key).validator.valid; - - /// Returns all associated metadata as a list - List> metadata() => _inputs - .map>( - (input) => input.metadata as FormInputMetadata, - ) - .toList(); - - /// Returns the metadata associated. With `M` the type of extra data. - FormInputMetadata metadataOf(String key) => - inputOf(key).metadata as FormInputMetadata; - - /// Updates metadata of a given input. (perform copyWith) - void updateMetadata(String key, FormInputMetadata meta) { - if (contains(key)) { - final index = _inputs.indexOf( - inputOf(key), - ); - _inputs[index] = _inputs[index].copyWith(metadata: meta); - } - } - - /// Check if this contains an input with the given key. - bool contains(String key) => _inputs.any((input) => input.key == key); - - /// Makes an intersection set operation and returns newly created [FormData] - FormData intersection(FormData other) { - final List inputs = []; - - for (final FormInput i in _inputs) { - if (other.contains(i.key)) { - inputs.add(i); - } - } - - return FormData(inputs); - } - - /// Makes a difference set operation and returns newly created [FormData] - FormData difference(FormData other) { - final List inputs = []; - - for (final FormInput i in other._inputs) { - if (!contains(i.key)) { - inputs.add(i); - } - } - - for (final FormInput i in _inputs) { - if (!other.contains(i.key)) { - inputs.add(i); - } - } - - return FormData(inputs); - } - - /// Makes an union set operation and returns newly created [FormData] - FormData union(FormData other) { - final List inputs = []; - - for (final FormInput i in _inputs) { - inputs.add(i); - } - - for (final FormInput i in other._inputs) { - if (!contains(i.key)) { - inputs.add(i); - } - } - - return FormData(inputs); - } - - /// Deeply copy this. - FormData clone() => FormData( - _inputs.map((input) => input.clone()).toList(), - ); - - /// Export this to [Map] format. - Map toMap() { - final map = {}; - for (final input in _inputs) { - if (input.metadata.export) { - map[input.name] = input.validator.value; - } - } - return map; - } - - /// Export this to [String] format. - String toJson() => jsonEncode(toMap()); - - @override - bool? get stringify => true; - - @override - List get props => _inputs; -} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart new file mode 100644 index 00000000..50ca2c34 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart @@ -0,0 +1,47 @@ +// 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 . + +import 'dart:async'; + +import 'package:equatable/equatable.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +part 'form_data_state.dart'; + +abstract class FormDataCubit extends Cubit { + FormDataCubit(super.initialState) : super(); + + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, + ); + + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }); + + FutureOr validate(); + + FutureOr reset(); + + FutureOr submit(); +} diff --git a/packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart similarity index 68% rename from packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart rename to packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart index 4629b0e6..f898d4bf 100644 --- a/packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart @@ -16,35 +16,19 @@ part of 'form_data_cubit.dart'; -class FormDataState extends Equatable { +abstract class FormDataState extends Equatable { /// Global status of a form. final FormStatus status; - + /// FormData with all inputs, and associated metadata. - final FormData data; + final WyattForm form; /// Optional error message. final String? errorMessage; const FormDataState({ - required this.data, + required this.form, this.status = FormStatus.pure, this.errorMessage, }); - - FormDataState copyWith({ - FormStatus? status, - FormData? data, - String? errorMessage, - }) => FormDataState( - status: status ?? this.status, - data: data ?? this.data, - errorMessage: errorMessage ?? this.errorMessage, - ); - - @override - bool? get stringify => true; - - @override - List get props => [status, data, errorMessage]; } diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart new file mode 100644 index 00000000..b5729d71 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart @@ -0,0 +1,86 @@ +// 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 . + +import 'dart:async'; + +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; +import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart'; + +part 'form_data_state_impl.dart'; + +abstract class FormDataCubitImpl extends FormDataCubit { + FormDataCubitImpl(WyattForm form) : super(FormDataStateImpl(form: form)); + + @override + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, + ) { + final form = state.form.clone(); + + try { + form.updateValidator(key, dirtyValue); + } catch (e) { + rethrow; + } + + emit( + state.copyWith( + form: form, + status: form.validate(), + ), + ); + } + + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm newForm = operation.operation.call(state.form, form); + + emit( + state.copyWith( + form: newForm, + status: newForm.validate(), + ), + ); + } + + @override + FutureOr reset() { + final form = state.form.reset(); + emit( + state.copyWith( + form: form, + status: form.validate(), + ), + ); + } + + @override + FutureOr validate() { + emit( + state.copyWith( + status: state.form.validate(), + ), + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart new file mode 100644 index 00000000..37cb8e5a --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart @@ -0,0 +1,42 @@ +// 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 . + +part of 'form_data_cubit_impl.dart'; + +class FormDataStateImpl extends FormDataState { + const FormDataStateImpl({ + required super.form, + super.status = FormStatus.pure, + super.errorMessage, + }); + + FormDataStateImpl copyWith({ + FormStatus? status, + WyattForm? form, + String? errorMessage, + }) => + FormDataStateImpl( + status: status ?? this.status, + form: form ?? this.form, + errorMessage: errorMessage ?? this.errorMessage, + ); + + @override + bool? get stringify => true; + + @override + List get props => [status, form, errorMessage]; +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart new file mode 100644 index 00000000..b23e33d2 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart @@ -0,0 +1,43 @@ +// 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 . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +class InputBuilder extends StatelessWidget { + const InputBuilder({required this.field, required this.builder, super.key}); + + final String field; + + final Widget Function( + BuildContext context, + Cubit cubit, + FormDataState state, + String field, + bool inputValid, + ) builder; + + @override + Widget build(BuildContext context) => + BlocBuilder( + builder: (context, state) { + final cubit = context.read(); + final inputValid = state.form.validatorOf(field).valid; + return builder.call(context, cubit, state, field, inputValid); + }, + ); +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_metadata.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_metadata.dart new file mode 100644 index 00000000..123287fc --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_metadata.dart @@ -0,0 +1,57 @@ +// 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 . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/presentation/presentation.dart'; + +class InputBuilderMetadata + extends StatelessWidget { + const InputBuilderMetadata({ + required this.field, + required this.builder, + super.key, + }); + + final String field; + + final Widget Function( + BuildContext context, + Cubit cubit, + FormDataState state, + String field, + bool inputValid, + FormInputMetadata? metadata, + ) builder; + + @override + Widget build(BuildContext context) => BlocBuilder( + builder: (context, state) { + final cubit = context.read(); + final inputValid = state.form.validatorOf(field).valid; + final metadata = state.form.metadataOf(field); + return builder.call( + context, + cubit, + state, + field, + inputValid, + metadata, + ); + }, + ); +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/submit_builder.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/submit_builder.dart new file mode 100644 index 00000000..ed1abd42 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/submit_builder.dart @@ -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 . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart'; + +class SubmitBuilder extends StatelessWidget { + const SubmitBuilder({required this.builder, super.key}); + + final Widget Function(BuildContext context, Cubit cubit, FormStatus status) + builder; + + @override + Widget build(BuildContext context) => BlocBuilder( + buildWhen: (previous, current) => previous.status != current.status, + builder: (context, state) => builder.call( + context, + context.read(), + state.status, + ), + ); +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart b/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart new file mode 100644 index 00000000..31292d02 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart @@ -0,0 +1,21 @@ +// 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 . + +export 'features/form_data/form_data_cubit.dart'; +export 'features/form_data_impl/form_data_cubit_impl.dart'; +export 'features/widgets/input_builder.dart'; +export 'features/widgets/input_builder_metadata.dart'; +export 'features/widgets/submit_builder.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/src.dart b/packages/wyatt_form_bloc/lib/src/src.dart index dd7f4605..c75563a1 100644 --- a/packages/wyatt_form_bloc/lib/src/src.dart +++ b/packages/wyatt_form_bloc/lib/src/src.dart @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'cubit/form_data_cubit.dart'; -export 'enums/enums.dart'; -export 'form/form.dart'; -export 'validators/validators.dart'; +export 'core/core.dart'; +export 'data/data.dart'; +export 'domain/domain.dart'; +export 'presentation/presentation.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/iban.dart b/packages/wyatt_form_bloc/lib/src/validators/inputs/iban.dart deleted file mode 100644 index 74bef3e3..00000000 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/iban.dart +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; - -/// {@template iban} -/// Form input for an IBAN input. -/// {@endtemplate} -class Iban extends RegexValidator { - /// {@macro iban} - const Iban.pure() : super.pure(); - - /// {@macro iban} - const Iban.dirty([super.value = '']) : super.dirty(); - - @override - ValidationStandardError get onEmpty => ValidationStandardError.empty; - @override - ValidationStandardError get onError => ValidationStandardError.invalid; - - @override - RegExp get regex => RegExp( - r'^(?:((?:IT|SM)\d{2}[A-Z]{1}\d{22})|(NL\d{2}[A-Z]{4}\d{10})|(LV\d{2}[A-Z]{4}\d{13})|((?:BG|GB|IE)\d{2}[A-Z]{4}\d{14})|(GI\d{2}[A-Z]{4}\d{15})|(RO\d{2}[A-Z]{4}\d{16})|(MT\d{2}[A-Z]{4}\d{23})|(NO\d{13})|((?:DK|FI)\d{16})|((?:SI)\d{17})|((?:AT|EE|LU|LT)\d{18})|((?:HR|LI|CH)\d{19})|((?:DE|VA)\d{20})|((?:AD|CZ|ES|MD|SK|SE)\d{22})|(PT\d{23})|((?:IS)\d{24})|((?:BE)\d{14})|((?:FR|MC|GR)\d{25})|((?:PL|HU|CY)\d{26}))$', - ); -} diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/list_option.dart b/packages/wyatt_form_bloc/lib/src/validators/inputs/list_option.dart deleted file mode 100644 index 00ddd74b..00000000 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/list_option.dart +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; - -/// {@template list_option} -/// Form input for a list input -/// {@endtemplate} -class ListOption - extends FormInputValidator, ValidationStandardError> { - /// {@macro list_option} - const ListOption.pure({List? defaultValue}) - : super.pure(defaultValue ?? const []); - - /// {@macro list_option} - const ListOption.dirty({List? value}) : super.dirty(value ?? const []); - - ListOption select(T? v) { - if (v == null) { - return this; - } - if (value.contains(v)) { - final List newValue = List.from(value)..remove(v); - return ListOption.dirty(value: newValue); - } else { - final List newValue = List.from(value)..add(v); - return ListOption.dirty(value: newValue); - } - } - - @override - ValidationStandardError? validator(List? value) => - value?.isNotEmpty ?? false == true - ? null - : ValidationStandardError.invalid; -} diff --git a/packages/wyatt_form_bloc/pubspec.yaml b/packages/wyatt_form_bloc/pubspec.yaml index 7b1e7c2a..7d9e5906 100644 --- a/packages/wyatt_form_bloc/pubspec.yaml +++ b/packages/wyatt_form_bloc/pubspec.yaml @@ -3,15 +3,33 @@ description: Manage forms in Dart & Flutter with Bloc repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_form_bloc version: 0.0.6 +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + environment: - sdk: '>=2.17.2 <3.0.0' + sdk: ">=2.17.2 <3.0.0" dependencies: - bloc: ^8.1.0 + flutter: + sdk: flutter + + flutter_bloc: ^8.1.0 equatable: ^2.0.5 + wyatt_architecture: + git: + url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages + ref: wyatt_architecture-v0.0.2-dev.0 + path: packages/wyatt_architecture + + wyatt_type_utils: + git: + url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages + ref: wyatt_type_utils-v0.0.3+1 + path: packages/wyatt_type_utils + dev_dependencies: - test: ^1.21.4 + flutter_test: + sdk: flutter wyatt_analysis: git: From 7a056ac38eafd9c9e5ce8865d947d676662fa465 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 01:05:12 -0500 Subject: [PATCH 08/18] feat!(form): add repository feature, and controller for inputs --- .../wyatt_form_bloc/lib/src/data/data.dart | 7 +- .../lib/src/data/form/wyatt_form_impl.dart | 45 +++++++---- .../data/form_operations/form_difference.dart | 1 + .../form_operations/form_intersection.dart | 1 + .../src/data/form_operations/form_union.dart | 1 + .../repositories/form_repository_impl.dart | 60 +++++++++++++++ .../lib/src/domain/domain.dart | 7 +- .../lib/src/domain/entities/form_input.dart | 5 +- .../lib/src/domain/form/wyatt_form.dart | 1 + .../form_operations/form_operation.dart | 1 + .../form_input_validator.dart | 6 +- .../domain/repositories/form_repository.dart | 27 +++++++ .../features/form_data/form_data_cubit.dart | 2 + .../form_data_impl/form_data_cubit_impl.dart | 18 ++++- .../form_data_impl/form_data_state_impl.dart | 5 +- .../features/widgets/input_builder.dart | 2 +- .../input_builder_text_controller.dart | 75 +++++++++++++++++++ .../lib/src/presentation/presentation.dart | 1 + 18 files changed, 233 insertions(+), 32 deletions(-) create mode 100644 packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart create mode 100644 packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart create mode 100644 packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart diff --git a/packages/wyatt_form_bloc/lib/src/data/data.dart b/packages/wyatt_form_bloc/lib/src/data/data.dart index 743bef59..f86212c5 100644 --- a/packages/wyatt_form_bloc/lib/src/data/data.dart +++ b/packages/wyatt_form_bloc/lib/src/data/data.dart @@ -1,16 +1,16 @@ // 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 . @@ -32,3 +32,4 @@ export 'input_validators/name.dart'; export 'input_validators/password.dart'; export 'input_validators/phone.dart'; export 'input_validators/text_string.dart'; +export 'repositories/form_repository_impl.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart index 235ce5c8..9b17b055 100644 --- a/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart @@ -30,6 +30,7 @@ class WyattFormImpl extends WyattForm { FormInput, dynamic>> _inputs; final FormValidator _validator; + final String _name; late List< FormInput, @@ -37,8 +38,10 @@ class WyattFormImpl extends WyattForm { WyattFormImpl( this._inputs, { + required String name, FormValidator validationStrategy = const EveryInputValidator(), - }) : _validator = validationStrategy { + }) : _name = name, + _validator = validationStrategy { _inputsInitial = _inputs.map((input) => input.clone()).toList(); } @@ -50,6 +53,9 @@ class WyattFormImpl extends WyattForm { @override FormValidator get formValidationStrategy => _validator; + @override + String get name => _name; + @override bool containsKey(String key) => inputs.any((input) => input.key == key); @@ -94,22 +100,24 @@ class WyattFormImpl extends WyattForm { FormStatus validate() => formValidationStrategy.validate(this); @override - WyattForm clone() => WyattFormImpl( - _inputs.map((input) => input.clone()).toList(), - validationStrategy: formValidationStrategy, - ); + WyattForm clone() { + final clone = WyattFormImpl( + _inputs.map((input) => input.clone()).toList(), + name: _name, + validationStrategy: formValidationStrategy, + ).._inputsInitial = _inputsInitial; + return clone; + } @override - WyattForm reset() => WyattFormImpl( - _inputsInitial, - validationStrategy: formValidationStrategy, - ); - - @override - bool? get stringify => true; - - @override - List get props => _inputs; + WyattForm reset() { + final newForm = WyattFormImpl( + _inputsInitial, + name: _name, + validationStrategy: formValidationStrategy, + ).._inputsInitial = _inputsInitial; + return newForm; + } @override void updateMetadata(String key, FormInputMetadata metadata) { @@ -133,4 +141,11 @@ class WyattFormImpl extends WyattForm { @override WyattForm operationWith(FormOperation operation, WyattForm other) => operation.call(this, other); + + @override + List get props => [_inputs, _name, _validator]; + + @override + String toString() => + 'WyattForm(name: $name, validation: ${_validator.runtimeType}, inputs: $inputs)'; } diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart index 20a5fee4..14a78d9c 100644 --- a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart @@ -44,6 +44,7 @@ class FormDifference extends FormOperation { return WyattFormImpl( inputs, + name: a.name, validationStrategy: a.formValidationStrategy, ); } diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart index 1a5d75bb..2c1d4cb6 100644 --- a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart @@ -38,6 +38,7 @@ class FormIntersection extends FormOperation { return WyattFormImpl( inputs, + name: a.name, validationStrategy: a.formValidationStrategy, ); } diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart index 06d0c067..a466750b 100644 --- a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart @@ -42,6 +42,7 @@ class FormUnion extends FormOperation { return WyattFormImpl( inputs, + name: a.name, validationStrategy: a.formValidationStrategy, ); } diff --git a/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart b/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart new file mode 100644 index 00000000..0d97327b --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart @@ -0,0 +1,60 @@ +// 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 . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/repositories/form_repository.dart'; + +class FormRepositoryImpl extends FormRepository { + final Map _runtimeForms = {}; + + @override + Map get runtimeForms => _runtimeForms; + + @override + WyattForm accessForm(String formName) { + if (_runtimeForms.containsKey(formName)) { + return _runtimeForms[formName]!; + } else { + throw ClientException( + 'Form $formName is not registered. Just use ' + '`FormRepository.register(yourForm);` before any operation on it.', + ); + } + } + + @override + void registerForm(WyattForm form) { + _runtimeForms[form.name] = form; + } + + @override + void updateForm(WyattForm form) { + if (_runtimeForms.containsKey(form.name)) { + _runtimeForms[form.name] = form; + } else { + throw ClientException( + 'Form ${form.name} is not registered. Just use ' + '`FormRepository.register(yourForm);` before any operation on it.', + ); + } + } + + @override + void unregisterForm(String formName) { + _runtimeForms.remove(formName); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/domain/domain.dart b/packages/wyatt_form_bloc/lib/src/domain/domain.dart index 9eada269..a7eae716 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/domain.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/domain.dart @@ -1,16 +1,16 @@ // 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 . @@ -21,3 +21,4 @@ export 'form_encoders/form_encoder.dart'; export 'form_operations/form_operation.dart'; export 'form_validators/form_validator.dart'; export 'input_validators/form_input_validator.dart'; +export 'repositories/form_repository.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart index 41eb70aa..b8abfd7e 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart @@ -59,8 +59,9 @@ class FormInput< ); @override - bool? get stringify => true; + List get props => [key, validator, metadata]; @override - List get props => [key, validator, metadata]; + String toString() => + 'FormInput(name: $name, value: ${validator.value}, status: ${validator.status.name}'; } diff --git a/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart b/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart index 718e5be5..1b156c94 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart @@ -28,6 +28,7 @@ import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator abstract class WyattForm extends Equatable { List get inputs; FormValidator get formValidationStrategy; + String get name; bool containsKey(String key); diff --git a/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart b/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart index ab5f34de..eaf8f960 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart @@ -19,5 +19,6 @@ import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; // ignore: one_member_abstracts abstract class FormOperation { const FormOperation(); + // TODO(hpcl): handle operation on `initialInputs` WyattForm call(WyattForm a, WyattForm b); } diff --git a/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart index 16d2e21a..ebb539d3 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart @@ -18,11 +18,11 @@ import 'package:equatable/equatable.dart'; import 'package:wyatt_form_bloc/src/core/enums/form_input_status.dart'; import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +part 'any_validator.dart'; +part 'equality_validator.dart'; +part 'nullable_validator.dart'; part 'regex_validator.dart'; part 'text_validator.dart'; -part 'nullable_validator.dart'; -part 'equality_validator.dart'; -part 'any_validator.dart'; /// {@template form_input_validator} /// A [FormInputValidator] represents the value of a single form input field. diff --git a/packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart b/packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart new file mode 100644 index 00000000..3b5f1f05 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart @@ -0,0 +1,27 @@ +// 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 . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +abstract class FormRepository extends BaseRepository { + Map get runtimeForms; + + void registerForm(WyattForm form); + void updateForm(WyattForm form); + WyattForm accessForm(String formName); + void unregisterForm(String formName); +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart index 50ca2c34..3af6c99b 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart @@ -29,6 +29,8 @@ part 'form_data_state.dart'; abstract class FormDataCubit extends Cubit { FormDataCubit(super.initialState) : super(); + String get formName; + FutureOr dataChanged( String key, FormInputValidator dirtyValue, diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart index b5729d71..2eb50aa7 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart @@ -21,22 +21,31 @@ import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart'; import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; +import 'package:wyatt_form_bloc/src/domain/repositories/form_repository.dart'; import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart'; part 'form_data_state_impl.dart'; abstract class FormDataCubitImpl extends FormDataCubit { - FormDataCubitImpl(WyattForm form) : super(FormDataStateImpl(form: form)); + final FormRepository _formRepository; + final String _formName; + + FormDataCubitImpl(this._formRepository, this._formName) + : super(FormDataStateImpl(form: _formRepository.accessForm(_formName))); + + @override + String get formName => _formName; @override FutureOr dataChanged( String key, FormInputValidator dirtyValue, ) { - final form = state.form.clone(); + final form = _formRepository.accessForm(_formName).clone(); try { form.updateValidator(key, dirtyValue); + _formRepository.updateForm(form); } catch (e) { rethrow; } @@ -54,7 +63,9 @@ abstract class FormDataCubitImpl extends FormDataCubit { WyattForm form, { SetOperation operation = SetOperation.replace, }) { - final WyattForm newForm = operation.operation.call(state.form, form); + final WyattForm current = _formRepository.accessForm(_formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + _formRepository.updateForm(newForm); emit( state.copyWith( @@ -67,6 +78,7 @@ abstract class FormDataCubitImpl extends FormDataCubit { @override FutureOr reset() { final form = state.form.reset(); + _formRepository.updateForm(form); emit( state.copyWith( form: form, diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart index 37cb8e5a..dad01887 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart @@ -35,8 +35,9 @@ class FormDataStateImpl extends FormDataState { ); @override - bool? get stringify => true; + List get props => [status, form, errorMessage]; @override - List get props => [status, form, errorMessage]; + String toString() => + 'FormDataSate(status: ${status.name} ${(errorMessage != null) ? " [$errorMessage]" : ""}, $form'; } diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart index b23e33d2..c6cb9006 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart @@ -35,7 +35,7 @@ class InputBuilder extends StatelessWidget { Widget build(BuildContext context) => BlocBuilder( builder: (context, state) { - final cubit = context.read(); + final cubit = context.watch(); final inputValid = state.form.validatorOf(field).valid; return builder.call(context, cubit, state, field, inputValid); }, diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart new file mode 100644 index 00000000..17f5c16e --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart @@ -0,0 +1,75 @@ +// 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 . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/domain/repositories/form_repository.dart'; +import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart'; + +class InputBuilderTextController extends StatelessWidget { + InputBuilderTextController({ + required this.field, + required this.builder, + super.key, + }); + + final String field; + + final Widget Function( + BuildContext context, + Cubit cubit, + FormDataState state, + String field, + bool inputValid, + TextEditingController textEditingController, + FormInputMetadata? metadata, + ) builder; + + final TextEditingController _controller = TextEditingController(); + + @override + Widget build(BuildContext context) { + final formName = context.watch().formName; + final value = + context.read().accessForm(formName).valueOf(field); + _controller + ..text = value ?? '' + ..selection = TextSelection.fromPosition( + TextPosition( + offset: _controller.text.length, + ), + ); + + return BlocBuilder( + builder: (context, state) { + final cubit = context.read(); + final inputValid = state.form.validatorOf(field).valid; + final metadata = state.form.metadataOf(field); + return builder.call( + context, + cubit, + state, + field, + inputValid, + _controller, + metadata, + ); + }, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart b/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart index 31292d02..e0b0377d 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart @@ -18,4 +18,5 @@ export 'features/form_data/form_data_cubit.dart'; export 'features/form_data_impl/form_data_cubit_impl.dart'; export 'features/widgets/input_builder.dart'; export 'features/widgets/input_builder_metadata.dart'; +export 'features/widgets/input_builder_text_controller.dart'; export 'features/widgets/submit_builder.dart'; From 68a582c3ad952f9ea610e1401c57f0325947be0e Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 01:06:25 -0500 Subject: [PATCH 09/18] refactor(form): refactor simple example --- .../wyatt_form_bloc/example/lib/app/app.dart | 33 ++++++++--- .../example/lib/constants.dart | 2 + .../lib/sign_up/widgets/sign_up_form.dart | 6 +- .../sign_up/widgets/simple_sign_up_form.dart | 57 +++++++++++++++++++ .../simple_custom_form_cubit.dart | 2 +- 5 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 packages/wyatt_form_bloc/example/lib/sign_up/widgets/simple_sign_up_form.dart diff --git a/packages/wyatt_form_bloc/example/lib/app/app.dart b/packages/wyatt_form_bloc/example/lib/app/app.dart index f9000f08..63c35292 100644 --- a/packages/wyatt_form_bloc/example/lib/app/app.dart +++ b/packages/wyatt_form_bloc/example/lib/app/app.dart @@ -30,12 +30,12 @@ class App extends StatelessWidget { static List getNormalEntries() { return [ - FormInput(formFieldName, const Name.pure(), + FormInput(formFieldName, const Name.pure('Test'), metadata: const FormInputMetadata(extra: blue)), FormInput(formFieldEmail, const Email.pure(), metadata: const FormInputMetadata(extra: blue)), - FormInput(formFieldList, - const ListOption.pure(defaultValue: 'c3')), + FormInput( + formFieldList, const ListOption.pure(choices: ['c1', 'c2', 'c3'],defaultValue: 'c3')), FormInput(formFieldRadio, const TextString.pure()), FormInput(formFieldPro, const Boolean.pure(), metadata: const FormInputMetadata(name: 'business')), @@ -54,20 +54,35 @@ class App extends StatelessWidget { } static WyattForm getNormalFormData() { - return WyattFormImpl(getNormalEntries()); + return WyattFormImpl(getNormalEntries(), name: formSignUp); } static WyattForm getProFormData() { - return WyattFormImpl(getBusinessEntries()); + return WyattFormImpl(getBusinessEntries(), name: formSignUp); } @override Widget build(BuildContext context) { - SimpleCustomFormCubit formCubit = SimpleCustomFormCubit(getNormalFormData()); + FormRepository formRepository = FormRepositoryImpl() + ..registerForm(getNormalFormData()); + + // FormRepository formRepository = FormRepositoryImpl() + // ..registerForm(WyattFormImpl([ + // FormInput(formFieldName, const Name.pure('Test'), + // metadata: const FormInputMetadata(extra: blue)), + // ], name: formSignUp)); - return BlocProvider( - create: (context) => formCubit, - child: const WidgetTree(), + SimpleCustomFormCubit formCubit = SimpleCustomFormCubit( + formRepository, + formSignUp, + ); + + return RepositoryProvider.value( + value: formRepository, + child: BlocProvider( + create: (context) => formCubit, + child: const WidgetTree(), + ), ); } } diff --git a/packages/wyatt_form_bloc/example/lib/constants.dart b/packages/wyatt_form_bloc/example/lib/constants.dart index 573b5ef6..a52efc92 100644 --- a/packages/wyatt_form_bloc/example/lib/constants.dart +++ b/packages/wyatt_form_bloc/example/lib/constants.dart @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +const String formSignUp = 'signUp'; + const String formFieldName = 'name'; const String formFieldPhone = 'phone'; const String formFieldEmail = 'email'; diff --git a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart index 14ac7fbc..c1727ce5 100644 --- a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart +++ b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart @@ -36,9 +36,10 @@ Color computeColor(Metadata? meta) { class _NameInput extends StatelessWidget { @override Widget build(BuildContext context) { - return InputBuilderMetadata( + return InputBuilderTextController( field: formFieldName, - builder: (context, cubit, state, field, inputValid, metadata) { + builder: + (context, cubit, state, field, inputValid, controller, metadata) { final meta = state.form.metadataOf(field).extra; final color = computeColor(meta); return Row( @@ -57,6 +58,7 @@ class _NameInput extends StatelessWidget { SizedBox( width: MediaQuery.of(context).size.width - 45, child: TextField( + controller: controller, onChanged: (value) => cubit.dataChanged(field, Name.dirty(value)), keyboardType: TextInputType.name, diff --git a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/simple_sign_up_form.dart b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/simple_sign_up_form.dart new file mode 100644 index 00000000..a3a93310 --- /dev/null +++ b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/simple_sign_up_form.dart @@ -0,0 +1,57 @@ +// 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 . + +import 'package:flutter/material.dart'; +import 'package:form_bloc_example/app/metadata.dart'; +import 'package:form_bloc_example/constants.dart'; +import 'package:form_bloc_example/simple_custom_form_cubit/simple_custom_form_cubit.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +class _NameInput extends StatelessWidget { + @override + Widget build(BuildContext context) { + return InputBuilderTextController( + field: formFieldName, + builder: + (context, cubit, state, field, inputValid, controller, metadata) { + return TextField( + controller: controller, + onChanged: (value) => cubit.dataChanged(field, Name.dirty(value)), + keyboardType: TextInputType.name, + decoration: InputDecoration( + labelText: 'name', + helperText: '', + errorText: !inputValid ? 'invalid name' : null, + ), + ); + }, + ); + } +} + +class SimpleSignUpForm extends StatelessWidget { + const SimpleSignUpForm({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + _NameInput(), + const SizedBox(height: 8), + ], + ); + } +} diff --git a/packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart b/packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart index b8b0dfca..bb23ed9a 100644 --- a/packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart +++ b/packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart @@ -19,7 +19,7 @@ import 'dart:developer'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; class SimpleCustomFormCubit extends FormDataCubitImpl { - SimpleCustomFormCubit(super.form) : super(); + SimpleCustomFormCubit(super._formRepository, super._formName) : super(); @override Future submit() { From f031b3cbf5e1dad303b493112d262254ad6d586c Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 01:28:30 -0500 Subject: [PATCH 10/18] fix: make cubit custom implementation simpler --- .../features/form_data/form_data_cubit.dart | 1 + .../features/form_data/form_data_state.dart | 14 ++++++++++---- .../form_data_impl/form_data_state_impl.dart | 3 ++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart index 3af6c99b..3fcdbf8f 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart @@ -21,6 +21,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart'; import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart'; import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart index f898d4bf..a78d38d6 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart @@ -16,19 +16,25 @@ part of 'form_data_cubit.dart'; +// ignore: must_be_immutable abstract class FormDataState extends Equatable { /// Global status of a form. final FormStatus status; /// FormData with all inputs, and associated metadata. - final WyattForm form; + late WyattForm form; /// Optional error message. final String? errorMessage; - const FormDataState({ - required this.form, + FormDataState({ + WyattForm? form, this.status = FormStatus.pure, this.errorMessage, - }); + }) { + this.form = form ?? WyattFormImpl(const [], name: ''); + } + + @override + List get props => [status, form, errorMessage]; } diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart index dad01887..657187a4 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart @@ -16,8 +16,9 @@ part of 'form_data_cubit_impl.dart'; +// ignore: must_be_immutable class FormDataStateImpl extends FormDataState { - const FormDataStateImpl({ + FormDataStateImpl({ required super.form, super.status = FormStatus.pure, super.errorMessage, From ae3711a1366b845af6c6d961a38823822f2f88b0 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 13:24:00 -0500 Subject: [PATCH 11/18] fix!(form): fix states with required form --- .../features/form_data/form_data_state.dart | 11 ++++------- .../features/form_data_impl/form_data_state_impl.dart | 7 +++---- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart index a78d38d6..57ab4c95 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart @@ -16,24 +16,21 @@ part of 'form_data_cubit.dart'; -// ignore: must_be_immutable abstract class FormDataState extends Equatable { /// Global status of a form. final FormStatus status; /// FormData with all inputs, and associated metadata. - late WyattForm form; + final WyattForm form; /// Optional error message. final String? errorMessage; - FormDataState({ - WyattForm? form, + const FormDataState({ + required this.form, this.status = FormStatus.pure, this.errorMessage, - }) { - this.form = form ?? WyattFormImpl(const [], name: ''); - } + }); @override List get props => [status, form, errorMessage]; diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart index 657187a4..e31750ce 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart @@ -16,9 +16,8 @@ part of 'form_data_cubit_impl.dart'; -// ignore: must_be_immutable class FormDataStateImpl extends FormDataState { - FormDataStateImpl({ + const FormDataStateImpl({ required super.form, super.status = FormStatus.pure, super.errorMessage, @@ -39,6 +38,6 @@ class FormDataStateImpl extends FormDataState { List get props => [status, form, errorMessage]; @override - String toString() => - 'FormDataSate(status: ${status.name} ${(errorMessage != null) ? " [$errorMessage]" : ""}, $form'; + String toString() => 'FormDataSate(status: ${status.name} ' + '${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)'; } From 0c920e82454a591e7343b164fafd33431d2041e4 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 13:24:29 -0500 Subject: [PATCH 12/18] feat(form): clean and add toString and equality --- .../lib/src/data/form/wyatt_form_impl.dart | 8 +++++--- .../data/input_validators/confirmed_password.dart | 3 +++ .../src/data/repositories/form_repository_impl.dart | 3 +++ .../lib/src/domain/entities/form_input.dart | 2 +- .../src/domain/input_validators/any_validator.dart | 6 ++++++ .../domain/input_validators/equality_validator.dart | 12 +++++++++--- .../input_validators/form_input_validator.dart | 4 ++-- 7 files changed, 29 insertions(+), 9 deletions(-) diff --git a/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart index 9b17b055..d336b329 100644 --- a/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart @@ -73,7 +73,9 @@ class WyattFormImpl extends WyattForm { if (containsKey(key)) { return inputs.firstWhere((input) => input.key == key); } else { - throw Exception('FormInput with key `$key` does not exist in form'); + throw Exception( + 'FormInput with key `$key` does not exist in form `$name`', + ); } } @@ -146,6 +148,6 @@ class WyattFormImpl extends WyattForm { List get props => [_inputs, _name, _validator]; @override - String toString() => - 'WyattForm(name: $name, validation: ${_validator.runtimeType}, inputs: $inputs)'; + String toString() => 'WyattForm(name: $name, validation: ' + '${_validator.runtimeType}, inputs: $inputs)'; } diff --git a/packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart index 448efba2..b8df4c4c 100644 --- a/packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart @@ -41,4 +41,7 @@ class ConfirmedPassword @override ValidationStandardError get onNull => ValidationStandardError.invalid; + + @override + List get props => super.props + [password]; } diff --git a/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart b/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart index 0d97327b..b720c0f6 100644 --- a/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart @@ -57,4 +57,7 @@ class FormRepositoryImpl extends FormRepository { void unregisterForm(String formName) { _runtimeForms.remove(formName); } + + @override + String toString() => 'FormRepository($_runtimeForms)'; } diff --git a/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart index b8abfd7e..0947e7aa 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart @@ -63,5 +63,5 @@ class FormInput< @override String toString() => - 'FormInput(name: $name, value: ${validator.value}, status: ${validator.status.name}'; + 'FormInput(name: $name, $validator)'; } diff --git a/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart index 0869d8b5..396924d7 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart @@ -42,4 +42,10 @@ abstract class AnyValidator, } return onError; } + + @override + List get props => super.props + [allChoices]; + + @override + String toString() => '${super.toString()}, choices: $allChoices'; } diff --git a/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart index 531d55ab..3a70b9ad 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart @@ -1,16 +1,16 @@ // 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 . @@ -42,4 +42,10 @@ abstract class EqualityValidator } return null; } + + @override + List get props => super.props + [another]; + + @override + String toString() => '${super.toString()}, another: $another'; } diff --git a/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart index ebb539d3..676cf137 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart @@ -107,8 +107,8 @@ abstract class FormInputValidator Error? validator(Value? value); @override - bool? get stringify => true; + List get props => [value, pure]; @override - List get props => [value, pure]; + String toString() => 'value: $value, status: ${status.name}'; } From 59bd3edb0dd57140e13b98684ad62e0673ac9453 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 13:29:30 -0500 Subject: [PATCH 13/18] feat!(auth): use new form features --- .../features/sign_in/cubit/sign_in_cubit.dart | 109 +++++++++--- .../features/sign_in/cubit/sign_in_state.dart | 29 ++- .../features/sign_up/cubit/sign_up_cubit.dart | 166 ++++++++---------- .../features/sign_up/cubit/sign_up_state.dart | 32 ++-- 4 files changed, 187 insertions(+), 149 deletions(-) diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart index 531c94b4..b8cc1358 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart @@ -14,55 +14,96 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:equatable/equatable.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; +import 'dart:async'; + +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; part 'sign_in_state.dart'; -class SignInCubit extends Cubit { +class SignInCubit extends FormDataCubit { final AuthenticationRepository _authenticationRepository; - - final FormValidator _validationStrategy; + FormRepository get _formRepository => + _authenticationRepository.formRepository; SignInCubit({ required AuthenticationRepository authenticationRepository, - FormValidator validationStrategy = const EveryInputValidator(), }) : _authenticationRepository = authenticationRepository, - _validationStrategy = validationStrategy, - super(const SignInState()); + super( + SignInState( + form: authenticationRepository.formRepository + .accessForm(AuthFormName.signInForm), + ), + ); + + @override + String get formName => AuthFormName.signInForm; void emailChanged(String value) { final Email email = Email.dirty(value); - emit( - state.copyWith( - email: email, - status: _validationStrategy.rawValidate([email, state.password]), - ), - ); + dataChanged(AuthFormField.email, email); } void passwordChanged(String value) { final Password password = Password.dirty(value); + dataChanged(AuthFormField.password, password); + } + + @override + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, + ) { + final form = _formRepository.accessForm(formName).clone(); + + try { + form.updateValidator(key, dirtyValue); + _formRepository.updateForm(form); + } catch (e) { + rethrow; + } + emit( - state.copyWith( - password: password, - status: _validationStrategy.rawValidate([state.email, password]), - ), + state.copyWith(form: form, status: form.validate()), ); } - Future signInWithEmailAndPassword() async { + @override + FutureOr reset() { + final form = state.form.reset(); + _formRepository.updateForm(form); + emit( + state.copyWith(form: form, status: form.validate()), + ); + } + + @override + FutureOr submit() async { if (!state.status.isValidated) { return; } emit(state.copyWith(status: FormStatus.submissionInProgress)); + final form = _formRepository.accessForm(formName); + final email = form.valueOf(AuthFormField.email); + final password = form.valueOf(AuthFormField.password); + + if (email.isNullOrEmpty || password.isNullOrEmpty) { + emit( + state.copyWith( + errorMessage: 'An error occured while retrieving data from the form.', + status: FormStatus.submissionFailure, + ), + ); + } + final uid = await _authenticationRepository.signInWithEmailAndPassword( - email: state.email.value, - password: state.password.value, + email: email!, + password: password!, ); emit( @@ -75,4 +116,30 @@ class SignInCubit extends Cubit { ), ); } + + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm current = _formRepository.accessForm(formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + _formRepository.updateForm(newForm); + + emit( + state.copyWith( + form: newForm, + status: newForm.validate(), + ), + ); + } + + @override + FutureOr validate() { + emit( + state.copyWith( + status: _formRepository.accessForm(formName).validate(), + ), + ); + } } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart index 0e407276..85e4edb1 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart @@ -16,28 +16,23 @@ part of 'sign_in_cubit.dart'; -class SignInState extends Equatable { - final Email email; - final Password password; - final FormStatus status; - final String? errorMessage; +class SignInState extends FormDataState { + Email get email => form.validatorOf(AuthFormField.email); + Password get password => form.validatorOf(AuthFormField.password); const SignInState({ - this.email = const Email.pure(), - this.password = const Password.pure(), - this.status = FormStatus.pure, - this.errorMessage, + required super.form, + super.status = FormStatus.pure, + super.errorMessage, }); SignInState copyWith({ - Email? email, - Password? password, + WyattForm? form, FormStatus? status, String? errorMessage, }) => SignInState( - email: email ?? this.email, - password: password ?? this.password, + form: form ?? this.form, status: status ?? this.status, errorMessage: errorMessage ?? this.errorMessage, ); @@ -46,10 +41,6 @@ class SignInState extends Equatable { List get props => [email, password, status]; @override - String toString() => ''' - email: $email, - password: $password, - status: $status, - errorMessage: $errorMessage, - '''; + String toString() => 'SignInState(status: ${status.name} ' + '${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)'; } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart index 5d338498..9abdf146 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart @@ -16,132 +16,94 @@ import 'dart:async'; -import 'package:equatable/equatable.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; part 'sign_up_state.dart'; -class SignUpCubit extends Cubit { +class SignUpCubit extends FormDataCubit { final AuthenticationRepository _authenticationRepository; - - final FormValidator _validationStrategy; + FormRepository get _formRepository => + _authenticationRepository.formRepository; SignUpCubit({ required AuthenticationRepository authenticationRepository, - required FormData formData, - FormValidator validationStrategy = const EveryInputValidator(), }) : _authenticationRepository = authenticationRepository, - _validationStrategy = validationStrategy, - super(SignUpState(data: formData)); + super( + SignUpState( + form: authenticationRepository.formRepository + .accessForm(AuthFormName.signUpForm), + ), + ); + + @override + String get formName => AuthFormName.signUpForm; void emailChanged(String value) { final Email email = Email.dirty(value); - - final List> toValidate = [ - email, - state.password, - ...state.data.validators(), - ]; - - emit( - state.copyWith( - email: email, - status: _validationStrategy.rawValidate(toValidate), - ), - ); + dataChanged(AuthFormField.email, email); } void passwordChanged(String value) { final Password password = Password.dirty(value); - - final List> toValidate = [ - state.email, - password, - ...state.data.validators(), - ]; - - emit( - state.copyWith( - password: password, - status: _validationStrategy.rawValidate(toValidate), - ), - ); + dataChanged(AuthFormField.password, password); } - // Take from wyatt_form_bloc/wyatt_form_bloc.dart - void dataChanged( - String field, - FormInputValidator dirtyValue, + @override + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, ) { - final form = state.data.clone(); + final form = _formRepository.accessForm(formName).clone(); - if (form.contains(field)) { - form.updateValidator(field, dirtyValue); - } else { - throw Exception('Form field $field not found'); + try { + form.updateValidator(key, dirtyValue); + _formRepository.updateForm(form); + } catch (e) { + rethrow; } emit( - state.copyWith( - data: form, - status: _validationStrategy.rawValidate( - [ - state.email, - state.password, - ...state.data.validators(), - ], - ), - ), + state.copyWith(form: form, status: form.validate()), ); } - // Take from wyatt_form_bloc/wyatt_form_bloc.dart - void updateFormData( - FormData data, { - SetOperation operation = SetOperation.replace, - }) { - FormData form = data; - - switch (operation) { - case SetOperation.replace: - form = data; - break; - case SetOperation.difference: - form = state.data.difference(data); - break; - case SetOperation.intersection: - form = state.data.intersection(data); - break; - case SetOperation.union: - form = state.data.union(data); - break; - } - + @override + FutureOr reset() { + final form = state.form.reset(); + _formRepository.updateForm(form); emit( - state.copyWith( - data: form, - status: _validationStrategy.rawValidate( - [ - state.email, - state.password, - ...state.data.validators(), - ], - ), - ), + state.copyWith(form: form, status: form.validate()), ); } - Future signUpFormSubmitted() async { + @override + FutureOr submit() async { if (!state.status.isValidated) { return; } + emit(state.copyWith(status: FormStatus.submissionInProgress)); + final form = _formRepository.accessForm(formName); + final email = form.valueOf(AuthFormField.email); + final password = form.valueOf(AuthFormField.password); + + if (email.isNullOrEmpty || password.isNullOrEmpty) { + emit( + state.copyWith( + errorMessage: 'An error occured while retrieving data from the form.', + status: FormStatus.submissionFailure, + ), + ); + } + final uid = await _authenticationRepository.signUp( - email: state.email.value, - password: state.password.value, + email: email!, + password: password!, ); emit( @@ -154,4 +116,30 @@ class SignUpCubit extends Cubit { ), ); } + + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm current = _formRepository.accessForm(formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + _formRepository.updateForm(newForm); + + emit( + state.copyWith( + form: newForm, + status: newForm.validate(), + ), + ); + } + + @override + FutureOr validate() { + emit( + state.copyWith( + status: _formRepository.accessForm(formName).validate(), + ), + ); + } } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart index fefe5325..d6ba26c3 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart @@ -16,40 +16,32 @@ part of 'sign_up_cubit.dart'; -class SignUpState extends Equatable { - final Email email; - final Password password; - final FormStatus status; - final FormData data; - final String? errorMessage; +class SignUpState extends FormDataState { + Email get email => form.validatorOf(AuthFormField.email); + Password get password => form.validatorOf(AuthFormField.password); const SignUpState({ - required this.data, - this.email = const Email.pure(), - this.password = const Password.pure(), - this.status = FormStatus.pure, - this.errorMessage, + required super.form, + super.status = FormStatus.pure, + super.errorMessage, }); SignUpState copyWith({ - Email? email, - Password? password, + WyattForm? form, FormStatus? status, - FormData? data, String? errorMessage, }) => SignUpState( - email: email ?? this.email, - password: password ?? this.password, + form: form ?? this.form, status: status ?? this.status, - data: data ?? this.data, errorMessage: errorMessage ?? this.errorMessage, ); @override - String toString() => 'SignUpState(email: $email, password: $password, ' - 'status: $status, data: $data, errorMessage: $errorMessage)'; + List get props => [email, password, status, form]; @override - List get props => [email, password, status, data, errorMessage]; + @override + String toString() => 'SignUpState(status: ${status.name} ' + '${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)'; } From c0a91d64377609c3cf9731302b208a6766f86b16 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 13:30:13 -0500 Subject: [PATCH 14/18] feat!(auth): use form repository --- .../lib/src/core/constants/form_field.dart | 20 +++ .../lib/src/core/constants/form_name.dart | 20 +++ .../authentication_repository_impl.dart | 119 +++++++++++++----- .../authentication_repository.dart | 16 +-- 4 files changed, 136 insertions(+), 39 deletions(-) create mode 100644 packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart create mode 100644 packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart diff --git a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart new file mode 100644 index 00000000..295cfc2f --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart @@ -0,0 +1,20 @@ +// 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 . + +abstract class AuthFormField { + static const email = 'wyattEmailField'; + static const password = 'wyattPasswordField'; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart new file mode 100644 index 00000000..5a788715 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart @@ -0,0 +1,20 @@ +// 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 . + +abstract class AuthFormName { + static const String signUpForm = 'wyattSignUpForm'; + static const String signInForm = 'wyattSignInForm'; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart index e5526ea8..00bf067c 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart @@ -15,28 +15,75 @@ // along with this program. If not, see . import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; import 'package:wyatt_authentication_bloc/src/data/models/account_wrapper_model.dart'; -import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_local_data_source.dart'; +import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_cache_data_source.dart'; import 'package:wyatt_authentication_bloc/src/domain/data_sources/remote/authentication_remote_data_source.dart'; import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; +typedef OnSignUpSuccess = FutureResult Function( + Account? account, + WyattForm form, +); + +typedef OnAuthChange = FutureResult Function(Account? account); + class AuthenticationRepositoryImpl extends AuthenticationRepository { - final AuthenticationLocalDataSource _authenticationLocalDataSource; + final AuthenticationCacheDataSource _authenticationLocalDataSource; final AuthenticationRemoteDataSource _authenticationRemoteDataSource; - final FutureResult Function(Account? account)? _onSignUpSuccess; - final FutureResult Function(Account? account)? _onAccountChanges; + late FormRepository _formRepository; - AuthenticationRepositoryImpl( - this._authenticationLocalDataSource, - this._authenticationRemoteDataSource, - this._onSignUpSuccess, - this._onAccountChanges, - ); + final OnSignUpSuccess? _onSignUpSuccess; + + final OnAuthChange? _onAccountChanges; + + AuthenticationRepositoryImpl({ + required AuthenticationCacheDataSource authenticationCacheDataSource, + required AuthenticationRemoteDataSource authenticationRemoteDataSource, + FormRepository? formRepository, + // ignore: strict_raw_type + List? extraSignUpInputs, + OnSignUpSuccess? onSignUpSuccess, + OnAuthChange? onAuthChange, + }) : _authenticationLocalDataSource = authenticationCacheDataSource, + _authenticationRemoteDataSource = authenticationRemoteDataSource, + _onSignUpSuccess = onSignUpSuccess, + _onAccountChanges = onAuthChange { + _formRepository = formRepository ?? FormRepositoryImpl(); + if (formRepository != null) { + return; + } + _formRepository + ..registerForm( + WyattFormImpl( + [ + FormInput(AuthFormField.email, const Email.pure()), + FormInput(AuthFormField.password, const Password.pure()) + ], + name: AuthFormName.signInForm, + ), + ) + ..registerForm( + WyattFormImpl( + [ + FormInput(AuthFormField.email, const Email.pure()), + FormInput(AuthFormField.password, const Password.pure()), + ...extraSignUpInputs ?? [] + ], + name: AuthFormName.signUpForm, + ), + ); + } + + @override + FormRepository get formRepository => _formRepository; @override FutureResult signInWithEmailAndPassword({ @@ -50,7 +97,7 @@ class AuthenticationRepositoryImpl email: email, password: password, ); - _authenticationLocalDataSource.storeAccount(account); + await _authenticationLocalDataSource.storeAccount(account); return account; }, (error) => error, @@ -61,7 +108,7 @@ class AuthenticationRepositoryImpl Result.tryCatchAsync( () async { await _authenticationRemoteDataSource.signOut(); - _authenticationLocalDataSource.destroy(); + await _authenticationLocalDataSource.destroy(); }, (error) => error, ); @@ -77,10 +124,13 @@ class AuthenticationRepositoryImpl email: email, password: password, ); - _authenticationLocalDataSource.storeAccount(account); + await _authenticationLocalDataSource.storeAccount(account); if (_onSignUpSuccess.isNotNull) { - final dataResult = await _onSignUpSuccess!.call(account); - dataResult.fold( + final dataResult = await _onSignUpSuccess!.call( + account, + _formRepository.accessForm(AuthFormName.signUpForm).clone(), + ); + await dataResult.foldAsync( _authenticationLocalDataSource.storeData, (error) => throw error, ); @@ -91,46 +141,51 @@ class AuthenticationRepositoryImpl ); @override - Result destroyCache() => - Result.tryCatch( + FutureResult destroyCache() => + Result.tryCatchAsync( _authenticationLocalDataSource.destroy, (error) => error, ); @override - Result getAccount() => - Result.tryCatch( + FutureResult> getCache() => + Result.tryCatchAsync, AppException, AppException>( + _authenticationLocalDataSource.load, + (error) => error, + ); + + @override + FutureResult getAccount() => + Result.tryCatchAsync( _authenticationLocalDataSource.loadAccount, (error) => error, ); @override - Result setAccount( + FutureResult setAccount( Account account, ) => - Result.tryCatch( - () { - _authenticationLocalDataSource.storeAccount(account); - return account; + Result.tryCatchAsync( + () async { + await _authenticationLocalDataSource.storeAccount(account); }, (error) => error, ); @override - Result getData() => - Result.tryCatch( + FutureResult getData() => + Result.tryCatchAsync( _authenticationLocalDataSource.loadData, (error) => error, ); @override - Result setData( - T data, + FutureResult setData( + T? data, ) => - Result.tryCatch( - () { - _authenticationLocalDataSource.storeData(data); - return data; + Result.tryCatchAsync( + () async { + await _authenticationLocalDataSource.storeData(data); }, (error) => error, ); diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart index 432b1de6..cece19c9 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart @@ -17,13 +17,14 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; -import 'package:wyatt_type_utils/wyatt_type_utils.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; abstract class AuthenticationRepository extends BaseRepository { + FormRepository get formRepository; + FutureResult signUp({ required String email, required String password, - }); FutureResult signInWithEmailAndPassword({ @@ -37,11 +38,12 @@ abstract class AuthenticationRepository extends BaseRepository { FutureResult getIdentityToken(); - Result getAccount(); - Result setAccount(Account account); + FutureResult getAccount(); + FutureResult setAccount(Account account); - Result getData(); - Result setData(T data); + FutureResult getData(); + FutureResult setData(T? data); - Result destroyCache(); + FutureResult> getCache(); + FutureResult destroyCache(); } From b2a9dac7c6df3235a21bf106dd9b0131394f50e6 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 13:31:00 -0500 Subject: [PATCH 15/18] refactor(auth): rename local to cache auth data source --- .../lib/src/core/core.dart | 8 ++++--- ...authentication_cache_data_source_impl.dart | 23 ++++++++++++------- .../src/domain/data_sources/data_sources.dart | 3 +-- ...authentication_biometrics_data_source.dart | 19 --------------- ... => authentication_cache_data_source.dart} | 14 ++++++----- 5 files changed, 29 insertions(+), 38 deletions(-) delete mode 100644 packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_biometrics_data_source.dart rename packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/{authentication_local_data_source.dart => authentication_cache_data_source.dart} (71%) diff --git a/packages/wyatt_authentication_bloc/lib/src/core/core.dart b/packages/wyatt_authentication_bloc/lib/src/core/core.dart index 658cbca0..16b0264b 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/core.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/core.dart @@ -1,19 +1,21 @@ // 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 . +export 'constants/form_field.dart'; +export 'constants/form_name.dart'; export 'enums/enums.dart'; export 'exceptions/exceptions.dart'; export 'utils/utils.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart index 363ee51d..57b1191a 100644 --- a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart @@ -15,29 +15,28 @@ // along with this program. If not, see . import 'package:wyatt_architecture/wyatt_architecture.dart'; -import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_local_data_source.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; class AuthenticationCacheDataSourceImpl - extends AuthenticationLocalDataSource { + extends AuthenticationCacheDataSource { Account? _account; T? _data; AuthenticationCacheDataSourceImpl(); @override - void storeAccount(Account? account) { + Future storeAccount(Account? account) async { _account = account; } @override - void storeData(T? data) { + Future storeData(T? data) async { _data = data; } @override - Account loadAccount() { + Future loadAccount() async { if (_account.isNotNull) { return _account!; } @@ -45,7 +44,7 @@ class AuthenticationCacheDataSourceImpl } @override - T loadData() { + Future loadData() async { if (_data.isNotNull) { return _data!; } @@ -53,8 +52,16 @@ class AuthenticationCacheDataSourceImpl } @override - void destroy() { + Future destroy() async { _data = null; _account = null; } + + @override + Future> load() async { + if (_account.isNull) { + throw ClientException('Cached account is invalid'); + } + return AccountWrapperModel(_account, _data); + } } diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart index 1e726386..11efe02d 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart @@ -14,6 +14,5 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'local/authentication_biometrics_data_source.dart'; -export 'local/authentication_local_data_source.dart'; +export 'local/authentication_cache_data_source.dart'; export 'remote/authentication_remote_data_source.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_biometrics_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_biometrics_data_source.dart deleted file mode 100644 index 489c9919..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_biometrics_data_source.dart +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:wyatt_architecture/wyatt_architecture.dart'; - -abstract class AuthenticationBiometricsDataSource extends BaseLocalDataSource {} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_local_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart similarity index 71% rename from packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_local_data_source.dart rename to packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart index cd47d32e..c4d357e5 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_local_data_source.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart @@ -16,12 +16,14 @@ import 'package:wyatt_architecture/wyatt_architecture.dart'; import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; -abstract class AuthenticationLocalDataSource +abstract class AuthenticationCacheDataSource extends BaseLocalDataSource { - void storeAccount(Account? account); - void storeData(T? data); - Account loadAccount(); - T loadData(); - void destroy(); + Future storeAccount(Account? account); + Future storeData(T? data); + Future loadAccount(); + Future loadData(); + Future> load(); + Future destroy(); } From 6802a56bfc87929daacde5504121eafa26fabcf5 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 13:31:15 -0500 Subject: [PATCH 16/18] doc(auth): update example router --- .../lib/core/dependency_injection/get_it.dart | 2 +- .../example_router/lib/core/utils/forms.dart | 21 ---- .../lib/presentation/features/app/app.dart | 62 ++++++++---- .../presentation/features/home/home_page.dart | 2 +- .../sign_in/widgets/sign_in_form.dart | 44 ++++----- .../sign_up/widgets/sign_up_form.dart | 95 ++++++++----------- .../example_router/pubspec.yaml | 6 ++ 7 files changed, 112 insertions(+), 120 deletions(-) delete mode 100644 packages/wyatt_authentication_bloc/example_router/lib/core/utils/forms.dart diff --git a/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart b/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart index 0466f831..f75d34df 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart @@ -25,7 +25,7 @@ abstract class GetItInitializer { ..registerLazySingleton( () => AuthenticationFirebaseDataSourceImpl(), ) - ..registerLazySingleton>( + ..registerLazySingleton>( () => AuthenticationCacheDataSourceImpl(), ); diff --git a/packages/wyatt_authentication_bloc/example_router/lib/core/utils/forms.dart b/packages/wyatt_authentication_bloc/example_router/lib/core/utils/forms.dart deleted file mode 100644 index ead7fb45..00000000 --- a/packages/wyatt_authentication_bloc/example_router/lib/core/utils/forms.dart +++ /dev/null @@ -1,21 +0,0 @@ -// Author: Hugo Pointcheval -// Email: git@pcl.ovh -// ----- -// File: forms.dart -// Created Date: 19/08/2022 12:00:31 -// Last Modified: 19/08/2022 16:35:52 -// ----- -// Copyright (c) 2022 - -import 'package:example_router/core/constants/form_field.dart'; -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; - -class Forms { - static FormData getNormalData() => const FormData([ - FormInput( - AppFormField.confirmedPassword, - ConfirmedPassword.pure(), - metadata: FormInputMetadata(export: false), - ), - ]); -} diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart index 0f503aa6..9bf7f5cd 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart @@ -3,33 +3,58 @@ // ----- // File: app.dart // Created Date: 19/08/2022 12:05:38 -// Last Modified: Wed Nov 09 2022 +// Last Modified: Thu Nov 10 2022 // ----- // Copyright (c) 2022 import 'dart:async'; +import 'dart:math'; +import 'package:example_router/core/constants/form_field.dart'; import 'package:example_router/core/dependency_injection/get_it.dart'; import 'package:example_router/core/routes/router.dart'; -import 'package:example_router/core/utils/forms.dart'; -import 'package:example_router/presentation/features/home/home_page.dart'; -import 'package:example_router/presentation/features/welcome/welcome_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; import 'package:wyatt_type_utils/wyatt_type_utils.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; + +FutureResult onSignUpSuccess( + Account? account, + WyattForm form, +) async { + const id = -1; + final confirmedPassword = + form.valueOf(AppFormField.confirmedPassword); + + debugPrint( + 'onSignUpSuccess: $account, generatedId: $id, extraFormData: $confirmedPassword'); + return const Ok(id); +} + +FutureResult onAccountChanges(Account? account) async { + final id = Random().nextInt(1000); + debugPrint('onAccountChanges: $account, generatedId: $id'); + return Ok(id); +} class App extends StatelessWidget { final AuthenticationRepository authenticationRepository = - AuthenticationRepositoryImpl(getIt>(), - getIt(), (account) async { - debugPrint('onSignUpSuccess: $account'); - return const Ok(null); - }, (account) async { - debugPrint('onAccountChanges: $account'); - return const Ok(null); - }); + AuthenticationRepositoryImpl( + authenticationCacheDataSource: getIt>(), + authenticationRemoteDataSource: getIt(), + onSignUpSuccess: onSignUpSuccess, + onAuthChange: onAccountChanges, + extraSignUpInputs: [ + FormInput( + AppFormField.confirmedPassword, + const ConfirmedPassword.pure(), + metadata: const FormInputMetadata(export: false), + ), + ], + ); App({Key? key}) : super(key: key); @@ -65,12 +90,12 @@ class App extends StatelessWidget { if (isOnboarding) { return null; } else { - return state.namedLocation(WelcomePage.pageName); + return '/'; } } else { debugPrint('Logged'); if (isOnboarding) { - return state.namedLocation(HomePage.pageName); + return '/home'; } else { return null; } @@ -91,13 +116,12 @@ class App extends StatelessWidget { BlocProvider>.value( value: authenticationCubit, ), - BlocProvider( + BlocProvider>( create: (_) => SignUpCubit( authenticationRepository: authenticationRepository, - formData: Forms.getNormalData(), ), ), - BlocProvider( + BlocProvider>( create: (_) => SignInCubit( authenticationRepository: authenticationRepository, ), @@ -106,9 +130,7 @@ class App extends StatelessWidget { child: MaterialApp.router( title: 'Demo Authentication', debugShowCheckedModeBanner: false, - routerDelegate: router.routerDelegate, - routeInformationParser: router.routeInformationParser, - routeInformationProvider: router.routeInformationProvider, + routerConfig: router, ), ), ); diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart index bc980cd3..e271c7e1 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart @@ -36,7 +36,7 @@ class HomePage extends StatelessWidget { children: [ AuthenticationBuilder( authenticated: (context, accountWrapper) => - Text('Logged as ${accountWrapper.account?.email}'), + Text('Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'), unauthenticated: (context) => const Text('Not logged (unauthenticated)'), unknown: (context) => const Text('Not logged (unknown)'), diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart index 3f729ad1..7df70853 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart @@ -3,30 +3,31 @@ // ----- // File: sign_in_form.dart // Created Date: 19/08/2022 15:24:37 -// Last Modified: Wed Nov 09 2022 +// Last Modified: Thu Nov 10 2022 // ----- // Copyright (c) 2022 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( - buildWhen: (previous, current) => previous.email != current.email, - builder: (context, state) { + return InputBuilder>( + field: AuthFormField.email, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (email) => context.read().emailChanged(email), + onChanged: (email) => cubit.emailChanged(email), keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'Email', helperText: '', - errorText: state.email.invalid ? 'Invalid email' : null, + errorText: !inputValid ? 'Invalid email' : null, ), ); - }, + }), ); } } @@ -34,21 +35,19 @@ class _EmailInput extends StatelessWidget { class _PasswordInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.password != current.password, - builder: (context, state) { + return InputBuilder>( + field: AuthFormField.password, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (password) { - context.read().passwordChanged(password); - }, + onChanged: (pwd) => cubit.passwordChanged(pwd), obscureText: true, decoration: InputDecoration( labelText: 'Password', helperText: '', - errorText: state.password.invalid ? 'Invalid password' : null, + errorText: !inputValid ? 'Invalid password' : null, ), ); - }, + }), ); } } @@ -56,18 +55,15 @@ class _PasswordInput extends StatelessWidget { class _SignInButton extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return state.status.isSubmissionInProgress + return SubmitBuilder>( + builder: ((context, cubit, status) { + return status.isSubmissionInProgress ? const CircularProgressIndicator() : ElevatedButton( - onPressed: state.status.isValidated - ? () => - context.read().signInWithEmailAndPassword() - : null, + onPressed: status.isValidated ? () => cubit.submit() : null, child: const Text('Sign in'), ); - }, + }), ); } } @@ -77,7 +73,7 @@ class SignInForm extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocListener( + return BlocListener, SignInState>( listener: (context, state) { if (state.status.isSubmissionFailure) { ScaffoldMessenger.of(context) diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_up/widgets/sign_up_form.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_up/widgets/sign_up_form.dart index 4a7faf42..e01038ea 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_up/widgets/sign_up_form.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_up/widgets/sign_up_form.dart @@ -3,12 +3,12 @@ // ----- // File: sign_up_form.dart // Created Date: 19/08/2022 14:41:08 -// Last Modified: Fri Aug 26 2022 +// Last Modified: Thu Nov 10 2022 // ----- // Copyright (c) 2022 import 'package:example_router/core/constants/form_field.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide FormField; 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'; @@ -16,19 +16,19 @@ import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; class _EmailInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.email != current.email, - builder: (context, state) { + return InputBuilder>( + field: AuthFormField.email, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (email) => context.read().emailChanged(email), + onChanged: (email) => cubit.emailChanged(email), keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'Email', helperText: '', - errorText: state.email.invalid ? 'Invalid email' : null, + errorText: !inputValid ? 'Invalid email' : null, ), ); - }, + }), ); } } @@ -36,33 +36,27 @@ class _EmailInput extends StatelessWidget { class _PasswordInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.password != current.password, - builder: (context, state) { + return InputBuilder>( + field: AuthFormField.password, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (password) { - context.read().passwordChanged(password); - context.read().dataChanged( - AppFormField.confirmedPassword, - ConfirmedPassword.dirty( - password: password, - value: context - .read() - .state - .data - .valueOf( - AppFormField.confirmedPassword), - ), - ); + onChanged: (pwd) { + cubit.passwordChanged(pwd); + cubit.dataChanged( + AppFormField.confirmedPassword, + ConfirmedPassword.dirty( + password: pwd, + value: state.form + .valueOf(AppFormField.confirmedPassword))); }, obscureText: true, decoration: InputDecoration( labelText: 'Password', helperText: '', - errorText: state.password.invalid ? 'Invalid password' : null, + errorText: !inputValid ? 'Invalid password' : null, ), ); - }, + }), ); } } @@ -70,28 +64,27 @@ class _PasswordInput extends StatelessWidget { class _ConfirmPasswordInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { + return InputBuilder>( + field: AppFormField.confirmedPassword, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (confirmPassword) => context - .read() - .dataChanged( - AppFormField.confirmedPassword, - ConfirmedPassword.dirty( - password: context.read().state.password.value, - value: confirmPassword, - ), - ), + onChanged: (pwd) { + cubit.dataChanged( + field, + ConfirmedPassword.dirty( + password: + state.form.valueOf(AuthFormField.password) ?? '', + value: pwd), + ); + }, obscureText: true, decoration: InputDecoration( labelText: 'Confirm password', helperText: '', - errorText: state.data.isNotValid(AppFormField.confirmedPassword) - ? 'Passwords do not match' - : null, + errorText: !inputValid ? 'Passwords do not match' : null, ), ); - }, + }), ); } } @@ -99,17 +92,15 @@ class _ConfirmPasswordInput extends StatelessWidget { class _SignUpButton extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return state.status.isSubmissionInProgress + return SubmitBuilder>( + builder: ((context, cubit, status) { + return status.isSubmissionInProgress ? const CircularProgressIndicator() : ElevatedButton( - onPressed: state.status.isValidated - ? () => context.read().signUpFormSubmitted() - : null, + onPressed: status.isValidated ? () => cubit.submit() : null, child: const Text('Sign up'), ); - }, + }), ); } } @@ -119,11 +110,9 @@ class SignUpForm extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocListener( + return BlocListener, SignUpState>( listener: (context, state) { - if (state.status.isSubmissionSuccess) { - Navigator.of(context).pop(); - } else if (state.status.isSubmissionFailure) { + if (state.status.isSubmissionFailure) { ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar( diff --git a/packages/wyatt_authentication_bloc/example_router/pubspec.yaml b/packages/wyatt_authentication_bloc/example_router/pubspec.yaml index 98e04304..19c6e09e 100644 --- a/packages/wyatt_authentication_bloc/example_router/pubspec.yaml +++ b/packages/wyatt_authentication_bloc/example_router/pubspec.yaml @@ -41,6 +41,12 @@ dependencies: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages ref: wyatt_form_bloc-v0.0.6 path: packages/wyatt_form_bloc + + wyatt_type_utils: + git: + url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages + ref: wyatt_type_utils-v0.0.3+1 + path: packages/wyatt_type_utils # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. From 9b87eb7ed93c32ff486fee1f369df85b522bc4f5 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 13:38:55 -0500 Subject: [PATCH 17/18] chore(form): update pubspec --- .../features/form_data/form_data_cubit.dart | 1 - packages/wyatt_form_bloc/pubspec.yaml | 15 ++++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart index 3fcdbf8f..3af6c99b 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart @@ -21,7 +21,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart'; import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; -import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart'; import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; diff --git a/packages/wyatt_form_bloc/pubspec.yaml b/packages/wyatt_form_bloc/pubspec.yaml index 7d9e5906..c9c7afa9 100644 --- a/packages/wyatt_form_bloc/pubspec.yaml +++ b/packages/wyatt_form_bloc/pubspec.yaml @@ -20,19 +20,16 @@ dependencies: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages ref: wyatt_architecture-v0.0.2-dev.0 path: packages/wyatt_architecture - + wyatt_type_utils: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_type_utils-v0.0.3+1 - path: packages/wyatt_type_utils + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ + version: 0.0.3+1 + dev_dependencies: flutter_test: sdk: flutter wyatt_analysis: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_analysis-v2.2.2 - path: packages/wyatt_analysis + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ + version: 2.2.2 From 3588c3241b9fa45466e0b243cea2f1901853ec18 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 10 Nov 2022 13:39:07 -0500 Subject: [PATCH 18/18] chore(auth): update pubspec --- packages/wyatt_authentication_bloc/pubspec.yaml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/wyatt_authentication_bloc/pubspec.yaml b/packages/wyatt_authentication_bloc/pubspec.yaml index a70feec4..48360fa7 100644 --- a/packages/wyatt_authentication_bloc/pubspec.yaml +++ b/packages/wyatt_authentication_bloc/pubspec.yaml @@ -35,10 +35,8 @@ dependencies: path: packages/wyatt_architecture wyatt_type_utils: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_type_utils-v0.0.3+1 - path: packages/wyatt_type_utils + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ + version: 0.0.3+1 dev_dependencies: @@ -48,7 +46,5 @@ dev_dependencies: mocktail: ^0.3.0 wyatt_analysis: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_analysis-v2.2.2 - path: packages/wyatt_analysis + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ + version: 2.2.2