feat!(auth): use new form features

This commit is contained in:
Hugo Pointcheval 2022-11-10 13:29:30 -05:00
parent 0c920e8245
commit 59bd3edb0d
Signed by: hugo
GPG Key ID: A9E8E9615379254F
4 changed files with 187 additions and 149 deletions

View File

@ -14,55 +14,96 @@
// 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: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<Extra> extends Cubit<SignInState> {
class SignInCubit<Extra> extends FormDataCubit<SignInState> {
final AuthenticationRepository<Extra> _authenticationRepository;
final FormValidator _validationStrategy;
FormRepository get _formRepository =>
_authenticationRepository.formRepository;
SignInCubit({
required AuthenticationRepository<Extra> 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<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(
password: password,
status: _validationStrategy.rawValidate([state.email, password]),
),
state.copyWith(form: form, status: form.validate()),
);
}
Future<void> signInWithEmailAndPassword() async {
@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);
final password = form.valueOf<String?>(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<Extra> extends Cubit<SignInState> {
),
);
}
@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(),
),
);
}
}

View File

@ -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<Object> 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)';
}

View File

@ -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<Extra> extends Cubit<SignUpState> {
class SignUpCubit<Extra> extends FormDataCubit<SignUpState> {
final AuthenticationRepository<Extra> _authenticationRepository;
final FormValidator _validationStrategy;
FormRepository get _formRepository =>
_authenticationRepository.formRepository;
SignUpCubit({
required AuthenticationRepository<Extra> 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<FormInputValidator<dynamic, ValidationError>> toValidate = [
email,
state.password,
...state.data.validators<dynamic, ValidationError>(),
];
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<FormInputValidator<dynamic, ValidationError>> toValidate = [
state.email,
password,
...state.data.validators<dynamic, ValidationError>(),
];
emit(
state.copyWith(
password: password,
status: _validationStrategy.rawValidate(toValidate),
),
);
dataChanged(AuthFormField.password, password);
}
// Take from wyatt_form_bloc/wyatt_form_bloc.dart
void dataChanged<T>(
String field,
FormInputValidator<T, ValidationError> dirtyValue,
@override
FutureOr<void> dataChanged<Value>(
String key,
FormInputValidator<Value, ValidationError> 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<dynamic, ValidationError>(),
],
),
),
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<void> reset() {
final form = state.form.reset();
_formRepository.updateForm(form);
emit(
state.copyWith(
data: form,
status: _validationStrategy.rawValidate(
[
state.email,
state.password,
...state.data.validators<dynamic, ValidationError>(),
],
),
),
state.copyWith(form: form, status: form.validate()),
);
}
Future<void> signUpFormSubmitted() async {
@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);
final password = form.valueOf<String?>(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<Extra> extends Cubit<SignUpState> {
),
);
}
@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(),
),
);
}
}

View File

@ -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<Object?> get props => [email, password, status, form];
@override
List<Object?> get props => [email, password, status, data, errorMessage];
@override
String toString() => 'SignUpState(status: ${status.name} '
'${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)';
}