Compare commits
88
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c8ff373a1
|
||
|
|
640cfaf118
|
||
|
|
7fc3736854
|
||
|
|
29d8ec640f
|
||
|
|
7f9621b4f6
|
||
|
|
7b61f3f08a
|
||
|
|
75a5facfdc
|
||
|
|
c93b7fb5f7 | ||
|
|
aee7060a0b
|
||
|
|
4f49f4931c | ||
|
|
e8172004a3 | ||
|
|
c6d8ca37fe | ||
|
|
e01f47d41a | ||
|
|
7a24a36af0 | ||
|
|
244a286509 | ||
|
|
81a7ca5a1f | ||
|
|
45c7bd6fca | ||
|
|
cd2806b07b | ||
|
|
dd275460f6 | ||
|
|
dc0f0c61c6 | ||
|
|
1e305c75bd
|
||
|
|
9af76b8e1f | ||
|
|
5593620181 | ||
|
|
a19d4bc5ce | ||
|
|
21b18054ba | ||
|
|
ff90af47cd | ||
|
|
3bb57e65f8 | ||
|
|
9d0aac7894 | ||
|
|
a561cbff23 | ||
|
|
fafec78546 | ||
|
|
feca378131 | ||
|
|
f223811f4b
|
||
|
|
ed65489316
|
||
|
|
33797e4dbf | ||
|
|
3aa6d03dd6 | ||
|
|
bf03324fd0 | ||
|
|
5e83c9e74e
|
||
|
|
672aba7084
|
||
|
|
94d7efbe8c
|
||
|
|
5298bd99ed
|
||
|
|
d792f4cbe9 | ||
|
|
098ec9715e | ||
|
|
6d3c64d17c | ||
|
|
c615186f19 | ||
|
|
55e24fb23b | ||
|
|
4d04c3f446 | ||
|
|
a20e4a1715 | ||
|
|
cf9f1ddb65 | ||
|
|
0c141c715e | ||
|
|
d0f59bbf29 | ||
|
|
562f84dd33 | ||
|
|
771f600eb7 | ||
|
|
7fcb9e8ac3
|
||
|
|
2a4e29f38c
|
||
|
|
ca70f2eb1d
|
||
|
|
f123e537ae
|
||
|
|
c3315d968c | ||
|
|
45312473d1 | ||
|
|
17e7bce9e6 | ||
|
|
3886ef080e
|
||
|
|
626d951443
|
||
|
|
f36e0b51e0
|
||
|
|
80ce7aff91 | ||
|
|
a9121b6862 | ||
|
|
54f92e8042 | ||
|
|
00393a6ba7 | ||
|
|
136e0e8c98 | ||
|
|
500a6ae51d | ||
|
|
79fdde25fc | ||
|
|
742bf1d614 | ||
|
|
0dbde68d7d | ||
|
|
cd881da072 | ||
|
|
5918a5cf1f | ||
|
|
775d766d14 | ||
|
|
383098b147 | ||
|
|
4d51e2b786 | ||
|
|
32cc1f55d9 | ||
|
|
6ee101bf36 | ||
|
|
f0ed08bd49
|
||
|
|
390fb81b1e
|
||
|
|
279d451cd8
|
||
|
|
a66db23ace
|
||
|
|
3d7af98ac9
|
||
|
|
b033b97917 | ||
|
|
14b7f31b53
|
||
|
|
403bcafe93
|
||
|
|
21ab6f6021
|
||
|
|
198ecac5da
|
+36
@@ -0,0 +1,36 @@
|
|||||||
|
# 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/>.
|
||||||
|
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: quality-check
|
||||||
|
image: git.wyatt-studio.fr/wyatt-foss/flutter-melos:2.9.0
|
||||||
|
commands:
|
||||||
|
- melos run quality-check
|
||||||
|
- melos run publish:validate
|
||||||
|
- name: publish
|
||||||
|
image: git.wyatt-studio.fr/wyatt-foss/flutter-melos:2.9.0
|
||||||
|
commands:
|
||||||
|
- melos run publish:validate
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- master
|
||||||
|
event:
|
||||||
|
- push
|
||||||
+4
-1
@@ -197,4 +197,7 @@ $RECYCLE.BIN/
|
|||||||
.idea/
|
.idea/
|
||||||
*.iml
|
*.iml
|
||||||
google-services.json
|
google-services.json
|
||||||
pubspec_overrides.yaml
|
pubspec_overrides.yaml
|
||||||
|
|
||||||
|
# Mason
|
||||||
|
.mason/
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/compilerla/conventional-pre-commit
|
||||||
|
rev: v2.1.1
|
||||||
|
hooks:
|
||||||
|
- id: conventional-pre-commit
|
||||||
|
stages: [commit-msg]
|
||||||
|
args: [build, ci, docs, feat, fix, perf, refactor, style, test, chore]
|
||||||
+123
@@ -3,6 +3,129 @@
|
|||||||
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-12-12
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_analysis` - `v2.3.0`](#wyatt_analysis---v230)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_analysis` - `v2.3.0`
|
||||||
|
|
||||||
|
- **REFACTOR**: follow melos versioning.
|
||||||
|
- **FIX**: change file include to keep coherence.
|
||||||
|
- **FEAT**: exclude generated code, and add dart>2.16 rules.
|
||||||
|
- **FEAT**: add overwrite protection.
|
||||||
|
- **FEAT**: add 2.2.2 files for archive.
|
||||||
|
- **FEAT**: add utils script to easely bump version.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-12-04
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- [`wyatt_bloc_helper` - `v2.0.0`](#wyatt_bloc_helper---v200)
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_type_utils` - `v0.0.4`](#wyatt_type_utils---v004)
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.4.0+3`](#wyatt_authentication_bloc---v0403)
|
||||||
|
- [`wyatt_crud_bloc` - `v0.1.0+2`](#wyatt_crud_bloc---v0102)
|
||||||
|
- [`wyatt_architecture` - `v0.1.0+1`](#wyatt_architecture---v0101)
|
||||||
|
- [`wyatt_form_bloc` - `v0.2.0+2`](#wyatt_form_bloc---v0202)
|
||||||
|
|
||||||
|
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.4.0+3`
|
||||||
|
- `wyatt_crud_bloc` - `v0.1.0+2`
|
||||||
|
- `wyatt_architecture` - `v0.1.0+1`
|
||||||
|
- `wyatt_form_bloc` - `v0.2.0+2`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_bloc_helper` - `v2.0.0`
|
||||||
|
|
||||||
|
- **BREAKING** **REFACTOR**: update onWrap label (close #46).
|
||||||
|
|
||||||
|
#### `wyatt_type_utils` - `v0.0.4`
|
||||||
|
|
||||||
|
- **FEAT**: add Result extension on FutureOr type (close #40).
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-12-03
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- [`wyatt_architecture` - `v0.1.0`](#wyatt_architecture---v010)
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.4.0+2`](#wyatt_authentication_bloc---v0402)
|
||||||
|
- [`wyatt_crud_bloc` - `v0.1.0+1`](#wyatt_crud_bloc---v0101)
|
||||||
|
- [`wyatt_form_bloc` - `v0.2.0+1`](#wyatt_form_bloc---v0201)
|
||||||
|
|
||||||
|
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.4.0+2`
|
||||||
|
- `wyatt_crud_bloc` - `v0.1.0+1`
|
||||||
|
- `wyatt_form_bloc` - `v0.2.0+1`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_architecture` - `v0.1.0`
|
||||||
|
|
||||||
|
- **REFACTOR**: update naming methodes (close #47).
|
||||||
|
- **REFACTOR**: update example. (close #38).
|
||||||
|
- **FIX**: fix execute method on error handler. (#38).
|
||||||
|
- **FEAT**: update usecase en add & sepcific case. (#38).
|
||||||
|
- **FEAT**: add obsevers for alternative usecase scenarions (#38).
|
||||||
|
- **DOCS**: generate class model. (#38).
|
||||||
|
- **DOCS**: update Readme. (#38).
|
||||||
|
- **BREAKING** **CHORE**: update exports. (#38).
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-16
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.4.0+1`](#wyatt_authentication_bloc---v0401)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_authentication_bloc` - `v0.4.0+1`
|
||||||
|
|
||||||
|
- **FIX**: add sort of mutex on onAuthChanges callback trigger.
|
||||||
|
|
||||||
|
|
||||||
## 2022-11-16
|
## 2022-11-16
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<!--
|
<!--
|
||||||
* Copyright (C) 2022 WYATT GROUP
|
* Copyright (C) 2022 WYATT GROUP
|
||||||
* Please see the AUTHORS file for details.
|
* Please see the AUTHORS file for details.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* any later version.
|
* any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
@@ -51,39 +51,54 @@ and open source.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Development
|
## Contribution
|
||||||
|
|
||||||
Clone this repo.
|
Clone this repo.
|
||||||
|
|
||||||
You have to install [melos](https://github.com/invertase/melos).
|
```shell
|
||||||
|
git clone ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-packages.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prerequisite
|
||||||
|
|
||||||
|
- [Flutter](https://github.com/flutter/flutter).
|
||||||
|
|
||||||
|
- [Melos](https://github.com/invertase/melos). Used to manage Dart projects with multiple packages.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
dart pub global activate melos
|
dart pub global activate melos
|
||||||
```
|
```
|
||||||
|
|
||||||
Then bootstrap with `melos bs`.
|
- [Mason](https://github.com/felangel/mason). Used for code generation.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
dart pub global activate mason_cli
|
||||||
|
```
|
||||||
|
|
||||||
|
- [Lcov](https://github.com/linux-test-project/lcov). Used to generate coverage data.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# on macos
|
||||||
|
brew install lcov
|
||||||
|
```
|
||||||
|
|
||||||
|
- genhtml. Used to convert coverage data into html pages.
|
||||||
|
|
||||||
|
After installing all these packages, bootstrap with `melos bs`.
|
||||||
|
|
||||||
### Create a new package
|
### Create a new package
|
||||||
|
|
||||||
Create a new package in `packages/` folder.
|
Create a new package in `packages/` folder.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
dart create -t package-simple wyatt_<name>
|
mason make wyatt_package --package_name wyatt_<name> --description A new Wyatt package --flutter_only false
|
||||||
```
|
|
||||||
|
|
||||||
Remove any `example/` subfolder. Then create a new sample project.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
flutter create --platforms android --project-name <name>_example example
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Then bootstrap project with `melos bs` command.
|
Then bootstrap project with `melos bs` command.
|
||||||
|
|
||||||
### Convention
|
|
||||||
|
|
||||||
#### Naming
|
#### Naming
|
||||||
|
|
||||||
In the previous instructions `<name>` variable is important.
|
In the previous instructions `<name>` variable is important.
|
||||||
It have to be clear and intelligible.
|
It have to be clear and intelligible.
|
||||||
|
|
||||||
You **MUST** use underscores.
|
You **MUST** use underscores.
|
||||||
@@ -93,15 +108,44 @@ You **MUST** use `wyatt` prefix for package.
|
|||||||
You **MUST** name example with specific name.
|
You **MUST** name example with specific name.
|
||||||
|
|
||||||
For example, if name is CRUD BLOC
|
For example, if name is CRUD BLOC
|
||||||
|
|
||||||
- name will be crud_bloc
|
- name will be crud_bloc
|
||||||
- so the package will be: `wyatt_crud_bloc`
|
- so the package will be: `wyatt_crud_bloc`
|
||||||
- and the example will be: `crud_bloc_example`
|
- and the example will be: `crud_bloc_example`
|
||||||
|
|
||||||
#### Commits
|
### Create issues
|
||||||
|
|
||||||
|
Add the issues directly related to what you want to develop and label them correctly.
|
||||||
|
|
||||||
|
```
|
||||||
|
Type(scope): issue.
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, on notification bloc package :
|
||||||
|
|
||||||
|
- `Feature(notification_bloc): add firebase messaging data source.`
|
||||||
|
- `Test(notification_bloc): add test for pushwoosh datasource.`
|
||||||
|
|
||||||
|
### Branches
|
||||||
|
|
||||||
|
Master is protected. You can't push on it. Please develop your feature on another branch. The name of your branch has to match with the issue opened.
|
||||||
|
|
||||||
|
`type(scope):issue`
|
||||||
|
|
||||||
|
Example :
|
||||||
|
Issue :
|
||||||
|
|
||||||
|
- `Feature(notification_bloc): add firebase messaging data source.`
|
||||||
|
|
||||||
|
Branch related to this issue :
|
||||||
|
|
||||||
|
- `feature(notification_bloc)/add_firebase_messaging_data_source`
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
tl;dr : `type(scope): description`.
|
tl;dr : `type(scope): description #issue`.
|
||||||
Here allowed <type> values:
|
Here allowed <type> values:
|
||||||
|
|
||||||
- **feat** for a new feature for the user, not a new feature for build script. Such commit will trigger a release bumping a MINOR version.
|
- **feat** for a new feature for the user, not a new feature for build script. Such commit will trigger a release bumping a MINOR version.
|
||||||
@@ -115,11 +159,74 @@ Here allowed <type> values:
|
|||||||
|
|
||||||
Some examples :
|
Some examples :
|
||||||
|
|
||||||
- `feat(auth): add AWS support.` = add a feature in authentication_bloc package.
|
- `feat(auth): add AWS support. (#31)` = add a feature in authentication_bloc package, linked to the 31st issue.
|
||||||
- `docs: update readme.` = update **this** readme file.
|
- `docs: update readme.` = update **this** readme file.
|
||||||
- `fix(crud)!: fix bug in awesome() function.` = fix a bug, `!` is important and indicate `BREAKING CHANGES`.
|
- `fix(crud)!: fix bug in awesome() function. (#32)` = fix a bug, `!` is important and indicate `BREAKING CHANGES` linked with the 32nd issue.
|
||||||
|
|
||||||
Conventional commits are important for `melos version` command !
|
When you have finished developing, and are ready to close the issue, close it via your commit :
|
||||||
|
|
||||||
|
`feat(auth): add AWS support. (close #31)`
|
||||||
|
|
||||||
|
Note that your issue will be close after merging on master.
|
||||||
|
Before closing the issue, please check tests and update coverage. You might run :
|
||||||
|
|
||||||
|
```shell
|
||||||
|
melos run test:all # this will run all tests in this project
|
||||||
|
melos run gen-coverage # this will generate coverage report
|
||||||
|
melos run gen-class-models # this will generate plantuml class diagrams
|
||||||
|
melos run quality-check # this will run all targets generally expected in CI
|
||||||
|
melos run publish:validate # this will run a validation before publish packages
|
||||||
|
melos run publish # this will publish packages
|
||||||
|
```
|
||||||
|
|
||||||
|
> Note that only modified package will be verified and published.
|
||||||
|
|
||||||
|
#### Merge your work
|
||||||
|
|
||||||
|
After closing your issue, some work may have been done on master in the meantime. To keep a clean git history, please rebase before opening a change request.
|
||||||
|
|
||||||
|
Two situations :
|
||||||
|
|
||||||
|
- You have not yet created your branch and have committed locally :
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git pull --rebase
|
||||||
|
```
|
||||||
|
|
||||||
|
- You are already working on your branch :
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git rebase -i master
|
||||||
|
```
|
||||||
|
|
||||||
|
If possible, please use `--fixup` on your commit in interactive rebase.
|
||||||
|
|
||||||
|
Then, opend your PR, get the necessary approval and merge your work. Then you're done ✅.
|
||||||
|
|
||||||
|
#### Update version.
|
||||||
|
|
||||||
|
Once your work is on the master, you can update your package version. Please filter packages to update only your package. `--scope` is used to do it.
|
||||||
|
For example, after merging changes on `wyatt_otification_bloc` package, you might run :
|
||||||
|
|
||||||
|
```shell
|
||||||
|
melos version --scope="*wyatt_notification_bloc*"
|
||||||
|
```
|
||||||
|
|
||||||
|
In fact, melos will filter all packages that match the `wyatt_notification_block` pattern.
|
||||||
|
|
||||||
|
You can update check all packages tests by running :
|
||||||
|
|
||||||
|
```shell
|
||||||
|
melos run test
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Publish your package
|
||||||
|
|
||||||
|
If package is ready for procution, publish it runnig :
|
||||||
|
|
||||||
|
```shell
|
||||||
|
melos publish --scope"*package*"
|
||||||
|
```
|
||||||
|
|
||||||
#### Badging
|
#### Badging
|
||||||
|
|
||||||
@@ -130,7 +237,8 @@ In the package `readme.md` file, please specify the supported SDK:
|
|||||||
```markdown
|
```markdown
|
||||||

|

|
||||||
```
|
```
|
||||||
or
|
|
||||||
|
or
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -161,4 +269,10 @@ Here you can change `package name` and `package version`.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
This repository is maintained by Wyatt Studio but work is in progress.
|
This repository is maintained by Wyatt Studio but work is in progress.
|
||||||
|
|
||||||
|
## Simple work flow diagramm
|
||||||
|
|
||||||
|
To sum up, here a simple work flow diagramm.
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
escapedPath="$(echo `pwd` | sed 's/\//\\\//g')"
|
||||||
|
|
||||||
|
if grep flutter pubspec.yaml > /dev/null; then
|
||||||
|
if [ -d "coverage" ]; then
|
||||||
|
# combine line coverage info from package tests to a common file
|
||||||
|
if [ ! -d "$MELOS_ROOT_PATH/coverage" ]; then
|
||||||
|
mkdir "$MELOS_ROOT_PATH/coverage"
|
||||||
|
fi
|
||||||
|
sed "s/^SF:lib/SF:$escapedPath\/lib/g" coverage/lcov.info >> "$MELOS_ROOT_PATH/coverage/lcov.info"
|
||||||
|
rm -rf "coverage"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
@startuml Simple Developpment Workflow
|
||||||
|
start
|
||||||
|
:Create an issue;
|
||||||
|
:Create branch related to the issue;
|
||||||
|
repeat :Commit related to the issue;
|
||||||
|
repeat while (feature is done)
|
||||||
|
:Update coverage;
|
||||||
|
:Close issue via last commit;
|
||||||
|
:Rebase from `master`;
|
||||||
|
:Create pull request;
|
||||||
|
:Merge branches;
|
||||||
|
:Update version;
|
||||||
|
:Publish package;
|
||||||
|
stop
|
||||||
|
@enduml
|
||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1 @@
|
|||||||
|
{"bricks":{"wyatt_clean_code":{"git":{"url":"ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git","path":"bricks/wyatt_clean_code","ref":"033baa65408ec6b68e6a2ef43e64c24708ef16a1"}},"wyatt_feature_brick":{"git":{"url":"ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git","path":"bricks/wyatt_feature_brick","ref":"033baa65408ec6b68e6a2ef43e64c24708ef16a1"}},"wyatt_package":{"git":{"url":"ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git","path":"bricks/wyatt_package","ref":"033baa65408ec6b68e6a2ef43e64c24708ef16a1"}}}}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
bricks:
|
||||||
|
wyatt_clean_code:
|
||||||
|
git:
|
||||||
|
url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git
|
||||||
|
path: bricks/wyatt_clean_code
|
||||||
|
wyatt_feature_brick:
|
||||||
|
git:
|
||||||
|
url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git
|
||||||
|
path: bricks/wyatt_feature_brick
|
||||||
|
wyatt_package:
|
||||||
|
git:
|
||||||
|
url: ssh://git@git.wyatt-studio.fr:993/Wyatt-FOSS/wyatt-bricks.git
|
||||||
|
path: bricks/wyatt_package
|
||||||
+35
-2
@@ -21,8 +21,7 @@ scripts:
|
|||||||
|
|
||||||
analyze:
|
analyze:
|
||||||
run: |
|
run: |
|
||||||
melos exec -c 10 -- \
|
melos exec -c 1 -- flutter analyze --fatal-infos
|
||||||
flutter analyze --fatal-infos
|
|
||||||
description: Run `flutter analyze` for all packages.
|
description: Run `flutter analyze` for all packages.
|
||||||
|
|
||||||
format:
|
format:
|
||||||
@@ -36,6 +35,40 @@ scripts:
|
|||||||
clean:deep:
|
clean:deep:
|
||||||
run: git clean -x -d -f -q
|
run: git clean -x -d -f -q
|
||||||
description: Clean things very deeply with `git clean`.
|
description: Clean things very deeply with `git clean`.
|
||||||
|
|
||||||
|
test:selective_unit_test:
|
||||||
|
run: melos exec -- flutter test --no-pub --coverage
|
||||||
|
description: Run Flutter tests for a specific package in this project.
|
||||||
|
select-package:
|
||||||
|
dir-exists:
|
||||||
|
- test
|
||||||
|
ignore:
|
||||||
|
- '*example*'
|
||||||
|
|
||||||
|
test:all:
|
||||||
|
run: melos run test:selective_unit_test --no-select
|
||||||
|
description: Run all Flutter tests in this project.
|
||||||
|
|
||||||
|
gen-coverage: melos exec -- sh "\$MELOS_ROOT_PATH/combine_coverage.sh" && genhtml coverage/lcov.info -o coverage/html
|
||||||
|
|
||||||
|
gen-class-models:
|
||||||
|
run: melos exec -- dart pub global run dcdg -o models/class-models.puml
|
||||||
|
select-package:
|
||||||
|
ignore:
|
||||||
|
- '*example*'
|
||||||
|
|
||||||
|
quality-check:
|
||||||
|
run: |
|
||||||
|
melos clean && \
|
||||||
|
melos bootstrap && \
|
||||||
|
melos run test:all
|
||||||
|
description: Run all targets generally expected in CI for a full local quality check.
|
||||||
|
|
||||||
|
publish:validate:
|
||||||
|
run: melos publish --diff="origin/$DRONE_COMMIT_BRANCH...HEAD" --yes
|
||||||
|
|
||||||
|
# publish:
|
||||||
|
# run: melos publish --diff="origin/$DRONE_COMMIT_BRANCH...HEAD" --no-dry-run --yes
|
||||||
|
|
||||||
# Additional cleanup lifecycle script, executed when `melos clean` is run.
|
# Additional cleanup lifecycle script, executed when `melos clean` is run.
|
||||||
postclean: >
|
postclean: >
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
## 2.3.0
|
||||||
|
|
||||||
|
- **REFACTOR**: follow melos versioning.
|
||||||
|
- **FIX**: change file include to keep coherence.
|
||||||
|
- **FEAT**: exclude generated code, and add dart>2.16 rules.
|
||||||
|
- **FEAT**: add overwrite protection.
|
||||||
|
- **FEAT**: add 2.2.2 files for archive.
|
||||||
|
- **FEAT**: add utils script to easely bump version.
|
||||||
|
|
||||||
## 2.2.2
|
## 2.2.2
|
||||||
|
|
||||||
- **DOCS**: add publish_to self hosted pub server.
|
- **DOCS**: add publish_to self hosted pub server.
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
This package provides lint rules for Dart and Flutter which are used at [Wyatt](https://wyattapp.io) and [Wyatt Studio](https://wyatt-studio.fr). For more information, see the complete list of options in **lib/analysis_options.2.0.0.yaml**.
|
This package provides lint rules for Dart and Flutter which are used at [Wyatt](https://wyattapp.io) and [Wyatt Studio](https://wyatt-studio.fr). For more information, see the complete list of options in **lib/analysis_options.2.3.0.yaml**.
|
||||||
|
|
||||||
**Note**: This package was heavily inspired by [pedantic](https://github.com/dart-lang/pedantic), [Very Good Analysis](https://github.com/VeryGoodOpenSource/very_good_analysis) and the official [flutter_lints](https://pub.dev/packages/flutter_lints).
|
**Note**: This package was heavily inspired by [pedantic](https://github.com/dart-lang/pedantic), [Very Good Analysis](https://github.com/VeryGoodOpenSource/very_good_analysis) and the official [flutter_lints](https://pub.dev/packages/flutter_lints).
|
||||||
|
|
||||||
@@ -29,12 +29,9 @@ This package provides lint rules for Dart and Flutter which are used at [Wyatt](
|
|||||||
To use the lints, add a dependency in your `pubspec.yaml`:
|
To use the lints, add a dependency in your `pubspec.yaml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dev_dependencies:
|
wyatt_analysis:
|
||||||
wyatt_analysis:
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
git:
|
version: 2.3.0
|
||||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
|
||||||
ref: wyatt_analysis-v2.0.0
|
|
||||||
path: packages/wyatt_analysis
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, add an include in `analysis_options.yaml`:
|
Then, add an include in `analysis_options.yaml`:
|
||||||
@@ -52,13 +49,13 @@ include: package:wyatt_analysis/analysis_options.flutter.yaml
|
|||||||
If you wish to restrict the lint version, specify a version of `analysis_options.yaml` instead:
|
If you wish to restrict the lint version, specify a version of `analysis_options.yaml` instead:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
include: package:wyatt_analysis/analysis_options.flutter.2.0.0.yaml
|
include: package:wyatt_analysis/analysis_options.flutter.2.3.0.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
If you just want **Dart** version:
|
If you just want **Dart** version:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
include: package:wyatt_analysis/analysis_options.2.0.0.yaml
|
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Suppressing Lints
|
## Suppressing Lints
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
# 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/>.
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
language:
|
||||||
|
strict-casts: true
|
||||||
|
strict-inference: true
|
||||||
|
strict-raw-types: true
|
||||||
|
|
||||||
|
errors:
|
||||||
|
todo: ignore
|
||||||
|
close_sinks: ignore
|
||||||
|
missing_required_param: error
|
||||||
|
missing_return: error
|
||||||
|
|
||||||
|
exclude:
|
||||||
|
- example/**
|
||||||
|
- lib/l10n/**
|
||||||
|
- lib/generated/**
|
||||||
|
- lib/generated_plugin_registrant.dart
|
||||||
|
- test/.test_coverage.dart
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
- always_declare_return_types
|
||||||
|
- always_require_non_null_named_parameters
|
||||||
|
- always_put_control_body_on_new_line
|
||||||
|
- always_put_required_named_parameters_first
|
||||||
|
- always_use_package_imports
|
||||||
|
- annotate_overrides
|
||||||
|
- avoid_bool_literals_in_conditional_expressions
|
||||||
|
- avoid_catching_errors
|
||||||
|
- avoid_double_and_int_checks
|
||||||
|
- avoid_dynamic_calls
|
||||||
|
- avoid_empty_else
|
||||||
|
- avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
- avoid_escaping_inner_quotes
|
||||||
|
- avoid_field_initializers_in_const_classes
|
||||||
|
- avoid_function_literals_in_foreach_calls
|
||||||
|
- avoid_init_to_null
|
||||||
|
- avoid_js_rounded_ints
|
||||||
|
- avoid_null_checks_in_equality_operators
|
||||||
|
- avoid_positional_boolean_parameters
|
||||||
|
- avoid_private_typedef_functions
|
||||||
|
- avoid_redundant_argument_values
|
||||||
|
- avoid_relative_lib_imports
|
||||||
|
- avoid_renaming_method_parameters
|
||||||
|
- avoid_return_types_on_setters
|
||||||
|
- avoid_returning_null
|
||||||
|
- avoid_returning_null_for_future
|
||||||
|
- avoid_returning_null_for_void
|
||||||
|
- avoid_returning_this
|
||||||
|
- avoid_setters_without_getters
|
||||||
|
- avoid_shadowing_type_parameters
|
||||||
|
- avoid_single_cascade_in_expression_statements
|
||||||
|
- avoid_slow_async_io
|
||||||
|
- avoid_type_to_string
|
||||||
|
- avoid_types_as_parameter_names
|
||||||
|
- avoid_types_on_closure_parameters
|
||||||
|
- avoid_unused_constructor_parameters
|
||||||
|
- avoid_void_async
|
||||||
|
- await_only_futures
|
||||||
|
- camel_case_extensions
|
||||||
|
- camel_case_types
|
||||||
|
- cancel_subscriptions
|
||||||
|
- cascade_invocations
|
||||||
|
- cast_nullable_to_non_nullable
|
||||||
|
- comment_references
|
||||||
|
- conditional_uri_does_not_exist
|
||||||
|
- constant_identifier_names
|
||||||
|
- control_flow_in_finally
|
||||||
|
- curly_braces_in_flow_control_structures
|
||||||
|
- depend_on_referenced_packages
|
||||||
|
- deprecated_consistency
|
||||||
|
- directives_ordering
|
||||||
|
- empty_catches
|
||||||
|
- empty_constructor_bodies
|
||||||
|
- empty_statements
|
||||||
|
- eol_at_end_of_file
|
||||||
|
- exhaustive_cases
|
||||||
|
- file_names
|
||||||
|
- flutter_style_todos
|
||||||
|
- hash_and_equals
|
||||||
|
- implementation_imports
|
||||||
|
- iterable_contains_unrelated_type
|
||||||
|
- join_return_with_assignment
|
||||||
|
- leading_newlines_in_multiline_strings
|
||||||
|
- library_names
|
||||||
|
- library_prefixes
|
||||||
|
- library_private_types_in_public_api
|
||||||
|
- lines_longer_than_80_chars
|
||||||
|
- list_remove_unrelated_type
|
||||||
|
- literal_only_boolean_expressions
|
||||||
|
- missing_whitespace_between_adjacent_strings
|
||||||
|
- no_adjacent_strings_in_list
|
||||||
|
- no_default_cases
|
||||||
|
- no_duplicate_case_values
|
||||||
|
- no_leading_underscores_for_local_identifiers
|
||||||
|
- no_runtimeType_toString
|
||||||
|
- non_constant_identifier_names
|
||||||
|
- noop_primitive_operations
|
||||||
|
- null_check_on_nullable_type_parameter
|
||||||
|
- null_closures
|
||||||
|
- one_member_abstracts
|
||||||
|
- only_throw_errors
|
||||||
|
- overridden_fields
|
||||||
|
- package_api_docs
|
||||||
|
- package_names
|
||||||
|
- package_prefixed_library_names
|
||||||
|
- parameter_assignments
|
||||||
|
- prefer_adjacent_string_concatenation
|
||||||
|
- prefer_asserts_in_initializer_lists
|
||||||
|
- prefer_asserts_with_message
|
||||||
|
- prefer_collection_literals
|
||||||
|
- prefer_conditional_assignment
|
||||||
|
- prefer_const_constructors
|
||||||
|
- prefer_const_constructors_in_immutables
|
||||||
|
- prefer_const_declarations
|
||||||
|
- prefer_const_literals_to_create_immutables
|
||||||
|
- prefer_constructors_over_static_methods
|
||||||
|
- prefer_contains
|
||||||
|
- prefer_equal_for_default_values
|
||||||
|
- prefer_expression_function_bodies
|
||||||
|
- prefer_final_fields
|
||||||
|
- prefer_final_in_for_each
|
||||||
|
- prefer_final_locals
|
||||||
|
- prefer_for_elements_to_map_fromIterable
|
||||||
|
- prefer_function_declarations_over_variables
|
||||||
|
- prefer_generic_function_type_aliases
|
||||||
|
- prefer_if_elements_to_conditional_expressions
|
||||||
|
- prefer_if_null_operators
|
||||||
|
- prefer_initializing_formals
|
||||||
|
- prefer_inlined_adds
|
||||||
|
- prefer_int_literals
|
||||||
|
- prefer_interpolation_to_compose_strings
|
||||||
|
- prefer_is_empty
|
||||||
|
- prefer_is_not_empty
|
||||||
|
- prefer_is_not_operator
|
||||||
|
- prefer_iterable_whereType
|
||||||
|
- prefer_mixin
|
||||||
|
- prefer_null_aware_operators
|
||||||
|
- prefer_null_aware_method_calls
|
||||||
|
- prefer_single_quotes
|
||||||
|
- prefer_spread_collections
|
||||||
|
- prefer_typing_uninitialized_variables
|
||||||
|
- prefer_void_to_null
|
||||||
|
- provide_deprecation_message
|
||||||
|
- recursive_getters
|
||||||
|
- require_trailing_commas
|
||||||
|
- slash_for_doc_comments
|
||||||
|
- sort_unnamed_constructors_first
|
||||||
|
- test_types_in_equals
|
||||||
|
- throw_in_finally
|
||||||
|
- tighten_type_of_initializing_formals
|
||||||
|
- type_annotate_public_apis
|
||||||
|
- type_init_formals
|
||||||
|
- unawaited_futures
|
||||||
|
- unnecessary_await_in_return
|
||||||
|
- unnecessary_brace_in_string_interps
|
||||||
|
- unnecessary_const
|
||||||
|
- unnecessary_constructor_name
|
||||||
|
- unnecessary_getters_setters
|
||||||
|
- unnecessary_lambdas
|
||||||
|
- unnecessary_late
|
||||||
|
- unnecessary_new
|
||||||
|
- unnecessary_null_aware_assignments
|
||||||
|
- unnecessary_null_checks
|
||||||
|
- unnecessary_null_in_if_null_operators
|
||||||
|
- unnecessary_nullable_for_final_variable_declarations
|
||||||
|
- unnecessary_overrides
|
||||||
|
- unnecessary_parenthesis
|
||||||
|
- unnecessary_raw_strings
|
||||||
|
- unnecessary_statements
|
||||||
|
- unnecessary_string_escapes
|
||||||
|
- unnecessary_string_interpolations
|
||||||
|
- unnecessary_this
|
||||||
|
- unrelated_type_equality_checks
|
||||||
|
- unsafe_html
|
||||||
|
- use_enums
|
||||||
|
- use_function_type_syntax_for_parameters
|
||||||
|
- use_if_null_to_convert_nulls_to_bools
|
||||||
|
- use_is_even_rather_than_modulo
|
||||||
|
- use_late_for_private_fields_and_variables
|
||||||
|
- use_named_constants
|
||||||
|
- use_raw_strings
|
||||||
|
- use_rethrow_when_possible
|
||||||
|
- use_setters_to_change_properties
|
||||||
|
- use_string_buffers
|
||||||
|
- use_super_parameters
|
||||||
|
- use_test_throws_matchers
|
||||||
|
- use_to_and_as_if_applicable
|
||||||
|
- valid_regexps
|
||||||
|
- void_checks
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
# 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/>.
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
language:
|
||||||
|
strict-casts: true
|
||||||
|
strict-inference: true
|
||||||
|
strict-raw-types: true
|
||||||
|
|
||||||
|
errors:
|
||||||
|
todo: info
|
||||||
|
close_sinks: ignore
|
||||||
|
missing_required_param: error
|
||||||
|
missing_return: error
|
||||||
|
|
||||||
|
exclude:
|
||||||
|
- lib/l10n/**
|
||||||
|
- lib/generated/**
|
||||||
|
- lib/gen/**
|
||||||
|
- lib/generated_plugin_registrant.dart
|
||||||
|
- test/.test_coverage.dart
|
||||||
|
- '**/*.g.dart'
|
||||||
|
- '**/*.freezed.dart'
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
- always_declare_return_types
|
||||||
|
- always_put_control_body_on_new_line
|
||||||
|
- always_put_required_named_parameters_first
|
||||||
|
- always_require_non_null_named_parameters
|
||||||
|
- always_use_package_imports
|
||||||
|
- annotate_overrides
|
||||||
|
- avoid_bool_literals_in_conditional_expressions
|
||||||
|
- avoid_catching_errors
|
||||||
|
- avoid_double_and_int_checks
|
||||||
|
- avoid_dynamic_calls
|
||||||
|
- avoid_empty_else
|
||||||
|
- avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
- avoid_escaping_inner_quotes
|
||||||
|
- avoid_field_initializers_in_const_classes
|
||||||
|
- avoid_final_parameters
|
||||||
|
- avoid_function_literals_in_foreach_calls
|
||||||
|
- avoid_init_to_null
|
||||||
|
- avoid_js_rounded_ints
|
||||||
|
- avoid_multiple_declarations_per_line
|
||||||
|
- avoid_null_checks_in_equality_operators
|
||||||
|
- avoid_positional_boolean_parameters
|
||||||
|
- avoid_private_typedef_functions
|
||||||
|
- avoid_redundant_argument_values
|
||||||
|
- avoid_relative_lib_imports
|
||||||
|
- avoid_renaming_method_parameters
|
||||||
|
- avoid_return_types_on_setters
|
||||||
|
- avoid_returning_null
|
||||||
|
- avoid_returning_null_for_future
|
||||||
|
- avoid_returning_null_for_void
|
||||||
|
- avoid_returning_this
|
||||||
|
- avoid_setters_without_getters
|
||||||
|
- avoid_shadowing_type_parameters
|
||||||
|
- avoid_single_cascade_in_expression_statements
|
||||||
|
- avoid_slow_async_io
|
||||||
|
- avoid_type_to_string
|
||||||
|
- avoid_types_as_parameter_names
|
||||||
|
- avoid_types_on_closure_parameters
|
||||||
|
- avoid_unused_constructor_parameters
|
||||||
|
- avoid_void_async
|
||||||
|
- await_only_futures
|
||||||
|
- camel_case_extensions
|
||||||
|
- camel_case_types
|
||||||
|
- cancel_subscriptions
|
||||||
|
- cascade_invocations
|
||||||
|
- cast_nullable_to_non_nullable
|
||||||
|
- comment_references
|
||||||
|
- conditional_uri_does_not_exist
|
||||||
|
- constant_identifier_names
|
||||||
|
- control_flow_in_finally
|
||||||
|
- curly_braces_in_flow_control_structures
|
||||||
|
- depend_on_referenced_packages
|
||||||
|
- deprecated_consistency
|
||||||
|
- directives_ordering
|
||||||
|
- empty_catches
|
||||||
|
- empty_constructor_bodies
|
||||||
|
- empty_statements
|
||||||
|
- eol_at_end_of_file
|
||||||
|
- exhaustive_cases
|
||||||
|
- file_names
|
||||||
|
- flutter_style_todos
|
||||||
|
- hash_and_equals
|
||||||
|
- implementation_imports
|
||||||
|
- iterable_contains_unrelated_type
|
||||||
|
- join_return_with_assignment
|
||||||
|
- leading_newlines_in_multiline_strings
|
||||||
|
- library_names
|
||||||
|
- library_prefixes
|
||||||
|
- library_private_types_in_public_api
|
||||||
|
- lines_longer_than_80_chars
|
||||||
|
- list_remove_unrelated_type
|
||||||
|
- literal_only_boolean_expressions
|
||||||
|
- missing_whitespace_between_adjacent_strings
|
||||||
|
- no_adjacent_strings_in_list
|
||||||
|
- no_default_cases
|
||||||
|
- no_duplicate_case_values
|
||||||
|
- no_leading_underscores_for_library_prefixes
|
||||||
|
- no_leading_underscores_for_local_identifiers
|
||||||
|
- no_runtimeType_toString
|
||||||
|
- non_constant_identifier_names
|
||||||
|
- noop_primitive_operations
|
||||||
|
- null_check_on_nullable_type_parameter
|
||||||
|
- null_closures
|
||||||
|
- one_member_abstracts
|
||||||
|
- only_throw_errors
|
||||||
|
- overridden_fields
|
||||||
|
- package_api_docs
|
||||||
|
- package_names
|
||||||
|
- package_prefixed_library_names
|
||||||
|
- parameter_assignments
|
||||||
|
- prefer_adjacent_string_concatenation
|
||||||
|
- prefer_asserts_in_initializer_lists
|
||||||
|
- prefer_asserts_with_message
|
||||||
|
- prefer_collection_literals
|
||||||
|
- prefer_conditional_assignment
|
||||||
|
- prefer_const_constructors
|
||||||
|
- prefer_const_constructors_in_immutables
|
||||||
|
- prefer_const_declarations
|
||||||
|
- prefer_const_literals_to_create_immutables
|
||||||
|
- prefer_constructors_over_static_methods
|
||||||
|
- prefer_contains
|
||||||
|
- prefer_equal_for_default_values
|
||||||
|
- prefer_expression_function_bodies
|
||||||
|
- prefer_final_fields
|
||||||
|
- prefer_final_in_for_each
|
||||||
|
- prefer_final_locals
|
||||||
|
- prefer_for_elements_to_map_fromIterable
|
||||||
|
- prefer_function_declarations_over_variables
|
||||||
|
- prefer_generic_function_type_aliases
|
||||||
|
- prefer_if_elements_to_conditional_expressions
|
||||||
|
- prefer_if_null_operators
|
||||||
|
- prefer_initializing_formals
|
||||||
|
- prefer_inlined_adds
|
||||||
|
- prefer_int_literals
|
||||||
|
- prefer_interpolation_to_compose_strings
|
||||||
|
- prefer_is_empty
|
||||||
|
- prefer_is_not_empty
|
||||||
|
- prefer_is_not_operator
|
||||||
|
- prefer_iterable_whereType
|
||||||
|
- prefer_mixin
|
||||||
|
- prefer_null_aware_method_calls
|
||||||
|
- prefer_null_aware_operators
|
||||||
|
- prefer_single_quotes
|
||||||
|
- prefer_spread_collections
|
||||||
|
- prefer_typing_uninitialized_variables
|
||||||
|
- prefer_void_to_null
|
||||||
|
- provide_deprecation_message
|
||||||
|
- recursive_getters
|
||||||
|
- require_trailing_commas
|
||||||
|
- slash_for_doc_comments
|
||||||
|
- sort_constructors_first
|
||||||
|
- sort_unnamed_constructors_first
|
||||||
|
- test_types_in_equals
|
||||||
|
- throw_in_finally
|
||||||
|
- tighten_type_of_initializing_formals
|
||||||
|
- type_annotate_public_apis
|
||||||
|
- type_init_formals
|
||||||
|
- unawaited_futures
|
||||||
|
- unnecessary_await_in_return
|
||||||
|
- unnecessary_brace_in_string_interps
|
||||||
|
- unnecessary_const
|
||||||
|
- unnecessary_constructor_name
|
||||||
|
- unnecessary_getters_setters
|
||||||
|
- unnecessary_lambdas
|
||||||
|
- unnecessary_late
|
||||||
|
- unnecessary_new
|
||||||
|
- unnecessary_null_aware_assignments
|
||||||
|
- unnecessary_null_checks
|
||||||
|
- unnecessary_null_in_if_null_operators
|
||||||
|
- unnecessary_nullable_for_final_variable_declarations
|
||||||
|
- unnecessary_overrides
|
||||||
|
- unnecessary_parenthesis
|
||||||
|
- unnecessary_raw_strings
|
||||||
|
- unnecessary_statements
|
||||||
|
- unnecessary_string_escapes
|
||||||
|
- unnecessary_string_interpolations
|
||||||
|
- unnecessary_this
|
||||||
|
- unnecessary_to_list_in_spreads
|
||||||
|
- unrelated_type_equality_checks
|
||||||
|
- unsafe_html
|
||||||
|
- use_enums
|
||||||
|
- use_function_type_syntax_for_parameters
|
||||||
|
- use_if_null_to_convert_nulls_to_bools
|
||||||
|
- use_is_even_rather_than_modulo
|
||||||
|
- use_late_for_private_fields_and_variables
|
||||||
|
- use_named_constants
|
||||||
|
- use_raw_strings
|
||||||
|
- use_rethrow_when_possible
|
||||||
|
- use_setters_to_change_properties
|
||||||
|
- use_string_buffers
|
||||||
|
- use_super_parameters
|
||||||
|
- use_test_throws_matchers
|
||||||
|
- use_to_and_as_if_applicable
|
||||||
|
- valid_regexps
|
||||||
|
- void_checks
|
||||||
@@ -14,7 +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/>.
|
||||||
|
|
||||||
include: package:wyatt_analysis/analysis_options.2.1.1.yaml
|
include: package:wyatt_analysis/analysis_options.2.2.0.yaml
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
rules:
|
rules:
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# 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/>.
|
||||||
|
|
||||||
|
include: package:wyatt_analysis/analysis_options.2.2.2.yaml
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
- avoid_print
|
||||||
|
- avoid_unnecessary_containers
|
||||||
|
- avoid_web_libraries_in_flutter
|
||||||
|
- no_logic_in_create_state
|
||||||
|
- sized_box_for_whitespace
|
||||||
|
- sized_box_shrink_expand
|
||||||
|
- sort_child_properties_last
|
||||||
|
- use_build_context_synchronously
|
||||||
|
- use_colored_box
|
||||||
|
- use_decorated_box
|
||||||
|
- use_full_hex_values_for_flutter_colors
|
||||||
|
- use_key_in_widget_constructors
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# 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/>.
|
||||||
|
|
||||||
|
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
- avoid_print
|
||||||
|
- avoid_unnecessary_containers
|
||||||
|
- avoid_web_libraries_in_flutter
|
||||||
|
- no_logic_in_create_state
|
||||||
|
- sized_box_for_whitespace
|
||||||
|
- sized_box_shrink_expand
|
||||||
|
- sort_child_properties_last
|
||||||
|
- use_build_context_synchronously
|
||||||
|
- use_colored_box
|
||||||
|
- use_decorated_box
|
||||||
|
- use_full_hex_values_for_flutter_colors
|
||||||
|
- use_key_in_widget_constructors
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
# 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,4 +15,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/>.
|
||||||
|
|
||||||
include: package:wyatt_analysis/analysis_options.flutter.2.2.1.yaml
|
include: package:wyatt_analysis/analysis_options.flutter.2.3.0.yaml
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
# 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,4 +15,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/>.
|
||||||
|
|
||||||
include: package:wyatt_analysis/analysis_options.2.2.1.yaml
|
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
/// Wyatt analyzer settings and best practices
|
/// Wyatt analyzer settings and best practices
|
||||||
/// used internally at [Wyatt](https://wyattapp.io)
|
/// used internally at [Wyatt Studio](https://wyatt-studio.fr).
|
||||||
/// and [Wyatt Studio](https://wyatt-studio.fr).
|
|
||||||
library wyatt_analysis;
|
library wyatt_analysis;
|
||||||
|
|
||||||
const String wyattAnalysisVersion = '2.2.1';
|
const String wyattAnalysisVersion = '2.3.0';
|
||||||
|
|||||||
Executable
+133
@@ -0,0 +1,133 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
usage="
|
||||||
|
usage:
|
||||||
|
$(basename "$0") <previous_version> <new_version> -- create new analyzer files.
|
||||||
|
|
||||||
|
where:
|
||||||
|
previous_version: last version, for example \`2.3.0\`
|
||||||
|
new_version: new version, for example \`2.4.0\`"
|
||||||
|
|
||||||
|
old=$1
|
||||||
|
new=$2
|
||||||
|
|
||||||
|
if [ -z "$old" ]; then
|
||||||
|
echo "previous_version cannot be null"
|
||||||
|
echo "${usage}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$new" ]; then
|
||||||
|
echo "new_version cannot be null"
|
||||||
|
echo "${usage}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCRIPT_PATH="${BASH_SOURCE:-$0}"
|
||||||
|
ABS_SCRIPT_PATH="$(realpath "${SCRIPT_PATH}")"
|
||||||
|
ABS_DIRECTORY="$(dirname "${ABS_SCRIPT_PATH}")"
|
||||||
|
|
||||||
|
LIB="${ABS_DIRECTORY}/lib/wyatt_analysis.dart"
|
||||||
|
OPTIONS="${ABS_DIRECTORY}/lib/analysis_options.yaml"
|
||||||
|
OLD_OPTIONS="${ABS_DIRECTORY}/lib/analysis_options.${old}.yaml"
|
||||||
|
NEW_OPTIONS="${ABS_DIRECTORY}/lib/analysis_options.${new}.yaml"
|
||||||
|
|
||||||
|
OPTIONS_FLUTTER="${ABS_DIRECTORY}/lib/analysis_options.flutter.yaml"
|
||||||
|
OLD_OPTIONS_FLUTTER="${ABS_DIRECTORY}/lib/analysis_options.flutter.${old}.yaml"
|
||||||
|
NEW_OPTIONS_FLUTTER="${ABS_DIRECTORY}/lib/analysis_options.flutter.${new}.yaml"
|
||||||
|
|
||||||
|
if [ ! -e "$OLD_OPTIONS" ]; then
|
||||||
|
echo "analysis_options.${old}.yaml doesn't exists"
|
||||||
|
echo "${usage}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e "$OLD_OPTIONS_FLUTTER" ]; then
|
||||||
|
echo "analysis_options.flutter.${old}.yaml doesn't exists"
|
||||||
|
echo "${usage}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$NEW_OPTIONS" ]; then
|
||||||
|
echo "analysis_options.${new}.yaml already exists"
|
||||||
|
echo "${usage}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e "$NEW_OPTIONS_FLUTTER" ]; then
|
||||||
|
echo "analysis_options.flutter.${old}.yaml already exists"
|
||||||
|
echo "${usage}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy previous version files
|
||||||
|
cp "${OLD_OPTIONS}" "${NEW_OPTIONS}"
|
||||||
|
cp "${OLD_OPTIONS_FLUTTER}" "${NEW_OPTIONS_FLUTTER}"
|
||||||
|
|
||||||
|
# Search and replace old version string occurences in new files
|
||||||
|
sed -e "s/${old}/${new}/g" "${NEW_OPTIONS_FLUTTER}" > tempfile.tmp
|
||||||
|
mv -f tempfile.tmp "${NEW_OPTIONS_FLUTTER}"
|
||||||
|
|
||||||
|
sed -e "s/${old}/${new}/g" "${LIB}" > tempfile.tmp
|
||||||
|
mv -f tempfile.tmp "${LIB}"
|
||||||
|
|
||||||
|
sed -e "s/${old}/${new}/g" "README.md" > tempfile.tmp
|
||||||
|
mv -f tempfile.tmp "README.md"
|
||||||
|
|
||||||
|
echo "
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
include: package:wyatt_analysis/analysis_options.${new}.yaml
|
||||||
|
" > "${OPTIONS}"
|
||||||
|
|
||||||
|
echo "
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
include: package:wyatt_analysis/analysis_options.flutter.${new}.yaml
|
||||||
|
" > "${OPTIONS_FLUTTER}"
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
name: wyatt_analysis
|
name: wyatt_analysis
|
||||||
description: Lint rules for Dart and Flutter used internally at Wyatt and Wyatt Studio.
|
description: Lint rules for Dart and Flutter used internally at Wyatt Studio.
|
||||||
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis
|
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis
|
||||||
version: 2.2.2
|
version: 2.3.0
|
||||||
|
|
||||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
## 0.1.0+1
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
|
## 0.1.0
|
||||||
|
|
||||||
|
> Note: This release has breaking changes.
|
||||||
|
|
||||||
|
- **REFACTOR**: update naming methodes (close #47).
|
||||||
|
- **REFACTOR**: update example. (close #38).
|
||||||
|
- **FIX**: fix execute method on error handler. (#38).
|
||||||
|
- **FEAT**: update usecase en add & sepcific case. (#38).
|
||||||
|
- **FEAT**: add obsevers for alternative usecase scenarions (#38).
|
||||||
|
- **DOCS**: generate class model. (#38).
|
||||||
|
- **DOCS**: update Readme. (#38).
|
||||||
|
- **BREAKING** **CHORE**: update exports. (#38).
|
||||||
|
|
||||||
## 0.0.2
|
## 0.0.2
|
||||||
|
|
||||||
- Graduate package to a stable release. See pre-releases prior to this version for changelog entries.
|
- Graduate package to a stable release. See pre-releases prior to this version for changelog entries.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* any later version.
|
* any later version.
|
||||||
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
@@ -31,10 +31,10 @@ The Wyatt Architecture for Flutter.
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Usecase
|
- Usecase
|
||||||
* Repository
|
- Repository
|
||||||
* DataSource
|
- DataSource
|
||||||
* Entity
|
- Entity
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -73,19 +73,20 @@ abstract class PhotoRepository extends BaseRepository {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> Here the repository is just a proxy of the data sources with result type (to have beautiful error handling).
|
> 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>` :
|
And finaly create your different usecases :
|
||||||
|
|
||||||
|
Several use cases are supported :
|
||||||
|
|
||||||
|
- Classic usecase :
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
class RetrieveAllPhoto extends UseCase<QueryParameters, List<Photo>> {
|
class Test extends AsyncUseCase<QueryParameters, List<Photo>>> {
|
||||||
final PhotoRepository _photoRepository;
|
|
||||||
|
|
||||||
RetrieveAllPhotos(this._photoRepository);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Photo>> call(QueryParameters params) {
|
FuturOrResult<List<Photo>>> call(QueryParameters? params) {
|
||||||
final photos = _photoRepository.getAllPhotos(
|
final photos = _photoRepository.getAllPhotos(
|
||||||
start: params.start,
|
start: params.start,
|
||||||
limit: params.limit,
|
limit: params.limit,
|
||||||
);
|
);
|
||||||
@@ -94,6 +95,54 @@ class RetrieveAllPhoto extends UseCase<QueryParameters, List<Photo>> {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can add alternatve scenarios and check pre/post conditions using our extensions :
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class SearchPhotos extends AsyncUseCase<QueryParameters, List<Photo>>> {
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOrResult<List<Photo>>> call(QueryParameters? params) {
|
||||||
|
final photos = _photoRepository.getAllPhotos(
|
||||||
|
start: params.start,
|
||||||
|
limit: params.limit,
|
||||||
|
);
|
||||||
|
return photos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> onStart(QueryParameters? params) {
|
||||||
|
if(params.start == null || params.limit == null){
|
||||||
|
throw ClientException('Préconndition non valides');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can implement error scenarios overriding `onError`, or check postconditions by overriding `onComplete` .
|
||||||
|
|
||||||
|
- Stream usecase :
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class SearchPhotos extends StreamUseCase<QueryParameters, List<Photo>>> {
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOrResult<Stream<List<Photo>>>> call(QueryParameters? params) {
|
||||||
|
final photos = _photoRepository.getAllPhotos(
|
||||||
|
start: params.start,
|
||||||
|
limit: params.limit,
|
||||||
|
);
|
||||||
|
return photos;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
On this case, observers allow you to add alternative scénarios when data changed, overriding `onData` or `onDone`.
|
||||||
|
|
||||||
|
Please note that to use handlers, call `call` method and not `execute`.
|
||||||
|
|
||||||
> In fact, here we need a new parameter object, so let's create it:
|
> In fact, here we need a new parameter object, so let's create it:
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
@@ -171,4 +220,4 @@ class PhotoRepositoryImpl extends PhotoRepository {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
That's all.
|
That's all.
|
||||||
|
|||||||
+10
-9
@@ -35,46 +35,47 @@ class PhotoRepositoryImpl extends PhotoRepository {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> addPhotoToFavorites(Photo photo) => Result.tryCatchAsync(
|
FutureOrResult<void> addPhotoToFavorites(Photo photo) => Result.tryCatchAsync(
|
||||||
() => _favoriteLocalDataSource.addPhotoToFavorites(photo),
|
() => _favoriteLocalDataSource.addPhotoToFavorites(photo),
|
||||||
(error) => ClientException('Cannot add photo to favorites.'),
|
(error) => ClientException('Cannot add photo to favorites.'),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<bool> checkIfPhotoIsInFavorites(int id) => Result.tryCatchAsync(
|
FutureOrResult<bool> checkIfPhotoIsInFavorites(int id) =>
|
||||||
|
Result.tryCatchAsync(
|
||||||
() => _favoriteLocalDataSource.checkIfPhotoIsInFavorites(id),
|
() => _favoriteLocalDataSource.checkIfPhotoIsInFavorites(id),
|
||||||
(error) =>
|
(error) =>
|
||||||
ClientException('Cannot check if photo `$id` is in favorites.'),
|
ClientException('Cannot check if photo `$id` is in favorites.'),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> deletePhotoFromFavorites(int id) => Result.tryCatchAsync(
|
FutureOrResult<void> deletePhotoFromFavorites(int id) => Result.tryCatchAsync(
|
||||||
() => _favoriteLocalDataSource.deletePhotoFromFavorites(id),
|
() => _favoriteLocalDataSource.deletePhotoFromFavorites(id),
|
||||||
(error) => ClientException('Cannot delete photo `$id` from favorites.'),
|
(error) => ClientException('Cannot delete photo `$id` from favorites.'),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<Album> getAlbum(int id) => Result.tryCatchAsync(
|
FutureOrResult<Album> getAlbum(int id) => Result.tryCatchAsync(
|
||||||
() => _albumRemoteDataSource.getAlbum(id),
|
() => _albumRemoteDataSource.getAlbum(id),
|
||||||
(error) => ServerException('Cannot retrieve album $id.'),
|
(error) => ServerException('Cannot retrieve album $id.'),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Album>> getAllAlbums({int? start, int? limit}) =>
|
FutureOrResult<List<Album>> getAllAlbums({int? start, int? limit}) =>
|
||||||
Result.tryCatchAsync(
|
Result.tryCatchAsync(
|
||||||
() => _albumRemoteDataSource.getAllAlbums(start: start, limit: limit),
|
() => _albumRemoteDataSource.getAllAlbums(start: start, limit: limit),
|
||||||
(error) => ServerException('Cannot retrieve all albums.'),
|
(error) => ServerException('Cannot retrieve all albums.'),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Photo>> getAllPhotos({int? start, int? limit}) async =>
|
FutureOrResult<List<Photo>> getAllPhotos({int? start, int? limit}) async =>
|
||||||
Result.tryCatchAsync(
|
Result.tryCatchAsync(
|
||||||
() => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit),
|
() => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit),
|
||||||
(error) => ServerException('Cannot retrieve all photos.'),
|
(error) => ServerException('Cannot retrieve all photos.'),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Photo>> getAllPhotosFromFavorites() async {
|
FutureOrResult<List<Photo>> getAllPhotosFromFavorites() async {
|
||||||
try {
|
try {
|
||||||
final response = <Photo>[];
|
final response = <Photo>[];
|
||||||
final favorites =
|
final favorites =
|
||||||
@@ -95,13 +96,13 @@ class PhotoRepositoryImpl extends PhotoRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<Photo> getPhoto(int id) => Result.tryCatchAsync(
|
FutureOrResult<Photo> getPhoto(int id) => Result.tryCatchAsync(
|
||||||
() => _photoRemoteDataSource.getPhoto(id),
|
() => _photoRemoteDataSource.getPhoto(id),
|
||||||
(error) => ServerException('Cannot retrieve photo $id.'),
|
(error) => ServerException('Cannot retrieve photo $id.'),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Photo>> getPhotosFromAlbum(
|
FutureOrResult<List<Photo>> getPhotosFromAlbum(
|
||||||
int albumId, {
|
int albumId, {
|
||||||
int? start,
|
int? start,
|
||||||
int? limit,
|
int? limit,
|
||||||
|
|||||||
@@ -19,17 +19,17 @@ import 'package:architecture_example/domain/entities/photo.dart';
|
|||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
abstract class PhotoRepository extends BaseRepository {
|
abstract class PhotoRepository extends BaseRepository {
|
||||||
FutureResult<Album> getAlbum(int id);
|
FutureOrResult<Album> getAlbum(int id);
|
||||||
FutureResult<List<Album>> getAllAlbums({int? start, int? limit});
|
FutureOrResult<List<Album>> getAllAlbums({int? start, int? limit});
|
||||||
FutureResult<Photo> getPhoto(int id);
|
FutureOrResult<Photo> getPhoto(int id);
|
||||||
FutureResult<List<Photo>> getAllPhotos({int? start, int? limit});
|
FutureOrResult<List<Photo>> getAllPhotos({int? start, int? limit});
|
||||||
FutureResult<List<Photo>> getPhotosFromAlbum(
|
FutureOrResult<List<Photo>> getPhotosFromAlbum(
|
||||||
int albumId, {
|
int albumId, {
|
||||||
int? start,
|
int? start,
|
||||||
int? limit,
|
int? limit,
|
||||||
});
|
});
|
||||||
FutureResult<void> addPhotoToFavorites(Photo photo);
|
FutureOrResult<void> addPhotoToFavorites(Photo photo);
|
||||||
FutureResult<void> deletePhotoFromFavorites(int id);
|
FutureOrResult<void> deletePhotoFromFavorites(int id);
|
||||||
FutureResult<List<Photo>> getAllPhotosFromFavorites();
|
FutureOrResult<List<Photo>> getAllPhotosFromFavorites();
|
||||||
FutureResult<bool> checkIfPhotoIsInFavorites(int id);
|
FutureOrResult<bool> checkIfPhotoIsInFavorites(int id);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-6
@@ -1,31 +1,40 @@
|
|||||||
// Copyright (C) 2022 WYATT GROUP
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Please see the AUTHORS file for details.
|
// Please see the AUTHORS file for details.
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// any later version.
|
// any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:architecture_example/domain/entities/photo.dart';
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
class AddPhotoToFavorites extends UseCase<Photo, List<Photo>> {
|
class AddPhotoToFavorites extends AsyncUseCase<Photo, List<Photo>> {
|
||||||
final PhotoRepository _photoRepository;
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
AddPhotoToFavorites(this._photoRepository);
|
AddPhotoToFavorites(this._photoRepository);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Photo>> call(Photo params) async {
|
FutureOrResult<List<Photo>> execute(Photo? params) async {
|
||||||
await _photoRepository.addPhotoToFavorites(params);
|
await _photoRepository.addPhotoToFavorites(params!);
|
||||||
return _photoRepository.getAllPhotosFromFavorites();
|
return _photoRepository.getAllPhotosFromFavorites();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> onStart(Photo? params) {
|
||||||
|
if (params == null) {
|
||||||
|
throw ClientException('Photo cannot be null');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -14,15 +14,24 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
class CheckIfPhotoIsInFavorites extends UseCase<int, bool> {
|
class CheckIfPhotoIsInFavorites extends AsyncUseCase<int, bool> {
|
||||||
final PhotoRepository _photoRepository;
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
CheckIfPhotoIsInFavorites(this._photoRepository);
|
CheckIfPhotoIsInFavorites(this._photoRepository);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<bool> call(int params) async =>
|
FutureOrResult<bool> execute(int? params) async =>
|
||||||
_photoRepository.checkIfPhotoIsInFavorites(params);
|
_photoRepository.checkIfPhotoIsInFavorites(params!);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> onStart(int? params) {
|
||||||
|
if (params == null) {
|
||||||
|
throw ClientException('id cannot be null');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -1,16 +1,16 @@
|
|||||||
// Copyright (C) 2022 WYATT GROUP
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Please see the AUTHORS file for details.
|
// Please see the AUTHORS file for details.
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// any later version.
|
// any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
@@ -18,13 +18,13 @@ import 'package:architecture_example/domain/entities/photo.dart';
|
|||||||
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
class DisplayFavorites extends UseCase<void, List<Photo>> {
|
class DisplayFavorites extends AsyncUseCase<NoParam, List<Photo>> {
|
||||||
final PhotoRepository _photoRepository;
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
DisplayFavorites(this._photoRepository);
|
DisplayFavorites(this._photoRepository);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Photo>> call(void params) {
|
FutureOrResult<List<Photo>> execute(void params) {
|
||||||
final photos = _photoRepository.getAllPhotosFromFavorites();
|
final photos = _photoRepository.getAllPhotosFromFavorites();
|
||||||
return photos;
|
return photos;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,18 +14,27 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:architecture_example/domain/entities/photo.dart';
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
class DisplayPhoto extends UseCase<int, Photo> {
|
class DisplayPhoto extends AsyncUseCase<int, Photo> {
|
||||||
final PhotoRepository _photoRepository;
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
DisplayPhoto(this._photoRepository);
|
DisplayPhoto(this._photoRepository);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<Photo> call(int params) {
|
FutureOrResult<Photo> execute(int? params) {
|
||||||
final photo = _photoRepository.getPhoto(params);
|
final photo = _photoRepository.getPhoto(params!);
|
||||||
return photo;
|
return photo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> onStart(int? params) {
|
||||||
|
if (params == null) {
|
||||||
|
throw ClientException('id cannot be null');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,24 +14,33 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:architecture_example/domain/entities/photo.dart';
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart';
|
import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
class OpenAlbum extends UseCase<QueryParameters, List<Photo>> {
|
class OpenAlbum extends AsyncUseCase<QueryParameters, List<Photo>> {
|
||||||
final PhotoRepository _photoRepository;
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
OpenAlbum(this._photoRepository);
|
OpenAlbum(this._photoRepository);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Photo>> call(QueryParameters params) {
|
FutureOrResult<List<Photo>> execute(QueryParameters? params) {
|
||||||
final photos = _photoRepository.getPhotosFromAlbum(
|
final photos = _photoRepository.getPhotosFromAlbum(
|
||||||
params.albumId,
|
params!.albumId,
|
||||||
start: params.start,
|
start: params.start,
|
||||||
limit: params.limit,
|
limit: params.limit,
|
||||||
);
|
);
|
||||||
|
|
||||||
return photos;
|
return photos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> onStart(QueryParameters? params) {
|
||||||
|
if (params == null) {
|
||||||
|
throw ClientException('params cannot be null');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -14,18 +14,27 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:architecture_example/domain/entities/photo.dart';
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
class RemovePhotoFromFavorites extends UseCase<int, List<Photo>> {
|
class RemovePhotoFromFavorites extends AsyncUseCase<int, List<Photo>> {
|
||||||
final PhotoRepository _photoRepository;
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
RemovePhotoFromFavorites(this._photoRepository);
|
RemovePhotoFromFavorites(this._photoRepository);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Photo>> call(int params) async {
|
FutureOrResult<List<Photo>> execute(int? params) async {
|
||||||
await _photoRepository.deletePhotoFromFavorites(params);
|
await _photoRepository.deletePhotoFromFavorites(params!);
|
||||||
return _photoRepository.getAllPhotosFromFavorites();
|
return _photoRepository.getAllPhotosFromFavorites();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> onStart(int? params) {
|
||||||
|
if (params == null) {
|
||||||
|
throw ClientException('id cannot be null');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -14,22 +14,31 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:architecture_example/domain/entities/album.dart';
|
import 'package:architecture_example/domain/entities/album.dart';
|
||||||
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart';
|
import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
class RetrieveAllAlbums extends UseCase<QueryParameters, List<Album>> {
|
class RetrieveAllAlbums extends AsyncUseCase<QueryParameters, List<Album>> {
|
||||||
final PhotoRepository _photoRepository;
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
RetrieveAllAlbums(this._photoRepository);
|
RetrieveAllAlbums(this._photoRepository);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<List<Album>> call(QueryParameters params) {
|
FutureOrResult<List<Album>> execute(QueryParameters? params) {
|
||||||
final albums = _photoRepository.getAllAlbums(
|
final albums = _photoRepository.getAllAlbums(
|
||||||
start: params.start,
|
start: params!.start,
|
||||||
limit: params.limit,
|
limit: params.limit,
|
||||||
);
|
);
|
||||||
return albums;
|
return albums;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> onStart(QueryParameters? params) {
|
||||||
|
if (params == null) {
|
||||||
|
throw ClientException('params cannot be null');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ dependencies:
|
|||||||
|
|
||||||
wyatt_type_utils:
|
wyatt_type_utils:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
version: ^0.0.3+1
|
version: ^0.0.4
|
||||||
|
|
||||||
wyatt_http_client:
|
wyatt_http_client:
|
||||||
git:
|
git:
|
||||||
@@ -49,7 +49,7 @@ dependencies:
|
|||||||
|
|
||||||
wyatt_bloc_helper:
|
wyatt_bloc_helper:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
version: ^1.2.0
|
version: ^2.0.0
|
||||||
equatable: ^2.0.5
|
equatable: ^2.0.5
|
||||||
stream_transform: ^2.1.0
|
stream_transform: ^2.1.0
|
||||||
bloc_concurrency: ^0.2.0
|
bloc_concurrency: ^0.2.0
|
||||||
@@ -67,7 +67,7 @@ dev_dependencies:
|
|||||||
wyatt_analysis:
|
wyatt_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||||
ref: wyatt_analysis-v2.2.2
|
ref: wyatt_analysis-v2.3.0
|
||||||
path: packages/wyatt_analysis
|
path: packages/wyatt_analysis
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// 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:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
/// Usecase observers
|
||||||
|
mixin Observer<Parameters, ReturnType> {
|
||||||
|
/// Called before usecase is runned.
|
||||||
|
/// Usefull to check the preconditions
|
||||||
|
FutureOr<void> onStart(Parameters? params) {}
|
||||||
|
|
||||||
|
/// Called when error occures during main scenario
|
||||||
|
/// Usefull to run alternative scenario
|
||||||
|
FutureOr<void> onError(AppException? error) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Specific observer for classic usecase
|
||||||
|
mixin AsyncObserver<ReturnType> {
|
||||||
|
FutureOr<void> onComplete(ReturnType? data) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Specific observer for stream case usecase
|
||||||
|
mixin StreamObserver<ReturnType> {
|
||||||
|
/// Replaces the data event handler of this subscription.
|
||||||
|
void onDone() {}
|
||||||
|
|
||||||
|
/// Replaces the done event handler of this subscription.
|
||||||
|
void onData(ReturnType? data) {}
|
||||||
|
}
|
||||||
@@ -1,27 +1,80 @@
|
|||||||
// Copyright (C) 2022 WYATT GROUP
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Please see the AUTHORS file for details.
|
// Please see the AUTHORS file for details.
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// any later version.
|
// any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart';
|
import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart';
|
||||||
|
import 'package:wyatt_architecture/src/domain/usecases/observers.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 FutureOrResult<T> = FutureOr<Result<T, AppException>>;
|
||||||
typedef StreamResult<T> = Stream<Result<T, AppException>>;
|
typedef StreamResult<T> = Stream<Result<T, AppException>>;
|
||||||
typedef Res<T> = Result<T, AppException>;
|
|
||||||
|
|
||||||
// ignore: one_member_abstracts
|
/// Abstract class of a use case
|
||||||
abstract class UseCase<Parameters, ReturnType> {
|
abstract class BaseUseCase<Parameters, ReturnType> {
|
||||||
FutureResult<ReturnType> call(Parameters params);
|
/// Run use case scenarios
|
||||||
|
ReturnType call(Parameters parameters);
|
||||||
|
|
||||||
|
/// Private function to implement main scenario
|
||||||
|
/// of your usecase.
|
||||||
|
ReturnType execute(Parameters params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Abstract class of a use case that deals specifically
|
||||||
|
/// with the response and its state.
|
||||||
|
abstract class UseCase<Parameters, ReturnType>
|
||||||
|
extends BaseUseCase<Parameters?, FutureOrResult<ReturnType>>
|
||||||
|
with Observer<Parameters, ReturnType> {
|
||||||
|
FutureOr<void> _onSuccess(ReturnType data);
|
||||||
|
|
||||||
|
/// Supports the result of the main scenario and integrates
|
||||||
|
/// some alternative scenarios if necessary.
|
||||||
|
@override
|
||||||
|
FutureOrResult<ReturnType> call(Parameters? parameters) async {
|
||||||
|
try {
|
||||||
|
await onStart(parameters);
|
||||||
|
final response = await execute(parameters);
|
||||||
|
if (response.isErr) {
|
||||||
|
await onError(response.err);
|
||||||
|
} else if (response.isOk && response.ok != null) {
|
||||||
|
await _onSuccess(response.ok as ReturnType);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
return Err(ClientException(e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Abtstract classic usecase.
|
||||||
|
abstract class AsyncUseCase<Parameters, ReturnType>
|
||||||
|
extends UseCase<Parameters?, ReturnType> with AsyncObserver<ReturnType> {
|
||||||
|
@override
|
||||||
|
FutureOr<void> _onSuccess(ReturnType data) => onComplete(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Abstract specific usecase bases on streams
|
||||||
|
abstract class StreamUseCase<Parameters, ReturnType>
|
||||||
|
extends UseCase<Parameters?, Stream<ReturnType>>
|
||||||
|
with StreamObserver<ReturnType> {
|
||||||
|
@override
|
||||||
|
FutureOr<void> _onSuccess(Stream<ReturnType> data) {
|
||||||
|
data.listen(
|
||||||
|
onData,
|
||||||
|
onDone: onDone,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,5 @@
|
|||||||
// 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 'no_param.dart';
|
||||||
|
export 'observers.dart';
|
||||||
export 'usecase.dart';
|
export 'usecase.dart';
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
@@ -0,0 +1,86 @@
|
|||||||
|
@startuml
|
||||||
|
set namespaceSeparator ::
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" {
|
||||||
|
+String? message
|
||||||
|
+String toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
"dart::core::Exception" <|-- "wyatt_architecture::src::core::exceptions::exceptions.dart::AppException"
|
||||||
|
|
||||||
|
class "wyatt_architecture::src::core::exceptions::exceptions.dart::ClientException" {
|
||||||
|
}
|
||||||
|
|
||||||
|
"wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" <|-- "wyatt_architecture::src::core::exceptions::exceptions.dart::ClientException"
|
||||||
|
class "wyatt_architecture::src::core::exceptions::exceptions.dart::ServerException" {
|
||||||
|
}
|
||||||
|
|
||||||
|
"wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" <|-- "wyatt_architecture::src::core::exceptions::exceptions.dart::ServerException"
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::repositories::base_repository.dart::BaseRepository" {
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::data_sources::local::base_local_data_source.dart::BaseLocalDataSource" {
|
||||||
|
}
|
||||||
|
|
||||||
|
"wyatt_architecture::src::domain::data_sources::base_data_source.dart::BaseDataSource" <|-- "wyatt_architecture::src::domain::data_sources::local::base_local_data_source.dart::BaseLocalDataSource"
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::data_sources::base_data_source.dart::BaseDataSource" {
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::data_sources::remote::base_remote_data_source.dart::BaseRemoteDataSource" {
|
||||||
|
}
|
||||||
|
|
||||||
|
"wyatt_architecture::src::domain::data_sources::base_data_source.dart::BaseDataSource" <|-- "wyatt_architecture::src::domain::data_sources::remote::base_remote_data_source.dart::BaseRemoteDataSource"
|
||||||
|
|
||||||
|
class "wyatt_architecture::src::domain::usecases::no_param.dart::NoParam" {
|
||||||
|
}
|
||||||
|
|
||||||
|
"wyatt_architecture::src::domain::entities::entity.dart::Entity" <|-- "wyatt_architecture::src::domain::usecases::no_param.dart::NoParam"
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::usecases::observers.dart::Observer" {
|
||||||
|
+FutureOr<void> onStart()
|
||||||
|
+FutureOr<void> onError()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::usecases::observers.dart::AsyncObserver" {
|
||||||
|
+FutureOr<void> onComplete()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::usecases::observers.dart::StreamObserver" {
|
||||||
|
+void onDone()
|
||||||
|
+void onData()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::BaseUseCase" {
|
||||||
|
+ReturnType execute()
|
||||||
|
+ReturnType call()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" {
|
||||||
|
-FutureOr<void> _onSuccess()
|
||||||
|
+FutureOr<Result<ReturnType, AppException>> execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
"wyatt_architecture::src::domain::usecases::usecase.dart::BaseUseCase" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase"
|
||||||
|
"wyatt_architecture::src::domain::usecases::observers.dart::Observer" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase"
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::AsyncUseCase" {
|
||||||
|
-FutureOr<void> _onSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
"wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::AsyncUseCase"
|
||||||
|
"wyatt_architecture::src::domain::usecases::observers.dart::AsyncObserver" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::AsyncUseCase"
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::StreamUseCase" {
|
||||||
|
-FutureOr<void> _onSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
"wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::StreamUseCase"
|
||||||
|
"wyatt_architecture::src::domain::usecases::observers.dart::StreamObserver" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::StreamUseCase"
|
||||||
|
|
||||||
|
abstract class "wyatt_architecture::src::domain::entities::entity.dart::Entity" {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@enduml
|
||||||
@@ -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
|
version: 0.1.0+1
|
||||||
|
|
||||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ dependencies:
|
|||||||
|
|
||||||
wyatt_type_utils:
|
wyatt_type_utils:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
version: ^0.0.3+1
|
version: ^0.0.4
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
||||||
@@ -24,4 +24,4 @@ dev_dependencies:
|
|||||||
|
|
||||||
wyatt_analysis:
|
wyatt_analysis:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
version: ^2.2.2
|
version: ^2.3.0
|
||||||
@@ -1 +1,2 @@
|
|||||||
firebase_options.dart
|
firebase_options.dart
|
||||||
|
.vscode
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../.vscode/
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
// Dart
|
||||||
|
"dart.runPubGetOnPubspecChanges": "never",
|
||||||
|
// Gitea
|
||||||
|
"gitea.owner": "Wyatt-FOSS",
|
||||||
|
"gitea.repo": "wyatt-packages",
|
||||||
|
// Header
|
||||||
|
"psi-header.changes-tracking": {
|
||||||
|
"isActive": true
|
||||||
|
},
|
||||||
|
"psi-header.config": {
|
||||||
|
"blankLinesAfter": 1,
|
||||||
|
"forceToTop": true
|
||||||
|
},
|
||||||
|
"psi-header.lang-config": [
|
||||||
|
{
|
||||||
|
"beforeHeader": [
|
||||||
|
"# -*- coding:utf-8 -*-",
|
||||||
|
"#!/usr/bin/env python3"
|
||||||
|
],
|
||||||
|
"begin": "###",
|
||||||
|
"end": "###",
|
||||||
|
"language": "python",
|
||||||
|
"prefix": "# "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"beforeHeader": [
|
||||||
|
"#!/usr/bin/env sh",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"language": "shellscript",
|
||||||
|
"begin": "",
|
||||||
|
"end": "",
|
||||||
|
"prefix": "# "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"begin": "",
|
||||||
|
"end": "",
|
||||||
|
"language": "dart",
|
||||||
|
"prefix": "// "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"begin": "",
|
||||||
|
"end": "",
|
||||||
|
"language": "yaml",
|
||||||
|
"prefix": "# "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"begin": "<!--",
|
||||||
|
"end": "-->",
|
||||||
|
"language": "markdown",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"psi-header.templates": [
|
||||||
|
{
|
||||||
|
"language": "*",
|
||||||
|
"template": [
|
||||||
|
"Copyright (C) <<year>> 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/>."
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -1,3 +1,15 @@
|
|||||||
|
## 0.4.0+3
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
|
## 0.4.0+2
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
|
## 0.4.0+1
|
||||||
|
|
||||||
|
- **FIX**: add sort of mutex on onAuthChanges callback trigger.
|
||||||
|
|
||||||
## 0.4.0
|
## 0.4.0
|
||||||
|
|
||||||
> Note: This release has breaking changes.
|
> Note: This release has breaking changes.
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: bootstrap.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 15:05:17
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Fri Nov 11 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:async';
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: form_field.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 11:52:33
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 16:35:39
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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 AppFormField {
|
abstract class AppFormField {
|
||||||
|
static const oldPassword = 'oldPassword';
|
||||||
static const confirmedPassword = 'confirmedPassword';
|
static const confirmedPassword = 'confirmedPassword';
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -14,6 +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/>.
|
||||||
|
|
||||||
import 'dart:io';
|
abstract class AppFormName {
|
||||||
|
static const editProfile = 'editProfile';
|
||||||
bool get supportsAnsiColor => stdout.supportsAnsiEscapes;
|
}
|
||||||
@@ -1,12 +1,20 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: router.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 11:52:22
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 16:39:07
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/presentation/features/edit_profile/edit_profile_page.dart';
|
||||||
import 'package:example_router/presentation/features/home/home_page.dart';
|
import 'package:example_router/presentation/features/home/home_page.dart';
|
||||||
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';
|
||||||
@@ -75,5 +83,14 @@ class AppRouter {
|
|||||||
const SubPage(),
|
const SubPage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/home/edit',
|
||||||
|
name: EditProfilePage.pageName,
|
||||||
|
pageBuilder: (context, state) => defaultTransition(
|
||||||
|
context,
|
||||||
|
state,
|
||||||
|
const EditProfilePage(),
|
||||||
|
),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: app_bloc_observer.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:02:23
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 12:02:45
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// 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_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
|
class CustomPassword extends RegexValidator<ValidationStandardError> {
|
||||||
|
const CustomPassword.pure([super.value]) : super.pure();
|
||||||
|
const CustomPassword.dirty([super.value]) : super.dirty();
|
||||||
|
|
||||||
|
@override
|
||||||
|
ValidationStandardError get onEmpty => ValidationStandardError.empty;
|
||||||
|
@override
|
||||||
|
ValidationStandardError get onError => ValidationStandardError.invalid;
|
||||||
|
|
||||||
|
@override
|
||||||
|
RegExp get regex => RegExp(r'^(?=.*[A-Za-z\w\s])(?=.*\d).{6,}$');
|
||||||
|
}
|
||||||
+14
-32
@@ -14,37 +14,19 @@
|
|||||||
// 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/>.
|
||||||
|
|
||||||
part of prompt.framework;
|
import 'package:example_router/core/constants/form_field.dart';
|
||||||
|
import 'package:example_router/core/constants/form_name.dart';
|
||||||
|
import 'package:example_router/core/utils/custom_password.dart';
|
||||||
|
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||||
|
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
abstract class State<W extends Widget<dynamic>> {
|
abstract class AppForms {
|
||||||
W? _widget;
|
static WyattForm getEditProfileForm() => WyattFormImpl(
|
||||||
W get widget => _widget!;
|
[
|
||||||
|
FormInput(AuthFormField.email, const Email.pure()),
|
||||||
BuildContext? _context;
|
FormInput(AuthFormField.password, const CustomPassword.pure()),
|
||||||
BuildContext get context => _context!;
|
FormInput(AppFormField.oldPassword, const CustomPassword.pure()),
|
||||||
|
],
|
||||||
void build();
|
name: AppFormName.editProfile,
|
||||||
|
);
|
||||||
dynamic prompt();
|
|
||||||
|
|
||||||
@protected
|
|
||||||
@mustCallSuper
|
|
||||||
void dispose() {
|
|
||||||
_context = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@protected
|
|
||||||
@mustCallSuper
|
|
||||||
void initState() {
|
|
||||||
_context ??= BuildContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@protected
|
|
||||||
@mustCallSuper
|
|
||||||
void setState(void Function() fn) {
|
|
||||||
fn();
|
|
||||||
context.wipe();
|
|
||||||
build();
|
|
||||||
context.incrementBuildCount();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,3 +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/>.
|
||||||
|
|
||||||
import 'package:example_router/bootstrap.dart';
|
import 'package:example_router/bootstrap.dart';
|
||||||
import 'package:example_router/presentation/features/app/app.dart';
|
import 'package:example_router/presentation/features/app/app.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: app.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:05:38
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Thu Nov 10 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:async';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
@@ -13,6 +20,8 @@ import 'dart:math';
|
|||||||
import 'package:example_router/core/constants/form_field.dart';
|
import 'package:example_router/core/constants/form_field.dart';
|
||||||
import 'package:example_router/core/dependency_injection/get_it.dart';
|
import 'package:example_router/core/dependency_injection/get_it.dart';
|
||||||
import 'package:example_router/core/routes/router.dart';
|
import 'package:example_router/core/routes/router.dart';
|
||||||
|
import 'package:example_router/core/utils/custom_password.dart';
|
||||||
|
import 'package:example_router/core/utils/forms.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';
|
||||||
@@ -21,7 +30,8 @@ import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
|||||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
FutureResult<int?> onSignUpSuccess(
|
FutureOrResult<int?> onSignUpSuccess(
|
||||||
|
AuthenticationRepository<int> repo,
|
||||||
Account? account,
|
Account? account,
|
||||||
WyattForm form,
|
WyattForm form,
|
||||||
) async {
|
) async {
|
||||||
@@ -34,9 +44,15 @@ FutureResult<int?> onSignUpSuccess(
|
|||||||
return const Ok<int, AppException>(id);
|
return const Ok<int, AppException>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureResult<int?> onAccountChanges(Account? account) async {
|
FutureOrResult<int?> onAccountChanges(
|
||||||
|
AuthenticationRepository<int> repo,
|
||||||
|
Account? account,
|
||||||
|
) async {
|
||||||
final id = Random().nextInt(1000);
|
final id = Random().nextInt(1000);
|
||||||
debugPrint('onAccountChanges: $account, generatedId: $id');
|
final token =
|
||||||
|
await repo.getIdentityToken().fold((value) => value, (error) => 'null');
|
||||||
|
|
||||||
|
debugPrint('onAccountChanges: $account, token: $token, generatedId: $id');
|
||||||
return Ok<int, AppException>(id);
|
return Ok<int, AppException>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +63,7 @@ class App extends StatelessWidget {
|
|||||||
authenticationRemoteDataSource: getIt<AuthenticationRemoteDataSource>(),
|
authenticationRemoteDataSource: getIt<AuthenticationRemoteDataSource>(),
|
||||||
onSignUpSuccess: onSignUpSuccess,
|
onSignUpSuccess: onSignUpSuccess,
|
||||||
onAuthChange: onAccountChanges,
|
onAuthChange: onAccountChanges,
|
||||||
|
customPasswordValidator: const CustomPassword.pure(),
|
||||||
extraSignUpInputs: [
|
extraSignUpInputs: [
|
||||||
FormInput(
|
FormInput(
|
||||||
AppFormField.confirmedPassword,
|
AppFormField.confirmedPassword,
|
||||||
@@ -60,7 +77,7 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
AuthenticationState? previous;
|
AuthenticationState<int>? previous;
|
||||||
|
|
||||||
final AuthenticationCubit<int> authenticationCubit =
|
final AuthenticationCubit<int> authenticationCubit =
|
||||||
AuthenticationCubit(authenticationRepository: authenticationRepository);
|
AuthenticationCubit(authenticationRepository: authenticationRepository);
|
||||||
@@ -76,29 +93,18 @@ class App extends StatelessWidget {
|
|||||||
redirect: (context, state) {
|
redirect: (context, state) {
|
||||||
final authState = authenticationCubit.state;
|
final authState = authenticationCubit.state;
|
||||||
|
|
||||||
if (authState != previous) {
|
if (authState.status != previous?.status) {
|
||||||
previous = authState;
|
previous = authState;
|
||||||
// Check if current user is logged in
|
|
||||||
final loggedIn =
|
|
||||||
authState.status == AuthenticationStatus.authenticated;
|
|
||||||
|
|
||||||
// Checking if current path is onboarding or not
|
// Checking if current path is onboarding or not
|
||||||
final isOnboarding = AppRouter.publicRoutes.contains(state.subloc);
|
final isOnboarding = AppRouter.publicRoutes.contains(state.subloc);
|
||||||
|
if (authState.status == AuthenticationStatus.unauthenticated) {
|
||||||
if (!loggedIn) {
|
|
||||||
debugPrint('Not logged');
|
debugPrint('Not logged');
|
||||||
if (isOnboarding) {
|
if (!isOnboarding) {
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return '/';
|
return '/';
|
||||||
}
|
}
|
||||||
} else {
|
} else if (authState.status == AuthenticationStatus.authenticated) {
|
||||||
debugPrint('Logged');
|
debugPrint('Logged');
|
||||||
if (isOnboarding) {
|
return '/home';
|
||||||
return '/home';
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -107,9 +113,13 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
return MultiRepositoryProvider(
|
return MultiRepositoryProvider(
|
||||||
providers: [
|
providers: [
|
||||||
RepositoryProvider<AuthenticationRepository>.value(
|
RepositoryProvider<AuthenticationRepository<int>>.value(
|
||||||
value: authenticationRepository,
|
value: authenticationRepository,
|
||||||
),
|
),
|
||||||
|
RepositoryProvider<FormRepository>(
|
||||||
|
create: (context) =>
|
||||||
|
FormRepositoryImpl()..registerForm(AppForms.getEditProfileForm()),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: MultiBlocProvider(
|
child: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
// 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:example_router/core/constants/form_field.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';
|
||||||
|
|
||||||
|
class EditProfileCubit extends FormDataCubitImpl {
|
||||||
|
final AuthenticationRepository<int> authenticationRepository;
|
||||||
|
|
||||||
|
EditProfileCubit(
|
||||||
|
super._formRepository,
|
||||||
|
super._formName, {
|
||||||
|
required this.authenticationRepository,
|
||||||
|
}) : super();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> submit() async {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
status: FormStatus.submissionInProgress,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final user = (await authenticationRepository.getAccount()).ok;
|
||||||
|
|
||||||
|
final form = state.form;
|
||||||
|
final email = form.valueOf<String?>(AuthFormField.email);
|
||||||
|
final oldPassword = form.valueOf<String?>(AppFormField.oldPassword);
|
||||||
|
final newPassword = form.valueOf<String?>(AuthFormField.password);
|
||||||
|
|
||||||
|
if (email.isNullOrEmpty ||
|
||||||
|
oldPassword.isNullOrEmpty ||
|
||||||
|
newPassword.isNullOrEmpty) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
errorMessage: 'An error occured while retrieving data from the form.',
|
||||||
|
status: FormStatus.submissionFailure,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// await authenticationRepository.signInWithEmailAndPassword(
|
||||||
|
// email: user?.email ?? '',
|
||||||
|
// password: oldPassword ?? '',
|
||||||
|
// );
|
||||||
|
// await authenticationRepository.reauthenticateWithCredential();
|
||||||
|
await authenticationRepository.updateEmail(email: email!);
|
||||||
|
await authenticationRepository.updatePassword(password: newPassword!);
|
||||||
|
} on Exception catch (e) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
status: FormStatus.submissionFailure,
|
||||||
|
errorMessage: e.toString(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
emit(state.copyWith(status: FormStatus.submissionSuccess));
|
||||||
|
}
|
||||||
|
}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
// 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:example_router/core/constants/form_name.dart';
|
||||||
|
import 'package:example_router/presentation/features/edit_profile/blocs/edit_profile_cubit.dart';
|
||||||
|
import 'package:example_router/presentation/features/edit_profile/widgets/edit_profile_form.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_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
|
class EditProfilePage extends StatelessWidget {
|
||||||
|
const EditProfilePage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
static String pageName = 'EditProfile';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: const Text('Edit Profile')),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: BlocProvider<EditProfileCubit>(
|
||||||
|
create: (context) => EditProfileCubit(
|
||||||
|
context.read<FormRepository>(),
|
||||||
|
AppFormName.editProfile,
|
||||||
|
authenticationRepository:
|
||||||
|
context.read<AuthenticationRepository<int>>(),
|
||||||
|
)..dataChanged<String?>(
|
||||||
|
AuthFormField.email,
|
||||||
|
Email.dirty(
|
||||||
|
context
|
||||||
|
.read<AuthenticationCubit<int>>()
|
||||||
|
.state
|
||||||
|
.accountWrapper
|
||||||
|
?.account
|
||||||
|
?.email ??
|
||||||
|
'',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: const EditProfileForm(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+136
@@ -0,0 +1,136 @@
|
|||||||
|
// 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:example_router/core/constants/form_field.dart';
|
||||||
|
import 'package:example_router/core/utils/custom_password.dart';
|
||||||
|
import 'package:example_router/presentation/features/edit_profile/blocs/edit_profile_cubit.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_form_bloc/wyatt_form_bloc.dart';
|
||||||
|
|
||||||
|
class _EmailInput extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InputBuilderTextController<EditProfileCubit, String?, void>(
|
||||||
|
field: AuthFormField.email,
|
||||||
|
builder: ((context, cubit, state, field, input, controller, extra) {
|
||||||
|
return TextField(
|
||||||
|
onChanged: (email) => cubit.dataChanged<String?>(
|
||||||
|
AuthFormField.email, Email.dirty(email)),
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
controller: controller,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Email',
|
||||||
|
helperText: '',
|
||||||
|
errorText: input.validator.invalid ? 'Invalid email' : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _OldPasswordInput extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InputBuilder<EditProfileCubit>(
|
||||||
|
field: AppFormField.oldPassword,
|
||||||
|
builder: ((context, cubit, state, field, input) {
|
||||||
|
return TextField(
|
||||||
|
onChanged: (pwd) => cubit.dataChanged<String?>(
|
||||||
|
AppFormField.oldPassword, CustomPassword.dirty(pwd)),
|
||||||
|
obscureText: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Old Password',
|
||||||
|
helperText: '',
|
||||||
|
errorText: input.validator.invalid ? 'Invalid password' : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NewPasswordInput extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InputBuilder<EditProfileCubit>(
|
||||||
|
field: AuthFormField.password,
|
||||||
|
builder: ((context, cubit, state, field, input) {
|
||||||
|
return TextField(
|
||||||
|
onChanged: (pwd) => cubit.dataChanged<String?>(
|
||||||
|
AuthFormField.password, CustomPassword.dirty(pwd)),
|
||||||
|
obscureText: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'New Password',
|
||||||
|
helperText: '',
|
||||||
|
errorText: input.validator.invalid ? 'Invalid password' : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EditButton extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SubmitBuilder<EditProfileCubit>(
|
||||||
|
builder: ((context, cubit, status) {
|
||||||
|
return status.isSubmissionInProgress
|
||||||
|
? const CircularProgressIndicator()
|
||||||
|
: ElevatedButton(
|
||||||
|
onPressed: status.isValidated ? () => cubit.submit() : null,
|
||||||
|
child: const Text('Edit profile'),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EditProfileForm extends StatelessWidget {
|
||||||
|
const EditProfileForm({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocListener<EditProfileCubit, FormDataState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state.status == FormStatus.submissionFailure) {
|
||||||
|
ScaffoldMessenger.of(context)
|
||||||
|
..hideCurrentSnackBar()
|
||||||
|
..showSnackBar(
|
||||||
|
SnackBar(content: Text(state.errorMessage ?? 'Edit Failure')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
_EmailInput(),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
_OldPasswordInput(),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
_NewPasswordInput(),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
_EditButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+27
-13
@@ -1,12 +1,20 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: home_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 14:38:24
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Wed Nov 09 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/presentation/features/edit_profile/edit_profile_page.dart';
|
||||||
import 'package:example_router/presentation/features/sub/sub_page.dart';
|
import 'package:example_router/presentation/features/sub/sub_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';
|
||||||
@@ -25,7 +33,8 @@ class HomePage extends StatelessWidget {
|
|||||||
title: const Text('Home'),
|
title: const Text('Home'),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
onPressed: () =>
|
||||||
|
context.read<AuthenticationCubit<int>>().signOut(),
|
||||||
icon: const Icon(Icons.logout_rounded))
|
icon: const Icon(Icons.logout_rounded))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -35,8 +44,8 @@ class HomePage extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
AuthenticationBuilder<int>(
|
AuthenticationBuilder<int>(
|
||||||
authenticated: (context, accountWrapper) =>
|
authenticated: (context, accountWrapper) => Text(
|
||||||
Text('Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
'Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
||||||
unauthenticated: (context) =>
|
unauthenticated: (context) =>
|
||||||
const Text('Not logged (unauthenticated)'),
|
const Text('Not logged (unauthenticated)'),
|
||||||
unknown: (context) => const Text('Not logged (unknown)'),
|
unknown: (context) => const Text('Not logged (unknown)'),
|
||||||
@@ -45,8 +54,13 @@ class HomePage extends StatelessWidget {
|
|||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () => context.pushNamed(SubPage.pageName),
|
onPressed: () => context.pushNamed(SubPage.pageName),
|
||||||
child: const Text('Go to sub page')),
|
child: const Text('Go to sub page'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => context.pushNamed(EditProfilePage.pageName),
|
||||||
|
child: const Text('Go to edit profile page'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
+15
-8
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sign_in_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:41:42
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 15:26:36
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/presentation/features/sign_in/widgets/sign_in_form.dart';
|
import 'package:example_router/presentation/features/sign_in/widgets/sign_in_form.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|||||||
+21
-10
@@ -1,12 +1,20 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sign_in_form.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 15:24:37
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Wed Nov 16 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/core/utils/custom_password.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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';
|
||||||
@@ -38,7 +46,8 @@ class _PasswordInput extends StatelessWidget {
|
|||||||
field: AuthFormField.password,
|
field: AuthFormField.password,
|
||||||
builder: ((context, cubit, state, field, input) {
|
builder: ((context, cubit, state, field, input) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (pwd) => cubit.passwordChanged(pwd),
|
onChanged: (pwd) => cubit
|
||||||
|
.passwordCustomChanged<CustomPassword>(CustomPassword.dirty(pwd)),
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Password',
|
labelText: 'Password',
|
||||||
@@ -59,7 +68,9 @@ class _SignInButton extends StatelessWidget {
|
|||||||
return status.isSubmissionInProgress
|
return status.isSubmissionInProgress
|
||||||
? const CircularProgressIndicator()
|
? const CircularProgressIndicator()
|
||||||
: ElevatedButton(
|
: ElevatedButton(
|
||||||
onPressed: status.isValidated ? () => cubit.signInWithEmailAndPassword() : null,
|
onPressed: status.isValidated
|
||||||
|
? () => cubit.signInWithEmailAndPassword()
|
||||||
|
: null,
|
||||||
child: const Text('Sign in with credentials'),
|
child: const Text('Sign in with credentials'),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|||||||
+15
-8
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sign_up_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:41:27
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 14:58:51
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/presentation/features/sign_up/widgets/sign_up_form.dart';
|
import 'package:example_router/presentation/features/sign_up/widgets/sign_up_form.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|||||||
+18
-9
@@ -1,13 +1,21 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sign_up_form.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 14:41:08
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Wed Nov 16 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/core/constants/form_field.dart';
|
import 'package:example_router/core/constants/form_field.dart';
|
||||||
|
import 'package:example_router/core/utils/custom_password.dart';
|
||||||
import 'package:flutter/material.dart' hide FormField;
|
import 'package:flutter/material.dart' hide FormField;
|
||||||
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';
|
||||||
@@ -40,7 +48,8 @@ class _PasswordInput extends StatelessWidget {
|
|||||||
builder: ((context, cubit, state, field, input) {
|
builder: ((context, cubit, state, field, input) {
|
||||||
return TextField(
|
return TextField(
|
||||||
onChanged: (pwd) {
|
onChanged: (pwd) {
|
||||||
cubit.passwordChanged(pwd);
|
cubit.passwordCustomChanged<CustomPassword>(
|
||||||
|
CustomPassword.dirty(pwd));
|
||||||
cubit.dataChanged(
|
cubit.dataChanged(
|
||||||
AppFormField.confirmedPassword,
|
AppFormField.confirmedPassword,
|
||||||
ConfirmedPassword.dirty(
|
ConfirmedPassword.dirty(
|
||||||
|
|||||||
+19
-9
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sub_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 16:10:05
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Wed Nov 09 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@@ -24,7 +31,10 @@ class SubPage extends StatelessWidget {
|
|||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
||||||
icon: const Icon(Icons.logout_rounded))
|
icon: const Icon(Icons.logout_rounded)),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => context.read<AuthenticationRepository<int>>().refresh(),
|
||||||
|
icon: const Icon(Icons.refresh))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: const Padding(
|
body: const Padding(
|
||||||
|
|||||||
+15
-8
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: welcome_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:33:21
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Wed Nov 09 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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: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';
|
||||||
|
|||||||
@@ -40,15 +40,15 @@ dependencies:
|
|||||||
|
|
||||||
wyatt_form_bloc:
|
wyatt_form_bloc:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
version: 0.2.0
|
version: 0.2.0+2
|
||||||
|
|
||||||
wyatt_architecture:
|
wyatt_architecture:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
version: 0.0.2
|
version: 0.1.0+1
|
||||||
|
|
||||||
wyatt_type_utils:
|
wyatt_type_utils:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
version: 0.0.3+1
|
version: 0.0.4
|
||||||
|
|
||||||
# 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.
|
||||||
|
|||||||
@@ -256,3 +256,24 @@ abstract class GetIdTokenFailureInterface
|
|||||||
|
|
||||||
GetIdTokenFailureInterface.fromCode(super.code) : super.fromCode();
|
GetIdTokenFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class ReauthenticateFailureInterface
|
||||||
|
extends AuthenticationFailureInterface {
|
||||||
|
ReauthenticateFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
|
ReauthenticateFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class UpdateEmailFailureInterface
|
||||||
|
extends AuthenticationFailureInterface {
|
||||||
|
UpdateEmailFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
|
UpdateEmailFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class UpdatePasswordFailureInterface
|
||||||
|
extends AuthenticationFailureInterface {
|
||||||
|
UpdatePasswordFailureInterface(super.code, super.msg);
|
||||||
|
|
||||||
|
UpdatePasswordFailureInterface.fromCode(super.code) : super.fromCode();
|
||||||
|
}
|
||||||
|
|||||||
@@ -277,3 +277,75 @@ class GetIdTokenFailureFirebase extends GetIdTokenFailureInterface {
|
|||||||
|
|
||||||
GetIdTokenFailureFirebase.fromCode(super.code) : super.fromCode();
|
GetIdTokenFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ReauthenticateFailureFirebase extends ReauthenticateFailureInterface {
|
||||||
|
ReauthenticateFailureFirebase([String? code, String? msg])
|
||||||
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
ReauthenticateFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||||
|
switch (code) {
|
||||||
|
case 'user-mismatch':
|
||||||
|
msg = 'Given credential does not correspond to the user.';
|
||||||
|
break;
|
||||||
|
case 'user-not-found':
|
||||||
|
msg = 'User is not found, please create an account.';
|
||||||
|
break;
|
||||||
|
case 'invalid-credential':
|
||||||
|
msg = 'The credential received is malformed or has expired.';
|
||||||
|
break;
|
||||||
|
case 'invalid-email':
|
||||||
|
msg = 'Email is not valid or badly formatted.';
|
||||||
|
break;
|
||||||
|
case 'wrong-password':
|
||||||
|
msg = 'Incorrect password, please try again.';
|
||||||
|
break;
|
||||||
|
case 'invalid-verification-code':
|
||||||
|
msg = 'The credential verification code received is invalid.';
|
||||||
|
break;
|
||||||
|
case 'invalid-verification-id':
|
||||||
|
msg = 'The credential verification ID received is invalid.';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.code = 'unknown';
|
||||||
|
msg = 'An unknown error occurred.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateEmailFailureFirebase extends UpdateEmailFailureInterface {
|
||||||
|
UpdateEmailFailureFirebase([String? code, String? msg])
|
||||||
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
UpdateEmailFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||||
|
switch (code) {
|
||||||
|
case 'invalid-email':
|
||||||
|
msg = 'Email is not valid or badly formatted.';
|
||||||
|
break;
|
||||||
|
case 'email-already-in-use':
|
||||||
|
msg = 'An account already exists for that email.';
|
||||||
|
break;
|
||||||
|
case 'requires-recent-login':
|
||||||
|
msg = "User's last sign-in time does not meet the security threshold.";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.code = 'unknown';
|
||||||
|
msg = 'An unknown error occurred.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdatePasswordFailureFirebase extends UpdatePasswordFailureInterface {
|
||||||
|
UpdatePasswordFailureFirebase([String? code, String? msg])
|
||||||
|
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||||
|
UpdatePasswordFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||||
|
switch (code) {
|
||||||
|
case 'weak-password':
|
||||||
|
msg = 'Please enter a stronger password.';
|
||||||
|
break;
|
||||||
|
case 'requires-recent-login':
|
||||||
|
msg = "User's last sign-in time does not meet the security threshold.";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.code = 'unknown';
|
||||||
|
msg = 'An unknown error occurred.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+61
@@ -21,6 +21,7 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
|||||||
class AuthenticationFirebaseDataSourceImpl
|
class AuthenticationFirebaseDataSourceImpl
|
||||||
extends AuthenticationRemoteDataSource {
|
extends AuthenticationRemoteDataSource {
|
||||||
final FirebaseAuth _firebaseAuth;
|
final FirebaseAuth _firebaseAuth;
|
||||||
|
UserCredential? _latestCreds;
|
||||||
|
|
||||||
AuthenticationFirebaseDataSourceImpl({FirebaseAuth? firebaseAuth})
|
AuthenticationFirebaseDataSourceImpl({FirebaseAuth? firebaseAuth})
|
||||||
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
|
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
|
||||||
@@ -51,6 +52,7 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
);
|
);
|
||||||
|
_latestCreds = userCredential;
|
||||||
final user = userCredential.user;
|
final user = userCredential.user;
|
||||||
if (user.isNotNull) {
|
if (user.isNotNull) {
|
||||||
return _mapper(user!);
|
return _mapper(user!);
|
||||||
@@ -76,6 +78,7 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
);
|
);
|
||||||
|
_latestCreds = userCredential;
|
||||||
final user = userCredential.user;
|
final user = userCredential.user;
|
||||||
if (user.isNotNull) {
|
if (user.isNotNull) {
|
||||||
return _mapper(user!);
|
return _mapper(user!);
|
||||||
@@ -92,6 +95,7 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
@override
|
@override
|
||||||
Future<void> signOut() async {
|
Future<void> signOut() async {
|
||||||
try {
|
try {
|
||||||
|
_latestCreds = null;
|
||||||
await _firebaseAuth.signOut();
|
await _firebaseAuth.signOut();
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
throw SignOutFailureFirebase();
|
throw SignOutFailureFirebase();
|
||||||
@@ -164,6 +168,7 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
Future<Account> signInAnonymously() async {
|
Future<Account> signInAnonymously() async {
|
||||||
try {
|
try {
|
||||||
final userCredential = await _firebaseAuth.signInAnonymously();
|
final userCredential = await _firebaseAuth.signInAnonymously();
|
||||||
|
_latestCreds = userCredential;
|
||||||
final user = userCredential.user;
|
final user = userCredential.user;
|
||||||
if (user.isNotNull) {
|
if (user.isNotNull) {
|
||||||
return _mapper(user!);
|
return _mapper(user!);
|
||||||
@@ -199,4 +204,60 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
throw RefreshFailureFirebase();
|
throw RefreshFailureFirebase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> reauthenticateWithCredential() async {
|
||||||
|
try {
|
||||||
|
if (_latestCreds?.credential != null) {
|
||||||
|
await _firebaseAuth.currentUser
|
||||||
|
?.reauthenticateWithCredential(_latestCreds!.credential!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
final user = _firebaseAuth.currentUser;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw ReauthenticateFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw ReauthenticateFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> updateEmail({required String email}) async {
|
||||||
|
try {
|
||||||
|
await _firebaseAuth.currentUser!.updateEmail(email);
|
||||||
|
final user = _firebaseAuth.currentUser;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw UpdateEmailFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw UpdateEmailFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> updatePassword({required String password}) async {
|
||||||
|
try {
|
||||||
|
await _firebaseAuth.currentUser!.updatePassword(password);
|
||||||
|
final user = _firebaseAuth.currentUser;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw UpdatePasswordFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw UpdatePasswordFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+48
@@ -23,6 +23,7 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
|||||||
class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||||
Pair<Account, String>? _connectedMock;
|
Pair<Account, String>? _connectedMock;
|
||||||
Pair<Account, String>? _registeredMock;
|
Pair<Account, String>? _registeredMock;
|
||||||
|
DateTime _lastSignInTime = DateTime.now();
|
||||||
final StreamController<Account?> _streamAccount = StreamController()
|
final StreamController<Account?> _streamAccount = StreamController()
|
||||||
..add(null);
|
..add(null);
|
||||||
|
|
||||||
@@ -114,9 +115,11 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
|||||||
providerId: 'wyatt',
|
providerId: 'wyatt',
|
||||||
creationTime: creation,
|
creationTime: creation,
|
||||||
lastSignInTime: creation,
|
lastSignInTime: creation,
|
||||||
|
isNewUser: creation == creation,
|
||||||
);
|
);
|
||||||
_streamAccount.add(mock);
|
_streamAccount.add(mock);
|
||||||
_connectedMock = _connectedMock?.copyWith(left: mock);
|
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||||
|
_lastSignInTime = DateTime.now();
|
||||||
return Future.value(mock);
|
return Future.value(mock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,6 +151,7 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
|||||||
}
|
}
|
||||||
_streamAccount.add(_registeredMock!.left);
|
_streamAccount.add(_registeredMock!.left);
|
||||||
_connectedMock = _registeredMock!.copyWith();
|
_connectedMock = _registeredMock!.copyWith();
|
||||||
|
_lastSignInTime = DateTime.now();
|
||||||
return _registeredMock!.left!;
|
return _registeredMock!.left!;
|
||||||
}
|
}
|
||||||
throw SignInWithCredentialFailureFirebase();
|
throw SignInWithCredentialFailureFirebase();
|
||||||
@@ -188,9 +192,12 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
|||||||
email: email,
|
email: email,
|
||||||
creationTime: creation,
|
creationTime: creation,
|
||||||
lastSignInTime: creation,
|
lastSignInTime: creation,
|
||||||
|
isNewUser: creation == creation,
|
||||||
);
|
);
|
||||||
_streamAccount.add(mock);
|
_streamAccount.add(mock);
|
||||||
_registeredMock = Pair(mock, password);
|
_registeredMock = Pair(mock, password);
|
||||||
|
_connectedMock = _registeredMock!.copyWith();
|
||||||
|
_lastSignInTime = DateTime.now();
|
||||||
return Future.value(mock);
|
return Future.value(mock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,4 +209,45 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
|||||||
await _randomDelay();
|
await _randomDelay();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> reauthenticateWithCredential() async {
|
||||||
|
await _randomDelay();
|
||||||
|
if (_connectedMock.isNull) {
|
||||||
|
throw ReauthenticateFailureFirebase();
|
||||||
|
}
|
||||||
|
await refresh();
|
||||||
|
_lastSignInTime = DateTime.now();
|
||||||
|
return Future.value(_connectedMock?.left);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> updateEmail({required String email}) {
|
||||||
|
final before = DateTime.now().subtract(const Duration(seconds: 10));
|
||||||
|
if (_lastSignInTime.isBefore(before)) {
|
||||||
|
throw UpdateEmailFailureFirebase('requires-recent-login');
|
||||||
|
}
|
||||||
|
final refresh = DateTime.now();
|
||||||
|
final mock = (_connectedMock?.left as AccountModel?)
|
||||||
|
?.copyWith(lastSignInTime: refresh, email: email);
|
||||||
|
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||||
|
_registeredMock = _registeredMock?.copyWith(left: mock);
|
||||||
|
_streamAccount.add(mock);
|
||||||
|
return Future.value(_connectedMock?.left);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Account> updatePassword({required String password}) {
|
||||||
|
final before = DateTime.now().subtract(const Duration(seconds: 10));
|
||||||
|
if (_lastSignInTime.isBefore(before)) {
|
||||||
|
throw UpdatePasswordFailureFirebase('requires-recent-login');
|
||||||
|
}
|
||||||
|
final refresh = DateTime.now();
|
||||||
|
final mock = (_connectedMock?.left as AccountModel?)
|
||||||
|
?.copyWith(lastSignInTime: refresh);
|
||||||
|
_connectedMock = _connectedMock?.copyWith(left: mock, right: password);
|
||||||
|
_registeredMock = _registeredMock?.copyWith(left: mock, right: password);
|
||||||
|
_streamAccount.add(mock);
|
||||||
|
return Future.value(_connectedMock?.left);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+108
-34
@@ -14,6 +14,9 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:rxdart/rxdart.dart';
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart';
|
import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart';
|
||||||
import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart';
|
import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart';
|
||||||
@@ -26,12 +29,16 @@ import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication
|
|||||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
typedef OnSignUpSuccess<T> = FutureResult<T?> Function(
|
typedef OnSignUpSuccess<T> = FutureOrResult<T?> Function(
|
||||||
|
AuthenticationRepository<T> repo,
|
||||||
Account? account,
|
Account? account,
|
||||||
WyattForm form,
|
WyattForm form,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef OnAuthChange<T> = FutureResult<T?> Function(Account? account);
|
typedef OnAuthChange<T> = FutureOrResult<T?> Function(
|
||||||
|
AuthenticationRepository<T> repo,
|
||||||
|
Account? account,
|
||||||
|
);
|
||||||
|
|
||||||
class AuthenticationRepositoryImpl<T extends Object>
|
class AuthenticationRepositoryImpl<T extends Object>
|
||||||
extends AuthenticationRepository<T> {
|
extends AuthenticationRepository<T> {
|
||||||
@@ -43,6 +50,10 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
final OnSignUpSuccess<T>? _onSignUpSuccess;
|
final OnSignUpSuccess<T>? _onSignUpSuccess;
|
||||||
|
|
||||||
final OnAuthChange<T>? _onAccountChanges;
|
final OnAuthChange<T>? _onAccountChanges;
|
||||||
|
final StreamController<FutureOrResult<AccountWrapper<T>>> _signUpStream =
|
||||||
|
StreamController();
|
||||||
|
|
||||||
|
bool _pause = false; // Semaphore
|
||||||
|
|
||||||
AuthenticationRepositoryImpl({
|
AuthenticationRepositoryImpl({
|
||||||
required AuthenticationCacheDataSource<T> authenticationCacheDataSource,
|
required AuthenticationCacheDataSource<T> authenticationCacheDataSource,
|
||||||
@@ -50,6 +61,8 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
FormRepository? formRepository,
|
FormRepository? formRepository,
|
||||||
// ignore: strict_raw_type
|
// ignore: strict_raw_type
|
||||||
List<FormInput>? extraSignUpInputs,
|
List<FormInput>? extraSignUpInputs,
|
||||||
|
FormInputValidator<String?, ValidationError>? customEmailValidator,
|
||||||
|
FormInputValidator<String?, ValidationError>? customPasswordValidator,
|
||||||
OnSignUpSuccess<T>? onSignUpSuccess,
|
OnSignUpSuccess<T>? onSignUpSuccess,
|
||||||
OnAuthChange<T>? onAuthChange,
|
OnAuthChange<T>? onAuthChange,
|
||||||
}) : _authenticationLocalDataSource = authenticationCacheDataSource,
|
}) : _authenticationLocalDataSource = authenticationCacheDataSource,
|
||||||
@@ -64,8 +77,14 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
..registerForm(
|
..registerForm(
|
||||||
WyattFormImpl(
|
WyattFormImpl(
|
||||||
[
|
[
|
||||||
FormInput(AuthFormField.email, const Email.pure()),
|
FormInput(
|
||||||
FormInput(AuthFormField.password, const Password.pure())
|
AuthFormField.email,
|
||||||
|
customEmailValidator ?? const Email.pure(),
|
||||||
|
),
|
||||||
|
FormInput(
|
||||||
|
AuthFormField.password,
|
||||||
|
customPasswordValidator ?? const Password.pure(),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
name: AuthFormName.signInForm,
|
name: AuthFormName.signInForm,
|
||||||
),
|
),
|
||||||
@@ -73,8 +92,14 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
..registerForm(
|
..registerForm(
|
||||||
WyattFormImpl(
|
WyattFormImpl(
|
||||||
[
|
[
|
||||||
FormInput(AuthFormField.email, const Email.pure()),
|
FormInput(
|
||||||
FormInput(AuthFormField.password, const Password.pure()),
|
AuthFormField.email,
|
||||||
|
customEmailValidator ?? const Email.pure(),
|
||||||
|
),
|
||||||
|
FormInput(
|
||||||
|
AuthFormField.password,
|
||||||
|
customPasswordValidator ?? const Password.pure(),
|
||||||
|
),
|
||||||
...extraSignUpInputs ?? []
|
...extraSignUpInputs ?? []
|
||||||
],
|
],
|
||||||
name: AuthFormName.signUpForm,
|
name: AuthFormName.signUpForm,
|
||||||
@@ -86,7 +111,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
FormRepository get formRepository => _formRepository;
|
FormRepository get formRepository => _formRepository;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<Account> signInWithEmailAndPassword({
|
FutureOrResult<Account> signInWithEmailAndPassword({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
}) =>
|
}) =>
|
||||||
@@ -104,7 +129,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> signOut() =>
|
FutureOrResult<void> signOut() =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
() async {
|
() async {
|
||||||
await _authenticationRemoteDataSource.signOut();
|
await _authenticationRemoteDataSource.signOut();
|
||||||
@@ -114,12 +139,13 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<Account> signUp({
|
FutureOrResult<Account> signUp({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
}) =>
|
}) =>
|
||||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
() async {
|
() async {
|
||||||
|
_pause = true;
|
||||||
final account = await _authenticationRemoteDataSource.signUp(
|
final account = await _authenticationRemoteDataSource.signUp(
|
||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
@@ -127,42 +153,51 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
await _authenticationLocalDataSource.storeAccount(account);
|
await _authenticationLocalDataSource.storeAccount(account);
|
||||||
if (_onSignUpSuccess.isNotNull) {
|
if (_onSignUpSuccess.isNotNull) {
|
||||||
final dataResult = await _onSignUpSuccess!.call(
|
final dataResult = await _onSignUpSuccess!.call(
|
||||||
|
this,
|
||||||
account,
|
account,
|
||||||
_formRepository.accessForm(AuthFormName.signUpForm).clone(),
|
_formRepository.accessForm(AuthFormName.signUpForm).clone(),
|
||||||
);
|
);
|
||||||
await dataResult.foldAsync(
|
await dataResult.foldAsync(
|
||||||
_authenticationLocalDataSource.storeData,
|
(data) async {
|
||||||
|
await _authenticationLocalDataSource.storeData(data);
|
||||||
|
_signUpStream
|
||||||
|
.add(Future.value(Ok(AccountWrapperModel(account, data))));
|
||||||
|
},
|
||||||
(error) async => error,
|
(error) async => error,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
_pause = false;
|
||||||
return account;
|
return account;
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) {
|
||||||
|
_pause = false;
|
||||||
|
return error;
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> destroyCache() =>
|
FutureOrResult<void> destroyCache() =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
_authenticationLocalDataSource.destroy,
|
_authenticationLocalDataSource.destroy,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<AccountWrapper<T>> getCache() =>
|
FutureOrResult<AccountWrapper<T>> getCache() =>
|
||||||
Result.tryCatchAsync<AccountWrapper<T>, AppException, AppException>(
|
Result.tryCatchAsync<AccountWrapper<T>, AppException, AppException>(
|
||||||
_authenticationLocalDataSource.load,
|
_authenticationLocalDataSource.load,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<Account> getAccount() =>
|
FutureOrResult<Account> getAccount() =>
|
||||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
_authenticationLocalDataSource.loadAccount,
|
_authenticationLocalDataSource.loadAccount,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> setAccount(
|
FutureOrResult<void> setAccount(
|
||||||
Account account,
|
Account account,
|
||||||
) =>
|
) =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
@@ -173,14 +208,14 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<T> getData() =>
|
FutureOrResult<T> getData() =>
|
||||||
Result.tryCatchAsync<T, AppException, AppException>(
|
Result.tryCatchAsync<T, AppException, AppException>(
|
||||||
_authenticationLocalDataSource.loadData,
|
_authenticationLocalDataSource.loadData,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> setData(
|
FutureOrResult<void> setData(
|
||||||
T? data,
|
T? data,
|
||||||
) =>
|
) =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
@@ -191,26 +226,31 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<String> getIdentityToken() =>
|
FutureOrResult<String> getIdentityToken() =>
|
||||||
Result.tryCatchAsync<String, AppException, AppException>(
|
Result.tryCatchAsync<String, AppException, AppException>(
|
||||||
_authenticationRemoteDataSource.getIdentityToken,
|
_authenticationRemoteDataSource.getIdentityToken,
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<FutureResult<AccountWrapper<T>>> streamAccount() =>
|
Stream<FutureOrResult<AccountWrapper<T>>> streamAccount() => MergeStream([
|
||||||
_authenticationRemoteDataSource.streamAccount().map((account) async {
|
_signUpStream.stream.asBroadcastStream(),
|
||||||
if (_onAccountChanges.isNotNull) {
|
_authenticationRemoteDataSource.streamAccount().map((account) async {
|
||||||
final dataResult = await _onAccountChanges!.call(account);
|
if (_onAccountChanges.isNotNull && !_pause) {
|
||||||
return dataResult.map((data) => AccountWrapperModel(account, data));
|
final dataResult = await _onAccountChanges!.call(this, account);
|
||||||
}
|
return dataResult.map((data) {
|
||||||
return Ok<AccountWrapperModel<T>, AppException>(
|
_authenticationLocalDataSource.storeData(data);
|
||||||
AccountWrapperModel<T>(account, null),
|
return AccountWrapperModel(account, data);
|
||||||
);
|
});
|
||||||
});
|
}
|
||||||
|
return Ok<AccountWrapperModel<T>, AppException>(
|
||||||
|
AccountWrapperModel<T>(account, null),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> confirmPasswordReset({
|
FutureOrResult<void> confirmPasswordReset({
|
||||||
required String code,
|
required String code,
|
||||||
required String newPassword,
|
required String newPassword,
|
||||||
}) =>
|
}) =>
|
||||||
@@ -225,7 +265,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> sendEmailVerification() =>
|
FutureOrResult<void> sendEmailVerification() =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
() async {
|
() async {
|
||||||
await _authenticationRemoteDataSource.sendEmailVerification();
|
await _authenticationRemoteDataSource.sendEmailVerification();
|
||||||
@@ -234,7 +274,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> sendPasswordResetEmail({required String email}) =>
|
FutureOrResult<void> sendPasswordResetEmail({required String email}) =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
() async {
|
() async {
|
||||||
await _authenticationRemoteDataSource.sendPasswordResetEmail(
|
await _authenticationRemoteDataSource.sendPasswordResetEmail(
|
||||||
@@ -245,7 +285,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<Account> signInAnonymously() =>
|
FutureOrResult<Account> signInAnonymously() =>
|
||||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
() async {
|
() async {
|
||||||
final account =
|
final account =
|
||||||
@@ -256,7 +296,7 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<bool> verifyPasswordResetCode({required String code}) =>
|
FutureOrResult<bool> verifyPasswordResetCode({required String code}) =>
|
||||||
Result.tryCatchAsync<bool, AppException, AppException>(
|
Result.tryCatchAsync<bool, AppException, AppException>(
|
||||||
() async {
|
() async {
|
||||||
final response = await _authenticationRemoteDataSource
|
final response = await _authenticationRemoteDataSource
|
||||||
@@ -267,11 +307,45 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureResult<void> refresh() =>
|
FutureOrResult<void> refresh() =>
|
||||||
Result.tryCatchAsync<void, AppException, AppException>(
|
Result.tryCatchAsync<void, AppException, AppException>(
|
||||||
() async {
|
() async {
|
||||||
await _authenticationRemoteDataSource.refresh();
|
await _authenticationRemoteDataSource.refresh();
|
||||||
},
|
},
|
||||||
(error) => error,
|
(error) => error,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOrResult<Account> reauthenticateWithCredential() =>
|
||||||
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
final account = await _authenticationRemoteDataSource
|
||||||
|
.reauthenticateWithCredential();
|
||||||
|
return account;
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOrResult<Account> updateEmail({required String email}) =>
|
||||||
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
final account =
|
||||||
|
await _authenticationRemoteDataSource.updateEmail(email: email);
|
||||||
|
return account;
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOrResult<Account> updatePassword({required String password}) =>
|
||||||
|
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||||
|
() async {
|
||||||
|
final account = await _authenticationRemoteDataSource.updatePassword(
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
|
return account;
|
||||||
|
},
|
||||||
|
(error) => error,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -48,4 +48,10 @@ abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource {
|
|||||||
Future<bool> verifyPasswordResetCode({required String code});
|
Future<bool> verifyPasswordResetCode({required String code});
|
||||||
|
|
||||||
Future<Account> signInAnonymously();
|
Future<Account> signInAnonymously();
|
||||||
|
|
||||||
|
Future<Account> updateEmail({required String email});
|
||||||
|
|
||||||
|
Future<Account> updatePassword({required String password});
|
||||||
|
|
||||||
|
Future<Account> reauthenticateWithCredential();
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-17
@@ -30,7 +30,7 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
|||||||
/// Throws a SignUpWithEmailAndPasswordFailureInterface if
|
/// Throws a SignUpWithEmailAndPasswordFailureInterface if
|
||||||
/// an exception occurs.
|
/// an exception occurs.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FutureResult<Account> signUp({
|
FutureOrResult<Account> signUp({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
});
|
});
|
||||||
@@ -40,21 +40,21 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
|||||||
///
|
///
|
||||||
/// Throws a SendEmailVerificationFailureInterface if an exception occurs.
|
/// Throws a SendEmailVerificationFailureInterface if an exception occurs.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FutureResult<void> sendEmailVerification();
|
FutureOrResult<void> sendEmailVerification();
|
||||||
|
|
||||||
/// {@template send_password_reset_email}
|
/// {@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.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FutureResult<void> sendPasswordResetEmail({required String email});
|
FutureOrResult<void> sendPasswordResetEmail({required String email});
|
||||||
|
|
||||||
/// {@template confirm_password_reset}
|
/// {@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.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FutureResult<void> confirmPasswordReset({
|
FutureOrResult<void> confirmPasswordReset({
|
||||||
required String code,
|
required String code,
|
||||||
required String newPassword,
|
required String newPassword,
|
||||||
});
|
});
|
||||||
@@ -64,14 +64,14 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
|||||||
///
|
///
|
||||||
/// Throws a VerifyPasswordResetCodeFailureInterface if an exception occurs.
|
/// Throws a VerifyPasswordResetCodeFailureInterface if an exception occurs.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FutureResult<bool> verifyPasswordResetCode({required String code});
|
FutureOrResult<bool> verifyPasswordResetCode({required String code});
|
||||||
|
|
||||||
/// {@template signin_anom}
|
/// {@template signin_anom}
|
||||||
/// Sign in anonymously.
|
/// Sign in anonymously.
|
||||||
///
|
///
|
||||||
/// Throws a SignInAnonymouslyFailureInterface if an exception occurs.
|
/// Throws a SignInAnonymouslyFailureInterface if an exception occurs.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FutureResult<Account> signInAnonymously();
|
FutureOrResult<Account> signInAnonymously();
|
||||||
|
|
||||||
/// {@template signin_pwd}
|
/// {@template signin_pwd}
|
||||||
/// Signs in with the provided [email] and [password].
|
/// Signs in with the provided [email] and [password].
|
||||||
@@ -79,18 +79,51 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
|||||||
/// Throws a SignInWithEmailAndPasswordFailureInterface if
|
/// Throws a SignInWithEmailAndPasswordFailureInterface if
|
||||||
/// an exception occurs.
|
/// an exception occurs.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FutureResult<Account> signInWithEmailAndPassword({
|
FutureOrResult<Account> signInWithEmailAndPassword({
|
||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// {@template update_email}
|
||||||
|
/// Update or add [email].
|
||||||
|
///
|
||||||
|
/// Throws a UpdateEmailFailureInterface if
|
||||||
|
/// an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureOrResult<Account> updateEmail({
|
||||||
|
required String email,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// {@template update_password}
|
||||||
|
/// Update or add [password].
|
||||||
|
///
|
||||||
|
/// Throws a UpdatePasswordFailureInterface if
|
||||||
|
/// an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureOrResult<Account> updatePassword({
|
||||||
|
required String password,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// {@template reauthenticate}
|
||||||
|
/// Some security-sensitive actions—such as deleting an account,
|
||||||
|
/// setting a primary email address, and changing a password—require that
|
||||||
|
/// the user has recently signed in.
|
||||||
|
///
|
||||||
|
/// Throws a ReauthenticateFailureInterface if
|
||||||
|
/// an exception occurs.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureOrResult<Account> reauthenticateWithCredential();
|
||||||
|
|
||||||
/// {@template signout}
|
/// {@template signout}
|
||||||
/// Signs out the current user.
|
/// Signs out the current user.
|
||||||
/// It also clears the cache and the associated data.
|
/// It also clears the cache and the associated data.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FutureResult<void> signOut();
|
FutureOrResult<void> signOut();
|
||||||
|
|
||||||
FutureResult<void> refresh();
|
/// {@template refresh}
|
||||||
|
/// Refreshes the current user, if signed in.
|
||||||
|
/// {@endtemplate}
|
||||||
|
FutureOrResult<void> refresh();
|
||||||
|
|
||||||
/// {@template stream_account}
|
/// {@template stream_account}
|
||||||
/// Stream of [AccountWrapper] which will emit the current account when
|
/// Stream of [AccountWrapper] which will emit the current account when
|
||||||
@@ -99,16 +132,16 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
|||||||
/// Emits [AccountWrapper] with null [Account] if the user is not
|
/// Emits [AccountWrapper] with null [Account] if the user is not
|
||||||
/// authenticated.
|
/// authenticated.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
Stream<FutureResult<AccountWrapper<T>>> streamAccount();
|
Stream<FutureOrResult<AccountWrapper<T>>> streamAccount();
|
||||||
|
|
||||||
FutureResult<String> getIdentityToken();
|
FutureOrResult<String> getIdentityToken();
|
||||||
|
|
||||||
FutureResult<Account> getAccount();
|
FutureOrResult<Account> getAccount();
|
||||||
FutureResult<void> setAccount(Account account);
|
FutureOrResult<void> setAccount(Account account);
|
||||||
|
|
||||||
FutureResult<T> getData();
|
FutureOrResult<T> getData();
|
||||||
FutureResult<void> setData(T? data);
|
FutureOrResult<void> setData(T? data);
|
||||||
|
|
||||||
FutureResult<AccountWrapper<T>> getCache();
|
FutureOrResult<AccountWrapper<T>> getCache();
|
||||||
FutureResult<void> destroyCache();
|
FutureOrResult<void> destroyCache();
|
||||||
}
|
}
|
||||||
|
|||||||
+13
@@ -56,6 +56,19 @@ class AuthenticationCubit<Extra> extends Cubit<AuthenticationState<Extra>> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If authenticated, re-emits state with data freshly loaded from cache.
|
||||||
|
FutureOr<void> reloadCache() async {
|
||||||
|
if (state.status == AuthenticationStatus.authenticated) {
|
||||||
|
final data = await _authenticationRepository.getCache();
|
||||||
|
emit(
|
||||||
|
data.fold(
|
||||||
|
AuthenticationState<Extra>.authenticated,
|
||||||
|
(error) => state,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FutureOr<void> signOut() {
|
FutureOr<void> signOut() {
|
||||||
// TODO(hpcl): maybe force unauthenticated by emitting an event
|
// TODO(hpcl): maybe force unauthenticated by emitting an event
|
||||||
_authenticationRepository.signOut();
|
_authenticationRepository.signOut();
|
||||||
|
|||||||
+38
-1
@@ -41,15 +41,52 @@ class SignInCubit<Extra> extends FormDataCubit<SignInState> {
|
|||||||
String get formName => AuthFormName.signInForm;
|
String get formName => AuthFormName.signInForm;
|
||||||
|
|
||||||
void emailChanged(String value) {
|
void emailChanged(String value) {
|
||||||
|
final emailValidatorType = _formRepository
|
||||||
|
.accessForm(formName)
|
||||||
|
.validatorOf(AuthFormField.email)
|
||||||
|
.runtimeType;
|
||||||
|
assert(
|
||||||
|
emailValidatorType == Email,
|
||||||
|
'Use emailCustomChanged(...) with validator $emailValidatorType',
|
||||||
|
);
|
||||||
|
|
||||||
final Email email = Email.dirty(value);
|
final Email email = Email.dirty(value);
|
||||||
dataChanged(AuthFormField.email, email);
|
dataChanged(AuthFormField.email, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
void passwordChanged(String value) {
|
void passwordChanged(String value) {
|
||||||
|
final passwordValidatorType = _formRepository
|
||||||
|
.accessForm(formName)
|
||||||
|
.validatorOf(AuthFormField.password)
|
||||||
|
.runtimeType;
|
||||||
|
assert(
|
||||||
|
passwordValidatorType == Password,
|
||||||
|
'Use passwordCustomChanged(...) with validator $passwordValidatorType',
|
||||||
|
);
|
||||||
final Password password = Password.dirty(value);
|
final Password password = Password.dirty(value);
|
||||||
dataChanged(AuthFormField.password, password);
|
dataChanged(AuthFormField.password, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Same as [emailChanged] but with a custom [Validator].
|
||||||
|
///
|
||||||
|
/// Sort of short hand for [dataChanged].
|
||||||
|
void emailCustomChanged<
|
||||||
|
Validator extends FormInputValidator<String?, ValidationError>>(
|
||||||
|
Validator validator,
|
||||||
|
) {
|
||||||
|
dataChanged(AuthFormField.email, validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as [passwordChanged] but with a custom [Validator].
|
||||||
|
///
|
||||||
|
/// Sort of short hand for [dataChanged].
|
||||||
|
void passwordCustomChanged<
|
||||||
|
Validator extends FormInputValidator<String?, ValidationError>>(
|
||||||
|
Validator validator,
|
||||||
|
) {
|
||||||
|
dataChanged(AuthFormField.password, validator);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<void> dataChanged<Value>(
|
FutureOr<void> dataChanged<Value>(
|
||||||
String key,
|
String key,
|
||||||
@@ -114,7 +151,7 @@ class SignInCubit<Extra> extends FormDataCubit<SignInState> {
|
|||||||
if (state.status.isSubmissionInProgress) {
|
if (state.status.isSubmissionInProgress) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.status.isValidated) {
|
if (!state.status.isValidated) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -17,8 +17,10 @@
|
|||||||
part of 'sign_in_cubit.dart';
|
part of 'sign_in_cubit.dart';
|
||||||
|
|
||||||
class SignInState extends FormDataState {
|
class SignInState extends FormDataState {
|
||||||
Email get email => form.validatorOf(AuthFormField.email);
|
FormInputValidator<String?, ValidationError> get email =>
|
||||||
Password get password => form.validatorOf(AuthFormField.password);
|
form.validatorOf(AuthFormField.email);
|
||||||
|
FormInputValidator<String?, ValidationError> get password =>
|
||||||
|
form.validatorOf(AuthFormField.password);
|
||||||
|
|
||||||
const SignInState({
|
const SignInState({
|
||||||
required super.form,
|
required super.form,
|
||||||
|
|||||||
@@ -43,15 +43,52 @@ class SignUpCubit<Extra> extends FormDataCubit<SignUpState> {
|
|||||||
String get formName => AuthFormName.signUpForm;
|
String get formName => AuthFormName.signUpForm;
|
||||||
|
|
||||||
void emailChanged(String value) {
|
void emailChanged(String value) {
|
||||||
|
final emailValidatorType = _formRepository
|
||||||
|
.accessForm(formName)
|
||||||
|
.validatorOf(AuthFormField.email)
|
||||||
|
.runtimeType;
|
||||||
|
assert(
|
||||||
|
emailValidatorType == Email,
|
||||||
|
'Use emailCustomChanged(...) with validator $emailValidatorType',
|
||||||
|
);
|
||||||
|
|
||||||
final Email email = Email.dirty(value);
|
final Email email = Email.dirty(value);
|
||||||
dataChanged(AuthFormField.email, email);
|
dataChanged(AuthFormField.email, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
void passwordChanged(String value) {
|
void passwordChanged(String value) {
|
||||||
|
final passwordValidatorType = _formRepository
|
||||||
|
.accessForm(formName)
|
||||||
|
.validatorOf(AuthFormField.password)
|
||||||
|
.runtimeType;
|
||||||
|
assert(
|
||||||
|
passwordValidatorType == Password,
|
||||||
|
'Use passwordCustomChanged(...) with validator $passwordValidatorType',
|
||||||
|
);
|
||||||
final Password password = Password.dirty(value);
|
final Password password = Password.dirty(value);
|
||||||
dataChanged(AuthFormField.password, password);
|
dataChanged(AuthFormField.password, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Same as [emailChanged] but with a custom [Validator].
|
||||||
|
///
|
||||||
|
/// Sort of short hand for [dataChanged].
|
||||||
|
void emailCustomChanged<
|
||||||
|
Validator extends FormInputValidator<String?, ValidationError>>(
|
||||||
|
Validator validator,
|
||||||
|
) {
|
||||||
|
dataChanged(AuthFormField.email, validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as [passwordChanged] but with a custom [Validator].
|
||||||
|
///
|
||||||
|
/// Sort of short hand for [dataChanged].
|
||||||
|
void passwordCustomChanged<
|
||||||
|
Validator extends FormInputValidator<String?, ValidationError>>(
|
||||||
|
Validator validator,
|
||||||
|
) {
|
||||||
|
dataChanged(AuthFormField.password, validator);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<void> dataChanged<Value>(
|
FutureOr<void> dataChanged<Value>(
|
||||||
String key,
|
String key,
|
||||||
|
|||||||
+4
-2
@@ -17,8 +17,10 @@
|
|||||||
part of 'sign_up_cubit.dart';
|
part of 'sign_up_cubit.dart';
|
||||||
|
|
||||||
class SignUpState extends FormDataState {
|
class SignUpState extends FormDataState {
|
||||||
Email get email => form.validatorOf(AuthFormField.email);
|
FormInputValidator<String?, ValidationError> get email =>
|
||||||
Password get password => form.validatorOf(AuthFormField.password);
|
form.validatorOf(AuthFormField.email);
|
||||||
|
FormInputValidator<String?, ValidationError> get password =>
|
||||||
|
form.validatorOf(AuthFormField.password);
|
||||||
|
|
||||||
const SignUpState({
|
const SignUpState({
|
||||||
required super.form,
|
required super.form,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: wyatt_authentication_bloc
|
name: wyatt_authentication_bloc
|
||||||
description: Authentication BLoC for Flutter
|
description: Authentication BLoC for Flutter
|
||||||
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_authentication_bloc
|
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_authentication_bloc
|
||||||
version: 0.4.0
|
version: 0.4.0+3
|
||||||
|
|
||||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
|
|
||||||
@@ -21,18 +21,19 @@ dependencies:
|
|||||||
flutter_facebook_auth: ^4.3.0
|
flutter_facebook_auth: ^4.3.0
|
||||||
sign_in_with_apple: ^3.3.0
|
sign_in_with_apple: ^3.3.0
|
||||||
twitter_login: ^4.2.3
|
twitter_login: ^4.2.3
|
||||||
|
rxdart: ^0.27.7
|
||||||
|
|
||||||
wyatt_form_bloc:
|
wyatt_form_bloc:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
version: ^0.2.0
|
version: ^0.2.0+2
|
||||||
|
|
||||||
wyatt_architecture:
|
wyatt_architecture:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
version: ^0.0.2
|
version: ^0.1.0+1
|
||||||
|
|
||||||
wyatt_type_utils:
|
wyatt_type_utils:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
version: ^0.0.3+1
|
version: ^0.0.4
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -42,4 +43,4 @@ dev_dependencies:
|
|||||||
|
|
||||||
wyatt_analysis:
|
wyatt_analysis:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
version: 2.2.2
|
version: 2.3.0
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
## 2.0.0
|
||||||
|
|
||||||
|
> Note: This release has breaking changes.
|
||||||
|
|
||||||
|
- **BREAKING** **REFACTOR**: update onWrap label (close #46).
|
||||||
|
|
||||||
## 1.2.0
|
## 1.2.0
|
||||||
|
|
||||||
- **REFACTOR**: general code update.
|
- **REFACTOR**: general code update.
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<!--
|
<!--
|
||||||
* Copyright (C) 2022 WYATT GROUP
|
* Copyright (C) 2022 WYATT GROUP
|
||||||
* Please see the AUTHORS file for details.
|
* Please see the AUTHORS file for details.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* any later version.
|
* any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
@@ -116,11 +116,11 @@ Widget onBuild(BuildContext context, CounterState state) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If needed, you can wrap what depends on the state with the function `onWrap`.
|
If needed, you can wrap what depends on the state with the function `parent`.
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
@override
|
@override
|
||||||
Widget onWrap(BuildContext context, Widget child) {
|
Widget parent(BuildContext context, Widget child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Title'),
|
title: const Text('Title'),
|
||||||
@@ -171,4 +171,4 @@ Widget onBuild(BuildContext context, CounterState state) {
|
|||||||
|
|
||||||
> Note: check **BlocProvider** and **BlocConsumer** documentation for more information.
|
> Note: check **BlocProvider** and **BlocConsumer** documentation for more information.
|
||||||
|
|
||||||
You'll find a more examples in the `example/lib/counter/` directory.
|
You'll find a more examples in the `example/lib/counter/` directory.
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ abstract class BlocProviderScreen<Bloc extends blocbase.Bloc<Event, State>,
|
|||||||
/// [shouldListenWhen] and [shouldBuildWhen] are optional and if they
|
/// [shouldListenWhen] and [shouldBuildWhen] are optional and if they
|
||||||
/// aren't implemented, they will default to `true`.
|
/// aren't implemented, they will default to `true`.
|
||||||
///
|
///
|
||||||
/// An optional [onWrap] can also be implemented. This build a wrapper arround
|
/// An optional [parent] can also be implemented. This build a wrapper arround
|
||||||
/// the built BlocConsumer that is **not** rebuild on each state.
|
/// the built BlocConsumer that is **not** rebuild on each state.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
abstract class BlocConsumerScreen<Bloc extends blocbase.Bloc<Event, State>,
|
abstract class BlocConsumerScreen<Bloc extends blocbase.Bloc<Event, State>,
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
/// [shouldListenWhen] and [shouldBuildWhen] are optional and if they
|
/// [shouldListenWhen] and [shouldBuildWhen] are optional and if they
|
||||||
/// aren't implemented, they will default to `true`.
|
/// aren't implemented, they will default to `true`.
|
||||||
///
|
///
|
||||||
/// An optional [onWrap] can also be implemented. This build a wrapper arround
|
/// An optional [parent] can also be implemented. This build a wrapper arround
|
||||||
/// the built [BlocConsumer] that is **not** rebuild on each state.
|
/// the built [BlocConsumer] that is **not** rebuild on each state.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
abstract class BlocBaseConsumerScreen<Bloc extends BlocBase<State>,
|
abstract class BlocBaseConsumerScreen<Bloc extends BlocBase<State>,
|
||||||
@@ -51,10 +51,10 @@ abstract class BlocBaseConsumerScreen<Bloc extends BlocBase<State>,
|
|||||||
/// [onListen] with the current `state`.
|
/// [onListen] with the current `state`.
|
||||||
bool shouldListenWhen(State previous, State current) => true;
|
bool shouldListenWhen(State previous, State current) => true;
|
||||||
|
|
||||||
/// The [onWrap] function which will be invoked on build.
|
/// The [parent] function which will be invoked on build.
|
||||||
/// The [onWrap] takes a `BuildContext` that **doesn't have** access
|
/// The [parent] takes a `BuildContext` that **doesn't have** access
|
||||||
/// to the [Bloc] or [Cubit].
|
/// to the [Bloc] or [Cubit].
|
||||||
Widget onWrap(BuildContext context, Widget child) => child;
|
Widget parent(BuildContext context, Widget child) => child;
|
||||||
|
|
||||||
/// The [onBuild] function which will be invoked on each widget build.
|
/// The [onBuild] function which will be invoked on each widget build.
|
||||||
/// The [onBuild] takes the `BuildContext` and current `state` and
|
/// The [onBuild] takes the `BuildContext` and current `state` and
|
||||||
@@ -66,7 +66,7 @@ abstract class BlocBaseConsumerScreen<Bloc extends BlocBase<State>,
|
|||||||
void onListen(BuildContext context, State state) {}
|
void onListen(BuildContext context, State state) {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => onWrap(
|
Widget build(BuildContext context) => parent(
|
||||||
context,
|
context,
|
||||||
BlocConsumer<Bloc, State>(
|
BlocConsumer<Bloc, State>(
|
||||||
listenWhen: shouldListenWhen,
|
listenWhen: shouldListenWhen,
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ abstract class CubitProviderScreen<Cubit extends blocbase.Cubit<State>,
|
|||||||
/// [shouldListenWhen] and [shouldBuildWhen] are optional and if they
|
/// [shouldListenWhen] and [shouldBuildWhen] are optional and if they
|
||||||
/// aren't implemented, they will default to `true`.
|
/// aren't implemented, they will default to `true`.
|
||||||
///
|
///
|
||||||
/// An optional [onWrap] can also be implemented. This build a wrapper arround
|
/// An optional [parent] can also be implemented. This build a wrapper arround
|
||||||
/// the built BlocConsumer that is **not** rebuild on each state.
|
/// the built BlocConsumer that is **not** rebuild on each state.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
abstract class CubitConsumerScreen<Cubit extends blocbase.Cubit<State>,
|
abstract class CubitConsumerScreen<Cubit extends blocbase.Cubit<State>,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: wyatt_bloc_helper
|
name: wyatt_bloc_helper
|
||||||
description: Your best friend for blocs in Flutter
|
description: Your best friend for blocs in Flutter
|
||||||
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_bloc_helper
|
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_bloc_helper
|
||||||
version: 1.2.0
|
version: 2.0.0
|
||||||
|
|
||||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
|
|
||||||
@@ -22,4 +22,4 @@ dev_dependencies:
|
|||||||
|
|
||||||
wyatt_analysis:
|
wyatt_analysis:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
version: ^2.2.2
|
version: ^2.3.0
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
# Miscellaneous
|
||||||
|
*.class
|
||||||
|
*.lock
|
||||||
|
*.log
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.buildlog/
|
||||||
|
.history
|
||||||
|
.svn/
|
||||||
|
|
||||||
|
# IntelliJ related
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/*
|
||||||
|
|
||||||
|
# Visual Studio Code related
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# Flutter repo-specific
|
||||||
|
/bin/cache/
|
||||||
|
/bin/mingit/
|
||||||
|
/dev/benchmarks/mega_gallery/
|
||||||
|
/dev/bots/.recipe_deps
|
||||||
|
/dev/bots/android_tools/
|
||||||
|
/dev/docs/doc/
|
||||||
|
/dev/docs/flutter.docs.zip
|
||||||
|
/dev/docs/lib/
|
||||||
|
/dev/docs/pubspec.yaml
|
||||||
|
/dev/integration_tests/**/xcuserdata
|
||||||
|
/dev/integration_tests/**/Pods
|
||||||
|
/packages/flutter/coverage/
|
||||||
|
version
|
||||||
|
|
||||||
|
# packages file containing multi-root paths
|
||||||
|
.packages.generated
|
||||||
|
|
||||||
|
# Flutter/Dart/Pub related
|
||||||
|
**/doc/api/
|
||||||
|
**/ios/Flutter/.last_build_id
|
||||||
|
.dart_tool/
|
||||||
|
.flutter-plugins
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
.packages
|
||||||
|
.pub-cache/
|
||||||
|
.pub/
|
||||||
|
build/
|
||||||
|
flutter_*.png
|
||||||
|
linked_*.ds
|
||||||
|
unlinked.ds
|
||||||
|
unlinked_spec.ds
|
||||||
|
.fvm/
|
||||||
|
|
||||||
|
# Android related
|
||||||
|
**/android/**/gradle-wrapper.jar
|
||||||
|
**/android/.gradle
|
||||||
|
**/android/captures/
|
||||||
|
**/android/gradlew
|
||||||
|
**/android/gradlew.bat
|
||||||
|
**/android/local.properties
|
||||||
|
**/android/**/GeneratedPluginRegistrant.java
|
||||||
|
**/android/key.properties
|
||||||
|
**/android/.idea/
|
||||||
|
*.jks
|
||||||
|
|
||||||
|
# iOS/XCode related
|
||||||
|
**/ios/**/*.mode1v3
|
||||||
|
**/ios/**/*.mode2v3
|
||||||
|
**/ios/**/*.moved-aside
|
||||||
|
**/ios/**/*.pbxuser
|
||||||
|
**/ios/**/*.perspectivev3
|
||||||
|
**/ios/**/*sync/
|
||||||
|
**/ios/**/.sconsign.dblite
|
||||||
|
**/ios/**/.tags*
|
||||||
|
**/ios/**/.vagrant/
|
||||||
|
**/ios/**/DerivedData/
|
||||||
|
**/ios/**/Icon?
|
||||||
|
**/ios/**/Pods/
|
||||||
|
**/ios/**/.symlinks/
|
||||||
|
**/ios/**/profile
|
||||||
|
**/ios/**/xcuserdata
|
||||||
|
**/ios/.generated/
|
||||||
|
**/ios/Flutter/App.framework
|
||||||
|
**/ios/Flutter/Flutter.framework
|
||||||
|
**/ios/Flutter/Flutter.podspec
|
||||||
|
**/ios/Flutter/Generated.xcconfig
|
||||||
|
**/ios/Flutter/app.flx
|
||||||
|
**/ios/Flutter/app.zip
|
||||||
|
**/ios/Flutter/.last_build_id
|
||||||
|
**/ios/Flutter/flutter_assets/
|
||||||
|
**/ios/Flutter/flutter_export_environment.sh
|
||||||
|
**/ios/ServiceDefinitions.json
|
||||||
|
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# Submodules
|
||||||
|
!pubspec.lock
|
||||||
|
packages/**/pubspec.lock
|
||||||
|
|
||||||
|
# Web related
|
||||||
|
lib/generated_plugin_registrant.dart
|
||||||
|
|
||||||
|
# Symbolication related
|
||||||
|
app.*.symbols
|
||||||
|
|
||||||
|
# Obfuscation related
|
||||||
|
app.*.map.json
|
||||||
|
|
||||||
|
# Exceptions to the above rules.
|
||||||
|
!**/ios/**/default.mode1v3
|
||||||
|
!**/ios/**/default.mode2v3
|
||||||
|
!**/ios/**/default.pbxuser
|
||||||
|
!**/ios/**/default.perspectivev3
|
||||||
|
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||||
|
!/dev/ci/**/Gemfile.lock
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.idea/codeStyles/
|
||||||
|
!.idea/dictionaries/
|
||||||
|
!.idea/runConfigurations/
|
||||||
|
|
||||||
|
# Omit committing pubspec.lock for library packages; see
|
||||||
|
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||||
|
pubspec.lock
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch Example",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "dart",
|
||||||
|
"cwd": "example/",
|
||||||
|
"program": "lib/main.dart",
|
||||||
|
"flutterMode": "debug"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
@@ -4,4 +4,5 @@
|
|||||||
# Name/Organization <email address>
|
# Name/Organization <email address>
|
||||||
|
|
||||||
Wyatt Group S.A.S
|
Wyatt Group S.A.S
|
||||||
Hugo Pointcheval <git@pcl.ovh>
|
Hugo Pointcheval <hugo.pointcheval@wyattapp.io>
|
||||||
|
Malo Léon <malo.leon@wyattapp.io>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# 0.0.1
|
||||||
|
|
||||||
|
- TODO: Describe initial release.
|
||||||
@@ -1,55 +1,43 @@
|
|||||||
<!--
|
<!--
|
||||||
* Copyright (C) 2022 WYATT GROUP
|
* Copyright (C) 2022 WYATT GROUP
|
||||||
* Please see the AUTHORS file for details.
|
* Please see the AUTHORS file for details.
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* any later version.
|
* any later version.
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# Dart - CLI Toolbox
|
|
||||||
|
# Flutter - Wyatt Bloc Layout
|
||||||
|
|
||||||
<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-Dart-blue?style=flat-square" alt="SDK: Dart" />
|
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
|
||||||
<img src="https://img.shields.io/badge/Status-WIP-red?style=flat-square" alt="WIP" />
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
Bloc Layout for Flutter.
|
||||||
|
|
||||||
|
|
||||||
TODO: Put a short description of the package here that helps potential users
|
|
||||||
know whether this package might be useful for them.
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
<!-- TODO -->
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
TODO: List prerequisites and provide or point to information on how to
|
<!-- TODO -->
|
||||||
start using the package.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
TODO: Include short and useful examples for package users. Add longer examples
|
<!-- TODO -->
|
||||||
to `/example` folder.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
const like = 'sample';
|
|
||||||
```
|
|
||||||
|
|
||||||
## Additional information
|
|
||||||
|
|
||||||
TODO: Tell users more about the package: where to find more information, how to
|
|
||||||
contribute to the package, how to file issues, what response they can expect
|
|
||||||
from the package authors, and more.
|
|
||||||
@@ -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/>.
|
||||||
|
|
||||||
|
|
||||||
|
include: package:wyatt_analysis/analysis_options.flutter.experimental.yaml
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
class ExampleCubit extends Cubit<CrudState> {
|
||||||
|
ExampleCubit() : super(CrudInitial());
|
||||||
|
|
||||||
|
FutureOr<void> run() async {
|
||||||
|
while (true) {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudLoading());
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudError('Cubit Error'));
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudLoaded<String>('DATA LOADED'));
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudInitial());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureOr<void> runList() async {
|
||||||
|
while (true) {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudLoading());
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudError('Cubit Error'));
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudListLoaded<String>([
|
||||||
|
'DATA LOADED 1',
|
||||||
|
'DATA LOADED 2',
|
||||||
|
'DATA LOADED 3',
|
||||||
|
'DATA LOADED 4'
|
||||||
|
]));
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudInitial());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
class AppThemeComponent {
|
||||||
|
static ComponentThemeData get components => ComponentThemeData.raw(
|
||||||
|
appBar: CustomAppBar(),
|
||||||
|
bottomNavigationBar: CustomBottomBar(),
|
||||||
|
loadingWidget: CustomLoadingWidget(),
|
||||||
|
errorWidget: CustomErrorWidget(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomAppBar extends AppBarComponent {
|
||||||
|
const CustomAppBar({super.title});
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => AppBar(
|
||||||
|
title: Text(title ?? 'Title'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
AppBarComponent? configure(
|
||||||
|
{String? title, Widget? leading, List<Widget>? actions}) =>
|
||||||
|
CustomAppBar(
|
||||||
|
title: title ?? this.title,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomBottomBar extends BottomNavigationBarComponent {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => BottomNavigationBar(
|
||||||
|
items: [
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.e_mobiledata,
|
||||||
|
),
|
||||||
|
label: 'Icon 1'),
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.do_not_disturb_off,
|
||||||
|
),
|
||||||
|
label: 'Icon 2'),
|
||||||
|
],
|
||||||
|
backgroundColor: Colors.blue,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
BottomNavigationBarComponent? configure(
|
||||||
|
{void Function(BuildContext p1, int p2)? onTap,
|
||||||
|
int currentIndex = 0}) =>
|
||||||
|
this;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomLoadingWidget extends LoadingWidgetComponent {
|
||||||
|
CustomLoadingWidget({super.color});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) =>
|
||||||
|
Center(child: CircularProgressIndicator(color: color));
|
||||||
|
|
||||||
|
@override
|
||||||
|
LoadingWidgetComponent? configure({Color? color}) => CustomLoadingWidget(
|
||||||
|
color: color ?? this.color,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomErrorWidget extends ErrorWidgetComponent {
|
||||||
|
CustomErrorWidget({super.error});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => ColoredBox(
|
||||||
|
color: Colors.red,
|
||||||
|
child: Center(child: Text(error ?? 'Error')),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ErrorWidgetComponent? configure({String? error}) => CustomErrorWidget(
|
||||||
|
error: error ?? this.error,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
// 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:bloc_layout_example/bloc/example_cubit.dart';
|
||||||
|
import 'package:bloc_layout_example/components/theme_components.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(const MyApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
const MyApp({super.key});
|
||||||
|
|
||||||
|
// This widget is the root of your application.
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ComponentTheme(
|
||||||
|
componentThemeWidget: AppThemeComponent.components,
|
||||||
|
child: MaterialApp(
|
||||||
|
title: 'Bloc Layout Example',
|
||||||
|
theme: ThemeData(
|
||||||
|
primarySwatch: Colors.blue,
|
||||||
|
),
|
||||||
|
home: Scaffold(
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (_) => ExampleCubit()..run(),
|
||||||
|
child: ExampleCrudStateManagement(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (_) => ExampleCubit()..runList(),
|
||||||
|
child: ExampleListCrudStateManagement(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (_) => ExampleCubit()..run(),
|
||||||
|
child: ExampleFrameLayoutCrudConsumer()),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (_) => ExampleCubit()..runList(),
|
||||||
|
child: ExampleFrameLayoutCrudListConsumer()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleCrudStateManagement
|
||||||
|
extends CrudCubitConsumerScreen<ExampleCubit, String> {
|
||||||
|
@override
|
||||||
|
Widget initialBuilder(BuildContext context, CrudInitial state) =>
|
||||||
|
Container(color: Colors.yellow);
|
||||||
|
@override
|
||||||
|
Widget successBuilder(BuildContext context, CrudLoaded<String> state) =>
|
||||||
|
Center(child: Text(state.data ?? 'errors'));
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleListCrudStateManagement
|
||||||
|
extends CrudListCubitConsumerScreen<ExampleCubit, String> {
|
||||||
|
@override
|
||||||
|
Widget initialBuilder(BuildContext context, CrudInitial state) =>
|
||||||
|
Container(color: Colors.green);
|
||||||
|
@override
|
||||||
|
Widget successBuilder(BuildContext context, CrudListLoaded<String> state) =>
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: state.data.map((e) => Text(e ?? 'error')).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleFrameLayoutCrudConsumer
|
||||||
|
extends FrameLayoutCrudConsumerScreen<ExampleCubit, String> {
|
||||||
|
const ExampleFrameLayoutCrudConsumer()
|
||||||
|
: super(
|
||||||
|
title: 'Example Title',
|
||||||
|
currentIndex: 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget successBuilder(BuildContext context, CrudLoaded<String> state) =>
|
||||||
|
Center(child: Text(state.data ?? 'errors'));
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleFrameLayoutCrudListConsumer
|
||||||
|
extends FrameLayoutCrudListConsumerScreen<ExampleCubit, String> {
|
||||||
|
const ExampleFrameLayoutCrudListConsumer()
|
||||||
|
: super(
|
||||||
|
title: 'Example Title',
|
||||||
|
currentIndex: 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget successBuilder(BuildContext context, CrudListLoaded<String> state) =>
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: state.data.map((e) => Text(e ?? 'error')).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
name: bloc_layout_example
|
||||||
|
description: A new Flutter project.
|
||||||
|
|
||||||
|
# The following line prevents the package from being accidentally published to
|
||||||
|
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||||
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
|
|
||||||
|
# The following defines the version and build number for your application.
|
||||||
|
# A version number is three numbers separated by dots, like 1.2.43
|
||||||
|
# followed by an optional build number separated by a +.
|
||||||
|
# Both the version and the builder number may be overridden in flutter
|
||||||
|
# build by specifying --build-name and --build-number, respectively.
|
||||||
|
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||||
|
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||||
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
|
# Read more about iOS versioning at
|
||||||
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
|
version: 1.0.0+1
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
|
|
||||||
|
# Dependencies specify other packages that your package needs in order to work.
|
||||||
|
# To automatically upgrade your package dependencies to the latest versions
|
||||||
|
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||||
|
# dependencies can be manually updated by changing the version numbers below to
|
||||||
|
# the latest version available on pub.dev. To see which dependencies have newer
|
||||||
|
# versions available, run `flutter pub outdated`.
|
||||||
|
dependencies:
|
||||||
|
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
|
||||||
|
wyatt_bloc_layout:
|
||||||
|
path: "../"
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
|
||||||
|
wyatt_analysis:
|
||||||
|
git:
|
||||||
|
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||||
|
ref: wyatt_analysis-v2.3.0
|
||||||
|
path: packages/wyatt_analysis
|
||||||
|
|
||||||
|
# For information on the generic Dart part of this file, see the
|
||||||
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
|
|
||||||
|
# The following section is specific to Flutter.
|
||||||
|
flutter:
|
||||||
|
|
||||||
|
# The following line ensures that the Material Icons font is
|
||||||
|
# included with your application, so that you can use the icons in
|
||||||
|
# the material Icons class.
|
||||||
|
uses-material-design: true
|
||||||
|
|
||||||
|
# To add assets to your application, add an assets section, like this:
|
||||||
|
# assets:
|
||||||
|
# - images/a_dot_burr.jpeg
|
||||||
|
# - images/a_dot_ham.jpeg
|
||||||
|
|
||||||
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
|
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||||
|
|
||||||
|
# For details regarding adding assets from package dependencies, see
|
||||||
|
# https://flutter.dev/assets-and-images/#from-packages
|
||||||
|
|
||||||
|
# To add custom fonts to your application, add a fonts section here,
|
||||||
|
# in this "flutter" section. Each entry in this list should have a
|
||||||
|
# "family" key with the font family name, and a "fonts" key with a
|
||||||
|
# list giving the asset and other descriptors for the font. For
|
||||||
|
# example:
|
||||||
|
# fonts:
|
||||||
|
# - family: Schyler
|
||||||
|
# fonts:
|
||||||
|
# - asset: fonts/Schyler-Regular.ttf
|
||||||
|
# - asset: fonts/Schyler-Italic.ttf
|
||||||
|
# style: italic
|
||||||
|
# - family: Trajan Pro
|
||||||
|
# fonts:
|
||||||
|
# - asset: fonts/TrajanPro.ttf
|
||||||
|
# - asset: fonts/TrajanPro_Bold.ttf
|
||||||
|
# weight: 700
|
||||||
|
#
|
||||||
|
# For details regarding fonts from package dependencies,
|
||||||
|
# see https://flutter.dev/custom-fonts/#from-packages
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// 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/>.
|
||||||
|
Before Width: | Height: | Size: 917 B After Width: | Height: | Size: 917 B |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user