feat(auth)!: add email verification, password reset support
This commit is contained in:
parent
1dd49fa080
commit
03a51b97ad
@ -17,4 +17,5 @@
|
|||||||
abstract class AuthFormName {
|
abstract class AuthFormName {
|
||||||
static const String signUpForm = 'wyattSignUpForm';
|
static const String signUpForm = 'wyattSignUpForm';
|
||||||
static const String signInForm = 'wyattSignInForm';
|
static const String signInForm = 'wyattSignInForm';
|
||||||
|
static const String passwordResetForm = 'wyattPasswordResetForm';
|
||||||
}
|
}
|
||||||
|
@ -246,3 +246,10 @@ abstract class SignOutFailureInterface extends AuthenticationFailureInterface {
|
|||||||
/// {@macro sign_out_failure}
|
/// {@macro sign_out_failure}
|
||||||
SignOutFailureInterface.fromCode(super.code) : super.fromCode();
|
SignOutFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class GetIdTokenFailureInterface
|
||||||
|
extends AuthenticationFailureInterface {
|
||||||
|
GetIdTokenFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
|
GetIdTokenFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
|
}
|
||||||
|
@ -270,3 +270,10 @@ class SignOutFailureFirebase extends SignOutFailureInterface {
|
|||||||
|
|
||||||
SignOutFailureFirebase.fromCode(super.code) : super.fromCode();
|
SignOutFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GetIdTokenFailureFirebase extends GetIdTokenFailureInterface {
|
||||||
|
GetIdTokenFailureFirebase([String? code, String? msg])
|
||||||
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
|
||||||
|
GetIdTokenFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
|
}
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
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_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
@ -28,7 +27,18 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
|
|
||||||
Account _mapper(User user) => AccountModel(
|
Account _mapper(User user) => AccountModel(
|
||||||
uid: user.uid,
|
uid: user.uid,
|
||||||
|
emailVerified: user.emailVerified,
|
||||||
|
isAnonymous: user.isAnonymous,
|
||||||
|
providerId: user.providerData.first.providerId,
|
||||||
|
creationTime: user.metadata.creationTime,
|
||||||
|
lastSignInTime: user.metadata.lastSignInTime,
|
||||||
|
isNewUser: (user.metadata.creationTime != null &&
|
||||||
|
user.metadata.lastSignInTime != null)
|
||||||
|
? user.metadata.lastSignInTime! == user.metadata.creationTime!
|
||||||
|
: null,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
|
phoneNumber: user.phoneNumber,
|
||||||
|
photoURL: user.photoURL,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -55,6 +65,8 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
||||||
|
/// {@macro signup}
|
||||||
Future<Account> signUp({
|
Future<Account> signUp({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
@ -95,9 +107,10 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
} else {
|
} else {
|
||||||
throw Exception(); // Get caught just after.
|
throw Exception(); // Get caught just after.
|
||||||
}
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw GetIdTokenFailureFirebase.fromCode(e.code);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// TODO(hpcl): implement a non ambiguous exception for this case
|
throw GetIdTokenFailureFirebase();
|
||||||
throw ServerException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,4 +120,83 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
final Account? account = (user.isNotNull) ? _mapper(user!) : null;
|
final Account? account = (user.isNotNull) ? _mapper(user!) : null;
|
||||||
return account;
|
return account;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> sendEmailVerification() async {
|
||||||
|
try {
|
||||||
|
await _firebaseAuth.currentUser!.sendEmailVerification();
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw SendEmailVerificationFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw SendEmailVerificationFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> 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<Account> signInAnonymously() async {
|
||||||
|
try {
|
||||||
|
final userCredential = await _firebaseAuth.signInAnonymously();
|
||||||
|
final user = userCredential.user;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw SignInAnonymouslyFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw SignInAnonymouslyFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> verifyPasswordResetCode({required String code}) async {
|
||||||
|
try {
|
||||||
|
final email = await _firebaseAuth.verifyPasswordResetCode(code);
|
||||||
|
return email.isNotNullOrEmpty;
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw VerifyPasswordResetCodeFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw VerifyPasswordResetCodeFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> refresh() async {
|
||||||
|
try {
|
||||||
|
await _firebaseAuth.currentUser!.reload();
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw RefreshFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw RefreshFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
// Copyright (C) 2022 WYATT GROUP
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Please see the AUTHORS file for details.
|
// Please see the AUTHORS file for details.
|
||||||
//
|
//
|
||||||
@ -16,12 +17,47 @@
|
|||||||
|
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
|
||||||
|
|
||||||
class AccountModel implements Account {
|
class AccountModel extends Account {
|
||||||
@override
|
@override
|
||||||
final String uid;
|
final String uid;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final String? email;
|
final String? email;
|
||||||
|
|
||||||
AccountModel({required this.uid, required this.email});
|
@override
|
||||||
|
final DateTime? creationTime;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final bool emailVerified;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final bool isAnonymous;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final bool? isNewUser;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final DateTime? lastSignInTime;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String? phoneNumber;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String? photoURL;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String providerId;
|
||||||
|
|
||||||
|
AccountModel({
|
||||||
|
required this.uid,
|
||||||
|
required this.emailVerified,
|
||||||
|
required this.isAnonymous,
|
||||||
|
required this.providerId,
|
||||||
|
this.lastSignInTime,
|
||||||
|
this.creationTime,
|
||||||
|
this.isNewUser,
|
||||||
|
this.email,
|
||||||
|
this.phoneNumber,
|
||||||
|
this.photoURL,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -208,4 +208,70 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
AccountWrapperModel<T>(account, null),
|
AccountWrapperModel<T>(account, null),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> confirmPasswordReset({
|
||||||
|
required String code,
|
||||||
|
required String newPassword,
|
||||||
|
}) =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationRemoteDataSource.confirmPasswordReset(
|
||||||
|
code: code,
|
||||||
|
newPassword: newPassword,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> sendEmailVerification() =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationRemoteDataSource.sendEmailVerification();
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> sendPasswordResetEmail({required String email}) =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationRemoteDataSource.sendPasswordResetEmail(
|
||||||
|
email: email,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<Account> signInAnonymously() =>
|
||||||
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
final account =
|
||||||
|
await _authenticationRemoteDataSource.signInAnonymously();
|
||||||
|
return account;
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<bool> verifyPasswordResetCode({required String code}) =>
|
||||||
|
Result.tryCatchAsync<bool, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
final response = await _authenticationRemoteDataSource
|
||||||
|
.verifyPasswordResetCode(code: code);
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> refresh() =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationRemoteDataSource.refresh();
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,22 @@ abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource {
|
|||||||
|
|
||||||
Future<void> signOut();
|
Future<void> signOut();
|
||||||
|
|
||||||
|
Future<void> refresh();
|
||||||
|
|
||||||
Stream<Account?> streamAccount();
|
Stream<Account?> streamAccount();
|
||||||
|
|
||||||
Future<String> getIdentityToken();
|
Future<String> getIdentityToken();
|
||||||
|
|
||||||
|
Future<void> sendEmailVerification();
|
||||||
|
|
||||||
|
Future<void> sendPasswordResetEmail({required String email});
|
||||||
|
|
||||||
|
Future<void> confirmPasswordReset({
|
||||||
|
required String code,
|
||||||
|
required String newPassword,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<bool> verifyPasswordResetCode({required String code});
|
||||||
|
|
||||||
|
Future<Account> signInAnonymously();
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,10 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
abstract class Account extends Entity {
|
abstract class Account extends Equatable implements Entity {
|
||||||
/// The user's unique ID.
|
/// The user's unique ID.
|
||||||
String get uid;
|
String get uid;
|
||||||
|
|
||||||
@ -24,4 +25,52 @@ abstract class Account extends Entity {
|
|||||||
///
|
///
|
||||||
/// Will be `null` if signing in anonymously.
|
/// Will be `null` if signing in anonymously.
|
||||||
String? get email;
|
String? get email;
|
||||||
|
|
||||||
|
/// Returns whether the users email address has been verified.
|
||||||
|
///
|
||||||
|
/// To send a verification email, see `SendEmailVerification`.
|
||||||
|
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.
|
||||||
|
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;
|
||||||
|
|
||||||
|
/// The provider ID for the user.
|
||||||
|
String get providerId;
|
||||||
|
|
||||||
|
/// Whether the user account has been recently created.
|
||||||
|
bool? get isNewUser;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [
|
||||||
|
uid,
|
||||||
|
email,
|
||||||
|
emailVerified,
|
||||||
|
isAnonymous,
|
||||||
|
creationTime,
|
||||||
|
lastSignInTime,
|
||||||
|
phoneNumber,
|
||||||
|
photoURL,
|
||||||
|
providerId,
|
||||||
|
isNewUser,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,14 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.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.dart';
|
||||||
|
|
||||||
abstract class AccountWrapper<T> extends Entity {
|
abstract class AccountWrapper<T> extends Equatable implements Entity {
|
||||||
Account? get account;
|
Account? get account;
|
||||||
T? get data;
|
T? get data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [account, data];
|
||||||
}
|
}
|
||||||
|
@ -22,18 +22,83 @@ import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
|||||||
abstract class AuthenticationRepository<T> extends BaseRepository {
|
abstract class AuthenticationRepository<T> extends BaseRepository {
|
||||||
FormRepository get formRepository;
|
FormRepository get formRepository;
|
||||||
|
|
||||||
|
/// {@template signup}
|
||||||
|
/// 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.
|
||||||
|
/// {@endtemplate}
|
||||||
FutureResult<Account> signUp({
|
FutureResult<Account> signUp({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// {@template send_email_verification}
|
||||||
|
/// Sends verification email to the account email.
|
||||||
|
///
|
||||||
|
/// Throws a SendEmailVerificationFailureInterface if an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureResult<void> sendEmailVerification();
|
||||||
|
|
||||||
|
/// {@template send_password_reset_email}
|
||||||
|
/// Sends a password reset email to the provided [email].
|
||||||
|
///
|
||||||
|
/// Throws a SendPasswordResetEmailFailureInterface if an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureResult<void> sendPasswordResetEmail({required String email});
|
||||||
|
|
||||||
|
/// {@template confirm_password_reset}
|
||||||
|
/// Confirms the password reset with the provided [newPassword] and [code].
|
||||||
|
///
|
||||||
|
/// Throws a ConfirmPasswordResetFailureInterface if an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureResult<void> confirmPasswordReset({
|
||||||
|
required String code,
|
||||||
|
required String newPassword,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// {@template verify_password_reset_code}
|
||||||
|
/// Verify password reset code.
|
||||||
|
///
|
||||||
|
/// Throws a VerifyPasswordResetCodeFailureInterface if an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureResult<bool> verifyPasswordResetCode({required String code});
|
||||||
|
|
||||||
|
/// {@template signin_anom}
|
||||||
|
/// Sign in anonymously.
|
||||||
|
///
|
||||||
|
/// Throws a SignInAnonymouslyFailureInterface if an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureResult<Account> signInAnonymously();
|
||||||
|
|
||||||
|
/// {@template signin_pwd}
|
||||||
|
/// Signs in with the provided [email] and [password].
|
||||||
|
///
|
||||||
|
/// Throws a SignInWithEmailAndPasswordFailureInterface if
|
||||||
|
/// an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
FutureResult<Account> signInWithEmailAndPassword({
|
FutureResult<Account> signInWithEmailAndPassword({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// {@template signout}
|
||||||
|
/// Signs out the current user.
|
||||||
|
/// It also clears the cache and the associated data.
|
||||||
|
/// {@endtemplate}
|
||||||
FutureResult<void> signOut();
|
FutureResult<void> signOut();
|
||||||
|
|
||||||
|
FutureResult<void> refresh();
|
||||||
|
|
||||||
|
/// {@template stream_account}
|
||||||
|
/// Stream of [AccountWrapper] which will emit the current account when
|
||||||
|
/// the authentication state changes.
|
||||||
|
///
|
||||||
|
/// Emits [AccountWrapper] with null [Account] if the user is not
|
||||||
|
/// authenticated.
|
||||||
|
/// {@endtemplate}
|
||||||
Stream<FutureResult<AccountWrapper<T>>> streamAccount();
|
Stream<FutureResult<AccountWrapper<T>>> streamAccount();
|
||||||
|
|
||||||
FutureResult<String> getIdentityToken();
|
FutureResult<String> getIdentityToken();
|
||||||
|
@ -40,16 +40,16 @@ class AuthenticationCubit<Extra> extends Cubit<AuthenticationState<Extra>> {
|
|||||||
accountFutureResult.fold(
|
accountFutureResult.fold(
|
||||||
(value) {
|
(value) {
|
||||||
if (value.account.isNotNull) {
|
if (value.account.isNotNull) {
|
||||||
emit(AuthenticationState.authenticated(value));
|
emit(AuthenticationState<Extra>.authenticated(value));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_authenticationRepository.destroyCache();
|
_authenticationRepository.destroyCache();
|
||||||
emit(const AuthenticationState.unauthenticated());
|
emit(AuthenticationState<Extra>.unauthenticated());
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
(error) {
|
(error) {
|
||||||
_authenticationRepository.destroyCache();
|
_authenticationRepository.destroyCache();
|
||||||
emit(const AuthenticationState.unauthenticated());
|
emit(AuthenticationState<Extra>.unauthenticated());
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -35,7 +35,7 @@ class AuthenticationState<Extra> extends Equatable {
|
|||||||
: this._(status: AuthenticationStatus.unauthenticated);
|
: this._(status: AuthenticationStatus.unauthenticated);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [status];
|
List<Object?> get props => [status, accountWrapper];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
String toString() =>
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/src/features/email_verification/cubit/email_verification_cubit.dart';
|
||||||
|
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
|
class EmailVerificationBuilder<Extra> extends StatelessWidget {
|
||||||
|
const EmailVerificationBuilder({
|
||||||
|
required this.verified,
|
||||||
|
required this.notVerified,
|
||||||
|
required this.onError,
|
||||||
|
this.customBuilder,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Widget Function(BuildContext context) verified;
|
||||||
|
final Widget Function(BuildContext context) notVerified;
|
||||||
|
final Widget Function(
|
||||||
|
BuildContext context,
|
||||||
|
FormStatus status,
|
||||||
|
String? errorMessage,
|
||||||
|
) onError;
|
||||||
|
|
||||||
|
final Widget Function(BuildContext context, EmailVerificationState)?
|
||||||
|
customBuilder;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) =>
|
||||||
|
BlocBuilder<EmailVerificationCubit<Extra>, EmailVerificationState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
if (customBuilder != null) {
|
||||||
|
return customBuilder!(context, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.status.isSubmissionFailure ||
|
||||||
|
state.status.isSubmissionCanceled) {
|
||||||
|
return onError(
|
||||||
|
context,
|
||||||
|
state.status,
|
||||||
|
state.errorMessage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.isVerified) {
|
||||||
|
return verified(context);
|
||||||
|
}
|
||||||
|
return notVerified(context);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/src/domain/repositories/repositories.dart';
|
||||||
|
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
|
part 'email_verification_state.dart';
|
||||||
|
|
||||||
|
class EmailVerificationCubit<Extra> extends Cubit<EmailVerificationState> {
|
||||||
|
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||||
|
|
||||||
|
EmailVerificationCubit({
|
||||||
|
required AuthenticationRepository<Extra> authenticationRepository,
|
||||||
|
}) : _authenticationRepository = authenticationRepository,
|
||||||
|
super(const EmailVerificationState());
|
||||||
|
|
||||||
|
FutureOr<void> sendEmailVerification() async {
|
||||||
|
emit(state.copyWith(status: FormStatus.submissionInProgress));
|
||||||
|
final response = await _authenticationRepository.sendEmailVerification();
|
||||||
|
emit(
|
||||||
|
response.fold(
|
||||||
|
(value) => state.copyWith(status: FormStatus.submissionSuccess),
|
||||||
|
(error) => state.copyWith(
|
||||||
|
errorMessage: error.message,
|
||||||
|
status: FormStatus.submissionFailure,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureOr<void> checkEmailVerification() async {
|
||||||
|
emit(state.copyWith(status: FormStatus.submissionInProgress));
|
||||||
|
|
||||||
|
final refresh = await _authenticationRepository.refresh();
|
||||||
|
if (refresh.isErr) {
|
||||||
|
final refreshError = refresh.err!;
|
||||||
|
emit(
|
||||||
|
EmailVerificationState(
|
||||||
|
errorMessage: refreshError.message,
|
||||||
|
status: FormStatus.submissionFailure,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final currentAccount = await _authenticationRepository.getAccount();
|
||||||
|
emit(
|
||||||
|
currentAccount.fold(
|
||||||
|
(value) => state.copyWith(
|
||||||
|
isVerified: value.emailVerified,
|
||||||
|
status: FormStatus.submissionSuccess,
|
||||||
|
),
|
||||||
|
(error) => EmailVerificationState(
|
||||||
|
errorMessage: error.message,
|
||||||
|
status: FormStatus.submissionFailure,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
part of 'email_verification_cubit.dart';
|
||||||
|
|
||||||
|
class EmailVerificationState extends Equatable {
|
||||||
|
final FormStatus status;
|
||||||
|
final bool isVerified;
|
||||||
|
final String? errorMessage;
|
||||||
|
|
||||||
|
const EmailVerificationState({
|
||||||
|
this.isVerified = false,
|
||||||
|
this.status = FormStatus.pure,
|
||||||
|
this.errorMessage,
|
||||||
|
});
|
||||||
|
|
||||||
|
EmailVerificationState copyWith({
|
||||||
|
FormStatus? status,
|
||||||
|
bool? isVerified,
|
||||||
|
String? errorMessage,
|
||||||
|
}) =>
|
||||||
|
EmailVerificationState(
|
||||||
|
status: status ?? this.status,
|
||||||
|
isVerified: isVerified ?? this.isVerified,
|
||||||
|
errorMessage: errorMessage ?? this.errorMessage,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [status, isVerified, errorMessage];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'EmailVerificationState(status: ${status.name} '
|
||||||
|
'${(errorMessage != null) ? " [$errorMessage]" : ""}, '
|
||||||
|
'isVerified: $isVerified)';
|
||||||
|
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'builder/email_verification_builder.dart';
|
||||||
|
export 'cubit/email_verification_cubit.dart';
|
@ -1,19 +1,21 @@
|
|||||||
// Copyright (C) 2022 WYATT GROUP
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Please see the AUTHORS file for details.
|
// Please see the AUTHORS file for details.
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// any later version.
|
// any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
export 'authentication/authentication.dart';
|
export 'authentication/authentication.dart';
|
||||||
|
export 'email_verification/email_verification.dart';
|
||||||
|
export 'password_reset/password_reset.dart';
|
||||||
export 'sign_in/sign_in.dart';
|
export 'sign_in/sign_in.dart';
|
||||||
export 'sign_up/sign_up.dart';
|
export 'sign_up/sign_up.dart';
|
||||||
|
@ -0,0 +1,138 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart: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 'password_reset_state.dart';
|
||||||
|
|
||||||
|
class PasswordResetCubit<Extra> extends FormDataCubit<PasswordResetState> {
|
||||||
|
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||||
|
FormRepository get _formRepository =>
|
||||||
|
_authenticationRepository.formRepository;
|
||||||
|
|
||||||
|
PasswordResetCubit({
|
||||||
|
required AuthenticationRepository<Extra> authenticationRepository,
|
||||||
|
}) : _authenticationRepository = authenticationRepository,
|
||||||
|
super(
|
||||||
|
PasswordResetState(
|
||||||
|
form: authenticationRepository.formRepository
|
||||||
|
.accessForm(AuthFormName.passwordResetForm),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get formName => AuthFormName.passwordResetForm;
|
||||||
|
|
||||||
|
void emailChanged(String value) {
|
||||||
|
final Email email = Email.dirty(value);
|
||||||
|
dataChanged(AuthFormField.email, email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> dataChanged<Value>(
|
||||||
|
String key,
|
||||||
|
FormInputValidator<Value, ValidationError> dirtyValue,
|
||||||
|
) {
|
||||||
|
final form = _formRepository.accessForm(formName).clone();
|
||||||
|
|
||||||
|
try {
|
||||||
|
form.updateValidator(key, dirtyValue);
|
||||||
|
_formRepository.updateForm(form);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(
|
||||||
|
state.copyWith(form: form, status: form.validate()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> reset() {
|
||||||
|
final form = state.form.reset();
|
||||||
|
_formRepository.updateForm(form);
|
||||||
|
emit(
|
||||||
|
state.copyWith(form: form, status: form.validate()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> submit() async {
|
||||||
|
if (!state.status.isValidated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(state.copyWith(status: FormStatus.submissionInProgress));
|
||||||
|
|
||||||
|
final form = _formRepository.accessForm(formName);
|
||||||
|
final email = form.valueOf<String?>(AuthFormField.email);
|
||||||
|
|
||||||
|
if (email.isNullOrEmpty) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
errorMessage: 'An error occured while retrieving data from the form.',
|
||||||
|
status: FormStatus.submissionFailure,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await _authenticationRepository.sendPasswordResetEmail(
|
||||||
|
email: email!,
|
||||||
|
);
|
||||||
|
|
||||||
|
emit(
|
||||||
|
response.fold(
|
||||||
|
(value) => state.copyWith(status: FormStatus.submissionSuccess),
|
||||||
|
(error) => state.copyWith(
|
||||||
|
errorMessage: error.message,
|
||||||
|
status: FormStatus.submissionFailure,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> 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<void> validate() {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
status: _formRepository.accessForm(formName).validate(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
part of 'password_reset_cubit.dart';
|
||||||
|
|
||||||
|
class PasswordResetState extends FormDataState {
|
||||||
|
Email get email => form.validatorOf(AuthFormField.email);
|
||||||
|
|
||||||
|
const PasswordResetState({
|
||||||
|
required super.form,
|
||||||
|
super.status = FormStatus.pure,
|
||||||
|
super.errorMessage,
|
||||||
|
});
|
||||||
|
|
||||||
|
PasswordResetState copyWith({
|
||||||
|
WyattForm? form,
|
||||||
|
FormStatus? status,
|
||||||
|
String? errorMessage,
|
||||||
|
}) =>
|
||||||
|
PasswordResetState(
|
||||||
|
form: form ?? this.form,
|
||||||
|
status: status ?? this.status,
|
||||||
|
errorMessage: errorMessage ?? this.errorMessage,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [email, status];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'PasswordResetState(status: ${status.name} '
|
||||||
|
'${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)';
|
||||||
|
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'cubit/password_reset_cubit.dart';
|
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/src/features/sign_in/sign_in.dart';
|
||||||
|
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
|
class SignInListener<Extra> extends StatelessWidget {
|
||||||
|
const SignInListener({
|
||||||
|
required this.child,
|
||||||
|
this.onProgress,
|
||||||
|
this.onSuccess,
|
||||||
|
this.onError,
|
||||||
|
this.customBuilder,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final void Function(BuildContext context)? onProgress;
|
||||||
|
final void Function(BuildContext context)? onSuccess;
|
||||||
|
final void Function(
|
||||||
|
BuildContext context,
|
||||||
|
FormStatus status,
|
||||||
|
String? errorMessage,
|
||||||
|
)? onError;
|
||||||
|
final void Function(BuildContext context, SignInState state)? customBuilder;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) =>
|
||||||
|
BlocListener<SignInCubit<Extra>, SignInState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (customBuilder != null) {
|
||||||
|
return customBuilder!(context, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onSuccess != null &&
|
||||||
|
state.status == FormStatus.submissionSuccess) {
|
||||||
|
return onSuccess!(context);
|
||||||
|
}
|
||||||
|
if (onProgress != null &&
|
||||||
|
state.status == FormStatus.submissionInProgress) {
|
||||||
|
return onProgress!(context);
|
||||||
|
}
|
||||||
|
if (onError != null &&
|
||||||
|
(state.status == FormStatus.submissionCanceled ||
|
||||||
|
state.status == FormStatus.submissionFailure)) {
|
||||||
|
return onError!(context, state.status, state.errorMessage);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
@ -1,17 +1,18 @@
|
|||||||
// Copyright (C) 2022 WYATT GROUP
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Please see the AUTHORS file for details.
|
// Please see the AUTHORS file for details.
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// any later version.
|
// any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
export 'cubit/sign_in_cubit.dart';
|
export 'cubit/sign_in_cubit.dart';
|
||||||
|
export 'listener/sign_in_listener.dart';
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/src/features/sign_up/cubit/sign_up_cubit.dart';
|
||||||
|
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
|
class SignUpListener<Extra> extends StatelessWidget {
|
||||||
|
const SignUpListener({
|
||||||
|
required this.child,
|
||||||
|
this.onProgress,
|
||||||
|
this.onSuccess,
|
||||||
|
this.onError,
|
||||||
|
this.customBuilder,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final void Function(BuildContext context)? onProgress;
|
||||||
|
final void Function(BuildContext context)? onSuccess;
|
||||||
|
final void Function(
|
||||||
|
BuildContext context,
|
||||||
|
FormStatus status,
|
||||||
|
String? errorMessage,
|
||||||
|
)? onError;
|
||||||
|
final void Function(BuildContext context, SignUpState state)? customBuilder;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) =>
|
||||||
|
BlocListener<SignUpCubit<Extra>, SignUpState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (customBuilder != null) {
|
||||||
|
return customBuilder!(context, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onSuccess != null &&
|
||||||
|
state.status == FormStatus.submissionSuccess) {
|
||||||
|
return onSuccess!(context);
|
||||||
|
}
|
||||||
|
if (onProgress != null &&
|
||||||
|
state.status == FormStatus.submissionInProgress) {
|
||||||
|
return onProgress!(context);
|
||||||
|
}
|
||||||
|
if (onError != null &&
|
||||||
|
(state.status == FormStatus.submissionCanceled ||
|
||||||
|
state.status == FormStatus.submissionFailure)) {
|
||||||
|
return onError!(context, state.status, state.errorMessage);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
@ -1,17 +1,18 @@
|
|||||||
// Copyright (C) 2022 WYATT GROUP
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Please see the AUTHORS file for details.
|
// Please see the AUTHORS file for details.
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// any later version.
|
// any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
export 'cubit/sign_up_cubit.dart';
|
export 'cubit/sign_up_cubit.dart';
|
||||||
|
export 'listener/sign_up_listener.dart';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user