Compare commits
4 Commits
0c920e8245
...
6802a56bfc
Author | SHA1 | Date | |
---|---|---|---|
6802a56bfc | |||
b2a9dac7c6 | |||
c0a91d6437 | |||
59bd3edb0d |
@ -25,7 +25,7 @@ abstract class GetItInitializer {
|
|||||||
..registerLazySingleton<AuthenticationRemoteDataSource>(
|
..registerLazySingleton<AuthenticationRemoteDataSource>(
|
||||||
() => AuthenticationFirebaseDataSourceImpl(),
|
() => AuthenticationFirebaseDataSourceImpl(),
|
||||||
)
|
)
|
||||||
..registerLazySingleton<AuthenticationLocalDataSource<int>>(
|
..registerLazySingleton<AuthenticationCacheDataSource<int>>(
|
||||||
() => AuthenticationCacheDataSourceImpl<int>(),
|
() => AuthenticationCacheDataSourceImpl<int>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
// Author: Hugo Pointcheval
|
|
||||||
// Email: git@pcl.ovh
|
|
||||||
// -----
|
|
||||||
// File: forms.dart
|
|
||||||
// Created Date: 19/08/2022 12:00:31
|
|
||||||
// Last Modified: 19/08/2022 16:35:52
|
|
||||||
// -----
|
|
||||||
// Copyright (c) 2022
|
|
||||||
|
|
||||||
import 'package:example_router/core/constants/form_field.dart';
|
|
||||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
|
||||||
|
|
||||||
class Forms {
|
|
||||||
static FormData getNormalData() => const FormData([
|
|
||||||
FormInput(
|
|
||||||
AppFormField.confirmedPassword,
|
|
||||||
ConfirmedPassword.pure(),
|
|
||||||
metadata: FormInputMetadata<void>(export: false),
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
@ -3,33 +3,58 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: app.dart
|
// File: app.dart
|
||||||
// Created Date: 19/08/2022 12:05:38
|
// Created Date: 19/08/2022 12:05:38
|
||||||
// Last Modified: Wed Nov 09 2022
|
// Last Modified: Thu Nov 10 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(getIt<AuthenticationLocalDataSource<int>>(),
|
AuthenticationRepositoryImpl(
|
||||||
getIt<AuthenticationRemoteDataSource>(), (account) async {
|
authenticationCacheDataSource: getIt<AuthenticationCacheDataSource<int>>(),
|
||||||
debugPrint('onSignUpSuccess: $account');
|
authenticationRemoteDataSource: getIt<AuthenticationRemoteDataSource>(),
|
||||||
return const Ok(null);
|
onSignUpSuccess: onSignUpSuccess,
|
||||||
}, (account) async {
|
onAuthChange: onAccountChanges,
|
||||||
debugPrint('onAccountChanges: $account');
|
extraSignUpInputs: [
|
||||||
return const Ok(null);
|
FormInput(
|
||||||
});
|
AppFormField.confirmedPassword,
|
||||||
|
const ConfirmedPassword.pure(),
|
||||||
|
metadata: const FormInputMetadata<void>(export: false),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
App({Key? key}) : super(key: key);
|
App({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@ -65,12 +90,12 @@ class App extends StatelessWidget {
|
|||||||
if (isOnboarding) {
|
if (isOnboarding) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return state.namedLocation(WelcomePage.pageName);
|
return '/';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugPrint('Logged');
|
debugPrint('Logged');
|
||||||
if (isOnboarding) {
|
if (isOnboarding) {
|
||||||
return state.namedLocation(HomePage.pageName);
|
return '/home';
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -91,13 +116,12 @@ class App extends StatelessWidget {
|
|||||||
BlocProvider<AuthenticationCubit<int>>.value(
|
BlocProvider<AuthenticationCubit<int>>.value(
|
||||||
value: authenticationCubit,
|
value: authenticationCubit,
|
||||||
),
|
),
|
||||||
BlocProvider<SignUpCubit>(
|
BlocProvider<SignUpCubit<int>>(
|
||||||
create: (_) => SignUpCubit(
|
create: (_) => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
formData: Forms.getNormalData(),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider<SignInCubit>(
|
BlocProvider<SignInCubit<int>>(
|
||||||
create: (_) => SignInCubit(
|
create: (_) => SignInCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
),
|
),
|
||||||
@ -106,9 +130,7 @@ class App extends StatelessWidget {
|
|||||||
child: MaterialApp.router(
|
child: MaterialApp.router(
|
||||||
title: 'Demo Authentication',
|
title: 'Demo Authentication',
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
routerDelegate: router.routerDelegate,
|
routerConfig: router,
|
||||||
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}'),
|
Text('Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
||||||
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,30 +3,31 @@
|
|||||||
// -----
|
// -----
|
||||||
// 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: Wed Nov 09 2022
|
// Last Modified: Thu Nov 10 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 BlocBuilder<SignInCubit, SignInState>(
|
return InputBuilder<SignInCubit<int>>(
|
||||||
buildWhen: (previous, current) => previous.email != current.email,
|
field: AuthFormField.email,
|
||||||
builder: (context, state) {
|
builder: ((context, cubit, state, field, inputValid) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (email) => context.read<SignInCubit>().emailChanged(email),
|
onChanged: (email) => cubit.emailChanged(email),
|
||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Email',
|
labelText: 'Email',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: state.email.invalid ? 'Invalid email' : null,
|
errorText: !inputValid ? 'Invalid email' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,21 +35,19 @@ class _EmailInput extends StatelessWidget {
|
|||||||
class _PasswordInput extends StatelessWidget {
|
class _PasswordInput extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SignInCubit, SignInState>(
|
return InputBuilder<SignInCubit<int>>(
|
||||||
buildWhen: (previous, current) => previous.password != current.password,
|
field: AuthFormField.password,
|
||||||
builder: (context, state) {
|
builder: ((context, cubit, state, field, inputValid) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (password) {
|
onChanged: (pwd) => cubit.passwordChanged(pwd),
|
||||||
context.read<SignInCubit>().passwordChanged(password);
|
|
||||||
},
|
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Password',
|
labelText: 'Password',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: state.password.invalid ? 'Invalid password' : null,
|
errorText: !inputValid ? 'Invalid password' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,18 +55,15 @@ class _PasswordInput extends StatelessWidget {
|
|||||||
class _SignInButton extends StatelessWidget {
|
class _SignInButton extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SignInCubit, SignInState>(
|
return SubmitBuilder<SignInCubit<int>>(
|
||||||
builder: (context, state) {
|
builder: ((context, cubit, status) {
|
||||||
return state.status.isSubmissionInProgress
|
return status.isSubmissionInProgress
|
||||||
? const CircularProgressIndicator()
|
? const CircularProgressIndicator()
|
||||||
: ElevatedButton(
|
: ElevatedButton(
|
||||||
onPressed: state.status.isValidated
|
onPressed: status.isValidated ? () => cubit.submit() : null,
|
||||||
? () =>
|
|
||||||
context.read<SignInCubit>().signInWithEmailAndPassword()
|
|
||||||
: null,
|
|
||||||
child: const Text('Sign in'),
|
child: const Text('Sign in'),
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,7 +73,7 @@ class SignInForm extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocListener<SignInCubit, SignInState>(
|
return BlocListener<SignInCubit<int>, 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: Fri Aug 26 2022
|
// Last Modified: Thu Nov 10 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';
|
import 'package:flutter/material.dart' hide FormField;
|
||||||
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 BlocBuilder<SignUpCubit, SignUpState>(
|
return InputBuilder<SignUpCubit<int>>(
|
||||||
buildWhen: (previous, current) => previous.email != current.email,
|
field: AuthFormField.email,
|
||||||
builder: (context, state) {
|
builder: ((context, cubit, state, field, inputValid) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (email) => context.read<SignUpCubit>().emailChanged(email),
|
onChanged: (email) => cubit.emailChanged(email),
|
||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Email',
|
labelText: 'Email',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: state.email.invalid ? 'Invalid email' : null,
|
errorText: !inputValid ? 'Invalid email' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,33 +36,27 @@ class _EmailInput extends StatelessWidget {
|
|||||||
class _PasswordInput extends StatelessWidget {
|
class _PasswordInput extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SignUpCubit, SignUpState>(
|
return InputBuilder<SignUpCubit<int>>(
|
||||||
buildWhen: (previous, current) => previous.password != current.password,
|
field: AuthFormField.password,
|
||||||
builder: (context, state) {
|
builder: ((context, cubit, state, field, inputValid) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (password) {
|
onChanged: (pwd) {
|
||||||
context.read<SignUpCubit>().passwordChanged(password);
|
cubit.passwordChanged(pwd);
|
||||||
context.read<SignUpCubit>().dataChanged(
|
cubit.dataChanged(
|
||||||
AppFormField.confirmedPassword,
|
AppFormField.confirmedPassword,
|
||||||
ConfirmedPassword.dirty(
|
ConfirmedPassword.dirty(
|
||||||
password: password,
|
password: pwd,
|
||||||
value: context
|
value: state.form
|
||||||
.read<SignUpCubit>()
|
.valueOf<String?>(AppFormField.confirmedPassword)));
|
||||||
.state
|
|
||||||
.data
|
|
||||||
.valueOf<String>(
|
|
||||||
AppFormField.confirmedPassword),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Password',
|
labelText: 'Password',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: state.password.invalid ? 'Invalid password' : null,
|
errorText: !inputValid ? 'Invalid password' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,28 +64,27 @@ class _PasswordInput extends StatelessWidget {
|
|||||||
class _ConfirmPasswordInput extends StatelessWidget {
|
class _ConfirmPasswordInput extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SignUpCubit, SignUpState>(
|
return InputBuilder<SignUpCubit<int>>(
|
||||||
builder: (context, state) {
|
field: AppFormField.confirmedPassword,
|
||||||
|
builder: ((context, cubit, state, field, inputValid) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (confirmPassword) => context
|
onChanged: (pwd) {
|
||||||
.read<SignUpCubit>()
|
cubit.dataChanged(
|
||||||
.dataChanged(
|
field,
|
||||||
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: state.data.isNotValid(AppFormField.confirmedPassword)
|
errorText: !inputValid ? 'Passwords do not match' : null,
|
||||||
? 'Passwords do not match'
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,17 +92,15 @@ class _ConfirmPasswordInput extends StatelessWidget {
|
|||||||
class _SignUpButton extends StatelessWidget {
|
class _SignUpButton extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SignUpCubit, SignUpState>(
|
return SubmitBuilder<SignUpCubit<int>>(
|
||||||
builder: (context, state) {
|
builder: ((context, cubit, status) {
|
||||||
return state.status.isSubmissionInProgress
|
return status.isSubmissionInProgress
|
||||||
? const CircularProgressIndicator()
|
? const CircularProgressIndicator()
|
||||||
: ElevatedButton(
|
: ElevatedButton(
|
||||||
onPressed: state.status.isValidated
|
onPressed: status.isValidated ? () => cubit.submit() : null,
|
||||||
? () => context.read<SignUpCubit>().signUpFormSubmitted()
|
|
||||||
: null,
|
|
||||||
child: const Text('Sign up'),
|
child: const Text('Sign up'),
|
||||||
);
|
);
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,11 +110,9 @@ class SignUpForm extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocListener<SignUpCubit, SignUpState>(
|
return BlocListener<SignUpCubit<int>, SignUpState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state.status.isSubmissionSuccess) {
|
if (state.status.isSubmissionFailure) {
|
||||||
Navigator.of(context).pop();
|
|
||||||
} else if (state.status.isSubmissionFailure) {
|
|
||||||
ScaffoldMessenger.of(context)
|
ScaffoldMessenger.of(context)
|
||||||
..hideCurrentSnackBar()
|
..hideCurrentSnackBar()
|
||||||
..showSnackBar(
|
..showSnackBar(
|
||||||
|
@ -41,6 +41,12 @@ dependencies:
|
|||||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||||
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.
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// 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:wyatt_architecture/wyatt_architecture.dart';
|
abstract class AuthFormField {
|
||||||
|
static const email = 'wyattEmailField';
|
||||||
abstract class AuthenticationBiometricsDataSource extends BaseLocalDataSource {}
|
static const password = 'wyattPasswordField';
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
abstract class AuthFormName {
|
||||||
|
static const String signUpForm = 'wyattSignUpForm';
|
||||||
|
static const String signInForm = 'wyattSignInForm';
|
||||||
|
}
|
@ -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 '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,29 +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/domain/data_sources/local/authentication_local_data_source.dart';
|
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.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 AuthenticationLocalDataSource<T> {
|
extends AuthenticationCacheDataSource<T> {
|
||||||
Account? _account;
|
Account? _account;
|
||||||
T? _data;
|
T? _data;
|
||||||
|
|
||||||
AuthenticationCacheDataSourceImpl();
|
AuthenticationCacheDataSourceImpl();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void storeAccount(Account? account) {
|
Future<void> storeAccount(Account? account) async {
|
||||||
_account = account;
|
_account = account;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void storeData(T? data) {
|
Future<void> storeData(T? data) async {
|
||||||
_data = data;
|
_data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Account loadAccount() {
|
Future<Account> loadAccount() async {
|
||||||
if (_account.isNotNull) {
|
if (_account.isNotNull) {
|
||||||
return _account!;
|
return _account!;
|
||||||
}
|
}
|
||||||
@ -45,7 +44,7 @@ class AuthenticationCacheDataSourceImpl<T extends Object>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
T loadData() {
|
Future<T> loadData() async {
|
||||||
if (_data.isNotNull) {
|
if (_data.isNotNull) {
|
||||||
return _data!;
|
return _data!;
|
||||||
}
|
}
|
||||||
@ -53,8 +52,16 @@ class AuthenticationCacheDataSourceImpl<T extends Object>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void destroy() {
|
Future<void> destroy() async {
|
||||||
_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,28 +15,75 @@
|
|||||||
// 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_local_data_source.dart';
|
import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_cache_data_source.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/data_sources/remote/authentication_remote_data_source.dart';
|
import 'package:wyatt_authentication_bloc/src/domain/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 AuthenticationLocalDataSource<T> _authenticationLocalDataSource;
|
final AuthenticationCacheDataSource<T> _authenticationLocalDataSource;
|
||||||
final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
|
final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
|
||||||
|
|
||||||
final FutureResult<T?> Function(Account? account)? _onSignUpSuccess;
|
late FormRepository _formRepository;
|
||||||
final FutureResult<T?> Function(Account? account)? _onAccountChanges;
|
|
||||||
|
|
||||||
AuthenticationRepositoryImpl(
|
final OnSignUpSuccess<T>? _onSignUpSuccess;
|
||||||
this._authenticationLocalDataSource,
|
|
||||||
this._authenticationRemoteDataSource,
|
final OnAuthChange<T>? _onAccountChanges;
|
||||||
this._onSignUpSuccess,
|
|
||||||
this._onAccountChanges,
|
AuthenticationRepositoryImpl({
|
||||||
);
|
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({
|
||||||
@ -50,7 +97,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
);
|
);
|
||||||
_authenticationLocalDataSource.storeAccount(account);
|
await _authenticationLocalDataSource.storeAccount(account);
|
||||||
return account;
|
return account;
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
@ -61,7 +108,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
() async {
|
() async {
|
||||||
await _authenticationRemoteDataSource.signOut();
|
await _authenticationRemoteDataSource.signOut();
|
||||||
_authenticationLocalDataSource.destroy();
|
await _authenticationLocalDataSource.destroy();
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
@ -77,10 +124,13 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
);
|
);
|
||||||
_authenticationLocalDataSource.storeAccount(account);
|
await _authenticationLocalDataSource.storeAccount(account);
|
||||||
if (_onSignUpSuccess.isNotNull) {
|
if (_onSignUpSuccess.isNotNull) {
|
||||||
final dataResult = await _onSignUpSuccess!.call(account);
|
final dataResult = await _onSignUpSuccess!.call(
|
||||||
dataResult.fold(
|
account,
|
||||||
|
_formRepository.accessForm(AuthFormName.signUpForm).clone(),
|
||||||
|
);
|
||||||
|
await dataResult.foldAsync(
|
||||||
_authenticationLocalDataSource.storeData,
|
_authenticationLocalDataSource.storeData,
|
||||||
(error) => throw error,
|
(error) => throw error,
|
||||||
);
|
);
|
||||||
@ -91,46 +141,51 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Result<void, AppException> destroyCache() =>
|
FutureResult<void> destroyCache() =>
|
||||||
Result.tryCatch<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
_authenticationLocalDataSource.destroy,
|
_authenticationLocalDataSource.destroy,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Result<Account, AppException> getAccount() =>
|
FutureResult<AccountWrapper<T>> getCache() =>
|
||||||
Result.tryCatch<Account, AppException, AppException>(
|
Result.tryCatchAsync<AccountWrapper<T>, 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
|
||||||
Result<Account, AppException> setAccount(
|
FutureResult<void> setAccount(
|
||||||
Account account,
|
Account account,
|
||||||
) =>
|
) =>
|
||||||
Result.tryCatch<Account, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
() {
|
() async {
|
||||||
_authenticationLocalDataSource.storeAccount(account);
|
await _authenticationLocalDataSource.storeAccount(account);
|
||||||
return account;
|
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Result<T, AppException> getData() =>
|
FutureResult<T> getData() =>
|
||||||
Result.tryCatch<T, AppException, AppException>(
|
Result.tryCatchAsync<T, AppException, AppException>(
|
||||||
_authenticationLocalDataSource.loadData,
|
_authenticationLocalDataSource.loadData,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Result<T, AppException> setData(
|
FutureResult<void> setData(
|
||||||
T data,
|
T? data,
|
||||||
) =>
|
) =>
|
||||||
Result.tryCatch<T, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
() {
|
() async {
|
||||||
_authenticationLocalDataSource.storeData(data);
|
await _authenticationLocalDataSource.storeData(data);
|
||||||
return data;
|
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
@ -14,6 +14,5 @@
|
|||||||
// 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_biometrics_data_source.dart';
|
export 'local/authentication_cache_data_source.dart';
|
||||||
export 'local/authentication_local_data_source.dart';
|
|
||||||
export 'remote/authentication_remote_data_source.dart';
|
export 'remote/authentication_remote_data_source.dart';
|
||||||
|
@ -16,12 +16,14 @@
|
|||||||
|
|
||||||
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 AuthenticationLocalDataSource<T extends Object>
|
abstract class AuthenticationCacheDataSource<T extends Object>
|
||||||
extends BaseLocalDataSource {
|
extends BaseLocalDataSource {
|
||||||
void storeAccount(Account? account);
|
Future<void> storeAccount(Account? account);
|
||||||
void storeData(T? data);
|
Future<void> storeData(T? data);
|
||||||
Account loadAccount();
|
Future<Account> loadAccount();
|
||||||
T loadData();
|
Future<T> loadData();
|
||||||
void destroy();
|
Future<AccountWrapper<T>> load();
|
||||||
|
Future<void> destroy();
|
||||||
}
|
}
|
@ -17,13 +17,14 @@
|
|||||||
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_type_utils/wyatt_type_utils.dart';
|
import 'package:wyatt_form_bloc/wyatt_form_bloc.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({
|
||||||
@ -37,11 +38,12 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
|||||||
|
|
||||||
FutureResult<String> getIdentityToken();
|
FutureResult<String> getIdentityToken();
|
||||||
|
|
||||||
Result<Account, AppException> getAccount();
|
FutureResult<Account> getAccount();
|
||||||
Result<Account, AppException> setAccount(Account account);
|
FutureResult<void> setAccount(Account account);
|
||||||
|
|
||||||
Result<T, AppException> getData();
|
FutureResult<T> getData();
|
||||||
Result<T, AppException> setData(T data);
|
FutureResult<void> setData(T? data);
|
||||||
|
|
||||||
Result<void, AppException> destroyCache();
|
FutureResult<AccountWrapper<T>> getCache();
|
||||||
|
FutureResult<void> destroyCache();
|
||||||
}
|
}
|
||||||
|
@ -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(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
|
||||||
''';
|
|
||||||
}
|
}
|
||||||
|
@ -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(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)';
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user