Compare commits
No commits in common. "6802a56bfc87929daacde5504121eafa26fabcf5" and "0c920e82454a591e7343b164fafd33431d2041e4" have entirely different histories.
6802a56bfc
...
0c920e8245
@ -25,7 +25,7 @@ abstract class GetItInitializer {
|
|||||||
..registerLazySingleton<AuthenticationRemoteDataSource>(
|
..registerLazySingleton<AuthenticationRemoteDataSource>(
|
||||||
() => AuthenticationFirebaseDataSourceImpl(),
|
() => AuthenticationFirebaseDataSourceImpl(),
|
||||||
)
|
)
|
||||||
..registerLazySingleton<AuthenticationCacheDataSource<int>>(
|
..registerLazySingleton<AuthenticationLocalDataSource<int>>(
|
||||||
() => AuthenticationCacheDataSourceImpl<int>(),
|
() => AuthenticationCacheDataSourceImpl<int>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
// 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<void>(export: false),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
@ -3,58 +3,33 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: app.dart
|
// File: app.dart
|
||||||
// Created Date: 19/08/2022 12:05:38
|
// Created Date: 19/08/2022 12:05:38
|
||||||
// Last Modified: Thu Nov 10 2022
|
// Last Modified: Wed Nov 09 2022
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2022
|
// Copyright (c) 2022
|
||||||
|
|
||||||
import 'dart:async';
|
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/dependency_injection/get_it.dart';
|
||||||
import 'package:example_router/core/routes/router.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/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.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_type_utils/wyatt_type_utils.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
|
||||||
|
|
||||||
FutureResult<int?> onSignUpSuccess(
|
|
||||||
Account? account,
|
|
||||||
WyattForm form,
|
|
||||||
) async {
|
|
||||||
const id = -1;
|
|
||||||
final confirmedPassword =
|
|
||||||
form.valueOf<String?>(AppFormField.confirmedPassword);
|
|
||||||
|
|
||||||
debugPrint(
|
|
||||||
'onSignUpSuccess: $account, generatedId: $id, extraFormData: $confirmedPassword');
|
|
||||||
return const Ok<int, AppException>(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
FutureResult<int?> onAccountChanges(Account? account) async {
|
|
||||||
final id = Random().nextInt(1000);
|
|
||||||
debugPrint('onAccountChanges: $account, generatedId: $id');
|
|
||||||
return Ok<int, AppException>(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
class App extends StatelessWidget {
|
class App extends StatelessWidget {
|
||||||
final AuthenticationRepository<int> authenticationRepository =
|
final AuthenticationRepository<int> authenticationRepository =
|
||||||
AuthenticationRepositoryImpl(
|
AuthenticationRepositoryImpl(getIt<AuthenticationLocalDataSource<int>>(),
|
||||||
authenticationCacheDataSource: getIt<AuthenticationCacheDataSource<int>>(),
|
getIt<AuthenticationRemoteDataSource>(), (account) async {
|
||||||
authenticationRemoteDataSource: getIt<AuthenticationRemoteDataSource>(),
|
debugPrint('onSignUpSuccess: $account');
|
||||||
onSignUpSuccess: onSignUpSuccess,
|
return const Ok(null);
|
||||||
onAuthChange: onAccountChanges,
|
}, (account) async {
|
||||||
extraSignUpInputs: [
|
debugPrint('onAccountChanges: $account');
|
||||||
FormInput(
|
return const Ok(null);
|
||||||
AppFormField.confirmedPassword,
|
});
|
||||||
const ConfirmedPassword.pure(),
|
|
||||||
metadata: const FormInputMetadata<void>(export: false),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
App({Key? key}) : super(key: key);
|
App({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@ -90,12 +65,12 @@ class App extends StatelessWidget {
|
|||||||
if (isOnboarding) {
|
if (isOnboarding) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return '/';
|
return state.namedLocation(WelcomePage.pageName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugPrint('Logged');
|
debugPrint('Logged');
|
||||||
if (isOnboarding) {
|
if (isOnboarding) {
|
||||||
return '/home';
|
return state.namedLocation(HomePage.pageName);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -116,12 +91,13 @@ class App extends StatelessWidget {
|
|||||||
BlocProvider<AuthenticationCubit<int>>.value(
|
BlocProvider<AuthenticationCubit<int>>.value(
|
||||||
value: authenticationCubit,
|
value: authenticationCubit,
|
||||||
),
|
),
|
||||||
BlocProvider<SignUpCubit<int>>(
|
BlocProvider<SignUpCubit>(
|
||||||
create: (_) => SignUpCubit(
|
create: (_) => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
|
formData: Forms.getNormalData(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider<SignInCubit<int>>(
|
BlocProvider<SignInCubit>(
|
||||||
create: (_) => SignInCubit(
|
create: (_) => SignInCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
),
|
),
|
||||||
@ -130,7 +106,9 @@ class App extends StatelessWidget {
|
|||||||
child: MaterialApp.router(
|
child: MaterialApp.router(
|
||||||
title: 'Demo Authentication',
|
title: 'Demo Authentication',
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
routerConfig: router,
|
routerDelegate: router.routerDelegate,
|
||||||
|
routeInformationParser: router.routeInformationParser,
|
||||||
|
routeInformationProvider: router.routeInformationProvider,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -36,7 +36,7 @@ class HomePage extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
AuthenticationBuilder<int>(
|
AuthenticationBuilder<int>(
|
||||||
authenticated: (context, accountWrapper) =>
|
authenticated: (context, accountWrapper) =>
|
||||||
Text('Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
Text('Logged as ${accountWrapper.account?.email}'),
|
||||||
unauthenticated: (context) =>
|
unauthenticated: (context) =>
|
||||||
const Text('Not logged (unauthenticated)'),
|
const Text('Not logged (unauthenticated)'),
|
||||||
unknown: (context) => const Text('Not logged (unknown)'),
|
unknown: (context) => const Text('Not logged (unknown)'),
|
||||||
|
@ -3,31 +3,30 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: sign_in_form.dart
|
// File: sign_in_form.dart
|
||||||
// Created Date: 19/08/2022 15:24:37
|
// Created Date: 19/08/2022 15:24:37
|
||||||
// Last Modified: Thu Nov 10 2022
|
// Last Modified: Wed Nov 09 2022
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2022
|
// Copyright (c) 2022
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
|
||||||
|
|
||||||
class _EmailInput extends StatelessWidget {
|
class _EmailInput extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return InputBuilder<SignInCubit<int>>(
|
return BlocBuilder<SignInCubit, SignInState>(
|
||||||
field: AuthFormField.email,
|
buildWhen: (previous, current) => previous.email != current.email,
|
||||||
builder: ((context, cubit, state, field, inputValid) {
|
builder: (context, state) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (email) => cubit.emailChanged(email),
|
onChanged: (email) => context.read<SignInCubit>().emailChanged(email),
|
||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Email',
|
labelText: 'Email',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: !inputValid ? 'Invalid email' : null,
|
errorText: state.email.invalid ? 'Invalid email' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,19 +34,21 @@ class _EmailInput extends StatelessWidget {
|
|||||||
class _PasswordInput extends StatelessWidget {
|
class _PasswordInput extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return InputBuilder<SignInCubit<int>>(
|
return BlocBuilder<SignInCubit, SignInState>(
|
||||||
field: AuthFormField.password,
|
buildWhen: (previous, current) => previous.password != current.password,
|
||||||
builder: ((context, cubit, state, field, inputValid) {
|
builder: (context, state) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (pwd) => cubit.passwordChanged(pwd),
|
onChanged: (password) {
|
||||||
|
context.read<SignInCubit>().passwordChanged(password);
|
||||||
|
},
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Password',
|
labelText: 'Password',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: !inputValid ? 'Invalid password' : null,
|
errorText: state.password.invalid ? 'Invalid password' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,15 +56,18 @@ class _PasswordInput extends StatelessWidget {
|
|||||||
class _SignInButton extends StatelessWidget {
|
class _SignInButton extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SubmitBuilder<SignInCubit<int>>(
|
return BlocBuilder<SignInCubit, SignInState>(
|
||||||
builder: ((context, cubit, status) {
|
builder: (context, state) {
|
||||||
return status.isSubmissionInProgress
|
return state.status.isSubmissionInProgress
|
||||||
? const CircularProgressIndicator()
|
? const CircularProgressIndicator()
|
||||||
: ElevatedButton(
|
: ElevatedButton(
|
||||||
onPressed: status.isValidated ? () => cubit.submit() : null,
|
onPressed: state.status.isValidated
|
||||||
|
? () =>
|
||||||
|
context.read<SignInCubit>().signInWithEmailAndPassword()
|
||||||
|
: null,
|
||||||
child: const Text('Sign in'),
|
child: const Text('Sign in'),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +77,7 @@ class SignInForm extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocListener<SignInCubit<int>, SignInState>(
|
return BlocListener<SignInCubit, SignInState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state.status.isSubmissionFailure) {
|
if (state.status.isSubmissionFailure) {
|
||||||
ScaffoldMessenger.of(context)
|
ScaffoldMessenger.of(context)
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: sign_up_form.dart
|
// File: sign_up_form.dart
|
||||||
// Created Date: 19/08/2022 14:41:08
|
// Created Date: 19/08/2022 14:41:08
|
||||||
// Last Modified: Thu Nov 10 2022
|
// Last Modified: Fri Aug 26 2022
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2022
|
// Copyright (c) 2022
|
||||||
|
|
||||||
import 'package:example_router/core/constants/form_field.dart';
|
import 'package:example_router/core/constants/form_field.dart';
|
||||||
import 'package:flutter/material.dart' hide FormField;
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||||
import 'package:wyatt_form_bloc/wyatt_form_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 {
|
class _EmailInput extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return InputBuilder<SignUpCubit<int>>(
|
return BlocBuilder<SignUpCubit, SignUpState>(
|
||||||
field: AuthFormField.email,
|
buildWhen: (previous, current) => previous.email != current.email,
|
||||||
builder: ((context, cubit, state, field, inputValid) {
|
builder: (context, state) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (email) => cubit.emailChanged(email),
|
onChanged: (email) => context.read<SignUpCubit>().emailChanged(email),
|
||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Email',
|
labelText: 'Email',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: !inputValid ? 'Invalid email' : null,
|
errorText: state.email.invalid ? 'Invalid email' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,27 +36,33 @@ class _EmailInput extends StatelessWidget {
|
|||||||
class _PasswordInput extends StatelessWidget {
|
class _PasswordInput extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return InputBuilder<SignUpCubit<int>>(
|
return BlocBuilder<SignUpCubit, SignUpState>(
|
||||||
field: AuthFormField.password,
|
buildWhen: (previous, current) => previous.password != current.password,
|
||||||
builder: ((context, cubit, state, field, inputValid) {
|
builder: (context, state) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (pwd) {
|
onChanged: (password) {
|
||||||
cubit.passwordChanged(pwd);
|
context.read<SignUpCubit>().passwordChanged(password);
|
||||||
cubit.dataChanged(
|
context.read<SignUpCubit>().dataChanged(
|
||||||
AppFormField.confirmedPassword,
|
AppFormField.confirmedPassword,
|
||||||
ConfirmedPassword.dirty(
|
ConfirmedPassword.dirty(
|
||||||
password: pwd,
|
password: password,
|
||||||
value: state.form
|
value: context
|
||||||
.valueOf<String?>(AppFormField.confirmedPassword)));
|
.read<SignUpCubit>()
|
||||||
|
.state
|
||||||
|
.data
|
||||||
|
.valueOf<String>(
|
||||||
|
AppFormField.confirmedPassword),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Password',
|
labelText: 'Password',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: !inputValid ? 'Invalid password' : null,
|
errorText: state.password.invalid ? 'Invalid password' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,27 +70,28 @@ class _PasswordInput extends StatelessWidget {
|
|||||||
class _ConfirmPasswordInput extends StatelessWidget {
|
class _ConfirmPasswordInput extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return InputBuilder<SignUpCubit<int>>(
|
return BlocBuilder<SignUpCubit, SignUpState>(
|
||||||
field: AppFormField.confirmedPassword,
|
builder: (context, state) {
|
||||||
builder: ((context, cubit, state, field, inputValid) {
|
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (pwd) {
|
onChanged: (confirmPassword) => context
|
||||||
cubit.dataChanged(
|
.read<SignUpCubit>()
|
||||||
field,
|
.dataChanged(
|
||||||
|
AppFormField.confirmedPassword,
|
||||||
ConfirmedPassword.dirty(
|
ConfirmedPassword.dirty(
|
||||||
password:
|
password: context.read<SignUpCubit>().state.password.value,
|
||||||
state.form.valueOf<String?>(AuthFormField.password) ?? '',
|
value: confirmPassword,
|
||||||
value: pwd),
|
),
|
||||||
);
|
),
|
||||||
},
|
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Confirm password',
|
labelText: 'Confirm password',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: !inputValid ? 'Passwords do not match' : null,
|
errorText: state.data.isNotValid(AppFormField.confirmedPassword)
|
||||||
|
? 'Passwords do not match'
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,15 +99,17 @@ class _ConfirmPasswordInput extends StatelessWidget {
|
|||||||
class _SignUpButton extends StatelessWidget {
|
class _SignUpButton extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SubmitBuilder<SignUpCubit<int>>(
|
return BlocBuilder<SignUpCubit, SignUpState>(
|
||||||
builder: ((context, cubit, status) {
|
builder: (context, state) {
|
||||||
return status.isSubmissionInProgress
|
return state.status.isSubmissionInProgress
|
||||||
? const CircularProgressIndicator()
|
? const CircularProgressIndicator()
|
||||||
: ElevatedButton(
|
: ElevatedButton(
|
||||||
onPressed: status.isValidated ? () => cubit.submit() : null,
|
onPressed: state.status.isValidated
|
||||||
|
? () => context.read<SignUpCubit>().signUpFormSubmitted()
|
||||||
|
: null,
|
||||||
child: const Text('Sign up'),
|
child: const Text('Sign up'),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,9 +119,11 @@ class SignUpForm extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocListener<SignUpCubit<int>, SignUpState>(
|
return BlocListener<SignUpCubit, SignUpState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state.status.isSubmissionFailure) {
|
if (state.status.isSubmissionSuccess) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
} else if (state.status.isSubmissionFailure) {
|
||||||
ScaffoldMessenger.of(context)
|
ScaffoldMessenger.of(context)
|
||||||
..hideCurrentSnackBar()
|
..hideCurrentSnackBar()
|
||||||
..showSnackBar(
|
..showSnackBar(
|
||||||
|
@ -42,12 +42,6 @@ dependencies:
|
|||||||
ref: wyatt_form_bloc-v0.0.6
|
ref: wyatt_form_bloc-v0.0.6
|
||||||
path: packages/wyatt_form_bloc
|
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.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.5
|
cupertino_icons: ^1.0.5
|
||||||
|
@ -1,20 +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 <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
abstract class AuthFormName {
|
|
||||||
static const String signUpForm = 'wyattSignUpForm';
|
|
||||||
static const String signInForm = 'wyattSignInForm';
|
|
||||||
}
|
|
@ -14,8 +14,6 @@
|
|||||||
// 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 'constants/form_field.dart';
|
|
||||||
export 'constants/form_name.dart';
|
|
||||||
export 'enums/enums.dart';
|
export 'enums/enums.dart';
|
||||||
export 'exceptions/exceptions.dart';
|
export 'exceptions/exceptions.dart';
|
||||||
export 'utils/utils.dart';
|
export 'utils/utils.dart';
|
||||||
|
@ -15,28 +15,29 @@
|
|||||||
// 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:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.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';
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
class AuthenticationCacheDataSourceImpl<T extends Object>
|
class AuthenticationCacheDataSourceImpl<T extends Object>
|
||||||
extends AuthenticationCacheDataSource<T> {
|
extends AuthenticationLocalDataSource<T> {
|
||||||
Account? _account;
|
Account? _account;
|
||||||
T? _data;
|
T? _data;
|
||||||
|
|
||||||
AuthenticationCacheDataSourceImpl();
|
AuthenticationCacheDataSourceImpl();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> storeAccount(Account? account) async {
|
void storeAccount(Account? account) {
|
||||||
_account = account;
|
_account = account;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> storeData(T? data) async {
|
void storeData(T? data) {
|
||||||
_data = data;
|
_data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Account> loadAccount() async {
|
Account loadAccount() {
|
||||||
if (_account.isNotNull) {
|
if (_account.isNotNull) {
|
||||||
return _account!;
|
return _account!;
|
||||||
}
|
}
|
||||||
@ -44,7 +45,7 @@ class AuthenticationCacheDataSourceImpl<T extends Object>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<T> loadData() async {
|
T loadData() {
|
||||||
if (_data.isNotNull) {
|
if (_data.isNotNull) {
|
||||||
return _data!;
|
return _data!;
|
||||||
}
|
}
|
||||||
@ -52,16 +53,8 @@ class AuthenticationCacheDataSourceImpl<T extends Object>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> destroy() async {
|
void destroy() {
|
||||||
_data = null;
|
_data = null;
|
||||||
_account = null;
|
_account = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<AccountWrapper<T>> load() async {
|
|
||||||
if (_account.isNull) {
|
|
||||||
throw ClientException('Cached account is invalid');
|
|
||||||
}
|
|
||||||
return AccountWrapperModel(_account, _data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,75 +15,28 @@
|
|||||||
// 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:wyatt_architecture/wyatt_architecture.dart';
|
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/data/models/account_wrapper_model.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/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/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.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.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_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';
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
typedef OnSignUpSuccess<T> = FutureResult<T?> Function(
|
|
||||||
Account? account,
|
|
||||||
WyattForm form,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef OnAuthChange<T> = FutureResult<T?> Function(Account? account);
|
|
||||||
|
|
||||||
class AuthenticationRepositoryImpl<T extends Object>
|
class AuthenticationRepositoryImpl<T extends Object>
|
||||||
extends AuthenticationRepository<T> {
|
extends AuthenticationRepository<T> {
|
||||||
final AuthenticationCacheDataSource<T> _authenticationLocalDataSource;
|
final AuthenticationLocalDataSource<T> _authenticationLocalDataSource;
|
||||||
final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
|
final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
|
||||||
|
|
||||||
late FormRepository _formRepository;
|
final FutureResult<T?> Function(Account? account)? _onSignUpSuccess;
|
||||||
|
final FutureResult<T?> Function(Account? account)? _onAccountChanges;
|
||||||
|
|
||||||
final OnSignUpSuccess<T>? _onSignUpSuccess;
|
AuthenticationRepositoryImpl(
|
||||||
|
this._authenticationLocalDataSource,
|
||||||
final OnAuthChange<T>? _onAccountChanges;
|
this._authenticationRemoteDataSource,
|
||||||
|
this._onSignUpSuccess,
|
||||||
AuthenticationRepositoryImpl({
|
this._onAccountChanges,
|
||||||
required AuthenticationCacheDataSource<T> authenticationCacheDataSource,
|
|
||||||
required AuthenticationRemoteDataSource authenticationRemoteDataSource,
|
|
||||||
FormRepository? formRepository,
|
|
||||||
// ignore: strict_raw_type
|
|
||||||
List<FormInput>? extraSignUpInputs,
|
|
||||||
OnSignUpSuccess<T>? onSignUpSuccess,
|
|
||||||
OnAuthChange<T>? 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
|
@override
|
||||||
FutureResult<Account> signInWithEmailAndPassword({
|
FutureResult<Account> signInWithEmailAndPassword({
|
||||||
@ -97,7 +50,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
);
|
);
|
||||||
await _authenticationLocalDataSource.storeAccount(account);
|
_authenticationLocalDataSource.storeAccount(account);
|
||||||
return account;
|
return account;
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
@ -108,7 +61,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
() async {
|
() async {
|
||||||
await _authenticationRemoteDataSource.signOut();
|
await _authenticationRemoteDataSource.signOut();
|
||||||
await _authenticationLocalDataSource.destroy();
|
_authenticationLocalDataSource.destroy();
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
@ -124,13 +77,10 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
);
|
);
|
||||||
await _authenticationLocalDataSource.storeAccount(account);
|
_authenticationLocalDataSource.storeAccount(account);
|
||||||
if (_onSignUpSuccess.isNotNull) {
|
if (_onSignUpSuccess.isNotNull) {
|
||||||
final dataResult = await _onSignUpSuccess!.call(
|
final dataResult = await _onSignUpSuccess!.call(account);
|
||||||
account,
|
dataResult.fold(
|
||||||
_formRepository.accessForm(AuthFormName.signUpForm).clone(),
|
|
||||||
);
|
|
||||||
await dataResult.foldAsync(
|
|
||||||
_authenticationLocalDataSource.storeData,
|
_authenticationLocalDataSource.storeData,
|
||||||
(error) => throw error,
|
(error) => throw error,
|
||||||
);
|
);
|
||||||
@ -141,51 +91,46 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> destroyCache() =>
|
Result<void, AppException> destroyCache() =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatch<void, AppException, AppException>(
|
||||||
_authenticationLocalDataSource.destroy,
|
_authenticationLocalDataSource.destroy,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<AccountWrapper<T>> getCache() =>
|
Result<Account, AppException> getAccount() =>
|
||||||
Result.tryCatchAsync<AccountWrapper<T>, AppException, AppException>(
|
Result.tryCatch<Account, AppException, AppException>(
|
||||||
_authenticationLocalDataSource.load,
|
|
||||||
(error) => error,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
FutureResult<Account> getAccount() =>
|
|
||||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
|
||||||
_authenticationLocalDataSource.loadAccount,
|
_authenticationLocalDataSource.loadAccount,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> setAccount(
|
Result<Account, AppException> setAccount(
|
||||||
Account account,
|
Account account,
|
||||||
) =>
|
) =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatch<Account, AppException, AppException>(
|
||||||
() async {
|
() {
|
||||||
await _authenticationLocalDataSource.storeAccount(account);
|
_authenticationLocalDataSource.storeAccount(account);
|
||||||
|
return account;
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<T> getData() =>
|
Result<T, AppException> getData() =>
|
||||||
Result.tryCatchAsync<T, AppException, AppException>(
|
Result.tryCatch<T, AppException, AppException>(
|
||||||
_authenticationLocalDataSource.loadData,
|
_authenticationLocalDataSource.loadData,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> setData(
|
Result<T, AppException> setData(
|
||||||
T? data,
|
T data,
|
||||||
) =>
|
) =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatch<T, AppException, AppException>(
|
||||||
() async {
|
() {
|
||||||
await _authenticationLocalDataSource.storeData(data);
|
_authenticationLocalDataSource.storeData(data);
|
||||||
|
return data;
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
@ -14,5 +14,6 @@
|
|||||||
// 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 'local/authentication_cache_data_source.dart';
|
export 'local/authentication_biometrics_data_source.dart';
|
||||||
|
export 'local/authentication_local_data_source.dart';
|
||||||
export 'remote/authentication_remote_data_source.dart';
|
export 'remote/authentication_remote_data_source.dart';
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
// 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/>.
|
||||||
|
|
||||||
abstract class AuthFormField {
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
static const email = 'wyattEmailField';
|
|
||||||
static const password = 'wyattPasswordField';
|
abstract class AuthenticationBiometricsDataSource extends BaseLocalDataSource {}
|
||||||
}
|
|
@ -16,14 +16,12 @@
|
|||||||
|
|
||||||
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';
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
|
|
||||||
|
|
||||||
abstract class AuthenticationCacheDataSource<T extends Object>
|
abstract class AuthenticationLocalDataSource<T extends Object>
|
||||||
extends BaseLocalDataSource {
|
extends BaseLocalDataSource {
|
||||||
Future<void> storeAccount(Account? account);
|
void storeAccount(Account? account);
|
||||||
Future<void> storeData(T? data);
|
void storeData(T? data);
|
||||||
Future<Account> loadAccount();
|
Account loadAccount();
|
||||||
Future<T> loadData();
|
T loadData();
|
||||||
Future<AccountWrapper<T>> load();
|
void destroy();
|
||||||
Future<void> destroy();
|
|
||||||
}
|
}
|
@ -17,14 +17,13 @@
|
|||||||
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';
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
|
||||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
abstract class AuthenticationRepository<T> extends BaseRepository {
|
abstract class AuthenticationRepository<T> extends BaseRepository {
|
||||||
FormRepository get formRepository;
|
|
||||||
|
|
||||||
FutureResult<Account> signUp({
|
FutureResult<Account> signUp({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
FutureResult<Account> signInWithEmailAndPassword({
|
FutureResult<Account> signInWithEmailAndPassword({
|
||||||
@ -38,12 +37,11 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
|||||||
|
|
||||||
FutureResult<String> getIdentityToken();
|
FutureResult<String> getIdentityToken();
|
||||||
|
|
||||||
FutureResult<Account> getAccount();
|
Result<Account, AppException> getAccount();
|
||||||
FutureResult<void> setAccount(Account account);
|
Result<Account, AppException> setAccount(Account account);
|
||||||
|
|
||||||
FutureResult<T> getData();
|
Result<T, AppException> getData();
|
||||||
FutureResult<void> setData(T? data);
|
Result<T, AppException> setData(T data);
|
||||||
|
|
||||||
FutureResult<AccountWrapper<T>> getCache();
|
Result<void, AppException> destroyCache();
|
||||||
FutureResult<void> destroyCache();
|
|
||||||
}
|
}
|
||||||
|
@ -14,96 +14,55 @@
|
|||||||
// 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 '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_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 FormDataCubit<SignInState> {
|
class SignInCubit<Extra> extends Cubit<SignInState> {
|
||||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||||
FormRepository get _formRepository =>
|
|
||||||
_authenticationRepository.formRepository;
|
final FormValidator _validationStrategy;
|
||||||
|
|
||||||
SignInCubit({
|
SignInCubit({
|
||||||
required AuthenticationRepository<Extra> authenticationRepository,
|
required AuthenticationRepository<Extra> authenticationRepository,
|
||||||
|
FormValidator validationStrategy = const EveryInputValidator(),
|
||||||
}) : _authenticationRepository = authenticationRepository,
|
}) : _authenticationRepository = authenticationRepository,
|
||||||
super(
|
_validationStrategy = validationStrategy,
|
||||||
SignInState(
|
super(const 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);
|
||||||
dataChanged(AuthFormField.email, email);
|
emit(
|
||||||
|
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(form: form, status: form.validate()),
|
state.copyWith(
|
||||||
|
password: password,
|
||||||
|
status: _validationStrategy.rawValidate([state.email, password]),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
Future<void> signInWithEmailAndPassword() async {
|
||||||
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: email!,
|
email: state.email.value,
|
||||||
password: password!,
|
password: state.password.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
@ -116,30 +75,4 @@ class SignInCubit<Extra> extends FormDataCubit<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(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,23 +16,28 @@
|
|||||||
|
|
||||||
part of 'sign_in_cubit.dart';
|
part of 'sign_in_cubit.dart';
|
||||||
|
|
||||||
class SignInState extends FormDataState {
|
class SignInState extends Equatable {
|
||||||
Email get email => form.validatorOf(AuthFormField.email);
|
final Email email;
|
||||||
Password get password => form.validatorOf(AuthFormField.password);
|
final Password password;
|
||||||
|
final FormStatus status;
|
||||||
|
final String? errorMessage;
|
||||||
|
|
||||||
const SignInState({
|
const SignInState({
|
||||||
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,
|
||||||
});
|
});
|
||||||
|
|
||||||
SignInState copyWith({
|
SignInState copyWith({
|
||||||
WyattForm? form,
|
Email? email,
|
||||||
|
Password? password,
|
||||||
FormStatus? status,
|
FormStatus? status,
|
||||||
String? errorMessage,
|
String? errorMessage,
|
||||||
}) =>
|
}) =>
|
||||||
SignInState(
|
SignInState(
|
||||||
form: form ?? this.form,
|
email: email ?? this.email,
|
||||||
|
password: password ?? this.password,
|
||||||
status: status ?? this.status,
|
status: status ?? this.status,
|
||||||
errorMessage: errorMessage ?? this.errorMessage,
|
errorMessage: errorMessage ?? this.errorMessage,
|
||||||
);
|
);
|
||||||
@ -41,6 +46,10 @@ class SignInState extends FormDataState {
|
|||||||
List<Object> get props => [email, password, status];
|
List<Object> get props => [email, password, status];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'SignInState(status: ${status.name} '
|
String toString() => '''
|
||||||
'${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)';
|
email: $email,
|
||||||
|
password: $password,
|
||||||
|
status: $status,
|
||||||
|
errorMessage: $errorMessage,
|
||||||
|
''';
|
||||||
}
|
}
|
||||||
|
@ -16,94 +16,132 @@
|
|||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart';
|
import 'package:flutter_bloc/flutter_bloc.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 FormDataCubit<SignUpState> {
|
class SignUpCubit<Extra> extends Cubit<SignUpState> {
|
||||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||||
FormRepository get _formRepository =>
|
|
||||||
_authenticationRepository.formRepository;
|
final FormValidator _validationStrategy;
|
||||||
|
|
||||||
SignUpCubit({
|
SignUpCubit({
|
||||||
required AuthenticationRepository<Extra> authenticationRepository,
|
required AuthenticationRepository<Extra> authenticationRepository,
|
||||||
|
required FormData formData,
|
||||||
|
FormValidator validationStrategy = const EveryInputValidator(),
|
||||||
}) : _authenticationRepository = authenticationRepository,
|
}) : _authenticationRepository = authenticationRepository,
|
||||||
super(
|
_validationStrategy = validationStrategy,
|
||||||
SignUpState(
|
super(SignUpState(data: formData));
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
final List<FormInputValidator<dynamic, ValidationError>> toValidate = [
|
||||||
FutureOr<void> dataChanged<Value>(
|
state.email,
|
||||||
String key,
|
password,
|
||||||
FormInputValidator<Value, ValidationError> dirtyValue,
|
...state.data.validators<dynamic, ValidationError>(),
|
||||||
) {
|
];
|
||||||
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);
|
|
||||||
final password = form.valueOf<String?>(AuthFormField.password);
|
|
||||||
|
|
||||||
if (email.isNullOrEmpty || password.isNullOrEmpty) {
|
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
errorMessage: 'An error occured while retrieving data from the form.',
|
password: password,
|
||||||
status: FormStatus.submissionFailure,
|
status: _validationStrategy.rawValidate(toValidate),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Take from wyatt_form_bloc/wyatt_form_bloc.dart
|
||||||
|
void dataChanged<T>(
|
||||||
|
String field,
|
||||||
|
FormInputValidator<T, ValidationError> 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.rawValidate(
|
||||||
|
[
|
||||||
|
state.email,
|
||||||
|
state.password,
|
||||||
|
...state.data.validators<dynamic, ValidationError>(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
data: form,
|
||||||
|
status: _validationStrategy.rawValidate(
|
||||||
|
[
|
||||||
|
state.email,
|
||||||
|
state.password,
|
||||||
|
...state.data.validators<dynamic, ValidationError>(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> signUpFormSubmitted() async {
|
||||||
|
if (!state.status.isValidated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit(state.copyWith(status: FormStatus.submissionInProgress));
|
||||||
|
|
||||||
final uid = await _authenticationRepository.signUp(
|
final uid = await _authenticationRepository.signUp(
|
||||||
email: email!,
|
email: state.email.value,
|
||||||
password: password!,
|
password: state.password.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
@ -116,30 +154,4 @@ class SignUpCubit<Extra> extends FormDataCubit<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(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,32 +16,40 @@
|
|||||||
|
|
||||||
part of 'sign_up_cubit.dart';
|
part of 'sign_up_cubit.dart';
|
||||||
|
|
||||||
class SignUpState extends FormDataState {
|
class SignUpState extends Equatable {
|
||||||
Email get email => form.validatorOf(AuthFormField.email);
|
final Email email;
|
||||||
Password get password => form.validatorOf(AuthFormField.password);
|
final Password password;
|
||||||
|
final FormStatus status;
|
||||||
|
final FormData data;
|
||||||
|
final String? errorMessage;
|
||||||
|
|
||||||
const SignUpState({
|
const SignUpState({
|
||||||
required super.form,
|
required this.data,
|
||||||
super.status = FormStatus.pure,
|
this.email = const Email.pure(),
|
||||||
super.errorMessage,
|
this.password = const Password.pure(),
|
||||||
|
this.status = FormStatus.pure,
|
||||||
|
this.errorMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
SignUpState copyWith({
|
SignUpState copyWith({
|
||||||
WyattForm? form,
|
Email? email,
|
||||||
|
Password? password,
|
||||||
FormStatus? status,
|
FormStatus? status,
|
||||||
|
FormData? data,
|
||||||
String? errorMessage,
|
String? errorMessage,
|
||||||
}) =>
|
}) =>
|
||||||
SignUpState(
|
SignUpState(
|
||||||
form: form ?? this.form,
|
email: email ?? this.email,
|
||||||
|
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
|
||||||
List<Object?> get props => [email, password, status, form];
|
String toString() => 'SignUpState(email: $email, password: $password, '
|
||||||
|
'status: $status, data: $data, errorMessage: $errorMessage)';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@override
|
List<Object?> get props => [email, password, status, data, errorMessage];
|
||||||
String toString() => 'SignUpState(status: ${status.name} '
|
|
||||||
'${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)';
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user