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 // 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 'dart:async';
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_authentication_bloc/src/domain/repositories/authentication_repository.dart';
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
part 'sign_in_state.dart'; part 'sign_in_state.dart';
class SignInCubit<Extra> extends Cubit<SignInState> { class SignInCubit<Extra> extends FormDataCubit<SignInState> {
final AuthenticationRepository<Extra> _authenticationRepository; final AuthenticationRepository<Extra> _authenticationRepository;
FormRepository get _formRepository =>
final FormValidator _validationStrategy; _authenticationRepository.formRepository;
SignInCubit({ SignInCubit({
required AuthenticationRepository<Extra> authenticationRepository, required AuthenticationRepository<Extra> authenticationRepository,
FormValidator validationStrategy = const EveryInputValidator(),
}) : _authenticationRepository = authenticationRepository, }) : _authenticationRepository = authenticationRepository,
_validationStrategy = validationStrategy, super(
super(const SignInState()); SignInState(
form: authenticationRepository.formRepository
.accessForm(AuthFormName.signInForm),
),
);
@override
String get formName => AuthFormName.signInForm;
void emailChanged(String value) { void emailChanged(String value) {
final Email email = Email.dirty(value); final Email email = Email.dirty(value);
emit( dataChanged(AuthFormField.email, email);
state.copyWith(
email: email,
status: _validationStrategy.rawValidate([email, state.password]),
),
);
} }
void passwordChanged(String value) { void passwordChanged(String value) {
final Password password = Password.dirty(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( emit(
state.copyWith( state.copyWith(form: form, status: form.validate()),
password: password,
status: _validationStrategy.rawValidate([state.email, password]),
),
); );
} }
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) { if (!state.status.isValidated) {
return; return;
} }
emit(state.copyWith(status: FormStatus.submissionInProgress)); 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( final uid = await _authenticationRepository.signInWithEmailAndPassword(
email: state.email.value, email: email!,
password: state.password.value, password: password!,
); );
emit( 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'; part of 'sign_in_cubit.dart';
class SignInState extends Equatable { class SignInState extends FormDataState {
final Email email; Email get email => form.validatorOf(AuthFormField.email);
final Password password; Password get password => form.validatorOf(AuthFormField.password);
final FormStatus status;
final String? errorMessage;
const SignInState({ const SignInState({
this.email = const Email.pure(), required super.form,
this.password = const Password.pure(), super.status = FormStatus.pure,
this.status = FormStatus.pure, super.errorMessage,
this.errorMessage,
}); });
SignInState copyWith({ SignInState copyWith({
Email? email, WyattForm? form,
Password? password,
FormStatus? status, FormStatus? status,
String? errorMessage, String? errorMessage,
}) => }) =>
SignInState( SignInState(
email: email ?? this.email, form: form ?? this.form,
password: password ?? this.password,
status: status ?? this.status, status: status ?? this.status,
errorMessage: errorMessage ?? this.errorMessage, errorMessage: errorMessage ?? this.errorMessage,
); );
@ -46,10 +41,6 @@ class SignInState extends Equatable {
List<Object> get props => [email, password, status]; List<Object> get props => [email, password, status];
@override @override
String toString() => ''' String toString() => 'SignInState(status: ${status.name} '
email: $email, '${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)';
password: $password,
status: $status,
errorMessage: $errorMessage,
''';
} }

View File

@ -16,132 +16,94 @@
import 'dart:async'; import 'dart:async';
import 'package:equatable/equatable.dart'; import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart';
import 'package:flutter_bloc/flutter_bloc.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_authentication_bloc/src/domain/repositories/authentication_repository.dart';
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
part 'sign_up_state.dart'; part 'sign_up_state.dart';
class SignUpCubit<Extra> extends Cubit<SignUpState> { class SignUpCubit<Extra> extends FormDataCubit<SignUpState> {
final AuthenticationRepository<Extra> _authenticationRepository; final AuthenticationRepository<Extra> _authenticationRepository;
FormRepository get _formRepository =>
final FormValidator _validationStrategy; _authenticationRepository.formRepository;
SignUpCubit({ SignUpCubit({
required AuthenticationRepository<Extra> authenticationRepository, required AuthenticationRepository<Extra> authenticationRepository,
required FormData formData,
FormValidator validationStrategy = const EveryInputValidator(),
}) : _authenticationRepository = authenticationRepository, }) : _authenticationRepository = authenticationRepository,
_validationStrategy = validationStrategy, super(
super(SignUpState(data: formData)); SignUpState(
form: authenticationRepository.formRepository
.accessForm(AuthFormName.signUpForm),
),
);
@override
String get formName => AuthFormName.signUpForm;
void emailChanged(String value) { void emailChanged(String value) {
final Email email = Email.dirty(value); final Email email = Email.dirty(value);
dataChanged(AuthFormField.email, email);
final List<FormInputValidator<dynamic, ValidationError>> toValidate = [
email,
state.password,
...state.data.validators<dynamic, ValidationError>(),
];
emit(
state.copyWith(
email: email,
status: _validationStrategy.rawValidate(toValidate),
),
);
} }
void passwordChanged(String value) { void passwordChanged(String value) {
final Password password = Password.dirty(value); final Password password = Password.dirty(value);
dataChanged(AuthFormField.password, password);
final List<FormInputValidator<dynamic, ValidationError>> toValidate = [
state.email,
password,
...state.data.validators<dynamic, ValidationError>(),
];
emit(
state.copyWith(
password: password,
status: _validationStrategy.rawValidate(toValidate),
),
);
} }
// Take from wyatt_form_bloc/wyatt_form_bloc.dart @override
void dataChanged<T>( FutureOr<void> dataChanged<Value>(
String field, String key,
FormInputValidator<T, ValidationError> dirtyValue, FormInputValidator<Value, ValidationError> dirtyValue,
) { ) {
final form = state.data.clone(); final form = _formRepository.accessForm(formName).clone();
if (form.contains(field)) { try {
form.updateValidator(field, dirtyValue); form.updateValidator(key, dirtyValue);
} else { _formRepository.updateForm(form);
throw Exception('Form field $field not found'); } catch (e) {
rethrow;
} }
emit( emit(
state.copyWith( state.copyWith(form: form, status: form.validate()),
data: form,
status: _validationStrategy.rawValidate(
[
state.email,
state.password,
...state.data.validators<dynamic, ValidationError>(),
],
),
),
); );
} }
// Take from wyatt_form_bloc/wyatt_form_bloc.dart @override
void updateFormData( FutureOr<void> reset() {
FormData data, { final form = state.form.reset();
SetOperation operation = SetOperation.replace, _formRepository.updateForm(form);
}) {
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( emit(
state.copyWith( state.copyWith(form: form, status: form.validate()),
data: form,
status: _validationStrategy.rawValidate(
[
state.email,
state.password,
...state.data.validators<dynamic, ValidationError>(),
],
),
),
); );
} }
Future<void> signUpFormSubmitted() async { @override
FutureOr<void> submit() async {
if (!state.status.isValidated) { if (!state.status.isValidated) {
return; return;
} }
emit(state.copyWith(status: FormStatus.submissionInProgress)); 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( final uid = await _authenticationRepository.signUp(
email: state.email.value, email: email!,
password: state.password.value, password: password!,
); );
emit( 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'; part of 'sign_up_cubit.dart';
class SignUpState extends Equatable { class SignUpState extends FormDataState {
final Email email; Email get email => form.validatorOf(AuthFormField.email);
final Password password; Password get password => form.validatorOf(AuthFormField.password);
final FormStatus status;
final FormData data;
final String? errorMessage;
const SignUpState({ const SignUpState({
required this.data, required super.form,
this.email = const Email.pure(), super.status = FormStatus.pure,
this.password = const Password.pure(), super.errorMessage,
this.status = FormStatus.pure,
this.errorMessage,
}); });
SignUpState copyWith({ SignUpState copyWith({
Email? email, WyattForm? form,
Password? password,
FormStatus? status, FormStatus? status,
FormData? data,
String? errorMessage, String? errorMessage,
}) => }) =>
SignUpState( SignUpState(
email: email ?? this.email, form: form ?? this.form,
password: password ?? this.password,
status: status ?? this.status, status: status ?? this.status,
data: data ?? this.data,
errorMessage: errorMessage ?? this.errorMessage, errorMessage: errorMessage ?? this.errorMessage,
); );
@override @override
String toString() => 'SignUpState(email: $email, password: $password, ' List<Object?> get props => [email, password, status, form];
'status: $status, data: $data, errorMessage: $errorMessage)';
@override @override
List<Object?> get props => [email, password, status, data, errorMessage]; @override
String toString() => 'SignUpState(status: ${status.name} '
'${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)';
} }