Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95f41025f4
|
||
|
|
eceda684f0
|
||
|
|
291c195ceb
|
||
|
|
1896497c1a
|
||
|
|
87254ef547
|
||
|
|
da34acd35b
|
||
|
|
d9d0625c67
|
||
|
|
08f789725b
|
||
|
|
33ac5c6280
|
||
|
|
762b9bcd11
|
||
|
|
38480d84f4
|
||
|
|
03a51b97ad
|
||
|
|
1dd49fa080
|
||
|
|
0219e3d557
|
||
|
|
3de7d01173
|
||
|
|
4183da6259
|
||
|
|
1f24a76717
|
||
|
|
0a4a9c2feb
|
||
|
|
92f8b2916c | ||
|
|
3588c3241b
|
||
|
|
9b87eb7ed9
|
||
|
|
6802a56bfc
|
||
|
|
b2a9dac7c6
|
||
|
|
c0a91d6437
|
||
|
|
59bd3edb0d
|
||
|
|
0c920e8245
|
||
|
|
ae3711a136
|
||
|
|
f031b3cbf5
|
||
|
|
68a582c3ad
|
||
|
|
7a056ac38e
|
||
|
|
b89ef3de8a
|
||
|
|
79fdd3c837
|
||
|
|
0d00a67b7c
|
||
|
|
d2d8acdafb
|
||
|
|
2f572db4a4
|
||
|
|
3972c56e55
|
||
|
|
0bc2aa3512
|
@@ -3,6 +3,116 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## 2022-11-11
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.3.0+1`](#wyatt_authentication_bloc---v0301)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_authentication_bloc` - `v0.3.0+1`
|
||||||
|
|
||||||
|
- **FIX**: fix some bugs to validate publishing.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-11
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.3.0`](#wyatt_authentication_bloc---v030)
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- There are no other changes in this release.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_authentication_bloc` - `v0.3.0`
|
||||||
|
|
||||||
|
- **REFACTOR**: use correct deps.
|
||||||
|
- **REFACTOR**: update example with new listeners.
|
||||||
|
- **FIX**: return exception and not throwing it anymore.
|
||||||
|
- **FIX**: exception returns msg as message.
|
||||||
|
- **FEAT**: add fully functionnal mock data source.
|
||||||
|
- **FEAT**: add toString and equality on entities and models.
|
||||||
|
- **BREAKING** **FEAT**: add email verification, password reset support.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-10
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_architecture` - `v0.0.2`](#wyatt_architecture---v002)
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.2.1+6`](#wyatt_authentication_bloc---v0216)
|
||||||
|
- [`wyatt_form_bloc` - `v0.1.0+1`](#wyatt_form_bloc---v0101)
|
||||||
|
|
||||||
|
Packages graduated to a stable release (see pre-releases prior to the stable version for changelog entries):
|
||||||
|
|
||||||
|
- `wyatt_architecture` - `v0.0.2`
|
||||||
|
|
||||||
|
Packages with dependency updates only:
|
||||||
|
|
||||||
|
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||||
|
|
||||||
|
- `wyatt_authentication_bloc` - `v0.2.1+6`
|
||||||
|
- `wyatt_form_bloc` - `v0.1.0+1`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_architecture` - `v0.0.2`
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-10
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_form_bloc` - `v0.1.0`](#wyatt_form_bloc---v010)
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.2.1+5`](#wyatt_authentication_bloc---v0215)
|
||||||
|
|
||||||
|
Packages with dependency updates only:
|
||||||
|
|
||||||
|
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||||
|
|
||||||
|
- `wyatt_authentication_bloc` - `v0.2.1+5`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_form_bloc` - `v0.1.0`
|
||||||
|
|
||||||
|
- **REFACTOR**: refactor simple example.
|
||||||
|
- **FIX**: make cubit custom implementation simpler.
|
||||||
|
- **FEAT**: clean and add toString and equality.
|
||||||
|
|
||||||
|
|
||||||
## 2022-11-08
|
## 2022-11-08
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 0.0.2
|
||||||
|
|
||||||
|
- Graduate package to a stable release. See pre-releases prior to this version for changelog entries.
|
||||||
|
|
||||||
## 0.0.2-dev.0
|
## 0.0.2-dev.0
|
||||||
|
|
||||||
- **FEAT**: add exceptions, datasources, repositories, and usecases.
|
- **FEAT**: add exceptions, datasources, repositories, and usecases.
|
||||||
|
|||||||
@@ -16,31 +16,159 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
||||||
# Flutter - Wyatt Architecture
|
# Flutter - Wyatt Architecture
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
|
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
|
||||||
|
|
||||||
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
|
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
|
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Architecture for Flutter.
|
The Wyatt Architecture for Flutter.
|
||||||
|
|
||||||
Following: <https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html>
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Usecase
|
* Usecase
|
||||||
- Repository
|
* Repository
|
||||||
- DataSource
|
* DataSource
|
||||||
- Entity
|
* Entity
|
||||||
|
|
||||||
## Getting started
|
|
||||||
|
|
||||||
<!-- TODO -->
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
<!-- TODO -->
|
### Domain
|
||||||
|
|
||||||
|
Create your entities by extending `Entity` :
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class Photo extends Entity {
|
||||||
|
final int id;
|
||||||
|
final String url;
|
||||||
|
|
||||||
|
const Photo({
|
||||||
|
required this.id,
|
||||||
|
required this.url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then create the data sources by extending `BaseLocalDataSource` or `BaseRemoteDataSource` depending the type of data source.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
abstract class PhotoRemoteDataSource extends BaseRemoteDataSource {
|
||||||
|
Future<Photo> getPhoto(int id);
|
||||||
|
Future<List<Photo>> getAllPhotos({int? start, int? limit});
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can create your repositories by extenting `BaseRepository` :
|
||||||
|
|
||||||
|
```dart
|
||||||
|
abstract class PhotoRepository extends BaseRepository {
|
||||||
|
FutureResult<Photo> getPhoto(int id);
|
||||||
|
FutureResult<List<Photo>> getAllPhotos({int? start, int? limit});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Here the repository is just a proxy of the data sources with result type (to have beautiful error handling).
|
||||||
|
|
||||||
|
And finaly create your different usecases by using `UseCase<Parameters, ReturnType>` :
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class RetrieveAllPhoto extends UseCase<QueryParameters, List<Photo>> {
|
||||||
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
|
RetrieveAllPhotos(this._photoRepository);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> call(QueryParameters params) {
|
||||||
|
final photos = _photoRepository.getAllPhotos(
|
||||||
|
start: params.start,
|
||||||
|
limit: params.limit,
|
||||||
|
);
|
||||||
|
return photos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> In fact, here we need a new parameter object, so let's create it:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class QueryParameters {
|
||||||
|
final int? start;
|
||||||
|
final int? limit;
|
||||||
|
|
||||||
|
QueryParameters(this.start, this.limit);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data
|
||||||
|
|
||||||
|
We start by creating models for photos and list of photos. You can use `freezed`. The `PhotoModel` extends `Photo` with some de/serializer capabilities. And those are used only in data layer.
|
||||||
|
|
||||||
|
Then implements your data sources:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class PhotoApiDataSourceImpl extends PhotoRemoteDataSource {
|
||||||
|
final MiddlewareClient _client;
|
||||||
|
|
||||||
|
PhotoApiDataSourceImpl(this._client);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Photo> getPhoto(int id) async {
|
||||||
|
final response = await _client.get(Uri.parse('/photos/$id'));
|
||||||
|
final photo =
|
||||||
|
PhotoModel.fromJson(jsonDecode(response.body) as Map<String, Object?>);
|
||||||
|
return photo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Photo>> getAllPhotos({int? start, int? limit}) async {
|
||||||
|
final startQuery = start.isNotNull ? '_start=$start' : '';
|
||||||
|
final limitQuery = limit.isNotNull ? '_limit=$limit' : '';
|
||||||
|
final delimiter1 =
|
||||||
|
(startQuery.isNotEmpty || limitQuery.isNotEmpty) ? '?' : '';
|
||||||
|
final delimiter2 =
|
||||||
|
(startQuery.isNotEmpty && limitQuery.isNotEmpty) ? '&' : '';
|
||||||
|
final url = '/photos$delimiter1$startQuery$delimiter2$limitQuery';
|
||||||
|
final response = await _client.get(Uri.parse(url));
|
||||||
|
final photos =
|
||||||
|
ListPhotoModel.fromJson({'photos': jsonDecode(response.body)});
|
||||||
|
return photos.photos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> 1: Note that here we use `MiddlewareClient` from our http package.
|
||||||
|
|
||||||
|
> 2: You can create multiple implementations (one real and one mock for example).
|
||||||
|
|
||||||
|
And implement the repositories:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class PhotoRepositoryImpl extends PhotoRepository {
|
||||||
|
final PhotoRemoteDataSource _photoRemoteDataSource;
|
||||||
|
|
||||||
|
PhotoRepositoryImpl(
|
||||||
|
this._photoRemoteDataSource,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<Photo> getPhoto(int id) => Result.tryCatchAsync(
|
||||||
|
() => _photoRemoteDataSource.getPhoto(id),
|
||||||
|
(error) => ServerException('Cannot retrieve photo $id.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> getAllPhotos({int? start, int? limit}) async =>
|
||||||
|
Result.tryCatchAsync(
|
||||||
|
() => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit),
|
||||||
|
(error) => ServerException('Cannot retrieve all photos.'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
That's all.
|
||||||
@@ -14,4 +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 BaseDataSource {}
|
abstract class BaseDataSource {
|
||||||
|
const BaseDataSource();
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,4 +16,6 @@
|
|||||||
|
|
||||||
import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart';
|
import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart';
|
||||||
|
|
||||||
abstract class BaseLocalDataSource extends BaseDataSource {}
|
abstract class BaseLocalDataSource extends BaseDataSource {
|
||||||
|
const BaseLocalDataSource();
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,4 +16,6 @@
|
|||||||
|
|
||||||
import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart';
|
import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart';
|
||||||
|
|
||||||
abstract class BaseRemoteDataSource extends BaseDataSource {}
|
abstract class BaseRemoteDataSource extends BaseDataSource {
|
||||||
|
const BaseRemoteDataSource();
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,4 +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/>.
|
||||||
|
|
||||||
class BaseRepository {}
|
abstract class BaseRepository {
|
||||||
|
const BaseRepository();
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart';
|
|||||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
typedef FutureResult<T> = Future<Result<T, AppException>>;
|
typedef FutureResult<T> = Future<Result<T, AppException>>;
|
||||||
|
typedef StreamResult<T> = Stream<Result<T, AppException>>;
|
||||||
|
typedef Res<T> = Result<T, AppException>;
|
||||||
|
|
||||||
// ignore: one_member_abstracts
|
// ignore: one_member_abstracts
|
||||||
abstract class UseCase<Parameters, ReturnType> {
|
abstract class UseCase<Parameters, ReturnType> {
|
||||||
|
|||||||
@@ -14,4 +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 'no_param.dart';
|
||||||
export 'usecase.dart';
|
export 'usecase.dart';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: wyatt_architecture
|
name: wyatt_architecture
|
||||||
description: A new Wyatt package
|
description: A new Wyatt package
|
||||||
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_architecture
|
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_architecture
|
||||||
version: 0.0.2-dev.0
|
version: 0.0.2
|
||||||
|
|
||||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
|
|
||||||
|
|||||||
@@ -14,4 +14,4 @@
|
|||||||
// 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/>.
|
||||||
|
|
||||||
// TODO(wyatt): Add some tests
|
// Nothing to test as there is no logic in this package.
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
firebase_options.dart
|
||||||
@@ -1,3 +1,27 @@
|
|||||||
|
## 0.3.0+1
|
||||||
|
|
||||||
|
- **FIX**: fix some bugs to validate publishing.
|
||||||
|
|
||||||
|
## 0.3.0
|
||||||
|
|
||||||
|
> Note: This release has breaking changes.
|
||||||
|
|
||||||
|
- **REFACTOR**: use correct deps.
|
||||||
|
- **REFACTOR**: update example with new listeners.
|
||||||
|
- **FIX**: return exception and not throwing it anymore.
|
||||||
|
- **FIX**: exception returns msg as message.
|
||||||
|
- **FEAT**: add fully functionnal mock data source.
|
||||||
|
- **FEAT**: add toString and equality on entities and models.
|
||||||
|
- **BREAKING** **FEAT**: add email verification, password reset support.
|
||||||
|
|
||||||
|
## 0.2.1+6
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
|
## 0.2.1+5
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
## 0.2.1+4
|
## 0.2.1+4
|
||||||
|
|
||||||
- Update a dependency to the latest release.
|
- Update a dependency to the latest release.
|
||||||
|
|||||||
@@ -29,43 +29,28 @@ Authentication Bloc for Flutter.
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- UserInterface
|
- Wyatt Architecture
|
||||||
* UserFirebase : FirebaseAuth user implementation
|
- Entities:
|
||||||
- AuthenticationRepositoryInterface
|
- Account : AccountModel -> Contains account information from provider
|
||||||
* AuthenticationRepositoryFirebase : FirebaseAuth implementation
|
- AccountWrapper : AccountWrapperModel -> Contains account and extra data.
|
||||||
- ExceptionsInterface
|
- Data Sources:
|
||||||
* ExceptionsFirebase : FirebaseAuth Exception parsing implementation
|
- Local:
|
||||||
- AuthenticationBloc
|
- Cached Authentication Data : AuthenticationCacheDataSourceImpl -> Provides a cache implementation
|
||||||
* Tracks every user changes
|
- Remote:
|
||||||
- Right after the listener has been registered.
|
- Remote Authentication Data : AuthenticationFirebaseDataSourceImpl -> Provides a proxy to FirebaseAuth
|
||||||
- When a user is signed in.
|
- Repositories:
|
||||||
- When the current user is signed out.
|
- AuthenticationRepository : AuthenticationRepositoryImpl -> Provides all authentication methods
|
||||||
- When there is a change in the current user's token.
|
- Features:
|
||||||
- On `refresh()`
|
- Authentication:
|
||||||
* Start/Stop listening on demand
|
- AuthenticationBuilder : widget to build reactive view from authentication state
|
||||||
- `start()` to listen to user changes
|
- AuthenticationCubit : tracks every auth changes, have sign out capability.
|
||||||
- `stop()` to cancel listener
|
- SignUp:
|
||||||
- SignUpCubit
|
- SignUpCubit: implementation of a FormDataCubit from `wyatt_form_bloc` for the sign up
|
||||||
* Handles email/password validation and password confirmation
|
- SignIn:
|
||||||
* Handles register with email/password
|
- SignUpCubit: implementation of a FormDataCubit from `wyatt_form_bloc` for the sign in
|
||||||
* Handles custom form fields thanks `wyatt_form_bloc`
|
|
||||||
- Use `entries` to pass a `FormData` object
|
|
||||||
- You can use several pre configured `FormInput` for validation
|
|
||||||
- You can use `updateFormData()` to change FormData and validators during runtime (intersection, union, difference or replace)
|
|
||||||
- SignInCubit
|
|
||||||
* Handles email/password validation
|
|
||||||
* Handles login with email/password
|
|
||||||
- EmailVerificationCubit
|
|
||||||
* Handles send email verification process
|
|
||||||
* Handles email verification check
|
|
||||||
- PasswordResetCubit
|
|
||||||
* Handles send password reset email process
|
|
||||||
- Builders
|
|
||||||
* AuthenticationBuilder to build widgets on user state changes
|
|
||||||
- Consistent
|
- Consistent
|
||||||
* Every class have same naming convention
|
* Every class have same naming convention
|
||||||
- Tested
|
- Tested
|
||||||
* Partially tested with *bloc_test*
|
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
@@ -77,227 +62,4 @@ import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Create an authentication repository:
|
// TODO
|
||||||
|
|
||||||
```dart
|
|
||||||
final AuthenticationRepositoryInterface _authenticationRepository = AuthenticationRepositoryFirebase();
|
|
||||||
```
|
|
||||||
|
|
||||||
Create an authentication cubit:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
final AuthenticationCubit _authenticationCubit = AuthenticationCubit(
|
|
||||||
authenticationRepository: _authenticationRepository,
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
Create a sign up cubit:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
final SignUpCubit _signUpCubit = SignUpCubit(
|
|
||||||
authenticationRepository: _authenticationRepository,
|
|
||||||
authenticationCubit: _authenticationCubit,
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
You can use `AuthenticationBloc` to route your app.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
return MultiRepositoryProvider(
|
|
||||||
providers: [
|
|
||||||
RepositoryProvider<AuthenticationRepositoryInterface>(
|
|
||||||
create: (context) => _authenticationRepository,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
child: MultiBlocProvider(
|
|
||||||
providers: [
|
|
||||||
BlocProvider<AuthenticationCubit>(
|
|
||||||
create: (context) => _authenticationCubit..init(),
|
|
||||||
),
|
|
||||||
BlocProvider<SignUpCubit>(
|
|
||||||
create: (context) => _signUpCubit,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
child: const AppView(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
```
|
|
||||||
> Don't forget to call `init()` on authentication cubit.
|
|
||||||
|
|
||||||
And in `AppView` use an `AuthenticationBuilder`:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
AuthenticationBuilder(
|
|
||||||
unknown: (context) => const LoadingPage(),
|
|
||||||
unauthenticated: (context) => const LoginPage(),
|
|
||||||
authenticated: (context, user, userData) => const HomePage(),
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
To create a `SignInCubit` you'll need the same `AuthenticationRepository`, you can use the `context`:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
BlocProvider(
|
|
||||||
create: (_) => SignInCubit(context.read<AuthenticationRepositoryInterface>()),
|
|
||||||
child: const LoginForm(),
|
|
||||||
),
|
|
||||||
```
|
|
||||||
|
|
||||||
> In practice it's better to create it in the main `MultiBlocProvider` because the LoginPage can be destroyed, and cubit closed, before login flow ends
|
|
||||||
|
|
||||||
## Recipes
|
|
||||||
|
|
||||||
### Password confirmation
|
|
||||||
|
|
||||||
In this recipe we'll se how to create a custom `FormEntry` to confirm password.
|
|
||||||
|
|
||||||
First, create an entry at the SignUpCubit creation:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
SignUpCubit _signUpCubit = SignUpCubit(
|
|
||||||
authenticationRepository: _authenticationRepository,
|
|
||||||
authenticationCubit: _authenticationCubit,
|
|
||||||
entries: const FormData([
|
|
||||||
FormEntry('form_field_confirmPassword', ConfirmedPassword.pure()),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, in the sign up form, create an input for password confirmation:
|
|
||||||
|
|
||||||
- `ConfirmedPassword` validator need password value and confirm password value to compare.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
return BlocBuilder<SignUpCubit, SignUpState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return TextField(
|
|
||||||
onChanged: (confirmPassword) => context
|
|
||||||
.read<SignUpCubit>()
|
|
||||||
.dataChanged(
|
|
||||||
'form_field_confirmPassword',
|
|
||||||
ConfirmedPassword.dirty(
|
|
||||||
password: context.read<SignUpCubit>().state.password.value,
|
|
||||||
value: confirmPassword,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
obscureText: true,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'confirm password',
|
|
||||||
errorText: state.data!.input('form_field_confirmPassword').invalid
|
|
||||||
? 'passwords do not match'
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
> `form_field_confirmPassword` is the field identifier used in all application to retrieve data. You can use a constant to avoid typos.
|
|
||||||
|
|
||||||
You'll need to update password input to update confirm state on password update !
|
|
||||||
|
|
||||||
```dart
|
|
||||||
return BlocBuilder<SignUpCubit, SignUpState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return TextField(
|
|
||||||
onChanged: (password) {
|
|
||||||
context.read<SignUpCubit>().passwordChanged(password);
|
|
||||||
context.read<SignUpCubit>().dataChanged(
|
|
||||||
'form_field_confirmPassword',
|
|
||||||
ConfirmedPassword.dirty(
|
|
||||||
password: password,
|
|
||||||
value: context
|
|
||||||
.read<SignUpCubit>()
|
|
||||||
.state
|
|
||||||
.data!
|
|
||||||
.input('form_field_confirmPassword')
|
|
||||||
.value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
obscureText: true,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'password',
|
|
||||||
errorText: state.password.invalid ? 'invalid password' : null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
> Here you call standard `passwordChanged()` AND `dataChanged()`.
|
|
||||||
|
|
||||||
And voilà !
|
|
||||||
|
|
||||||
### Create Firestore Document on Sign Up
|
|
||||||
|
|
||||||
In this recipe we'll se how to create a Firestore Document on sign up success.
|
|
||||||
|
|
||||||
First create a callback function:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
Future<void> onSignUpSuccess(SignUpState state, String? uid) async {
|
|
||||||
if (uid != null) {
|
|
||||||
final user = {
|
|
||||||
'uid': uid,
|
|
||||||
'email': state.email.value,
|
|
||||||
...state.data.toMap(),
|
|
||||||
};
|
|
||||||
await FirebaseFirestore.instance.collection('users').doc(uid).set(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Then create SignUpCubit with custom entries and register callback:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
SignUpCubit _signUpCubit = SignUpCubit(
|
|
||||||
authenticationRepository: _authenticationRepository,
|
|
||||||
authenticationCubit: _authenticationCubit,
|
|
||||||
entries: const FormData([
|
|
||||||
FormEntry('form_field_name', Name.pure(), fieldName: 'name'),
|
|
||||||
FormEntry('form_field_phone', Phone.pure(), fieldName: 'phone'),
|
|
||||||
FormEntry('form_field_confirmPassword', ConfirmedPassword.pure(), export: false),
|
|
||||||
]),
|
|
||||||
onSignUpSuccess: onSignUpSuccess,
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
> Use `fieldName` and `export` to control `.toMap()` result on FormData ! Useful to disable exportation of sensible data like passwords.
|
|
||||||
|
|
||||||
Create widgets for each inputs:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
class _PhoneInput extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return BlocBuilder<SignUpCubit, SignUpState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return TextField(
|
|
||||||
onChanged: (phone) => context
|
|
||||||
.read<SignUpCubit>()
|
|
||||||
.dataChanged('form_field_phone', Phone.dirty(phone)),
|
|
||||||
keyboardType: TextInputType.phone,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'phone',
|
|
||||||
helperText: '',
|
|
||||||
errorText: state.data!.input('form_field_phone').invalid
|
|
||||||
? 'invalid phone'
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
> Create widgets for Name and ConfirmedPassword too.
|
|
||||||
|
|
||||||
Then add a sign up button with:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
context.read<SignUpCubit>().signUpFormSubmitted()
|
|
||||||
```
|
|
||||||
|
|
||||||
And voilà, a document with `uid` as id, and fields `email`, `name`, `phone`, `uid` will be create in `users` collection.
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
{
|
|
||||||
"project_info": {
|
|
||||||
"project_number": "136771801992",
|
|
||||||
"firebase_url": "https://tchat-beta.firebaseio.com",
|
|
||||||
"project_id": "tchat-beta",
|
|
||||||
"storage_bucket": "tchat-beta.appspot.com"
|
|
||||||
},
|
|
||||||
"client": [
|
|
||||||
{
|
|
||||||
"client_info": {
|
|
||||||
"mobilesdk_app_id": "1:136771801992:android:4ff419f07afdad6097203d",
|
|
||||||
"android_client_info": {
|
|
||||||
"package_name": "com.example.authentication_bloc_example"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "136771801992-nps7ic22shstvgdv0c2ojvbkj3dkntum.apps.googleusercontent.com",
|
|
||||||
"client_type": 1,
|
|
||||||
"android_info": {
|
|
||||||
"package_name": "com.example.authentication_bloc_example",
|
|
||||||
"certificate_hash": "5d8790309e13b68c35e5d4d8437c35c6d15e6131"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client_id": "136771801992-ncuib3rbu7p4ro4eo5su4vaudn2u4qrv.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"api_key": [
|
|
||||||
{
|
|
||||||
"current_key": "AIzaSyAYS14uXupkS158Q5QAFP1864UrUN_yDSk"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"services": {
|
|
||||||
"appinvite_service": {
|
|
||||||
"other_platform_oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "136771801992-ncuib3rbu7p4ro4eo5su4vaudn2u4qrv.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client_id": "136771801992-e585bm1n9b3lv89t4phrl9u0glsg52ua.apps.googleusercontent.com",
|
|
||||||
"client_type": 2,
|
|
||||||
"ios_info": {
|
|
||||||
"bundle_id": "com.example.example"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client_info": {
|
|
||||||
"mobilesdk_app_id": "1:136771801992:android:8482c9b90bc29de697203d",
|
|
||||||
"android_client_info": {
|
|
||||||
"package_name": "com.example.crud_bloc_example"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "136771801992-ncuib3rbu7p4ro4eo5su4vaudn2u4qrv.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"api_key": [
|
|
||||||
{
|
|
||||||
"current_key": "AIzaSyAYS14uXupkS158Q5QAFP1864UrUN_yDSk"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"services": {
|
|
||||||
"appinvite_service": {
|
|
||||||
"other_platform_oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "136771801992-ncuib3rbu7p4ro4eo5su4vaudn2u4qrv.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client_id": "136771801992-e585bm1n9b3lv89t4phrl9u0glsg52ua.apps.googleusercontent.com",
|
|
||||||
"client_type": 2,
|
|
||||||
"ios_info": {
|
|
||||||
"bundle_id": "com.example.example"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"configuration_version": "1"
|
|
||||||
}
|
|
||||||
@@ -38,7 +38,7 @@ dependencies:
|
|||||||
wyatt_form_bloc:
|
wyatt_form_bloc:
|
||||||
git:
|
git:
|
||||||
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.1.0+1
|
||||||
path: packages/wyatt_form_bloc
|
path: packages/wyatt_form_bloc
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
|
|||||||
@@ -45,3 +45,5 @@ app.*.map.json
|
|||||||
/android/app/debug
|
/android/app/debug
|
||||||
/android/app/profile
|
/android/app/profile
|
||||||
/android/app/release
|
/android/app/release
|
||||||
|
|
||||||
|
firebase_options.dart
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
# This file should be version controlled.
|
# This file should be version controlled.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
channel: stable
|
channel: stable
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
@@ -13,11 +13,11 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
- platform: android
|
- platform: ios
|
||||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
**/dgph
|
||||||
|
*.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
*.moved-aside
|
||||||
|
*.pbxuser
|
||||||
|
*.perspectivev3
|
||||||
|
**/*sync/
|
||||||
|
.sconsign.dblite
|
||||||
|
.tags*
|
||||||
|
**/.vagrant/
|
||||||
|
**/DerivedData/
|
||||||
|
Icon?
|
||||||
|
**/Pods/
|
||||||
|
**/.symlinks/
|
||||||
|
profile
|
||||||
|
xcuserdata
|
||||||
|
**/.generated/
|
||||||
|
Flutter/App.framework
|
||||||
|
Flutter/Flutter.framework
|
||||||
|
Flutter/Flutter.podspec
|
||||||
|
Flutter/Generated.xcconfig
|
||||||
|
Flutter/ephemeral/
|
||||||
|
Flutter/app.flx
|
||||||
|
Flutter/app.zip
|
||||||
|
Flutter/flutter_assets/
|
||||||
|
Flutter/flutter_export_environment.sh
|
||||||
|
ServiceDefinitions.json
|
||||||
|
Runner/GeneratedPluginRegistrant.*
|
||||||
|
|
||||||
|
# Exceptions to above rules.
|
||||||
|
!default.mode1v3
|
||||||
|
!default.mode2v3
|
||||||
|
!default.pbxuser
|
||||||
|
!default.perspectivev3
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>App</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>io.flutter.flutter.app</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>App</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>MinimumOSVersion</key>
|
||||||
|
<string>11.0</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
|
#include "Generated.xcconfig"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
|
#include "Generated.xcconfig"
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
# platform :ios, '11.0'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_ios_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_ios_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
PODS:
|
||||||
|
- AppAuth (1.6.0):
|
||||||
|
- AppAuth/Core (= 1.6.0)
|
||||||
|
- AppAuth/ExternalUserAgent (= 1.6.0)
|
||||||
|
- AppAuth/Core (1.6.0)
|
||||||
|
- AppAuth/ExternalUserAgent (1.6.0):
|
||||||
|
- AppAuth/Core
|
||||||
|
- FBAEMKit (14.1.0):
|
||||||
|
- FBSDKCoreKit_Basics (= 14.1.0)
|
||||||
|
- FBSDKCoreKit (14.1.0):
|
||||||
|
- FBAEMKit (= 14.1.0)
|
||||||
|
- FBSDKCoreKit_Basics (= 14.1.0)
|
||||||
|
- FBSDKCoreKit_Basics (14.1.0)
|
||||||
|
- FBSDKLoginKit (14.1.0):
|
||||||
|
- FBSDKCoreKit (= 14.1.0)
|
||||||
|
- Firebase/Auth (10.0.0):
|
||||||
|
- Firebase/CoreOnly
|
||||||
|
- FirebaseAuth (~> 10.0.0)
|
||||||
|
- Firebase/CoreOnly (10.0.0):
|
||||||
|
- FirebaseCore (= 10.0.0)
|
||||||
|
- firebase_auth (4.1.1):
|
||||||
|
- Firebase/Auth (= 10.0.0)
|
||||||
|
- firebase_core
|
||||||
|
- Flutter
|
||||||
|
- firebase_core (2.1.1):
|
||||||
|
- Firebase/CoreOnly (= 10.0.0)
|
||||||
|
- Flutter
|
||||||
|
- FirebaseAuth (10.0.0):
|
||||||
|
- FirebaseCore (~> 10.0)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||||
|
- GoogleUtilities/Environment (~> 7.8)
|
||||||
|
- GTMSessionFetcher/Core (~> 2.1)
|
||||||
|
- FirebaseCore (10.0.0):
|
||||||
|
- FirebaseCoreInternal (~> 10.0)
|
||||||
|
- GoogleUtilities/Environment (~> 7.8)
|
||||||
|
- GoogleUtilities/Logger (~> 7.8)
|
||||||
|
- FirebaseCoreInternal (10.1.0):
|
||||||
|
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||||
|
- Flutter (1.0.0)
|
||||||
|
- flutter_facebook_auth (4.4.1):
|
||||||
|
- FBSDKLoginKit (= 14.1.0)
|
||||||
|
- Flutter
|
||||||
|
- google_sign_in_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- GoogleSignIn (~> 6.2)
|
||||||
|
- GoogleSignIn (6.2.4):
|
||||||
|
- AppAuth (~> 1.5)
|
||||||
|
- GTMAppAuth (~> 1.3)
|
||||||
|
- GTMSessionFetcher/Core (< 3.0, >= 1.1)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (7.8.0):
|
||||||
|
- GoogleUtilities/Environment
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Network
|
||||||
|
- GoogleUtilities/Environment (7.8.0):
|
||||||
|
- PromisesObjC (< 3.0, >= 1.2)
|
||||||
|
- GoogleUtilities/Logger (7.8.0):
|
||||||
|
- GoogleUtilities/Environment
|
||||||
|
- GoogleUtilities/Network (7.8.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- "GoogleUtilities/NSData+zlib"
|
||||||
|
- GoogleUtilities/Reachability
|
||||||
|
- "GoogleUtilities/NSData+zlib (7.8.0)"
|
||||||
|
- GoogleUtilities/Reachability (7.8.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GTMAppAuth (1.3.1):
|
||||||
|
- AppAuth/Core (~> 1.6)
|
||||||
|
- GTMSessionFetcher/Core (< 3.0, >= 1.5)
|
||||||
|
- GTMSessionFetcher/Core (2.1.0)
|
||||||
|
- PromisesObjC (2.1.1)
|
||||||
|
- sign_in_with_apple (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- twitter_login (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
|
||||||
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`)
|
||||||
|
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`)
|
||||||
|
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
|
||||||
|
- twitter_login (from `.symlinks/plugins/twitter_login/ios`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- AppAuth
|
||||||
|
- FBAEMKit
|
||||||
|
- FBSDKCoreKit
|
||||||
|
- FBSDKCoreKit_Basics
|
||||||
|
- FBSDKLoginKit
|
||||||
|
- Firebase
|
||||||
|
- FirebaseAuth
|
||||||
|
- FirebaseCore
|
||||||
|
- FirebaseCoreInternal
|
||||||
|
- GoogleSignIn
|
||||||
|
- GoogleUtilities
|
||||||
|
- GTMAppAuth
|
||||||
|
- GTMSessionFetcher
|
||||||
|
- PromisesObjC
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
firebase_auth:
|
||||||
|
:path: ".symlinks/plugins/firebase_auth/ios"
|
||||||
|
firebase_core:
|
||||||
|
:path: ".symlinks/plugins/firebase_core/ios"
|
||||||
|
Flutter:
|
||||||
|
:path: Flutter
|
||||||
|
flutter_facebook_auth:
|
||||||
|
:path: ".symlinks/plugins/flutter_facebook_auth/ios"
|
||||||
|
google_sign_in_ios:
|
||||||
|
:path: ".symlinks/plugins/google_sign_in_ios/ios"
|
||||||
|
sign_in_with_apple:
|
||||||
|
:path: ".symlinks/plugins/sign_in_with_apple/ios"
|
||||||
|
twitter_login:
|
||||||
|
:path: ".symlinks/plugins/twitter_login/ios"
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
AppAuth: 8fca6b5563a5baef2c04bee27538025e4ceb2add
|
||||||
|
FBAEMKit: a899515e45476027f73aef377b5cffadcd56ca3a
|
||||||
|
FBSDKCoreKit: 24f8bc8d3b5b2a8c5c656a1329492a12e8efa792
|
||||||
|
FBSDKCoreKit_Basics: 6e578c9bdc7aa1365dbbbde633c9ebb536bcaa98
|
||||||
|
FBSDKLoginKit: 787de205d524c3a4b17d527916f1d066e4361660
|
||||||
|
Firebase: 1b810f3d0c0532e27a48f1961f8c0400a668a2cf
|
||||||
|
firebase_auth: dd33e93fce72a1c72040f7380dacf06e89db5705
|
||||||
|
firebase_core: 5c0bb0ca7d0e70480a68a6e9ad9bf55d1edd5305
|
||||||
|
FirebaseAuth: 493382cf533cc45e2862b00e9aa4cfe4c98daf71
|
||||||
|
FirebaseCore: 97f48a3a567a72b8d4daa0f03c3aadb78df4e995
|
||||||
|
FirebaseCoreInternal: 96d75228e10fd369564da51bd898414eb0f54df5
|
||||||
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||||
|
flutter_facebook_auth: 361ac7a57263ebf327f26089507ead0d66558ee8
|
||||||
|
google_sign_in_ios: 4f85eb9f937450765c8573bb85fd8cd6a5af675c
|
||||||
|
GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a
|
||||||
|
GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7
|
||||||
|
GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd
|
||||||
|
GTMSessionFetcher: ffbb25ec00ebcb5201adab0a56d808f6f1902d9f
|
||||||
|
PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb
|
||||||
|
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
|
||||||
|
twitter_login: 2794db69b7640681171b17b3c2c84ad9dfb4a57f
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
||||||
|
|
||||||
|
COCOAPODS: 1.11.3
|
||||||
@@ -0,0 +1,552 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 50;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
69F3BBCD5DEB05A456F6B74F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0A061B2E527F311149C3581 /* Pods_Runner.framework */; };
|
||||||
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 10;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
name = "Embed Frameworks";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
07E343497E760D6A90A105C5 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
B0A061B2E527F311149C3581 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
F0D7945BAE0BEA457137ED73 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
F9340E3A859C31E59380BD0F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
69F3BBCD5DEB05A456F6B74F /* Pods_Runner.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
66B357379C2757D2844F12BB /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
F0D7945BAE0BEA457137ED73 /* Pods-Runner.debug.xcconfig */,
|
||||||
|
F9340E3A859C31E59380BD0F /* Pods-Runner.release.xcconfig */,
|
||||||
|
07E343497E760D6A90A105C5 /* Pods-Runner.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Pods;
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||||
|
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Flutter;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146E51CF9000F007C117D = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
|
66B357379C2757D2844F12BB /* Pods */,
|
||||||
|
BC1E25CE0DADDF7B7201CCF8 /* Frameworks */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146EF1CF9000F007C117D /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||||
|
97C147021CF9000F007C117D /* Info.plist */,
|
||||||
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||||
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||||
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||||
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||||
|
);
|
||||||
|
path = Runner;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
BC1E25CE0DADDF7B7201CCF8 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
B0A061B2E527F311149C3581 /* Pods_Runner.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
|
buildPhases = (
|
||||||
|
92D20EC4971D81AAB7475BDB /* [CP] Check Pods Manifest.lock */,
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
DEBBE8DDE939288865FFA279 /* [CP] Embed Pods Frameworks */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = Runner;
|
||||||
|
productName = Runner;
|
||||||
|
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastUpgradeCheck = 1300;
|
||||||
|
ORGANIZATIONNAME = "";
|
||||||
|
TargetAttributes = {
|
||||||
|
97C146ED1CF9000F007C117D = {
|
||||||
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
|
LastSwiftMigration = 1100;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||||
|
compatibilityVersion = "Xcode 9.3";
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 97C146E51CF9000F007C117D;
|
||||||
|
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||||
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||||
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||||
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Thin Binary";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||||
|
};
|
||||||
|
92D20EC4971D81AAB7475BDB /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Run Script";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
|
};
|
||||||
|
DEBBE8DDE939288865FFA279 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||||
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
97C146FB1CF9000F007C117D /* Base */,
|
||||||
|
);
|
||||||
|
name = Main.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
97C147001CF9000F007C117D /* Base */,
|
||||||
|
);
|
||||||
|
name = LaunchScreen.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = 6Z5P8GG96U;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleRouter;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
97C147031CF9000F007C117D /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
97C147041CF9000F007C117D /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
97C147061CF9000F007C117D /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = 6Z5P8GG96U;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleRouter;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
97C147071CF9000F007C117D /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = 6Z5P8GG96U;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleRouter;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
97C147031CF9000F007C117D /* Debug */,
|
||||||
|
97C147041CF9000F007C117D /* Release */,
|
||||||
|
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
97C147061CF9000F007C117D /* Debug */,
|
||||||
|
97C147071CF9000F007C117D /* Release */,
|
||||||
|
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1300"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Profile"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:Runner.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import UIKit
|
||||||
|
import Flutter
|
||||||
|
|
||||||
|
@UIApplicationMain
|
||||||
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
|
override func application(
|
||||||
|
_ application: UIApplication,
|
||||||
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
|
) -> Bool {
|
||||||
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-20x20@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-40x40@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-60x60@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-60x60@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-20x20@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-40x40@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-76x76@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-76x76@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "83.5x83.5",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "1024x1024",
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"filename" : "Icon-App-1024x1024@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 564 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "LaunchImage.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "LaunchImage@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "LaunchImage@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 68 B |
|
After Width: | Height: | Size: 68 B |
|
After Width: | Height: | Size: 68 B |
@@ -0,0 +1,5 @@
|
|||||||
|
# Launch Screen Assets
|
||||||
|
|
||||||
|
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
|
||||||
|
|
||||||
|
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
||||||
|
</imageView>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<image name="LaunchImage" width="168" height="185"/>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Flutter View Controller-->
|
||||||
|
<scene sceneID="tne-QT-ifu">
|
||||||
|
<objects>
|
||||||
|
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Example Router</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>example_router</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UIMainStoryboardFile</key>
|
||||||
|
<string>Main</string>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
|
<false/>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#import "GeneratedPluginRegistrant.h"
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"file_generated_by": "FlutterFire CLI",
|
||||||
|
"purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory",
|
||||||
|
"GOOGLE_APP_ID": "1:136771801992:ios:bcdca68d2b7d227097203d",
|
||||||
|
"FIREBASE_PROJECT_ID": "tchat-beta",
|
||||||
|
"GCM_SENDER_ID": "136771801992"
|
||||||
|
}
|
||||||
@@ -3,35 +3,27 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: bootstrap.dart
|
// File: bootstrap.dart
|
||||||
// Created Date: 19/08/2022 15:05:17
|
// Created Date: 19/08/2022 15:05:17
|
||||||
// Last Modified: 19/08/2022 15:21:47
|
// Last Modified: Fri Nov 11 2022
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2022
|
// Copyright (c) 2022
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:example_router/core/dependency_injection/get_it.dart';
|
||||||
import 'package:example_router/core/utils/app_bloc_observer.dart';
|
import 'package:example_router/core/utils/app_bloc_observer.dart';
|
||||||
import 'package:example_router/firebase_options.dart';
|
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
|
||||||
|
|
||||||
Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
|
Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
|
||||||
await runZonedGuarded(
|
await runZonedGuarded(
|
||||||
() async {
|
() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
Bloc.observer = AppBlocObserver();
|
||||||
|
|
||||||
FlutterError.onError = (details) {
|
FlutterError.onError = (details) {
|
||||||
debugPrint(details.toString());
|
debugPrint(details.toString());
|
||||||
};
|
};
|
||||||
|
await GetItInitializer.init();
|
||||||
await Firebase.initializeApp(
|
|
||||||
options: DefaultFirebaseOptions.currentPlatform,
|
|
||||||
);
|
|
||||||
|
|
||||||
GoRouter.setUrlPathStrategy(UrlPathStrategy.path);
|
|
||||||
|
|
||||||
Bloc.observer = AppBlocObserver();
|
|
||||||
|
|
||||||
runApp(await builder());
|
runApp(await builder());
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||||
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
final getIt = GetIt.I;
|
||||||
|
|
||||||
|
abstract class GetItInitializer {
|
||||||
|
static Future<void> init() async {
|
||||||
|
getIt
|
||||||
|
..registerLazySingleton<AuthenticationRemoteDataSource>(
|
||||||
|
() => AuthenticationMockDataSourceImpl(registeredAccounts: [
|
||||||
|
Pair(
|
||||||
|
AccountModel(
|
||||||
|
uid: '1',
|
||||||
|
emailVerified: true,
|
||||||
|
isAnonymous: false,
|
||||||
|
providerId: 'wyatt',
|
||||||
|
email: 'toto@test.fr',
|
||||||
|
),
|
||||||
|
'toto1234',
|
||||||
|
),
|
||||||
|
Pair(
|
||||||
|
AccountModel(
|
||||||
|
uid: '2',
|
||||||
|
emailVerified: false,
|
||||||
|
isAnonymous: false,
|
||||||
|
providerId: 'wyatt',
|
||||||
|
email: 'tata@test.fr',
|
||||||
|
),
|
||||||
|
'tata1234',
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
..registerLazySingleton<AuthenticationCacheDataSource<int>>(
|
||||||
|
() => AuthenticationCacheDataSourceImpl<int>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
await getIt.allReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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),
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
// File generated by FlutterFire CLI.
|
|
||||||
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
|
|
||||||
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
|
|
||||||
import 'package:flutter/foundation.dart'
|
|
||||||
show defaultTargetPlatform, kIsWeb, TargetPlatform;
|
|
||||||
|
|
||||||
/// Default [FirebaseOptions] for use with your Firebase apps.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```dart
|
|
||||||
/// import 'firebase_options.dart';
|
|
||||||
/// // ...
|
|
||||||
/// await Firebase.initializeApp(
|
|
||||||
/// options: DefaultFirebaseOptions.currentPlatform,
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
class DefaultFirebaseOptions {
|
|
||||||
static FirebaseOptions get currentPlatform {
|
|
||||||
if (kIsWeb) {
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions have not been configured for web - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
switch (defaultTargetPlatform) {
|
|
||||||
case TargetPlatform.android:
|
|
||||||
return android;
|
|
||||||
case TargetPlatform.iOS:
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions have not been configured for ios - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
case TargetPlatform.macOS:
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions have not been configured for macos - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
case TargetPlatform.windows:
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions have not been configured for windows - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
case TargetPlatform.linux:
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions have not been configured for linux - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions are not supported for this platform.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const FirebaseOptions android = FirebaseOptions(
|
|
||||||
apiKey: 'AIzaSyAYS14uXupkS158Q5QAFP1864UrUN_yDSk',
|
|
||||||
appId: '1:136771801992:android:ac3cfeb99fb0763e97203d',
|
|
||||||
messagingSenderId: '136771801992',
|
|
||||||
projectId: 'tchat-beta',
|
|
||||||
databaseURL: 'https://tchat-beta.firebaseio.com',
|
|
||||||
storageBucket: 'tchat-beta.appspot.com',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -3,22 +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: Fri Aug 26 2022
|
// Last Modified: Thu Nov 10 2022
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2022
|
// Copyright (c) 2022
|
||||||
|
|
||||||
|
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/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_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 authenticationRepository =
|
final AuthenticationRepository<int> authenticationRepository =
|
||||||
AuthenticationRepositoryFirebase();
|
AuthenticationRepositoryImpl(
|
||||||
|
authenticationCacheDataSource: getIt<AuthenticationCacheDataSource<int>>(),
|
||||||
|
authenticationRemoteDataSource: getIt<AuthenticationRemoteDataSource>(),
|
||||||
|
onSignUpSuccess: onSignUpSuccess,
|
||||||
|
onAuthChange: onAccountChanges,
|
||||||
|
extraSignUpInputs: [
|
||||||
|
FormInput(
|
||||||
|
AppFormField.confirmedPassword,
|
||||||
|
const ConfirmedPassword.pure(),
|
||||||
|
metadata: const FormInputMetadata<void>(export: false),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
App({Key? key}) : super(key: key);
|
App({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@@ -26,13 +62,8 @@ class App extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
AuthenticationState? previous;
|
AuthenticationState? previous;
|
||||||
|
|
||||||
final AuthenticationCubit authenticationCubit = AuthenticationCubit(
|
final AuthenticationCubit<int> authenticationCubit =
|
||||||
authenticationRepository: authenticationRepository,
|
AuthenticationCubit(authenticationRepository: authenticationRepository);
|
||||||
onAuthSuccess: (user) async {
|
|
||||||
debugPrint(user.toString());
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
final GoRouter router = GoRouter(
|
final GoRouter router = GoRouter(
|
||||||
initialLocation: '/',
|
initialLocation: '/',
|
||||||
@@ -42,7 +73,7 @@ class App extends StatelessWidget {
|
|||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
),
|
),
|
||||||
refreshListenable: GoRouterRefreshStream(authenticationCubit.stream),
|
refreshListenable: GoRouterRefreshStream(authenticationCubit.stream),
|
||||||
redirect: (state) {
|
redirect: (context, state) {
|
||||||
final authState = authenticationCubit.state;
|
final authState = authenticationCubit.state;
|
||||||
|
|
||||||
if (authState != previous) {
|
if (authState != previous) {
|
||||||
@@ -59,13 +90,12 @@ class App extends StatelessWidget {
|
|||||||
if (isOnboarding) {
|
if (isOnboarding) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return state.namedLocation(WelcomePage.pageName);
|
return '/';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final email = authState.user?.email;
|
debugPrint('Logged');
|
||||||
debugPrint('Logged as: $email');
|
|
||||||
if (isOnboarding) {
|
if (isOnboarding) {
|
||||||
return state.namedLocation(HomePage.pageName);
|
return '/home';
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -83,20 +113,15 @@ class App extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
child: MultiBlocProvider(
|
child: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider<AuthenticationCubit>.value(
|
BlocProvider<AuthenticationCubit<int>>.value(
|
||||||
value: authenticationCubit..init(),
|
value: authenticationCubit,
|
||||||
),
|
),
|
||||||
BlocProvider<SignUpCubit>(
|
BlocProvider<SignUpCubit<int>>(
|
||||||
create: (_) => SignUpCubit(
|
create: (_) => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
formData: Forms.getNormalData(),
|
|
||||||
onSignUpSuccess: (state, uid) async {
|
|
||||||
debugPrint(state.toString());
|
|
||||||
debugPrint(uid);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider<SignInCubit>(
|
BlocProvider<SignInCubit<int>>(
|
||||||
create: (_) => SignInCubit(
|
create: (_) => SignInCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
),
|
),
|
||||||
@@ -105,11 +130,26 @@ 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,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GoRouterRefreshStream extends ChangeNotifier {
|
||||||
|
GoRouterRefreshStream(Stream<dynamic> stream) {
|
||||||
|
notifyListeners();
|
||||||
|
_subscription = stream.asBroadcastStream().listen(
|
||||||
|
(dynamic _) => notifyListeners(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final StreamSubscription<dynamic> _subscription;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_subscription.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: home_page.dart
|
// File: home_page.dart
|
||||||
// Created Date: 19/08/2022 14:38:24
|
// Created Date: 19/08/2022 14:38:24
|
||||||
// Last Modified: 19/08/2022 16:12:22
|
// Last Modified: Wed Nov 09 2022
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2022
|
// Copyright (c) 2022
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ class HomePage extends StatelessWidget {
|
|||||||
title: const Text('Home'),
|
title: const Text('Home'),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => context.read<AuthenticationCubit>().logOut(),
|
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
||||||
icon: const Icon(Icons.logout_rounded))
|
icon: const Icon(Icons.logout_rounded))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -34,11 +34,12 @@ class HomePage extends StatelessWidget {
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
BlocBuilder<AuthenticationCubit, AuthenticationState>(
|
AuthenticationBuilder<int>(
|
||||||
builder: (context, state) {
|
authenticated: (context, accountWrapper) =>
|
||||||
final email = state.user?.email;
|
Text('Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
||||||
return Text('Logged as $email');
|
unauthenticated: (context) =>
|
||||||
},
|
const Text('Not logged (unauthenticated)'),
|
||||||
|
unknown: (context) => const Text('Not logged (unknown)'),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 8,
|
||||||
|
|||||||
@@ -3,30 +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: 19/08/2022 16:35:01
|
// Last Modified: Fri Nov 11 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: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 +34,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 +54,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,18 +72,12 @@ class SignInForm extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocListener<SignInCubit, SignInState>(
|
return SignInListener<int>(
|
||||||
listener: (context, state) {
|
onError: (context, status, errorMessage) => ScaffoldMessenger.of(context)
|
||||||
if (state.status.isSubmissionSuccess) {
|
..hideCurrentSnackBar()
|
||||||
Navigator.of(context).pop();
|
..showSnackBar(
|
||||||
} else if (state.status.isSubmissionFailure) {
|
SnackBar(content: Text(errorMessage ?? 'Sign In Failure')),
|
||||||
ScaffoldMessenger.of(context)
|
),
|
||||||
..hideCurrentSnackBar()
|
|
||||||
..showSnackBar(
|
|
||||||
SnackBar(content: Text(state.errorMessage ?? 'Sign In Failure')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -3,32 +3,31 @@
|
|||||||
// -----
|
// -----
|
||||||
// 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: Fri Nov 11 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: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';
|
||||||
|
|
||||||
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 +35,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 +63,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 +91,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,31 +109,25 @@ class SignUpForm extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocListener<SignUpCubit, SignUpState>(
|
return SignUpListener<int>(
|
||||||
listener: (context, state) {
|
onError: (context, status, errorMessage) =>
|
||||||
if (state.status.isSubmissionSuccess) {
|
ScaffoldMessenger.of(context)
|
||||||
Navigator.of(context).pop();
|
..hideCurrentSnackBar()
|
||||||
} else if (state.status.isSubmissionFailure) {
|
..showSnackBar(
|
||||||
ScaffoldMessenger.of(context)
|
SnackBar(content: Text(errorMessage ?? 'Sign Up Failure')),
|
||||||
..hideCurrentSnackBar()
|
),
|
||||||
..showSnackBar(
|
child: SingleChildScrollView(
|
||||||
SnackBar(content: Text(state.errorMessage ?? 'Sign Up Failure')),
|
child: Column(
|
||||||
);
|
children: [
|
||||||
}
|
_EmailInput(),
|
||||||
},
|
const SizedBox(height: 8),
|
||||||
child: SingleChildScrollView(
|
_PasswordInput(),
|
||||||
child: Column(
|
const SizedBox(height: 8),
|
||||||
children: [
|
_ConfirmPasswordInput(),
|
||||||
_EmailInput(),
|
const SizedBox(height: 16),
|
||||||
const SizedBox(height: 8),
|
_SignUpButton(),
|
||||||
_PasswordInput(),
|
],
|
||||||
const SizedBox(height: 8),
|
),
|
||||||
_ConfirmPasswordInput(),
|
));
|
||||||
const SizedBox(height: 16),
|
|
||||||
_SignUpButton(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: sub_page.dart
|
// File: sub_page.dart
|
||||||
// Created Date: 19/08/2022 16:10:05
|
// Created Date: 19/08/2022 16:10:05
|
||||||
// Last Modified: 19/08/2022 16:10:44
|
// Last Modified: Wed Nov 09 2022
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2022
|
// Copyright (c) 2022
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ class SubPage extends StatelessWidget {
|
|||||||
title: const Text('Sub'),
|
title: const Text('Sub'),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => context.read<AuthenticationCubit>().logOut(),
|
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
||||||
icon: const Icon(Icons.logout_rounded))
|
icon: const Icon(Icons.logout_rounded))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -3,16 +3,14 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: welcome_page.dart
|
// File: welcome_page.dart
|
||||||
// Created Date: 19/08/2022 12:33:21
|
// Created Date: 19/08/2022 12:33:21
|
||||||
// Last Modified: 19/08/2022 15:56:05
|
// Last Modified: Wed Nov 09 2022
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2022
|
// Copyright (c) 2022
|
||||||
|
|
||||||
import 'package:example_router/presentation/features/sign_in/sign_in_page.dart';
|
import 'package:example_router/presentation/features/sign_in/sign_in_page.dart';
|
||||||
import 'package:example_router/presentation/features/sign_up/sign_up_page.dart';
|
import 'package:example_router/presentation/features/sign_up/sign_up_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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';
|
|
||||||
|
|
||||||
class WelcomePage extends StatelessWidget {
|
class WelcomePage extends StatelessWidget {
|
||||||
const WelcomePage({Key? key}) : super(key: key);
|
const WelcomePage({Key? key}) : super(key: key);
|
||||||
@@ -24,12 +22,6 @@ class WelcomePage extends StatelessWidget {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Welcome'),
|
title: const Text('Welcome'),
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => context.read<AuthenticationCubit>().changeStatus(
|
|
||||||
context.read<AuthenticationCubit>().state.user!),
|
|
||||||
icon: const Icon(Icons.refresh_rounded))
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|||||||
@@ -30,21 +30,29 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
go_router: ^4.2.8
|
go_router: ^5.1.5
|
||||||
firebase_core: ^1.21.0
|
firebase_core: ^2.1.1
|
||||||
flutter_bloc: ^8.1.1
|
flutter_bloc: ^8.1.1
|
||||||
|
get_it: ^7.2.0
|
||||||
|
|
||||||
wyatt_authentication_bloc:
|
wyatt_authentication_bloc:
|
||||||
path: "../"
|
path: "../"
|
||||||
|
|
||||||
wyatt_form_bloc:
|
wyatt_form_bloc:
|
||||||
git:
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
version: 0.1.0+1
|
||||||
ref: wyatt_form_bloc-v0.0.6
|
|
||||||
path: packages/wyatt_form_bloc
|
wyatt_architecture:
|
||||||
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
|
version: 0.0.2
|
||||||
|
|
||||||
|
wyatt_type_utils:
|
||||||
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
|
version: 0.0.3+1
|
||||||
|
|
||||||
# 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.2
|
cupertino_icons: ^1.0.5
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -14,16 +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/>.
|
||||||
|
|
||||||
enum SetOperation {
|
abstract class AuthFormField {
|
||||||
/// Replace entire set with new set.
|
static const email = 'wyattEmailField';
|
||||||
replace,
|
static const password = 'wyattPasswordField';
|
||||||
|
|
||||||
/// Keep common elements between sets.
|
|
||||||
intersection,
|
|
||||||
|
|
||||||
/// Remove common elements between sets.
|
|
||||||
difference,
|
|
||||||
|
|
||||||
/// Add new elements to set.
|
|
||||||
union
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// 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';
|
||||||
|
static const String passwordResetForm = 'wyattPasswordResetForm';
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'constants/form_field.dart';
|
||||||
|
export 'constants/form_name.dart';
|
||||||
|
export 'enums/enums.dart';
|
||||||
|
export 'exceptions/exceptions.dart';
|
||||||
|
export 'utils/utils.dart';
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
enum AuthenticationStatus {
|
||||||
|
unknown,
|
||||||
|
authenticated,
|
||||||
|
unauthenticated,
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'authentication_status.dart';
|
||||||
@@ -14,13 +14,21 @@
|
|||||||
// 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 AuthenticationFailureInterface implements Exception {
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
String code;
|
|
||||||
String message;
|
|
||||||
|
|
||||||
AuthenticationFailureInterface(this.code, this.message);
|
part 'exceptions_firebase.dart';
|
||||||
|
|
||||||
|
abstract class AuthenticationFailureInterface extends AppException
|
||||||
|
implements Exception {
|
||||||
|
String code;
|
||||||
|
String msg;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get message => msg;
|
||||||
|
|
||||||
|
AuthenticationFailureInterface(this.code, this.msg);
|
||||||
AuthenticationFailureInterface.fromCode(this.code)
|
AuthenticationFailureInterface.fromCode(this.code)
|
||||||
: message = 'An unknown error occurred.';
|
: msg = 'An unknown error occurred.';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// {@template apply_action_code_failure}
|
/// {@template apply_action_code_failure}
|
||||||
@@ -29,7 +37,7 @@ abstract class AuthenticationFailureInterface implements Exception {
|
|||||||
abstract class ApplyActionCodeFailureInterface
|
abstract class ApplyActionCodeFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro apply_action_code_failure}
|
/// {@macro apply_action_code_failure}
|
||||||
ApplyActionCodeFailureInterface(super.code, super.message);
|
ApplyActionCodeFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro apply_action_code_failure}
|
/// {@macro apply_action_code_failure}
|
||||||
ApplyActionCodeFailureInterface.fromCode(super.code) : super.fromCode();
|
ApplyActionCodeFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -41,7 +49,7 @@ abstract class ApplyActionCodeFailureInterface
|
|||||||
abstract class SignUpWithEmailAndPasswordFailureInterface
|
abstract class SignUpWithEmailAndPasswordFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_up_with_email_and_password_failure}
|
/// {@macro sign_up_with_email_and_password_failure}
|
||||||
SignUpWithEmailAndPasswordFailureInterface(super.code, super.message);
|
SignUpWithEmailAndPasswordFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_up_with_email_and_password_failure}
|
/// {@macro sign_up_with_email_and_password_failure}
|
||||||
SignUpWithEmailAndPasswordFailureInterface.fromCode(super.code)
|
SignUpWithEmailAndPasswordFailureInterface.fromCode(super.code)
|
||||||
@@ -54,7 +62,7 @@ abstract class SignUpWithEmailAndPasswordFailureInterface
|
|||||||
abstract class FetchSignInMethodsForEmailFailureInterface
|
abstract class FetchSignInMethodsForEmailFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro fetch_sign_in_methods_failure}
|
/// {@macro fetch_sign_in_methods_failure}
|
||||||
FetchSignInMethodsForEmailFailureInterface(super.code, super.message);
|
FetchSignInMethodsForEmailFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro fetch_sign_in_methods_failure}
|
/// {@macro fetch_sign_in_methods_failure}
|
||||||
FetchSignInMethodsForEmailFailureInterface.fromCode(super.code)
|
FetchSignInMethodsForEmailFailureInterface.fromCode(super.code)
|
||||||
@@ -67,7 +75,7 @@ abstract class FetchSignInMethodsForEmailFailureInterface
|
|||||||
abstract class SignInWithCredentialFailureInterface
|
abstract class SignInWithCredentialFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_in_with_credential_failure}
|
/// {@macro sign_in_with_credential_failure}
|
||||||
SignInWithCredentialFailureInterface(super.code, super.message);
|
SignInWithCredentialFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_in_with_credential_failure}
|
/// {@macro sign_in_with_credential_failure}
|
||||||
SignInWithCredentialFailureInterface.fromCode(super.code) : super.fromCode();
|
SignInWithCredentialFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -79,7 +87,7 @@ abstract class SignInWithCredentialFailureInterface
|
|||||||
abstract class SignInAnonymouslyFailureInterface
|
abstract class SignInAnonymouslyFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_in_anonymously_failure}
|
/// {@macro sign_in_anonymously_failure}
|
||||||
SignInAnonymouslyFailureInterface(super.code, super.message);
|
SignInAnonymouslyFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_in_anonymously_failure}
|
/// {@macro sign_in_anonymously_failure}
|
||||||
SignInAnonymouslyFailureInterface.fromCode(super.code) : super.fromCode();
|
SignInAnonymouslyFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -91,7 +99,7 @@ abstract class SignInAnonymouslyFailureInterface
|
|||||||
abstract class SignInWithGoogleFailureInterface
|
abstract class SignInWithGoogleFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_in_with_google_failure}
|
/// {@macro sign_in_with_google_failure}
|
||||||
SignInWithGoogleFailureInterface(super.code, super.message);
|
SignInWithGoogleFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_in_with_google_failure}
|
/// {@macro sign_in_with_google_failure}
|
||||||
SignInWithGoogleFailureInterface.fromCode(super.code) : super.fromCode();
|
SignInWithGoogleFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -103,7 +111,7 @@ abstract class SignInWithGoogleFailureInterface
|
|||||||
abstract class SignInWithFacebookFailureInterface
|
abstract class SignInWithFacebookFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_in_with_facebook_failure}
|
/// {@macro sign_in_with_facebook_failure}
|
||||||
SignInWithFacebookFailureInterface(super.code, super.message);
|
SignInWithFacebookFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_in_with_facebook_failure}
|
/// {@macro sign_in_with_facebook_failure}
|
||||||
SignInWithFacebookFailureInterface.fromCode(super.code) : super.fromCode();
|
SignInWithFacebookFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -115,7 +123,7 @@ abstract class SignInWithFacebookFailureInterface
|
|||||||
abstract class SignInWithAppleFailureInterface
|
abstract class SignInWithAppleFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_in_with_apple_failure}
|
/// {@macro sign_in_with_apple_failure}
|
||||||
SignInWithAppleFailureInterface(super.code, super.message);
|
SignInWithAppleFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_in_with_apple_failure}
|
/// {@macro sign_in_with_apple_failure}
|
||||||
SignInWithAppleFailureInterface.fromCode(super.code) : super.fromCode();
|
SignInWithAppleFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -127,7 +135,7 @@ abstract class SignInWithAppleFailureInterface
|
|||||||
abstract class SignInWithTwitterFailureInterface
|
abstract class SignInWithTwitterFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_in_with_twitter_failure}
|
/// {@macro sign_in_with_twitter_failure}
|
||||||
SignInWithTwitterFailureInterface(super.code, super.message);
|
SignInWithTwitterFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_in_with_twitter_failure}
|
/// {@macro sign_in_with_twitter_failure}
|
||||||
SignInWithTwitterFailureInterface.fromCode(super.code) : super.fromCode();
|
SignInWithTwitterFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -139,7 +147,7 @@ abstract class SignInWithTwitterFailureInterface
|
|||||||
abstract class SignInWithEmailLinkFailureInterface
|
abstract class SignInWithEmailLinkFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_in_with_email_link_failure}
|
/// {@macro sign_in_with_email_link_failure}
|
||||||
SignInWithEmailLinkFailureInterface(super.code, super.message);
|
SignInWithEmailLinkFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_in_with_email_link_failure}
|
/// {@macro sign_in_with_email_link_failure}
|
||||||
SignInWithEmailLinkFailureInterface.fromCode(super.code) : super.fromCode();
|
SignInWithEmailLinkFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -151,7 +159,7 @@ abstract class SignInWithEmailLinkFailureInterface
|
|||||||
abstract class SignInWithEmailAndPasswordFailureInterface
|
abstract class SignInWithEmailAndPasswordFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_in_with_email_and_password_failure}
|
/// {@macro sign_in_with_email_and_password_failure}
|
||||||
SignInWithEmailAndPasswordFailureInterface(super.code, super.message);
|
SignInWithEmailAndPasswordFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_in_with_email_and_password_failure}
|
/// {@macro sign_in_with_email_and_password_failure}
|
||||||
SignInWithEmailAndPasswordFailureInterface.fromCode(super.code)
|
SignInWithEmailAndPasswordFailureInterface.fromCode(super.code)
|
||||||
@@ -164,7 +172,7 @@ abstract class SignInWithEmailAndPasswordFailureInterface
|
|||||||
abstract class SendEmailVerificationFailureInterface
|
abstract class SendEmailVerificationFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro send_email_verification_failure}
|
/// {@macro send_email_verification_failure}
|
||||||
SendEmailVerificationFailureInterface(super.code, super.message);
|
SendEmailVerificationFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro send_email_verification_failure}
|
/// {@macro send_email_verification_failure}
|
||||||
SendEmailVerificationFailureInterface.fromCode(super.code) : super.fromCode();
|
SendEmailVerificationFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -176,7 +184,7 @@ abstract class SendEmailVerificationFailureInterface
|
|||||||
abstract class SendPasswordResetEmailFailureInterface
|
abstract class SendPasswordResetEmailFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro send_password_reset_email_failure}
|
/// {@macro send_password_reset_email_failure}
|
||||||
SendPasswordResetEmailFailureInterface(super.code, super.message);
|
SendPasswordResetEmailFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro send_password_reset_email_failure}
|
/// {@macro send_password_reset_email_failure}
|
||||||
SendPasswordResetEmailFailureInterface.fromCode(super.code)
|
SendPasswordResetEmailFailureInterface.fromCode(super.code)
|
||||||
@@ -189,7 +197,7 @@ abstract class SendPasswordResetEmailFailureInterface
|
|||||||
abstract class SendSignInLinkEmailFailureInterface
|
abstract class SendSignInLinkEmailFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro send_sign_in_link_email_failure}
|
/// {@macro send_sign_in_link_email_failure}
|
||||||
SendSignInLinkEmailFailureInterface(super.code, super.message);
|
SendSignInLinkEmailFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro send_sign_in_link_email_failure}
|
/// {@macro send_sign_in_link_email_failure}
|
||||||
SendSignInLinkEmailFailureInterface.fromCode(super.code) : super.fromCode();
|
SendSignInLinkEmailFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -201,7 +209,7 @@ abstract class SendSignInLinkEmailFailureInterface
|
|||||||
abstract class ConfirmPasswordResetFailureInterface
|
abstract class ConfirmPasswordResetFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro confirm_password_reset_failure}
|
/// {@macro confirm_password_reset_failure}
|
||||||
ConfirmPasswordResetFailureInterface(super.code, super.message);
|
ConfirmPasswordResetFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro confirm_password_reset_failure}
|
/// {@macro confirm_password_reset_failure}
|
||||||
ConfirmPasswordResetFailureInterface.fromCode(super.code) : super.fromCode();
|
ConfirmPasswordResetFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -213,7 +221,7 @@ abstract class ConfirmPasswordResetFailureInterface
|
|||||||
abstract class VerifyPasswordResetCodeFailureInterface
|
abstract class VerifyPasswordResetCodeFailureInterface
|
||||||
extends AuthenticationFailureInterface {
|
extends AuthenticationFailureInterface {
|
||||||
/// {@macro verify_password_reset_code_failure}
|
/// {@macro verify_password_reset_code_failure}
|
||||||
VerifyPasswordResetCodeFailureInterface(super.code, super.message);
|
VerifyPasswordResetCodeFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro verify_password_reset_code_failure}
|
/// {@macro verify_password_reset_code_failure}
|
||||||
VerifyPasswordResetCodeFailureInterface.fromCode(super.code)
|
VerifyPasswordResetCodeFailureInterface.fromCode(super.code)
|
||||||
@@ -225,7 +233,7 @@ abstract class VerifyPasswordResetCodeFailureInterface
|
|||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
abstract class RefreshFailureInterface extends AuthenticationFailureInterface {
|
abstract class RefreshFailureInterface extends AuthenticationFailureInterface {
|
||||||
/// {@macro refresh_failure}
|
/// {@macro refresh_failure}
|
||||||
RefreshFailureInterface(super.code, super.message);
|
RefreshFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro refresh_failure}
|
/// {@macro refresh_failure}
|
||||||
RefreshFailureInterface.fromCode(super.code) : super.fromCode();
|
RefreshFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
@@ -236,8 +244,15 @@ abstract class RefreshFailureInterface extends AuthenticationFailureInterface {
|
|||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
abstract class SignOutFailureInterface extends AuthenticationFailureInterface {
|
abstract class SignOutFailureInterface extends AuthenticationFailureInterface {
|
||||||
/// {@macro sign_out_failure}
|
/// {@macro sign_out_failure}
|
||||||
SignOutFailureInterface(super.code, super.message);
|
SignOutFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
/// {@macro sign_out_failure}
|
/// {@macro sign_out_failure}
|
||||||
SignOutFailureInterface.fromCode(super.code) : super.fromCode();
|
SignOutFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class GetIdTokenFailureInterface
|
||||||
|
extends AuthenticationFailureInterface {
|
||||||
|
GetIdTokenFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
|
GetIdTokenFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,133 +14,130 @@
|
|||||||
// 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_authentication_bloc/src/core/exceptions/exceptions.dart';
|
part of 'exceptions.dart';
|
||||||
|
|
||||||
class ApplyActionCodeFailureFirebase extends ApplyActionCodeFailureInterface {
|
class ApplyActionCodeFailureFirebase extends ApplyActionCodeFailureInterface {
|
||||||
ApplyActionCodeFailureFirebase([String? code, String? message])
|
ApplyActionCodeFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
ApplyActionCodeFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
ApplyActionCodeFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 'expired-action-code':
|
case 'expired-action-code':
|
||||||
message = 'Action code has expired.';
|
msg = 'Action code has expired.';
|
||||||
break;
|
break;
|
||||||
case 'invalid-action-code':
|
case 'invalid-action-code':
|
||||||
message = 'Action code is invalid.';
|
msg = 'Action code is invalid.';
|
||||||
break;
|
break;
|
||||||
case 'user-disabled':
|
case 'user-disabled':
|
||||||
message =
|
msg = 'This user has been disabled. Please contact support for help.';
|
||||||
'This user has been disabled. Please contact support for help.';
|
|
||||||
break;
|
break;
|
||||||
case 'user-not-found':
|
case 'user-not-found':
|
||||||
message = 'Email is not found, please create an account.';
|
msg = 'Email is not found, please create an account.';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this.code = 'unknown';
|
this.code = 'unknown';
|
||||||
message = 'An unknown error occurred.';
|
msg = 'An unknown error occurred.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignUpWithEmailAndPasswordFailureFirebase
|
class SignUpWithEmailAndPasswordFailureFirebase
|
||||||
extends SignUpWithEmailAndPasswordFailureInterface {
|
extends SignUpWithEmailAndPasswordFailureInterface {
|
||||||
SignUpWithEmailAndPasswordFailureFirebase([String? code, String? message])
|
SignUpWithEmailAndPasswordFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
SignUpWithEmailAndPasswordFailureFirebase.fromCode(String code)
|
SignUpWithEmailAndPasswordFailureFirebase.fromCode(String code)
|
||||||
: super.fromCode(code) {
|
: super.fromCode(code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 'invalid-email':
|
case 'invalid-email':
|
||||||
message = 'The email address is badly formatted.';
|
msg = 'The email address is badly formatted.';
|
||||||
break;
|
break;
|
||||||
case 'user-disabled':
|
case 'user-disabled':
|
||||||
message =
|
msg = 'This user has been disabled. Please contact support for help.';
|
||||||
'This user has been disabled. Please contact support for help.';
|
|
||||||
break;
|
break;
|
||||||
case 'email-already-in-use':
|
case 'email-already-in-use':
|
||||||
message = 'An account already exists for that email.';
|
msg = 'An account already exists for that email.';
|
||||||
break;
|
break;
|
||||||
case 'operation-not-allowed':
|
case 'operation-not-allowed':
|
||||||
message = 'Operation is not allowed. Please contact support.';
|
msg = 'Operation is not allowed. Please contact support.';
|
||||||
break;
|
break;
|
||||||
case 'weak-password':
|
case 'weak-password':
|
||||||
message = 'Please enter a stronger password.';
|
msg = 'Please enter a stronger password.';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.code = 'unknown';
|
this.code = 'unknown';
|
||||||
message = 'An unknown error occurred.';
|
msg = 'An unknown error occurred.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FetchSignInMethodsForEmailFailureFirebase
|
class FetchSignInMethodsForEmailFailureFirebase
|
||||||
extends FetchSignInMethodsForEmailFailureInterface {
|
extends FetchSignInMethodsForEmailFailureInterface {
|
||||||
FetchSignInMethodsForEmailFailureFirebase([String? code, String? message])
|
FetchSignInMethodsForEmailFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
FetchSignInMethodsForEmailFailureFirebase.fromCode(String code)
|
FetchSignInMethodsForEmailFailureFirebase.fromCode(String code)
|
||||||
: super.fromCode(code) {
|
: super.fromCode(code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 'invalid-email':
|
case 'invalid-email':
|
||||||
message = 'The email address is badly formatted.';
|
msg = 'The email address is badly formatted.';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.code = 'unknown';
|
this.code = 'unknown';
|
||||||
message = 'An unknown error occurred.';
|
msg = 'An unknown error occurred.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignInAnonymouslyFailureFirebase
|
class SignInAnonymouslyFailureFirebase
|
||||||
extends SignInAnonymouslyFailureInterface {
|
extends SignInAnonymouslyFailureInterface {
|
||||||
SignInAnonymouslyFailureFirebase([String? code, String? message])
|
SignInAnonymouslyFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
SignInAnonymouslyFailureFirebase.fromCode(String code)
|
SignInAnonymouslyFailureFirebase.fromCode(String code)
|
||||||
: super.fromCode(code) {
|
: super.fromCode(code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 'operation-not-allowed':
|
case 'operation-not-allowed':
|
||||||
message = 'Operation is not allowed. Please contact support.';
|
msg = 'Operation is not allowed. Please contact support.';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.code = 'unknown';
|
this.code = 'unknown';
|
||||||
message = 'An unknown error occurred.';
|
msg = 'An unknown error occurred.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignInWithCredentialFailureFirebase
|
class SignInWithCredentialFailureFirebase
|
||||||
extends SignInWithCredentialFailureInterface {
|
extends SignInWithCredentialFailureInterface {
|
||||||
SignInWithCredentialFailureFirebase([String? code, String? message])
|
SignInWithCredentialFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
SignInWithCredentialFailureFirebase.fromCode(String code)
|
SignInWithCredentialFailureFirebase.fromCode(String code)
|
||||||
: super.fromCode(code) {
|
: super.fromCode(code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 'account-exists-with-different-credential':
|
case 'account-exists-with-different-credential':
|
||||||
message = 'Account exists with different credentials.';
|
msg = 'Account exists with different credentials.';
|
||||||
break;
|
break;
|
||||||
case 'invalid-credential':
|
case 'invalid-credential':
|
||||||
message = 'The credential received is malformed or has expired.';
|
msg = 'The credential received is malformed or has expired.';
|
||||||
break;
|
break;
|
||||||
case 'operation-not-allowed':
|
case 'operation-not-allowed':
|
||||||
message = 'Operation is not allowed. Please contact support.';
|
msg = 'Operation is not allowed. Please contact support.';
|
||||||
break;
|
break;
|
||||||
case 'user-disabled':
|
case 'user-disabled':
|
||||||
message =
|
msg = 'This user has been disabled. Please contact support for help.';
|
||||||
'This user has been disabled. Please contact support for help.';
|
|
||||||
break;
|
break;
|
||||||
case 'user-not-found':
|
case 'user-not-found':
|
||||||
message = 'Email is not found, please create an account.';
|
msg = 'Email is not found, please create an account.';
|
||||||
break;
|
break;
|
||||||
case 'wrong-password':
|
case 'wrong-password':
|
||||||
message = 'Incorrect password, please try again.';
|
msg = 'Incorrect password, please try again.';
|
||||||
break;
|
break;
|
||||||
case 'invalid-verification-code':
|
case 'invalid-verification-code':
|
||||||
message = 'The credential verification code received is invalid.';
|
msg = 'The credential verification code received is invalid.';
|
||||||
break;
|
break;
|
||||||
case 'invalid-verification-id':
|
case 'invalid-verification-id':
|
||||||
message = 'The credential verification ID received is invalid.';
|
msg = 'The credential verification ID received is invalid.';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.code = 'unknown';
|
this.code = 'unknown';
|
||||||
message = 'An unknown error occurred.';
|
msg = 'An unknown error occurred.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,130 +145,135 @@ class SignInWithCredentialFailureFirebase
|
|||||||
class SignInWithGoogleFailureFirebase
|
class SignInWithGoogleFailureFirebase
|
||||||
extends SignInWithCredentialFailureFirebase
|
extends SignInWithCredentialFailureFirebase
|
||||||
implements SignInWithGoogleFailureInterface {
|
implements SignInWithGoogleFailureInterface {
|
||||||
SignInWithGoogleFailureFirebase([super.code, super.message]);
|
SignInWithGoogleFailureFirebase([super.code, super.msg]);
|
||||||
SignInWithGoogleFailureFirebase.fromCode(super.code) : super.fromCode();
|
SignInWithGoogleFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignInWithFacebookFailureFirebase
|
class SignInWithFacebookFailureFirebase
|
||||||
extends SignInWithCredentialFailureFirebase
|
extends SignInWithCredentialFailureFirebase
|
||||||
implements SignInWithFacebookFailureInterface {
|
implements SignInWithFacebookFailureInterface {
|
||||||
SignInWithFacebookFailureFirebase([super.code, super.message]);
|
SignInWithFacebookFailureFirebase([super.code, super.msg]);
|
||||||
SignInWithFacebookFailureFirebase.fromCode(super.code) : super.fromCode();
|
SignInWithFacebookFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignInWithAppleFailureFirebase extends SignInWithCredentialFailureFirebase
|
class SignInWithAppleFailureFirebase extends SignInWithCredentialFailureFirebase
|
||||||
implements SignInWithAppleFailureInterface {
|
implements SignInWithAppleFailureInterface {
|
||||||
SignInWithAppleFailureFirebase([super.code, super.message]);
|
SignInWithAppleFailureFirebase([super.code, super.msg]);
|
||||||
SignInWithAppleFailureFirebase.fromCode(super.code) : super.fromCode();
|
SignInWithAppleFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignInWithTwitterFailureFirebase
|
class SignInWithTwitterFailureFirebase
|
||||||
extends SignInWithCredentialFailureFirebase
|
extends SignInWithCredentialFailureFirebase
|
||||||
implements SignInWithAppleFailureInterface {
|
implements SignInWithAppleFailureInterface {
|
||||||
SignInWithTwitterFailureFirebase([super.code, super.message]);
|
SignInWithTwitterFailureFirebase([super.code, super.msg]);
|
||||||
SignInWithTwitterFailureFirebase.fromCode(super.code) : super.fromCode();
|
SignInWithTwitterFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignInWithEmailLinkFailureFirebase
|
class SignInWithEmailLinkFailureFirebase
|
||||||
extends SignInWithEmailLinkFailureInterface {
|
extends SignInWithEmailLinkFailureInterface {
|
||||||
SignInWithEmailLinkFailureFirebase([String? code, String? message])
|
SignInWithEmailLinkFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
SignInWithEmailLinkFailureFirebase.fromCode(String code)
|
SignInWithEmailLinkFailureFirebase.fromCode(String code)
|
||||||
: super.fromCode(code) {
|
: super.fromCode(code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 'expired-action-code':
|
case 'expired-action-code':
|
||||||
message = 'Action code has expired.';
|
msg = 'Action code has expired.';
|
||||||
break;
|
break;
|
||||||
case 'invalid-email':
|
case 'invalid-email':
|
||||||
message = 'Email is not valid or badly formatted.';
|
msg = 'Email is not valid or badly formatted.';
|
||||||
break;
|
break;
|
||||||
case 'user-disabled':
|
case 'user-disabled':
|
||||||
message =
|
msg = 'This user has been disabled. Please contact support for help.';
|
||||||
'This user has been disabled. Please contact support for help.';
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.code = 'unknown';
|
this.code = 'unknown';
|
||||||
message = 'An unknown error occurred.';
|
msg = 'An unknown error occurred.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignInWithEmailAndPasswordFailureFirebase
|
class SignInWithEmailAndPasswordFailureFirebase
|
||||||
extends SignInWithEmailAndPasswordFailureInterface {
|
extends SignInWithEmailAndPasswordFailureInterface {
|
||||||
SignInWithEmailAndPasswordFailureFirebase([String? code, String? message])
|
SignInWithEmailAndPasswordFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
SignInWithEmailAndPasswordFailureFirebase.fromCode(String code)
|
SignInWithEmailAndPasswordFailureFirebase.fromCode(String code)
|
||||||
: super.fromCode(code) {
|
: super.fromCode(code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 'invalid-email':
|
case 'invalid-email':
|
||||||
message = 'Email is not valid or badly formatted.';
|
msg = 'Email is not valid or badly formatted.';
|
||||||
break;
|
break;
|
||||||
case 'user-disabled':
|
case 'user-disabled':
|
||||||
message =
|
msg = 'This user has been disabled. Please contact support for help.';
|
||||||
'This user has been disabled. Please contact support for help.';
|
|
||||||
break;
|
break;
|
||||||
case 'user-not-found':
|
case 'user-not-found':
|
||||||
message = 'Email is not found, please create an account.';
|
msg = 'Email is not found, please create an account.';
|
||||||
break;
|
break;
|
||||||
case 'wrong-password':
|
case 'wrong-password':
|
||||||
message = 'Incorrect password, please try again.';
|
msg = 'Incorrect password, please try again.';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.code = 'unknown';
|
this.code = 'unknown';
|
||||||
message = 'An unknown error occurred.';
|
msg = 'An unknown error occurred.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SendEmailVerificationFailureFirebase
|
class SendEmailVerificationFailureFirebase
|
||||||
extends SendEmailVerificationFailureInterface {
|
extends SendEmailVerificationFailureInterface {
|
||||||
SendEmailVerificationFailureFirebase([String? code, String? message])
|
SendEmailVerificationFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
|
||||||
SendEmailVerificationFailureFirebase.fromCode(super.code) : super.fromCode();
|
SendEmailVerificationFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SendPasswordResetEmailFailureFirebase
|
class SendPasswordResetEmailFailureFirebase
|
||||||
extends SendPasswordResetEmailFailureInterface {
|
extends SendPasswordResetEmailFailureInterface {
|
||||||
SendPasswordResetEmailFailureFirebase([String? code, String? message])
|
SendPasswordResetEmailFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
SendPasswordResetEmailFailureFirebase.fromCode(super.code) : super.fromCode();
|
SendPasswordResetEmailFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SendSignInLinkEmailFailureFirebase
|
class SendSignInLinkEmailFailureFirebase
|
||||||
extends SendSignInLinkEmailFailureInterface {
|
extends SendSignInLinkEmailFailureInterface {
|
||||||
SendSignInLinkEmailFailureFirebase([String? code, String? message])
|
SendSignInLinkEmailFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
|
||||||
SendSignInLinkEmailFailureFirebase.fromCode(super.code) : super.fromCode();
|
SendSignInLinkEmailFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfirmPasswordResetFailureFirebase
|
class ConfirmPasswordResetFailureFirebase
|
||||||
extends ConfirmPasswordResetFailureInterface {
|
extends ConfirmPasswordResetFailureInterface {
|
||||||
ConfirmPasswordResetFailureFirebase([String? code, String? message])
|
ConfirmPasswordResetFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
|
||||||
ConfirmPasswordResetFailureFirebase.fromCode(super.code) : super.fromCode();
|
ConfirmPasswordResetFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class VerifyPasswordResetCodeFailureFirebase
|
class VerifyPasswordResetCodeFailureFirebase
|
||||||
extends VerifyPasswordResetCodeFailureInterface {
|
extends VerifyPasswordResetCodeFailureInterface {
|
||||||
VerifyPasswordResetCodeFailureFirebase([String? code, String? message])
|
VerifyPasswordResetCodeFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
|
||||||
VerifyPasswordResetCodeFailureFirebase.fromCode(super.code)
|
VerifyPasswordResetCodeFailureFirebase.fromCode(super.code)
|
||||||
: super.fromCode();
|
: super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class RefreshFailureFirebase extends RefreshFailureInterface {
|
class RefreshFailureFirebase extends RefreshFailureInterface {
|
||||||
RefreshFailureFirebase([String? code, String? message])
|
RefreshFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
RefreshFailureFirebase.fromCode(super.code) : super.fromCode();
|
RefreshFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignOutFailureFirebase extends SignOutFailureInterface {
|
class SignOutFailureFirebase extends SignOutFailureInterface {
|
||||||
SignOutFailureFirebase([String? code, String? message])
|
SignOutFailureFirebase([String? code, String? msg])
|
||||||
: super(code ?? 'unknown', message ?? 'An unknown error occurred.');
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
|
||||||
SignOutFailureFirebase.fromCode(super.code) : super.fromCode();
|
SignOutFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GetIdTokenFailureFirebase extends GetIdTokenFailureInterface {
|
||||||
|
GetIdTokenFailureFirebase([String? code, String? msg])
|
||||||
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
|
||||||
|
GetIdTokenFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'cryptography.dart';
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'data_sources/data_sources.dart';
|
||||||
|
export 'models/models.dart';
|
||||||
|
export 'repositories/repositories.dart';
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'local/authentication_cache_data_source_impl.dart';
|
||||||
|
export 'remote/authentication_firebase_data_source_impl.dart';
|
||||||
|
export 'remote/authentication_mock_data_source_impl.dart';
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||||
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
class AuthenticationCacheDataSourceImpl<T extends Object>
|
||||||
|
extends AuthenticationCacheDataSource<T> {
|
||||||
|
Account? _account;
|
||||||
|
T? _data;
|
||||||
|
|
||||||
|
AuthenticationCacheDataSourceImpl();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> storeAccount(Account? account) async {
|
||||||
|
_account = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> storeData(T? data) async {
|
||||||
|
_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> loadAccount() async {
|
||||||
|
if (_account.isNotNull) {
|
||||||
|
return _account!;
|
||||||
|
}
|
||||||
|
throw ClientException('Cached account is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<T> loadData() async {
|
||||||
|
if (_data.isNotNull) {
|
||||||
|
return _data!;
|
||||||
|
}
|
||||||
|
throw ClientException('Cached data is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> destroy() async {
|
||||||
|
_data = null;
|
||||||
|
_account = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<AccountWrapper<T>> load() async {
|
||||||
|
if (_account.isNull) {
|
||||||
|
throw ClientException('Cached account is invalid');
|
||||||
|
}
|
||||||
|
return AccountWrapperModel(_account, _data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||||
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
class AuthenticationFirebaseDataSourceImpl
|
||||||
|
extends AuthenticationRemoteDataSource {
|
||||||
|
final FirebaseAuth _firebaseAuth;
|
||||||
|
|
||||||
|
AuthenticationFirebaseDataSourceImpl({FirebaseAuth? firebaseAuth})
|
||||||
|
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
|
||||||
|
|
||||||
|
Account _mapper(User user) => AccountModel(
|
||||||
|
uid: user.uid,
|
||||||
|
emailVerified: user.emailVerified,
|
||||||
|
isAnonymous: user.isAnonymous,
|
||||||
|
providerId: user.providerData.first.providerId,
|
||||||
|
creationTime: user.metadata.creationTime,
|
||||||
|
lastSignInTime: user.metadata.lastSignInTime,
|
||||||
|
isNewUser: (user.metadata.creationTime != null &&
|
||||||
|
user.metadata.lastSignInTime != null)
|
||||||
|
? user.metadata.lastSignInTime! == user.metadata.creationTime!
|
||||||
|
: null,
|
||||||
|
email: user.email,
|
||||||
|
phoneNumber: user.phoneNumber,
|
||||||
|
photoURL: user.photoURL,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> signInWithEmailAndPassword({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final userCredential = await _firebaseAuth.signInWithEmailAndPassword(
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
|
final user = userCredential.user;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw SignInWithEmailAndPasswordFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
|
||||||
|
/// {@macro signup}
|
||||||
|
Future<Account> signUp({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final userCredential = await _firebaseAuth.createUserWithEmailAndPassword(
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
|
final user = userCredential.user;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw SignUpWithEmailAndPasswordFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> signOut() async {
|
||||||
|
try {
|
||||||
|
await _firebaseAuth.signOut();
|
||||||
|
} catch (_) {
|
||||||
|
throw SignOutFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> getIdentityToken() async {
|
||||||
|
try {
|
||||||
|
final token = await _firebaseAuth.currentUser?.getIdToken();
|
||||||
|
if (token.isNotNull) {
|
||||||
|
return token!;
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw GetIdTokenFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw GetIdTokenFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<Account?> streamAccount() =>
|
||||||
|
_firebaseAuth.userChanges().map<Account?>((user) {
|
||||||
|
final Account? account = (user.isNotNull) ? _mapper(user!) : null;
|
||||||
|
return account;
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> confirmPasswordReset({
|
||||||
|
required String code,
|
||||||
|
required String newPassword,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
await _firebaseAuth.confirmPasswordReset(
|
||||||
|
code: code,
|
||||||
|
newPassword: newPassword,
|
||||||
|
);
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw ConfirmPasswordResetFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw ConfirmPasswordResetFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> sendEmailVerification() async {
|
||||||
|
try {
|
||||||
|
await _firebaseAuth.currentUser!.sendEmailVerification();
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw SendEmailVerificationFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw SendEmailVerificationFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> sendPasswordResetEmail({required String email}) async {
|
||||||
|
try {
|
||||||
|
await _firebaseAuth.sendPasswordResetEmail(email: email);
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw SendPasswordResetEmailFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw SendPasswordResetEmailFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> signInAnonymously() async {
|
||||||
|
try {
|
||||||
|
final userCredential = await _firebaseAuth.signInAnonymously();
|
||||||
|
final user = userCredential.user;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw SignInAnonymouslyFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw SignInAnonymouslyFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> verifyPasswordResetCode({required String code}) async {
|
||||||
|
try {
|
||||||
|
final email = await _firebaseAuth.verifyPasswordResetCode(code);
|
||||||
|
return email.isNotNullOrEmpty;
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw VerifyPasswordResetCodeFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw VerifyPasswordResetCodeFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> refresh() async {
|
||||||
|
try {
|
||||||
|
await _firebaseAuth.currentUser!.reload();
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw RefreshFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw RefreshFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||||
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||||
|
Pair<Account, String>? _connectedMock;
|
||||||
|
Pair<Account, String>? _registeredMock;
|
||||||
|
final StreamController<Account?> _streamAccount = StreamController();
|
||||||
|
|
||||||
|
final List<Pair<Account, String>>? registeredAccounts;
|
||||||
|
final String idToken;
|
||||||
|
|
||||||
|
AuthenticationMockDataSourceImpl({
|
||||||
|
this.idToken = 'fake-id-token',
|
||||||
|
this.registeredAccounts,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> _randomDelay() async {
|
||||||
|
await Future<void>.delayed(
|
||||||
|
Duration(milliseconds: Random().nextInt(400) + 200),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> confirmPasswordReset({
|
||||||
|
required String code,
|
||||||
|
required String newPassword,
|
||||||
|
}) async {
|
||||||
|
await _randomDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> getIdentityToken() async {
|
||||||
|
await _randomDelay();
|
||||||
|
return idToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> refresh() async {
|
||||||
|
await _randomDelay();
|
||||||
|
if (_connectedMock.isNull) {
|
||||||
|
throw RefreshFailureFirebase();
|
||||||
|
}
|
||||||
|
final refresh = DateTime.now();
|
||||||
|
final mock = (_connectedMock?.left as AccountModel?)
|
||||||
|
?.copyWith(lastSignInTime: refresh);
|
||||||
|
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||||
|
_streamAccount.add(mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> sendEmailVerification() async {
|
||||||
|
await _randomDelay();
|
||||||
|
if (_connectedMock.isNotNull) {
|
||||||
|
final refresh = DateTime.now();
|
||||||
|
final mock = (_connectedMock?.left as AccountModel?)?.copyWith(
|
||||||
|
emailVerified: false,
|
||||||
|
lastSignInTime: refresh,
|
||||||
|
);
|
||||||
|
_streamAccount.add(mock);
|
||||||
|
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw SendEmailVerificationFailureFirebase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> sendPasswordResetEmail({required String email}) async {
|
||||||
|
await _randomDelay();
|
||||||
|
if (registeredAccounts.isNotNull) {
|
||||||
|
final accounts =
|
||||||
|
registeredAccounts?.where((pair) => pair.left?.email == email);
|
||||||
|
if (accounts.isNotNullOrEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_registeredMock.isNotNull) {
|
||||||
|
if (_registeredMock?.left?.email != email) {
|
||||||
|
throw SendPasswordResetEmailFailureFirebase();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw SendPasswordResetEmailFailureFirebase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> signInAnonymously() async {
|
||||||
|
await _randomDelay();
|
||||||
|
final creation = DateTime.now();
|
||||||
|
final mock = AccountModel(
|
||||||
|
uid: 'mock-id-anom',
|
||||||
|
emailVerified: false,
|
||||||
|
isAnonymous: true,
|
||||||
|
providerId: 'wyatt',
|
||||||
|
creationTime: creation,
|
||||||
|
lastSignInTime: creation,
|
||||||
|
);
|
||||||
|
_streamAccount.add(mock);
|
||||||
|
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||||
|
return Future.value(mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> signInWithEmailAndPassword({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
await _randomDelay();
|
||||||
|
if (registeredAccounts.isNotNull) {
|
||||||
|
final accounts =
|
||||||
|
registeredAccounts?.where((pair) => pair.left?.email == email);
|
||||||
|
if (accounts.isNotNullOrEmpty) {
|
||||||
|
final account = accounts?.first;
|
||||||
|
if (account?.right != password) {
|
||||||
|
throw SignInWithCredentialFailureFirebase.fromCode('wrong-password');
|
||||||
|
}
|
||||||
|
_streamAccount.add(account!.left);
|
||||||
|
_connectedMock = account.copyWith();
|
||||||
|
return account.left!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_registeredMock.isNotNull) {
|
||||||
|
if (_registeredMock?.left?.email != email) {
|
||||||
|
throw SignInWithCredentialFailureFirebase.fromCode('user-not-found');
|
||||||
|
}
|
||||||
|
if (_registeredMock?.right != password) {
|
||||||
|
throw SignInWithCredentialFailureFirebase.fromCode('wrong-password');
|
||||||
|
}
|
||||||
|
_streamAccount.add(_registeredMock!.left);
|
||||||
|
_connectedMock = _registeredMock!.copyWith();
|
||||||
|
return _registeredMock!.left!;
|
||||||
|
}
|
||||||
|
throw SignInWithCredentialFailureFirebase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> signOut() async {
|
||||||
|
_connectedMock = null;
|
||||||
|
_streamAccount.add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> signUp({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
await _randomDelay();
|
||||||
|
if (registeredAccounts.isNotNull) {
|
||||||
|
final accounts =
|
||||||
|
registeredAccounts?.where((pair) => pair.left?.email == email);
|
||||||
|
if (accounts.isNotNullOrEmpty) {
|
||||||
|
throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(
|
||||||
|
'email-already-in-use',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_registeredMock?.left?.email == email) {
|
||||||
|
throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(
|
||||||
|
'email-already-in-use',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final creation = DateTime.now();
|
||||||
|
final mock = AccountModel(
|
||||||
|
uid: 'mock-id-email',
|
||||||
|
emailVerified: false,
|
||||||
|
isAnonymous: false,
|
||||||
|
providerId: 'wyatt',
|
||||||
|
email: email,
|
||||||
|
creationTime: creation,
|
||||||
|
lastSignInTime: creation,
|
||||||
|
);
|
||||||
|
_streamAccount.add(mock);
|
||||||
|
_registeredMock = Pair(mock, password);
|
||||||
|
return Future.value(mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<Account?> streamAccount() => _streamAccount.stream.asBroadcastStream();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> verifyPasswordResetCode({required String code}) async {
|
||||||
|
await _randomDelay();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
|
||||||
|
|
||||||
|
class AccountModel extends Account {
|
||||||
|
@override
|
||||||
|
final String uid;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String? email;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final DateTime? creationTime;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final bool emailVerified;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final bool isAnonymous;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final bool? isNewUser;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final DateTime? lastSignInTime;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String? phoneNumber;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String? photoURL;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String providerId;
|
||||||
|
|
||||||
|
AccountModel({
|
||||||
|
required this.uid,
|
||||||
|
required this.emailVerified,
|
||||||
|
required this.isAnonymous,
|
||||||
|
required this.providerId,
|
||||||
|
this.lastSignInTime,
|
||||||
|
this.creationTime,
|
||||||
|
this.isNewUser,
|
||||||
|
this.email,
|
||||||
|
this.phoneNumber,
|
||||||
|
this.photoURL,
|
||||||
|
});
|
||||||
|
|
||||||
|
AccountModel copyWith({
|
||||||
|
String? uid,
|
||||||
|
String? email,
|
||||||
|
DateTime? creationTime,
|
||||||
|
bool? emailVerified,
|
||||||
|
bool? isAnonymous,
|
||||||
|
bool? isNewUser,
|
||||||
|
DateTime? lastSignInTime,
|
||||||
|
String? phoneNumber,
|
||||||
|
String? photoURL,
|
||||||
|
String? providerId,
|
||||||
|
}) => AccountModel(
|
||||||
|
uid: uid ?? this.uid,
|
||||||
|
email: email ?? this.email,
|
||||||
|
creationTime: creationTime ?? this.creationTime,
|
||||||
|
emailVerified: emailVerified ?? this.emailVerified,
|
||||||
|
isAnonymous: isAnonymous ?? this.isAnonymous,
|
||||||
|
isNewUser: isNewUser ?? this.isNewUser,
|
||||||
|
lastSignInTime: lastSignInTime ?? this.lastSignInTime,
|
||||||
|
phoneNumber: phoneNumber ?? this.phoneNumber,
|
||||||
|
photoURL: photoURL ?? this.photoURL,
|
||||||
|
providerId: providerId ?? this.providerId,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
// Copyright (C) 2022 WYATT GROUP
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Please see the AUTHORS file for details.
|
// Please see the AUTHORS file for details.
|
||||||
//
|
//
|
||||||
@@ -14,19 +15,22 @@
|
|||||||
// 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_form_bloc/src/enums/validation_error.dart';
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
|
||||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/text_validator.dart';
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
|
||||||
|
|
||||||
class EnumValidator<E> extends TextValidator<ValidationStandardError> {
|
|
||||||
/// {@macro text_string}
|
|
||||||
const EnumValidator.pure() : super.pure();
|
|
||||||
|
|
||||||
/// {@macro text_string}
|
|
||||||
EnumValidator.dirty(E value) : super.dirty(value.toString());
|
|
||||||
|
|
||||||
|
class AccountWrapperModel<T> extends AccountWrapper<T> {
|
||||||
@override
|
@override
|
||||||
ValidationStandardError get onEmpty => ValidationStandardError.empty;
|
final Account? account;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValidationStandardError get onNull => ValidationStandardError.invalid;
|
final T? data;
|
||||||
|
|
||||||
|
AccountWrapperModel(this.account, this.data);
|
||||||
|
|
||||||
|
AccountWrapperModel<T> copyWith({
|
||||||
|
Account? account,
|
||||||
|
T? data,
|
||||||
|
}) => AccountWrapperModel<T>(
|
||||||
|
account ?? this.account,
|
||||||
|
data ?? this.data,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'account_model.dart';
|
||||||
|
export 'account_wrapper_model.dart';
|
||||||
@@ -1,82 +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/>.
|
|
||||||
|
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart' as wyatt;
|
|
||||||
|
|
||||||
class UserFirebase implements wyatt.User {
|
|
||||||
final User? _user;
|
|
||||||
|
|
||||||
const UserFirebase(User user) : _user = user;
|
|
||||||
|
|
||||||
User? get inner => _user;
|
|
||||||
|
|
||||||
@override
|
|
||||||
const UserFirebase.empty() : _user = null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
DateTime? get creationTime => _user?.metadata.creationTime;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get displayName => _user?.displayName;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get email => _user?.email;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get emailVerified => _user?.emailVerified ?? false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get isAnonymous => _user?.isAnonymous ?? false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get isEmpty => _user == null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get isNotEmpty => _user != null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
DateTime? get lastSignInTime => _user?.metadata.lastSignInTime;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get phoneNumber => _user?.phoneNumber;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get photoURL => _user?.photoURL;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get refreshToken => _user?.refreshToken;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uid => _user?.uid ?? '';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get providerId => _user?.providerData.first.providerId;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool? get isNewUser {
|
|
||||||
if (_user?.metadata.lastSignInTime == null ||
|
|
||||||
_user?.metadata.creationTime == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return _user?.metadata.lastSignInTime == _user?.metadata.creationTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
// ignore: lines_longer_than_80_chars
|
|
||||||
String toString() => 'UserFirebase(creationTime: $creationTime, displayName: $displayName, email: $email, emailVerified: $emailVerified, isAnonymous: $isAnonymous, lastSignInTime: $lastSignInTime, phoneNumber: $phoneNumber, photoURL: $photoURL, refreshToken: $refreshToken, uid: $uid)';
|
|
||||||
}
|
|
||||||
@@ -1,338 +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/>.
|
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
|
||||||
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
|
|
||||||
import 'package:google_sign_in/google_sign_in.dart';
|
|
||||||
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
|
|
||||||
import 'package:twitter_login/twitter_login.dart';
|
|
||||||
import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart';
|
|
||||||
import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions_firebase.dart';
|
|
||||||
import 'package:wyatt_authentication_bloc/src/core/extensions/firebase_auth_user_x.dart';
|
|
||||||
import 'package:wyatt_authentication_bloc/src/core/utils/cryptography.dart';
|
|
||||||
import 'package:wyatt_authentication_bloc/src/data/models/user_firebase.dart';
|
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart'
|
|
||||||
as wyatt;
|
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart';
|
|
||||||
|
|
||||||
class AuthenticationRepositoryFirebase implements AuthenticationRepository {
|
|
||||||
final _controller = StreamController<AuthCubitStatus>();
|
|
||||||
final FirebaseAuth _firebaseAuth;
|
|
||||||
final TwitterLogin? _twitterLogin;
|
|
||||||
|
|
||||||
UserFirebase _userCache = const UserFirebase.empty();
|
|
||||||
|
|
||||||
AuthenticationRepositoryFirebase({
|
|
||||||
FirebaseAuth? firebaseAuth,
|
|
||||||
TwitterLogin? twitterLogin,
|
|
||||||
}) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance,
|
|
||||||
_twitterLogin = twitterLogin {
|
|
||||||
_controller.sink.add(AuthCubitStatus.stoped);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<AuthCubitStatus> get cubitStatus =>
|
|
||||||
_controller.stream.asBroadcastStream();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void changeCubitStatus(AuthCubitStatus status) =>
|
|
||||||
_controller.sink.add(status);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<wyatt.User> get user =>
|
|
||||||
_firebaseAuth.userChanges().map((firebaseUser) {
|
|
||||||
final UserFirebase user = (firebaseUser == null)
|
|
||||||
? const UserFirebase.empty()
|
|
||||||
: firebaseUser.model;
|
|
||||||
_userCache = user;
|
|
||||||
return user;
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
wyatt.User get currentUser => _userCache;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> applyActionCode(String code) async {
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.applyActionCode(code);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw ApplyActionCodeFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw ApplyActionCodeFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String?> signUp({
|
|
||||||
required String email,
|
|
||||||
required String password,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
final creds = await _firebaseAuth.createUserWithEmailAndPassword(
|
|
||||||
email: email,
|
|
||||||
password: password,
|
|
||||||
);
|
|
||||||
return creds.user?.uid;
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SignUpWithEmailAndPasswordFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<String>> fetchSignInMethodsForEmail({
|
|
||||||
required String email,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _firebaseAuth.fetchSignInMethodsForEmail(email);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw FetchSignInMethodsForEmailFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw FetchSignInMethodsForEmailFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> signInAnonymously() async {
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.signInAnonymously();
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SignInAnonymouslyFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SignInAnonymouslyFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> signInWithGoogle() async {
|
|
||||||
// Trigger the authentication flow
|
|
||||||
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
|
|
||||||
|
|
||||||
// Obtain the auth details from the request
|
|
||||||
final GoogleSignInAuthentication? googleAuth =
|
|
||||||
await googleUser?.authentication;
|
|
||||||
|
|
||||||
// Create a new credential
|
|
||||||
final credential = GoogleAuthProvider.credential(
|
|
||||||
accessToken: googleAuth?.accessToken,
|
|
||||||
idToken: googleAuth?.idToken,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.signInWithCredential(credential);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SignInWithGoogleFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SignInWithGoogleFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> signInWithFacebook() async {
|
|
||||||
// Trigger the sign-in flow
|
|
||||||
final LoginResult loginResult = await FacebookAuth.instance.login();
|
|
||||||
|
|
||||||
// Create a credential from the access token
|
|
||||||
final OAuthCredential credential =
|
|
||||||
FacebookAuthProvider.credential(loginResult.accessToken?.token ?? '');
|
|
||||||
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.signInWithCredential(credential);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SignInWithFacebookFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SignInWithFacebookFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> signInWithApple() async {
|
|
||||||
// To prevent replay attacks with the credential returned from Apple, we
|
|
||||||
// include a nonce in the credential request. When signing in with
|
|
||||||
// Firebase, the nonce in the id token returned by Apple, is expected to
|
|
||||||
// match the sha256 hash of `rawNonce`.
|
|
||||||
final rawNonce = Cryptography.generateNonce();
|
|
||||||
final nonce = Cryptography.sha256ofString(rawNonce);
|
|
||||||
|
|
||||||
// Request credential for the currently signed in Apple account.
|
|
||||||
final appleCredential = await SignInWithApple.getAppleIDCredential(
|
|
||||||
scopes: [
|
|
||||||
AppleIDAuthorizationScopes.email,
|
|
||||||
AppleIDAuthorizationScopes.fullName,
|
|
||||||
],
|
|
||||||
nonce: nonce,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create an `OAuthCredential` from the credential returned by Apple.
|
|
||||||
final credential = OAuthProvider('apple.com').credential(
|
|
||||||
idToken: appleCredential.identityToken,
|
|
||||||
rawNonce: rawNonce,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sign in the user with Firebase. If the nonce we generated earlier does
|
|
||||||
// not match the nonce in `appleCredential.identityToken`,
|
|
||||||
// sign in will fail.
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.signInWithCredential(credential);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SignInWithAppleFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SignInWithAppleFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> signInWithTwitter() async {
|
|
||||||
final twitterLogin = _twitterLogin;
|
|
||||||
if (twitterLogin == null) {
|
|
||||||
throw SignInWithTwitterFailureFirebase();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger the sign-in flow
|
|
||||||
final authResult = await twitterLogin.login();
|
|
||||||
|
|
||||||
// Create a credential from the access token
|
|
||||||
final credential = TwitterAuthProvider.credential(
|
|
||||||
accessToken: authResult.authToken!,
|
|
||||||
secret: authResult.authTokenSecret!,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.signInWithCredential(credential);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SignInWithCredentialFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SignInWithCredentialFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> signInWithEmailLink(String email, String emailLink) async {
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.signInWithEmailLink(
|
|
||||||
email: email,
|
|
||||||
emailLink: emailLink,
|
|
||||||
);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SignInWithEmailLinkFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SignInWithEmailLinkFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> signInWithEmailAndPassword({
|
|
||||||
required String email,
|
|
||||||
required String password,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.signInWithEmailAndPassword(
|
|
||||||
email: email,
|
|
||||||
password: password,
|
|
||||||
);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SignInWithEmailAndPasswordFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> sendEmailVerification() async {
|
|
||||||
try {
|
|
||||||
await _userCache.inner!.sendEmailVerification();
|
|
||||||
} catch (e) {
|
|
||||||
throw SendEmailVerificationFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> sendPasswordResetEmail({required String email}) async {
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.sendPasswordResetEmail(email: email);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SendPasswordResetEmailFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SendPasswordResetEmailFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> sendSignInLinkEmail({required String email}) async {
|
|
||||||
try {
|
|
||||||
// TODO(hpcl): implement sendSignInLinkEmail
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw SendSignInLinkEmailFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw SendSignInLinkEmailFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> confirmPasswordReset({
|
|
||||||
required String code,
|
|
||||||
required String newPassword,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.confirmPasswordReset(
|
|
||||||
code: code,
|
|
||||||
newPassword: newPassword,
|
|
||||||
);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw ConfirmPasswordResetFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw ConfirmPasswordResetFailureFirebase();
|
|
||||||
}
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> verifyPasswordResetCode({required String code}) async {
|
|
||||||
try {
|
|
||||||
await _firebaseAuth.verifyPasswordResetCode(code);
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw VerifyPasswordResetCodeFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw VerifyPasswordResetCodeFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> signOut() async {
|
|
||||||
try {
|
|
||||||
await Future.wait([
|
|
||||||
_firebaseAuth.signOut(),
|
|
||||||
]);
|
|
||||||
_userCache = const UserFirebase.empty();
|
|
||||||
} catch (_) {
|
|
||||||
throw SignOutFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> refresh() async {
|
|
||||||
try {
|
|
||||||
await _userCache.inner!.reload();
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw RefreshFailureFirebase.fromCode(e.code);
|
|
||||||
} catch (_) {
|
|
||||||
throw RefreshFailureFirebase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package: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/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/entities/account.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_form_bloc/wyatt_form_bloc.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>
|
||||||
|
extends AuthenticationRepository<T> {
|
||||||
|
final AuthenticationCacheDataSource<T> _authenticationLocalDataSource;
|
||||||
|
final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
|
||||||
|
|
||||||
|
late FormRepository _formRepository;
|
||||||
|
|
||||||
|
final OnSignUpSuccess<T>? _onSignUpSuccess;
|
||||||
|
|
||||||
|
final OnAuthChange<T>? _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
|
||||||
|
FutureResult<Account> signInWithEmailAndPassword({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) =>
|
||||||
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
final account =
|
||||||
|
await _authenticationRemoteDataSource.signInWithEmailAndPassword(
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
|
await _authenticationLocalDataSource.storeAccount(account);
|
||||||
|
return account;
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> signOut() =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationRemoteDataSource.signOut();
|
||||||
|
await _authenticationLocalDataSource.destroy();
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<Account> signUp({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) =>
|
||||||
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
final account = await _authenticationRemoteDataSource.signUp(
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
|
await _authenticationLocalDataSource.storeAccount(account);
|
||||||
|
if (_onSignUpSuccess.isNotNull) {
|
||||||
|
final dataResult = await _onSignUpSuccess!.call(
|
||||||
|
account,
|
||||||
|
_formRepository.accessForm(AuthFormName.signUpForm).clone(),
|
||||||
|
);
|
||||||
|
await dataResult.foldAsync(
|
||||||
|
_authenticationLocalDataSource.storeData,
|
||||||
|
(error) async => error,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return account;
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> destroyCache() =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
_authenticationLocalDataSource.destroy,
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<AccountWrapper<T>> getCache() =>
|
||||||
|
Result.tryCatchAsync<AccountWrapper<T>, AppException, AppException>(
|
||||||
|
_authenticationLocalDataSource.load,
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<Account> getAccount() =>
|
||||||
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
|
_authenticationLocalDataSource.loadAccount,
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> setAccount(
|
||||||
|
Account account,
|
||||||
|
) =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationLocalDataSource.storeAccount(account);
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<T> getData() =>
|
||||||
|
Result.tryCatchAsync<T, AppException, AppException>(
|
||||||
|
_authenticationLocalDataSource.loadData,
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> setData(
|
||||||
|
T? data,
|
||||||
|
) =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationLocalDataSource.storeData(data);
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<String> getIdentityToken() =>
|
||||||
|
Result.tryCatchAsync<String, AppException, AppException>(
|
||||||
|
_authenticationRemoteDataSource.getIdentityToken,
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<FutureResult<AccountWrapper<T>>> streamAccount() =>
|
||||||
|
_authenticationRemoteDataSource.streamAccount().map((account) async {
|
||||||
|
if (_onAccountChanges.isNotNull) {
|
||||||
|
final dataResult = await _onAccountChanges!.call(account);
|
||||||
|
return dataResult.map((data) => AccountWrapperModel(account, data));
|
||||||
|
}
|
||||||
|
return Ok<AccountWrapperModel<T>, AppException>(
|
||||||
|
AccountWrapperModel<T>(account, null),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> confirmPasswordReset({
|
||||||
|
required String code,
|
||||||
|
required String newPassword,
|
||||||
|
}) =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationRemoteDataSource.confirmPasswordReset(
|
||||||
|
code: code,
|
||||||
|
newPassword: newPassword,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> sendEmailVerification() =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationRemoteDataSource.sendEmailVerification();
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> sendPasswordResetEmail({required String email}) =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationRemoteDataSource.sendPasswordResetEmail(
|
||||||
|
email: email,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<Account> signInAnonymously() =>
|
||||||
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
final account =
|
||||||
|
await _authenticationRemoteDataSource.signInAnonymously();
|
||||||
|
return account;
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<bool> verifyPasswordResetCode({required String code}) =>
|
||||||
|
Result.tryCatchAsync<bool, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
final response = await _authenticationRemoteDataSource
|
||||||
|
.verifyPasswordResetCode(code: code);
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> refresh() =>
|
||||||
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
await _authenticationRemoteDataSource.refresh();
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'authentication_repository_impl.dart';
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'local/authentication_cache_data_source.dart';
|
||||||
|
export 'remote/authentication_remote_data_source.dart';
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.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>
|
||||||
|
extends BaseLocalDataSource {
|
||||||
|
Future<void> storeAccount(Account? account);
|
||||||
|
Future<void> storeData(T? data);
|
||||||
|
Future<Account> loadAccount();
|
||||||
|
Future<T> loadData();
|
||||||
|
Future<AccountWrapper<T>> load();
|
||||||
|
Future<void> destroy();
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
|
||||||
|
|
||||||
|
abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource {
|
||||||
|
Future<Account> signUp({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<Account> signInWithEmailAndPassword({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> signOut();
|
||||||
|
|
||||||
|
Future<void> refresh();
|
||||||
|
|
||||||
|
Stream<Account?> streamAccount();
|
||||||
|
|
||||||
|
Future<String> getIdentityToken();
|
||||||
|
|
||||||
|
Future<void> sendEmailVerification();
|
||||||
|
|
||||||
|
Future<void> sendPasswordResetEmail({required String email});
|
||||||
|
|
||||||
|
Future<void> confirmPasswordReset({
|
||||||
|
required String code,
|
||||||
|
required String newPassword,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<bool> verifyPasswordResetCode({required String code});
|
||||||
|
|
||||||
|
Future<Account> signInAnonymously();
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'data_sources/data_sources.dart';
|
||||||
|
export 'entities/entities.dart';
|
||||||
|
export 'repositories/repositories.dart';
|
||||||
@@ -14,14 +14,12 @@
|
|||||||
// 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 User {
|
import 'package:equatable/equatable.dart';
|
||||||
/// The empty user constructor.
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
const User.empty();
|
|
||||||
|
|
||||||
/// The users display name.
|
abstract class Account extends Equatable implements Entity {
|
||||||
///
|
/// The user's unique ID.
|
||||||
/// Will be `null` if signing in anonymously or via password authentication.
|
String get uid;
|
||||||
String? get displayName;
|
|
||||||
|
|
||||||
/// The users email address.
|
/// The users email address.
|
||||||
///
|
///
|
||||||
@@ -31,9 +29,6 @@ abstract class User {
|
|||||||
/// Returns whether the users email address has been verified.
|
/// Returns whether the users email address has been verified.
|
||||||
///
|
///
|
||||||
/// To send a verification email, see `SendEmailVerification`.
|
/// To send a verification email, see `SendEmailVerification`.
|
||||||
///
|
|
||||||
/// Once verified, call `reload` to ensure the latest user information is
|
|
||||||
/// retrieved from Firebase.
|
|
||||||
bool get emailVerified;
|
bool get emailVerified;
|
||||||
|
|
||||||
/// Returns whether the user is a anonymous.
|
/// Returns whether the user is a anonymous.
|
||||||
@@ -45,9 +40,6 @@ abstract class User {
|
|||||||
DateTime? get creationTime;
|
DateTime? get creationTime;
|
||||||
|
|
||||||
/// When the user last signed in as dictated by the server clock.
|
/// When the user last signed in as dictated by the server clock.
|
||||||
///
|
|
||||||
/// This is only accurate up to a granularity of 2 minutes for consecutive
|
|
||||||
/// sign-in attempts.
|
|
||||||
DateTime? get lastSignInTime;
|
DateTime? get lastSignInTime;
|
||||||
|
|
||||||
/// Returns the users phone number.
|
/// Returns the users phone number.
|
||||||
@@ -62,24 +54,30 @@ abstract class User {
|
|||||||
/// with a 3rd party OAuth provider (such as Google).
|
/// with a 3rd party OAuth provider (such as Google).
|
||||||
String? get photoURL;
|
String? get photoURL;
|
||||||
|
|
||||||
/// Returns a JWT refresh token for the user.
|
|
||||||
///
|
|
||||||
/// This property maybe `null` or empty if the underlying platform does not
|
|
||||||
/// support providing refresh tokens.
|
|
||||||
String? get refreshToken;
|
|
||||||
|
|
||||||
/// The user's unique ID.
|
|
||||||
String get uid;
|
|
||||||
|
|
||||||
/// The provider ID for the user.
|
/// The provider ID for the user.
|
||||||
String? get providerId;
|
String get providerId;
|
||||||
|
|
||||||
/// Whether the user account has been recently created.
|
/// Whether the user account has been recently created.
|
||||||
bool? get isNewUser;
|
bool? get isNewUser;
|
||||||
|
|
||||||
/// Convenience getter to determine whether the current user is empty.
|
@override
|
||||||
bool get isEmpty;
|
List<Object?> get props => [
|
||||||
|
uid,
|
||||||
|
email,
|
||||||
|
emailVerified,
|
||||||
|
isAnonymous,
|
||||||
|
creationTime,
|
||||||
|
lastSignInTime,
|
||||||
|
phoneNumber,
|
||||||
|
photoURL,
|
||||||
|
providerId,
|
||||||
|
isNewUser,
|
||||||
|
];
|
||||||
|
|
||||||
/// Convenience getter to determine whether the current user is not empty.
|
@override
|
||||||
bool get isNotEmpty;
|
String toString() => 'AccountModel(uid: $uid, email: $email, '
|
||||||
|
'creationTime: $creationTime, emailVerified: $emailVerified, '
|
||||||
|
'isAnonymous: $isAnonymous, isNewUser: $isNewUser, lastSignInTime: '
|
||||||
|
'$lastSignInTime, phoneNumber: $phoneNumber, photoURL: $photoURL, '
|
||||||
|
'providerId: $providerId)';
|
||||||
}
|
}
|
||||||
@@ -14,15 +14,17 @@
|
|||||||
// 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:convert';
|
|
||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:wyatt_form_bloc/src/enums/form_input_status.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
import 'package:wyatt_form_bloc/src/enums/form_status.dart';
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
|
||||||
import 'package:wyatt_form_bloc/src/enums/validation_error.dart';
|
|
||||||
|
|
||||||
part 'form_data.dart';
|
abstract class AccountWrapper<T> extends Equatable implements Entity {
|
||||||
part 'form_input.dart';
|
Account? get account;
|
||||||
part 'form_input_metadata.dart';
|
T? get data;
|
||||||
part 'form_input_validator.dart';
|
|
||||||
part 'form_validator.dart';
|
@override
|
||||||
|
List<Object?> get props => [account, data];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'AccountWrapper($account, data: $data)';
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'account.dart';
|
||||||
|
export 'account_wrapper.dart';
|
||||||
@@ -14,126 +14,101 @@
|
|||||||
// 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_authentication_bloc/src/core/enum/auth_cubit_status.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart';
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart';
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
|
||||||
|
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
/// {@template authentication_repository}
|
abstract class AuthenticationRepository<T> extends BaseRepository {
|
||||||
/// Repository which manages user authentication.
|
FormRepository get formRepository;
|
||||||
/// {@endtemplate}
|
|
||||||
abstract class AuthenticationRepository {
|
|
||||||
/// Stream of [AuthCubitStatus] wich will emit the current cubit status.
|
|
||||||
Stream<AuthCubitStatus> get cubitStatus;
|
|
||||||
|
|
||||||
/// Changes cubit status.(Useful to start or stop the engine.)
|
|
||||||
void changeCubitStatus(AuthCubitStatus status);
|
|
||||||
|
|
||||||
/// Stream of [User] which will emit the current user when
|
|
||||||
/// the authentication state changes.
|
|
||||||
///
|
|
||||||
/// Emits [User.empty] if the user is not authenticated.
|
|
||||||
Stream<User> get user;
|
|
||||||
|
|
||||||
/// Returns the current cached account.
|
|
||||||
/// Defaults to [User.empty] if there is no cached user.
|
|
||||||
User get currentUser;
|
|
||||||
|
|
||||||
/// Applies action code
|
|
||||||
///
|
|
||||||
/// [code] - The action code sent to the user's email address.
|
|
||||||
/// Throw [ApplyActionCodeFailureInterface] if an exception occurs.
|
|
||||||
Future<void> applyActionCode(String code);
|
|
||||||
|
|
||||||
|
/// {@template signup}
|
||||||
/// Creates a new user with the provided [email] and [password].
|
/// Creates a new user with the provided [email] and [password].
|
||||||
///
|
///
|
||||||
/// Returns the newly created user's unique identifier.
|
/// Returns the newly created user's unique identifier.
|
||||||
///
|
///
|
||||||
/// Throws a [SignUpWithEmailAndPasswordFailureInterface] if
|
/// Throws a SignUpWithEmailAndPasswordFailureInterface if
|
||||||
/// an exception occurs.
|
/// an exception occurs.
|
||||||
Future<String?> signUp({required String email, required String password});
|
/// {@endtemplate}
|
||||||
|
FutureResult<Account> signUp({
|
||||||
/// Fetches sign in methods for [email].
|
|
||||||
///
|
|
||||||
/// Throws a [FetchSignInMethodsForEmailFailureInterface] if
|
|
||||||
/// an exception occurs.
|
|
||||||
Future<List<String>> fetchSignInMethodsForEmail({required String email});
|
|
||||||
|
|
||||||
/// Sign in anonimously.
|
|
||||||
///
|
|
||||||
/// Throws a [SignInAnonymouslyFailureInterface] if an exception occurs.
|
|
||||||
Future<void> signInAnonymously();
|
|
||||||
|
|
||||||
/// Starts the Sign In with Google Flow.
|
|
||||||
///
|
|
||||||
/// Throws a [SignInWithGoogleFailureInterface] if an exception occurs.
|
|
||||||
Future<void> signInWithGoogle();
|
|
||||||
|
|
||||||
/// Starts the Sign In with Facebook Flow.
|
|
||||||
///
|
|
||||||
/// Throws a [SignInWithFacebookFailureInterface] if an exception occurs.
|
|
||||||
Future<void> signInWithFacebook();
|
|
||||||
|
|
||||||
/// Starts the Sign In with Apple Flow.
|
|
||||||
///
|
|
||||||
/// Throws a [SignInWithAppleFailureInterface] if an exception occurs.
|
|
||||||
Future<void> signInWithApple();
|
|
||||||
|
|
||||||
/// Starts the Sign In with Twitter Flow.
|
|
||||||
///
|
|
||||||
/// Throws a [SignInWithTwitterFailureInterface] if an exception occurs.
|
|
||||||
Future<void> signInWithTwitter();
|
|
||||||
|
|
||||||
/// Signs in using an email address and email sign-in link.
|
|
||||||
///
|
|
||||||
/// Throws a [SignInWithEmailLinkFailureInterface] if an exception occurs.
|
|
||||||
Future<void> signInWithEmailLink(
|
|
||||||
String email,
|
|
||||||
String emailLink,
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Signs in with the provided [email] and [password].
|
|
||||||
///
|
|
||||||
/// Throws a [SignInWithEmailAndPasswordFailureInterface] if
|
|
||||||
/// an exception occurs.
|
|
||||||
Future<void> signInWithEmailAndPassword({
|
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Sends verification email to the provided [user].
|
/// {@template send_email_verification}
|
||||||
|
/// Sends verification email to the account email.
|
||||||
///
|
///
|
||||||
/// Throws a [SendEmailVerificationFailureInterface] if an exception occurs.
|
/// Throws a SendEmailVerificationFailureInterface if an exception occurs.
|
||||||
Future<void> sendEmailVerification();
|
/// {@endtemplate}
|
||||||
|
FutureResult<void> sendEmailVerification();
|
||||||
|
|
||||||
|
/// {@template send_password_reset_email}
|
||||||
/// Sends a password reset email to the provided [email].
|
/// Sends a password reset email to the provided [email].
|
||||||
///
|
///
|
||||||
/// Throws a [SendPasswordResetEmailFailureInterface] if an exception occurs.
|
/// Throws a SendPasswordResetEmailFailureInterface if an exception occurs.
|
||||||
Future<void> sendPasswordResetEmail({required String email});
|
/// {@endtemplate}
|
||||||
|
FutureResult<void> sendPasswordResetEmail({required String email});
|
||||||
/// Sends link to login.
|
|
||||||
///
|
|
||||||
/// Throws a [SendSignInLinkEmailFailureInterface] if an exception occurs.
|
|
||||||
Future<void> sendSignInLinkEmail({required String email});
|
|
||||||
|
|
||||||
|
/// {@template confirm_password_reset}
|
||||||
/// Confirms the password reset with the provided [newPassword] and [code].
|
/// Confirms the password reset with the provided [newPassword] and [code].
|
||||||
///
|
///
|
||||||
/// Throws a [ConfirmPasswordResetFailureInterface] if an exception occurs.
|
/// Throws a ConfirmPasswordResetFailureInterface if an exception occurs.
|
||||||
Future<void> confirmPasswordReset({
|
/// {@endtemplate}
|
||||||
|
FutureResult<void> confirmPasswordReset({
|
||||||
required String code,
|
required String code,
|
||||||
required String newPassword,
|
required String newPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// {@template verify_password_reset_code}
|
||||||
/// Verify password reset code.
|
/// Verify password reset code.
|
||||||
///
|
///
|
||||||
/// Throws a [VerifyPasswordResetCodeFailureInterface] if an exception occurs.
|
/// Throws a VerifyPasswordResetCodeFailureInterface if an exception occurs.
|
||||||
Future<void> verifyPasswordResetCode({required String code});
|
/// {@endtemplate}
|
||||||
|
FutureResult<bool> verifyPasswordResetCode({required String code});
|
||||||
|
|
||||||
/// Signs out the current user which will emit
|
/// {@template signin_anom}
|
||||||
/// [User.empty] from the [user] Stream.
|
/// Sign in anonymously.
|
||||||
Future<void> signOut();
|
|
||||||
|
|
||||||
/// Refreshes the current user.
|
|
||||||
///
|
///
|
||||||
/// Throws a [RefreshFailureInterface] if an exception occurs.
|
/// Throws a SignInAnonymouslyFailureInterface if an exception occurs.
|
||||||
Future<void> refresh();
|
/// {@endtemplate}
|
||||||
|
FutureResult<Account> signInAnonymously();
|
||||||
|
|
||||||
|
/// {@template signin_pwd}
|
||||||
|
/// Signs in with the provided [email] and [password].
|
||||||
|
///
|
||||||
|
/// Throws a SignInWithEmailAndPasswordFailureInterface if
|
||||||
|
/// an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureResult<Account> signInWithEmailAndPassword({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// {@template signout}
|
||||||
|
/// Signs out the current user.
|
||||||
|
/// It also clears the cache and the associated data.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureResult<void> signOut();
|
||||||
|
|
||||||
|
FutureResult<void> refresh();
|
||||||
|
|
||||||
|
/// {@template stream_account}
|
||||||
|
/// Stream of [AccountWrapper] which will emit the current account when
|
||||||
|
/// the authentication state changes.
|
||||||
|
///
|
||||||
|
/// Emits [AccountWrapper] with null [Account] if the user is not
|
||||||
|
/// authenticated.
|
||||||
|
/// {@endtemplate}
|
||||||
|
Stream<FutureResult<AccountWrapper<T>>> streamAccount();
|
||||||
|
|
||||||
|
FutureResult<String> getIdentityToken();
|
||||||
|
|
||||||
|
FutureResult<Account> getAccount();
|
||||||
|
FutureResult<void> setAccount(Account account);
|
||||||
|
|
||||||
|
FutureResult<T> getData();
|
||||||
|
FutureResult<void> setData(T? data);
|
||||||
|
|
||||||
|
FutureResult<AccountWrapper<T>> getCache();
|
||||||
|
FutureResult<void> destroyCache();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export 'authentication_repository.dart';
|
||||||
@@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
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/src/domain/entities/user.dart';
|
import 'package:wyatt_authentication_bloc/src/core/enums/authentication_status.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/features/authentication/cubit/authentication_cubit.dart';
|
import 'package:wyatt_authentication_bloc/src/features/authentication/cubit/authentication_cubit.dart';
|
||||||
|
|
||||||
class AuthenticationBuilder<Extra> extends StatelessWidget {
|
class AuthenticationBuilder<Extra> extends StatelessWidget {
|
||||||
@@ -29,8 +30,7 @@ class AuthenticationBuilder<Extra> extends StatelessWidget {
|
|||||||
|
|
||||||
final Widget Function(
|
final Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
User user,
|
AccountWrapper<Extra> accountWrapper,
|
||||||
Extra? extra,
|
|
||||||
) authenticated;
|
) authenticated;
|
||||||
final Widget Function(BuildContext context) unauthenticated;
|
final Widget Function(BuildContext context) unauthenticated;
|
||||||
final Widget Function(BuildContext context) unknown;
|
final Widget Function(BuildContext context) unknown;
|
||||||
@@ -40,8 +40,8 @@ class AuthenticationBuilder<Extra> extends StatelessWidget {
|
|||||||
BlocBuilder<AuthenticationCubit<Extra>, AuthenticationState<Extra>>(
|
BlocBuilder<AuthenticationCubit<Extra>, AuthenticationState<Extra>>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state.status == AuthenticationStatus.authenticated) {
|
if (state.status == AuthenticationStatus.authenticated) {
|
||||||
if (state.user != null) {
|
if (state.accountWrapper != null) {
|
||||||
return authenticated(context, state.user!, state.extra);
|
return authenticated(context, state.accountWrapper!);
|
||||||
} else {
|
} else {
|
||||||
return unauthenticated(context);
|
return unauthenticated(context);
|
||||||
}
|
}
|
||||||
|
|||||||