Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a66db23ace
|
||
|
|
3d7af98ac9
|
||
|
|
b033b97917 | ||
|
|
14b7f31b53
|
||
|
|
403bcafe93
|
||
|
|
21ab6f6021
|
||
|
|
198ecac5da
|
||
|
|
c945cd435e
|
||
|
|
852d29ef0a
|
||
|
|
08383ec03b
|
||
|
|
ee8ce76839
|
||
|
|
f05f2230e9
|
||
|
|
54002beaab
|
||
|
|
d5698fbffc
|
||
|
|
31ad460757
|
||
|
|
4fd2a2a16c
|
||
|
|
6eb40de72c
|
||
|
|
cecbc94a95
|
||
|
|
3820fc4764
|
||
|
|
1b893a5b84
|
||
|
|
72661a343f
|
||
|
|
9ebe8e21dc
|
||
|
|
141f15b444
|
||
|
|
3a8a604a48
|
||
|
|
41493207b3
|
||
|
|
cbc4a2e149
|
||
|
|
7345e415a7
|
||
|
|
ff680614aa
|
||
|
|
3e110e2eb5
|
||
|
|
1ccb0a540e
|
||
|
|
f9da719b91
|
||
|
|
95f41025f4
|
||
|
|
eceda684f0
|
||
|
|
291c195ceb
|
||
|
|
1896497c1a
|
||
|
|
87254ef547
|
||
|
|
da34acd35b
|
||
|
|
d9d0625c67
|
||
|
|
08f789725b
|
||
|
|
33ac5c6280
|
||
|
|
762b9bcd11
|
||
|
|
38480d84f4
|
||
|
|
03a51b97ad
|
||
|
|
1dd49fa080
|
||
|
|
0219e3d557
|
||
|
|
3de7d01173
|
||
|
|
4183da6259
|
||
|
|
1f24a76717
|
||
|
|
0a4a9c2feb
|
||
|
|
92f8b2916c | ||
|
|
3588c3241b
|
||
|
|
9b87eb7ed9
|
||
|
|
6802a56bfc
|
||
|
|
b2a9dac7c6
|
||
|
|
c0a91d6437
|
||
|
|
59bd3edb0d
|
||
|
|
0c920e8245
|
||
|
|
ae3711a136
|
||
|
|
f031b3cbf5
|
||
|
|
68a582c3ad
|
||
|
|
7a056ac38e
|
||
|
|
b89ef3de8a
|
||
|
|
79fdd3c837
|
||
|
|
0d00a67b7c
|
||
|
|
d2d8acdafb
|
||
|
|
2f572db4a4
|
||
|
|
3972c56e55
|
||
|
|
0bc2aa3512
|
||
|
|
94f21a664f
|
||
|
|
6602db215f
|
||
|
|
db67491876
|
||
|
|
35aa6bb7c2
|
||
|
|
067ca4df5d
|
||
|
|
f3c17ad387
|
||
|
|
492d95b164
|
@@ -1,4 +1,10 @@
|
|||||||
{
|
{
|
||||||
|
// Dart
|
||||||
|
"dart.runPubGetOnPubspecChanges": "never",
|
||||||
|
// Gitea
|
||||||
|
"gitea.owner": "Wyatt-FOSS",
|
||||||
|
"gitea.repo": "wyatt-packages",
|
||||||
|
// Header
|
||||||
"psi-header.changes-tracking": {
|
"psi-header.changes-tracking": {
|
||||||
"isActive": true
|
"isActive": true
|
||||||
},
|
},
|
||||||
@@ -67,5 +73,4 @@
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dart.runPubGetOnPubspecChanges": false,
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,6 +3,268 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## 2022-11-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
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.4.0`](#wyatt_authentication_bloc---v040)
|
||||||
|
- [`wyatt_form_bloc` - `v0.2.0`](#wyatt_form_bloc---v020)
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- There are no other changes in this release.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_authentication_bloc` - `v0.4.0`
|
||||||
|
|
||||||
|
- **REFACTOR**: update example with new input builders.
|
||||||
|
- **FIX**: add initial null account event in stream in the mock authentication.
|
||||||
|
- **BREAKING** **FIX**: add signInWithEmailAndPassword and signInAnonymously methods in SignInCubit #26.
|
||||||
|
|
||||||
|
#### `wyatt_form_bloc` - `v0.2.0`
|
||||||
|
|
||||||
|
- **FIX**: disable status selection and rebuild SubmitBuilder on every state changes #28.
|
||||||
|
- **FIX**: fix set operations behaviors.
|
||||||
|
- **FIX**: add nullable validator on boolean value.
|
||||||
|
- **FEAT**: add metadata tag to bypass validation #29.
|
||||||
|
- **FEAT**: add shorthands to access validator status.
|
||||||
|
- **BREAKING** **REFACTOR**: input builders provides FormInput.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-13
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- [`wyatt_crud_bloc` - `v0.1.0`](#wyatt_crud_bloc---v010)
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- There are no other changes in this release.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_crud_bloc` - `v0.1.0`
|
||||||
|
|
||||||
|
- **REFACTOR**: add vscode config.
|
||||||
|
- **FIX**: update example.
|
||||||
|
- **BREAKING** **REFACTOR**: migrate to wyatt architecture.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-11
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.3.0+1`](#wyatt_authentication_bloc---v0301)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_authentication_bloc` - `v0.3.0+1`
|
||||||
|
|
||||||
|
- **FIX**: fix some bugs to validate publishing.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-11
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.3.0`](#wyatt_authentication_bloc---v030)
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- There are no other changes in this release.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_authentication_bloc` - `v0.3.0`
|
||||||
|
|
||||||
|
- **REFACTOR**: use correct deps.
|
||||||
|
- **REFACTOR**: update example with new listeners.
|
||||||
|
- **FIX**: return exception and not throwing it anymore.
|
||||||
|
- **FIX**: exception returns msg as message.
|
||||||
|
- **FEAT**: add fully functionnal mock data source.
|
||||||
|
- **FEAT**: add toString and equality on entities and models.
|
||||||
|
- **BREAKING** **FEAT**: add email verification, password reset support.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-10
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_architecture` - `v0.0.2`](#wyatt_architecture---v002)
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.2.1+6`](#wyatt_authentication_bloc---v0216)
|
||||||
|
- [`wyatt_form_bloc` - `v0.1.0+1`](#wyatt_form_bloc---v0101)
|
||||||
|
|
||||||
|
Packages graduated to a stable release (see pre-releases prior to the stable version for changelog entries):
|
||||||
|
|
||||||
|
- `wyatt_architecture` - `v0.0.2`
|
||||||
|
|
||||||
|
Packages with dependency updates only:
|
||||||
|
|
||||||
|
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||||
|
|
||||||
|
- `wyatt_authentication_bloc` - `v0.2.1+6`
|
||||||
|
- `wyatt_form_bloc` - `v0.1.0+1`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_architecture` - `v0.0.2`
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-10
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_form_bloc` - `v0.1.0`](#wyatt_form_bloc---v010)
|
||||||
|
- [`wyatt_authentication_bloc` - `v0.2.1+5`](#wyatt_authentication_bloc---v0215)
|
||||||
|
|
||||||
|
Packages with dependency updates only:
|
||||||
|
|
||||||
|
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||||
|
|
||||||
|
- `wyatt_authentication_bloc` - `v0.2.1+5`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_form_bloc` - `v0.1.0`
|
||||||
|
|
||||||
|
- **REFACTOR**: refactor simple example.
|
||||||
|
- **FIX**: make cubit custom implementation simpler.
|
||||||
|
- **FEAT**: clean and add toString and equality.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-08
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_architecture` - `v0.0.2-dev.0`](#wyatt_architecture---v002-dev0)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_architecture` - `v0.0.2-dev.0`
|
||||||
|
|
||||||
|
- **FEAT**: add exceptions, datasources, repositories, and usecases.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-07
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_type_utils` - `v0.0.3+1`](#wyatt_type_utils---v0031)
|
||||||
|
- [`wyatt_architecture` - `v0.0.1+2`](#wyatt_architecture---v0012)
|
||||||
|
|
||||||
|
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_architecture` - `v0.0.1+2`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_type_utils` - `v0.0.3+1`
|
||||||
|
|
||||||
|
- **REFACTOR**: rename future result extension.
|
||||||
|
|
||||||
|
|
||||||
|
## 2022-11-06
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`wyatt_bloc_helper` - `v1.2.0`](#wyatt_bloc_helper---v120)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `wyatt_bloc_helper` - `v1.2.0`
|
||||||
|
|
||||||
|
- **REFACTOR**: general code update.
|
||||||
|
- **FEAT**: add init function and multi provider.
|
||||||
|
- **FEAT**: add a lot of docs, fix `onWrap`, and add repo provider.
|
||||||
|
- **FEAT**: add wrap feature.
|
||||||
|
- **DOCS**: add ios example.
|
||||||
|
- **DOCS**: update license.
|
||||||
|
|
||||||
|
|
||||||
## 2022-11-06
|
## 2022-11-06
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
## 0.0.2
|
||||||
|
|
||||||
|
- Graduate package to a stable release. See pre-releases prior to this version for changelog entries.
|
||||||
|
|
||||||
|
## 0.0.2-dev.0
|
||||||
|
|
||||||
|
- **FEAT**: add exceptions, datasources, repositories, and usecases.
|
||||||
|
|
||||||
|
## 0.0.1+2
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
## 0.0.1+1
|
## 0.0.1+1
|
||||||
|
|
||||||
- Update a dependency to the latest release.
|
- Update a dependency to the latest release.
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -16,28 +16,159 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
||||||
# Flutter - Wyatt Architecture
|
# Flutter - Wyatt Architecture
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
|
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
|
||||||
|
|
||||||
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
|
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
|
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Architecture for Flutter.
|
The Wyatt Architecture for Flutter.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
<!-- TODO -->
|
* Usecase
|
||||||
|
* Repository
|
||||||
## Getting started
|
* DataSource
|
||||||
|
* Entity
|
||||||
<!-- TODO -->
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
<!-- TODO -->
|
### Domain
|
||||||
|
|
||||||
|
Create your entities by extending `Entity` :
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class Photo extends Entity {
|
||||||
|
final int id;
|
||||||
|
final String url;
|
||||||
|
|
||||||
|
const Photo({
|
||||||
|
required this.id,
|
||||||
|
required this.url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then create the data sources by extending `BaseLocalDataSource` or `BaseRemoteDataSource` depending the type of data source.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
abstract class PhotoRemoteDataSource extends BaseRemoteDataSource {
|
||||||
|
Future<Photo> getPhoto(int id);
|
||||||
|
Future<List<Photo>> getAllPhotos({int? start, int? limit});
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can create your repositories by extenting `BaseRepository` :
|
||||||
|
|
||||||
|
```dart
|
||||||
|
abstract class PhotoRepository extends BaseRepository {
|
||||||
|
FutureResult<Photo> getPhoto(int id);
|
||||||
|
FutureResult<List<Photo>> getAllPhotos({int? start, int? limit});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Here the repository is just a proxy of the data sources with result type (to have beautiful error handling).
|
||||||
|
|
||||||
|
And finaly create your different usecases by using `UseCase<Parameters, ReturnType>` :
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class RetrieveAllPhoto extends UseCase<QueryParameters, List<Photo>> {
|
||||||
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
|
RetrieveAllPhotos(this._photoRepository);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> call(QueryParameters params) {
|
||||||
|
final photos = _photoRepository.getAllPhotos(
|
||||||
|
start: params.start,
|
||||||
|
limit: params.limit,
|
||||||
|
);
|
||||||
|
return photos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> In fact, here we need a new parameter object, so let's create it:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class QueryParameters {
|
||||||
|
final int? start;
|
||||||
|
final int? limit;
|
||||||
|
|
||||||
|
QueryParameters(this.start, this.limit);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data
|
||||||
|
|
||||||
|
We start by creating models for photos and list of photos. You can use `freezed`. The `PhotoModel` extends `Photo` with some de/serializer capabilities. And those are used only in data layer.
|
||||||
|
|
||||||
|
Then implements your data sources:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class PhotoApiDataSourceImpl extends PhotoRemoteDataSource {
|
||||||
|
final MiddlewareClient _client;
|
||||||
|
|
||||||
|
PhotoApiDataSourceImpl(this._client);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Photo> getPhoto(int id) async {
|
||||||
|
final response = await _client.get(Uri.parse('/photos/$id'));
|
||||||
|
final photo =
|
||||||
|
PhotoModel.fromJson(jsonDecode(response.body) as Map<String, Object?>);
|
||||||
|
return photo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Photo>> getAllPhotos({int? start, int? limit}) async {
|
||||||
|
final startQuery = start.isNotNull ? '_start=$start' : '';
|
||||||
|
final limitQuery = limit.isNotNull ? '_limit=$limit' : '';
|
||||||
|
final delimiter1 =
|
||||||
|
(startQuery.isNotEmpty || limitQuery.isNotEmpty) ? '?' : '';
|
||||||
|
final delimiter2 =
|
||||||
|
(startQuery.isNotEmpty && limitQuery.isNotEmpty) ? '&' : '';
|
||||||
|
final url = '/photos$delimiter1$startQuery$delimiter2$limitQuery';
|
||||||
|
final response = await _client.get(Uri.parse(url));
|
||||||
|
final photos =
|
||||||
|
ListPhotoModel.fromJson({'photos': jsonDecode(response.body)});
|
||||||
|
return photos.photos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> 1: Note that here we use `MiddlewareClient` from our http package.
|
||||||
|
|
||||||
|
> 2: You can create multiple implementations (one real and one mock for example).
|
||||||
|
|
||||||
|
And implement the repositories:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class PhotoRepositoryImpl extends PhotoRepository {
|
||||||
|
final PhotoRemoteDataSource _photoRemoteDataSource;
|
||||||
|
|
||||||
|
PhotoRepositoryImpl(
|
||||||
|
this._photoRemoteDataSource,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<Photo> getPhoto(int id) => Result.tryCatchAsync(
|
||||||
|
() => _photoRemoteDataSource.getPhoto(id),
|
||||||
|
(error) => ServerException('Cannot retrieve photo $id.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> getAllPhotos({int? start, int? limit}) async =>
|
||||||
|
Result.tryCatchAsync(
|
||||||
|
() => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit),
|
||||||
|
(error) => ServerException('Cannot retrieve all photos.'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
That's all.
|
||||||
@@ -15,5 +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/>.
|
||||||
|
|
||||||
|
|
||||||
include: package:wyatt_analysis/analysis_options.flutter.experimental.yaml
|
include: package:wyatt_analysis/analysis_options.flutter.yaml
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
exclude: "!example/**"
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ migrate_working_dir/
|
|||||||
.pub/
|
.pub/
|
||||||
/build/
|
/build/
|
||||||
|
|
||||||
# Web related
|
|
||||||
lib/generated_plugin_registrant.dart
|
|
||||||
|
|
||||||
# Symbolication related
|
# Symbolication related
|
||||||
app.*.symbols
|
app.*.symbols
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
# This file should be version controlled.
|
# This file should be version controlled.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
channel: stable
|
channel: stable
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
@@ -13,11 +13,11 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
- platform: android
|
- platform: ios
|
||||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# example_router
|
# example
|
||||||
|
|
||||||
A new Flutter project.
|
A new Flutter project.
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# This file configures the analyzer, which statically analyzes Dart code to
|
||||||
|
# check for errors, warnings, and lints.
|
||||||
|
#
|
||||||
|
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||||
|
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||||
|
# invoked from the command line by running `flutter analyze`.
|
||||||
|
|
||||||
|
# The following line activates a set of recommended lints for Flutter apps,
|
||||||
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
|
include: package:wyatt_analysis/analysis_options.flutter.yaml
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
- lib/**/*.g.dart
|
||||||
|
- lib/**/*.freezed.dart
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
**/dgph
|
||||||
|
*.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
*.moved-aside
|
||||||
|
*.pbxuser
|
||||||
|
*.perspectivev3
|
||||||
|
**/*sync/
|
||||||
|
.sconsign.dblite
|
||||||
|
.tags*
|
||||||
|
**/.vagrant/
|
||||||
|
**/DerivedData/
|
||||||
|
Icon?
|
||||||
|
**/Pods/
|
||||||
|
**/.symlinks/
|
||||||
|
profile
|
||||||
|
xcuserdata
|
||||||
|
**/.generated/
|
||||||
|
Flutter/App.framework
|
||||||
|
Flutter/Flutter.framework
|
||||||
|
Flutter/Flutter.podspec
|
||||||
|
Flutter/Generated.xcconfig
|
||||||
|
Flutter/ephemeral/
|
||||||
|
Flutter/app.flx
|
||||||
|
Flutter/app.zip
|
||||||
|
Flutter/flutter_assets/
|
||||||
|
Flutter/flutter_export_environment.sh
|
||||||
|
ServiceDefinitions.json
|
||||||
|
Runner/GeneratedPluginRegistrant.*
|
||||||
|
|
||||||
|
# Exceptions to above rules.
|
||||||
|
!default.mode1v3
|
||||||
|
!default.mode2v3
|
||||||
|
!default.pbxuser
|
||||||
|
!default.perspectivev3
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>App</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>io.flutter.flutter.app</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>App</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>MinimumOSVersion</key>
|
||||||
|
<string>11.0</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
|
#include "Generated.xcconfig"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
|
#include "Generated.xcconfig"
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
# platform :ios, '11.0'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_ios_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_ios_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,552 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 50;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
|
9D08BF82920EBA33F23464F5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E946B0F0AD8828F4A7866A40 /* Pods_Runner.framework */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 10;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
name = "Embed Frameworks";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
06DDDDC67790BA3B67292B88 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
082A1BEB8CE5B02C4AABB40D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
0B7103FC187D9782DF68E292 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
E946B0F0AD8828F4A7866A40 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
9D08BF82920EBA33F23464F5 /* Pods_Runner.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
2C514ED236D54DCA1D9DFFC4 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E946B0F0AD8828F4A7866A40 /* Pods_Runner.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||||
|
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Flutter;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146E51CF9000F007C117D = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
|
AD70810057DA8269974A316F /* Pods */,
|
||||||
|
2C514ED236D54DCA1D9DFFC4 /* Frameworks */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146EF1CF9000F007C117D /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||||
|
97C147021CF9000F007C117D /* Info.plist */,
|
||||||
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||||
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||||
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||||
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||||
|
);
|
||||||
|
path = Runner;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
AD70810057DA8269974A316F /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
0B7103FC187D9782DF68E292 /* Pods-Runner.debug.xcconfig */,
|
||||||
|
082A1BEB8CE5B02C4AABB40D /* Pods-Runner.release.xcconfig */,
|
||||||
|
06DDDDC67790BA3B67292B88 /* Pods-Runner.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Pods;
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
|
buildPhases = (
|
||||||
|
FBD8EC5BAF7097A0A31AD63E /* [CP] Check Pods Manifest.lock */,
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
374960F8815E0EA685AB7576 /* [CP] Embed Pods Frameworks */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = Runner;
|
||||||
|
productName = Runner;
|
||||||
|
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastUpgradeCheck = 1300;
|
||||||
|
ORGANIZATIONNAME = "";
|
||||||
|
TargetAttributes = {
|
||||||
|
97C146ED1CF9000F007C117D = {
|
||||||
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
|
LastSwiftMigration = 1100;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||||
|
compatibilityVersion = "Xcode 9.3";
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 97C146E51CF9000F007C117D;
|
||||||
|
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||||
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||||
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||||
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
374960F8815E0EA685AB7576 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Thin Binary";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||||
|
};
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Run Script";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
|
};
|
||||||
|
FBD8EC5BAF7097A0A31AD63E /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||||
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
97C146FB1CF9000F007C117D /* Base */,
|
||||||
|
);
|
||||||
|
name = Main.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
97C147001CF9000F007C117D /* Base */,
|
||||||
|
);
|
||||||
|
name = LaunchScreen.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = 6Z5P8GG96U;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
97C147031CF9000F007C117D /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
97C147041CF9000F007C117D /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
97C147061CF9000F007C117D /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = 6Z5P8GG96U;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
97C147071CF9000F007C117D /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = 6Z5P8GG96U;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
97C147031CF9000F007C117D /* Debug */,
|
||||||
|
97C147041CF9000F007C117D /* Release */,
|
||||||
|
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
97C147061CF9000F007C117D /* Debug */,
|
||||||
|
97C147071CF9000F007C117D /* Release */,
|
||||||
|
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1300"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Profile"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:Runner.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import UIKit
|
||||||
|
import Flutter
|
||||||
|
|
||||||
|
@UIApplicationMain
|
||||||
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
|
override func application(
|
||||||
|
_ application: UIApplication,
|
||||||
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
|
) -> Bool {
|
||||||
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-20x20@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-40x40@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-60x60@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-60x60@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-20x20@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "20x20",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-40x40@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-76x76@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-76x76@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "83.5x83.5",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "1024x1024",
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"filename" : "Icon-App-1024x1024@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 564 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "LaunchImage.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "LaunchImage@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "LaunchImage@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 68 B |
|
After Width: | Height: | Size: 68 B |
|
After Width: | Height: | Size: 68 B |
@@ -0,0 +1,5 @@
|
|||||||
|
# Launch Screen Assets
|
||||||
|
|
||||||
|
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
|
||||||
|
|
||||||
|
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
||||||
|
</imageView>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<image name="LaunchImage" width="168" height="185"/>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Flutter View Controller-->
|
||||||
|
<scene sceneID="tne-QT-ifu">
|
||||||
|
<objects>
|
||||||
|
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Example</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>example</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UIMainStoryboardFile</key>
|
||||||
|
<string>Main</string>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
|
<false/>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#import "GeneratedPluginRegistrant.h"
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// 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:architecture_example/core/dependency_injection/get_it.dart';
|
||||||
|
import 'package:architecture_example/core/utils/app_bloc_observer.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
|
|
||||||
|
Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
Bloc.observer = AppBlocObserver();
|
||||||
|
await GetItInitializer.run();
|
||||||
|
await Hive.initFlutter();
|
||||||
|
|
||||||
|
runApp(
|
||||||
|
await builder.call(),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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/>.
|
||||||
|
|
||||||
|
abstract class HiveBoxes {
|
||||||
|
static const String favorites = 'favorites';
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// 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:architecture_example/data/data_sources/local/favorite_hive_data_source.dart';
|
||||||
|
import 'package:architecture_example/data/data_sources/local/favorite_mock_data_source.dart';
|
||||||
|
import 'package:architecture_example/data/data_sources/remote/album_api_data_source_impl.dart';
|
||||||
|
import 'package:architecture_example/data/data_sources/remote/album_mock_data_source_impl.dart';
|
||||||
|
import 'package:architecture_example/data/data_sources/remote/photo_api_data_source_impl.dart';
|
||||||
|
import 'package:architecture_example/data/data_sources/remote/photo_mock_data_source_impl.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/local/favorite_local_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/album_remote_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/photo_remote_data_source.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:wyatt_http_client/wyatt_http_client.dart';
|
||||||
|
|
||||||
|
final getIt = GetIt.I;
|
||||||
|
|
||||||
|
abstract class GetItInitializer {
|
||||||
|
static Future<void> _initGlobal() async {}
|
||||||
|
static Future<void> _initMocks() async {
|
||||||
|
getIt
|
||||||
|
..registerLazySingleton<FavoriteLocalDataSource>(
|
||||||
|
FavoriteMockDataSource.new,
|
||||||
|
)
|
||||||
|
..registerLazySingleton<PhotoRemoteDataSource>(
|
||||||
|
PhotoMockDataSourceImpl.new,
|
||||||
|
)
|
||||||
|
..registerLazySingleton<AlbumRemoteDataSource>(
|
||||||
|
AlbumMockDataSourceImpl.new,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> _initReal() async {
|
||||||
|
getIt
|
||||||
|
..registerLazySingleton<FavoriteLocalDataSource>(
|
||||||
|
FavoriteHiveDataSource.new,
|
||||||
|
)
|
||||||
|
..registerLazySingleton<MiddlewareClient>(() {
|
||||||
|
final Pipeline pipeline = Pipeline()
|
||||||
|
.addMiddleware(
|
||||||
|
UriPrefixMiddleware(
|
||||||
|
protocol: Protocols.https,
|
||||||
|
authority: 'jsonplaceholder.typicode.com',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.addMiddleware(BodyToJsonMiddleware());
|
||||||
|
return MiddlewareClient(pipeline: pipeline);
|
||||||
|
})
|
||||||
|
..registerLazySingleton<PhotoRemoteDataSource>(
|
||||||
|
() => PhotoApiDataSourceImpl(getIt()),
|
||||||
|
)
|
||||||
|
..registerLazySingleton<AlbumRemoteDataSource>(
|
||||||
|
() => AlbumApiDataSourceImpl(getIt()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> run({bool enableMocks = false}) async {
|
||||||
|
await _initGlobal();
|
||||||
|
enableMocks ? await _initMocks() : await _initReal();
|
||||||
|
|
||||||
|
await getIt.allReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,5 +14,8 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
export 'queries_firestore.dart';
|
enum FetchStatus {
|
||||||
export 'queries_interface.dart';
|
initial,
|
||||||
|
success,
|
||||||
|
failure,
|
||||||
|
}
|
||||||
@@ -14,31 +14,22 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class AppBlocObserver extends BlocObserver {
|
class AppBlocObserver extends BlocObserver {
|
||||||
@override
|
@override
|
||||||
void onEvent(Bloc bloc, Object? event) {
|
void onTransition(
|
||||||
super.onEvent(bloc, event);
|
Bloc<dynamic, dynamic> bloc,
|
||||||
debugPrint(event.toString());
|
Transition<dynamic, dynamic> transition,
|
||||||
}
|
) {
|
||||||
|
|
||||||
@override
|
|
||||||
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
|
|
||||||
debugPrint(error.toString());
|
|
||||||
super.onError(bloc, error, stackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onChange(BlocBase bloc, Change change) {
|
|
||||||
super.onChange(bloc, change);
|
|
||||||
debugPrint('curr:\t${change.currentState}\nnext:\t${change.nextState}');
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onTransition(Bloc bloc, Transition transition) {
|
|
||||||
super.onTransition(bloc, transition);
|
super.onTransition(bloc, transition);
|
||||||
debugPrint(transition.toString());
|
debugPrint(transition.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onError(BlocBase<dynamic> bloc, Object error, StackTrace stackTrace) {
|
||||||
|
debugPrint(error.toString());
|
||||||
|
super.onError(bloc, error, stackTrace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// 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:architecture_example/core/constants/hive_boxes.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/local/favorite_local_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
|
class FavoriteHiveDataSource extends FavoriteLocalDataSource {
|
||||||
|
@override
|
||||||
|
Future<void> addPhotoToFavorites(Photo photo) async {
|
||||||
|
final box = await Hive.openBox<bool>(HiveBoxes.favorites);
|
||||||
|
if (box.containsKey(photo.id)) {
|
||||||
|
throw Exception('Photo already in favorites');
|
||||||
|
}
|
||||||
|
await box.put(photo.id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> checkIfPhotoIsInFavorites(int id) async {
|
||||||
|
final box = await Hive.openBox<bool>(HiveBoxes.favorites);
|
||||||
|
return box.containsKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> deletePhotoFromFavorites(int id) async {
|
||||||
|
final box = await Hive.openBox<bool>(HiveBoxes.favorites);
|
||||||
|
if (!box.containsKey(id)) {
|
||||||
|
throw Exception('Unknown photo');
|
||||||
|
}
|
||||||
|
await box.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<int>> getAllPhotosFromFavorites() async {
|
||||||
|
final box = await Hive.openBox<bool>(HiveBoxes.favorites);
|
||||||
|
return box.keys.cast<int>().toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:architecture_example/data/models/photo_model.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/local/favorite_local_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
|
|
||||||
|
class FavoriteMockDataSource extends FavoriteLocalDataSource {
|
||||||
|
final Map<int, Photo> _mock = {
|
||||||
|
2: const PhotoModel(
|
||||||
|
albumId: 1,
|
||||||
|
id: 2,
|
||||||
|
title: 'Photo 2',
|
||||||
|
url: 'https://via.placeholder.com/600/771796',
|
||||||
|
thumbnailUrl: 'https://via.placeholder.com/150/771796',
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> addPhotoToFavorites(Photo photo) async {
|
||||||
|
if (_mock.containsKey(photo.id)) {
|
||||||
|
throw Exception('Photo already in favorites');
|
||||||
|
}
|
||||||
|
_mock.putIfAbsent(photo.id, () => photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> checkIfPhotoIsInFavorites(int id) async => _mock.containsKey(id);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> deletePhotoFromFavorites(int id) async {
|
||||||
|
if (!_mock.containsKey(id)) {
|
||||||
|
throw Exception('Unknown photo');
|
||||||
|
}
|
||||||
|
_mock.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<int>> getAllPhotosFromFavorites() async {
|
||||||
|
final result = _mock.keys;
|
||||||
|
return result.toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// 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:convert';
|
||||||
|
|
||||||
|
import 'package:architecture_example/data/models/album_model.dart';
|
||||||
|
import 'package:architecture_example/data/models/list_album_model.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/album_remote_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:wyatt_http_client/wyatt_http_client.dart';
|
||||||
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
class AlbumApiDataSourceImpl extends AlbumRemoteDataSource {
|
||||||
|
final MiddlewareClient _client;
|
||||||
|
|
||||||
|
AlbumApiDataSourceImpl(this._client);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Album> getAlbum(int id) async {
|
||||||
|
final response = await _client.get(Uri.parse('/albums/$id'));
|
||||||
|
final album =
|
||||||
|
AlbumModel.fromJson(jsonDecode(response.body) as Map<String, Object?>);
|
||||||
|
return album;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Album>> getAllAlbums({int? start, int? limit}) async {
|
||||||
|
final startQuery = start.isNotNull ? '_start=$start' : '';
|
||||||
|
final limitQuery = limit.isNotNull ? '_limit=$limit' : '';
|
||||||
|
final delimiter1 =
|
||||||
|
(startQuery.isNotEmpty || limitQuery.isNotEmpty) ? '?' : '';
|
||||||
|
final delimiter2 =
|
||||||
|
(startQuery.isNotEmpty && limitQuery.isNotEmpty) ? '&' : '';
|
||||||
|
final url = '/albums$delimiter1$startQuery$delimiter2$limitQuery';
|
||||||
|
final response = await _client.get(Uri.parse(url));
|
||||||
|
final albums =
|
||||||
|
ListAlbumModel.fromJson({'albums': jsonDecode(response.body)});
|
||||||
|
return albums.albums;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
// 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:architecture_example/data/models/album_model.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/album_remote_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
class AlbumMockDataSourceImpl extends AlbumRemoteDataSource {
|
||||||
|
final Map<int, Album> _mock = {
|
||||||
|
1: const AlbumModel(
|
||||||
|
id: 1,
|
||||||
|
userId: 1,
|
||||||
|
title: 'Album 1',
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Album> getAlbum(int id) async {
|
||||||
|
final response = _mock[id];
|
||||||
|
if (response.isNull) {
|
||||||
|
throw Exception('Unknown album');
|
||||||
|
}
|
||||||
|
return response!;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Album>> getAllAlbums({int? start, int? limit}) async {
|
||||||
|
final response = _mock.values;
|
||||||
|
final nullableEnd = (limit != null) ? start ?? 0 + limit : null;
|
||||||
|
return response.toList().sublist(start ?? 0, nullableEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
// 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:convert';
|
||||||
|
|
||||||
|
import 'package:architecture_example/data/models/list_photo_model.dart';
|
||||||
|
import 'package:architecture_example/data/models/photo_model.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/photo_remote_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:wyatt_http_client/wyatt_http_client.dart';
|
||||||
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
class PhotoApiDataSourceImpl extends PhotoRemoteDataSource {
|
||||||
|
final MiddlewareClient _client;
|
||||||
|
|
||||||
|
PhotoApiDataSourceImpl(this._client);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Photo> getPhoto(int id) async {
|
||||||
|
final response = await _client.get(Uri.parse('/photos/$id'));
|
||||||
|
final photo =
|
||||||
|
PhotoModel.fromJson(jsonDecode(response.body) as Map<String, Object?>);
|
||||||
|
return photo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Photo>> getAllPhotos({int? start, int? limit}) async {
|
||||||
|
final startQuery = start.isNotNull ? '_start=$start' : '';
|
||||||
|
final limitQuery = limit.isNotNull ? '_limit=$limit' : '';
|
||||||
|
final delimiter1 =
|
||||||
|
(startQuery.isNotEmpty || limitQuery.isNotEmpty) ? '?' : '';
|
||||||
|
final delimiter2 =
|
||||||
|
(startQuery.isNotEmpty && limitQuery.isNotEmpty) ? '&' : '';
|
||||||
|
final url = '/photos$delimiter1$startQuery$delimiter2$limitQuery';
|
||||||
|
final response = await _client.get(Uri.parse(url));
|
||||||
|
final photos =
|
||||||
|
ListPhotoModel.fromJson({'photos': jsonDecode(response.body)});
|
||||||
|
return photos.photos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Photo>> getPhotosFromAlbum(
|
||||||
|
int albumId, {
|
||||||
|
int? start,
|
||||||
|
int? limit,
|
||||||
|
}) async {
|
||||||
|
final startQuery = start.isNotNull ? '_start=$start' : '';
|
||||||
|
final limitQuery = limit.isNotNull ? '_limit=$limit' : '';
|
||||||
|
final delimiter =
|
||||||
|
(startQuery.isNotEmpty && limitQuery.isNotEmpty) ? '&' : '';
|
||||||
|
final url = '/photos?albumId=$albumId&$startQuery$delimiter$limitQuery';
|
||||||
|
final response = await _client.get(Uri.parse(url));
|
||||||
|
final photos =
|
||||||
|
ListPhotoModel.fromJson({'photos': jsonDecode(response.body)});
|
||||||
|
return photos.photos;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:architecture_example/data/models/photo_model.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/photo_remote_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
class PhotoMockDataSourceImpl extends PhotoRemoteDataSource {
|
||||||
|
final Map<int, Photo> _mock = {
|
||||||
|
1: const PhotoModel(
|
||||||
|
albumId: 1,
|
||||||
|
id: 1,
|
||||||
|
title: 'Photo 1',
|
||||||
|
url: 'https://via.placeholder.com/600/92c952',
|
||||||
|
thumbnailUrl: 'https://via.placeholder.com/150/92c952',
|
||||||
|
),
|
||||||
|
2: const PhotoModel(
|
||||||
|
albumId: 1,
|
||||||
|
id: 2,
|
||||||
|
title: 'Photo 2',
|
||||||
|
url: 'https://via.placeholder.com/600/771796',
|
||||||
|
thumbnailUrl: 'https://via.placeholder.com/150/771796',
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Photo> getPhoto(int id) async {
|
||||||
|
final response = _mock[id];
|
||||||
|
if (response.isNull) {
|
||||||
|
throw Exception('Unknown photo');
|
||||||
|
}
|
||||||
|
return response!;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Photo>> getAllPhotos({int? start, int? limit}) async {
|
||||||
|
final response = _mock.values;
|
||||||
|
final nullableEnd = (limit != null) ? start ?? 0 + limit : null;
|
||||||
|
return response.toList().sublist(start ?? 0, nullableEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Photo>> getPhotosFromAlbum(
|
||||||
|
int albumId, {
|
||||||
|
int? start,
|
||||||
|
int? limit,
|
||||||
|
}) async {
|
||||||
|
// TODO(hpcl): use start and limit
|
||||||
|
final response = _mock.values
|
||||||
|
..where((element) => element.albumId == albumId);
|
||||||
|
return response.toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// 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:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'album_model.freezed.dart';
|
||||||
|
part 'album_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class AlbumModel extends Album with _$AlbumModel {
|
||||||
|
const factory AlbumModel({
|
||||||
|
required int userId,
|
||||||
|
required int id,
|
||||||
|
required String title,
|
||||||
|
}) = _AlbumModel;
|
||||||
|
|
||||||
|
factory AlbumModel.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$AlbumModelFromJson(json);
|
||||||
|
}
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
|
||||||
|
|
||||||
|
part of 'album_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||||
|
|
||||||
|
AlbumModel _$AlbumModelFromJson(Map<String, dynamic> json) {
|
||||||
|
return _AlbumModel.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$AlbumModel {
|
||||||
|
int get userId => throw _privateConstructorUsedError;
|
||||||
|
int get id => throw _privateConstructorUsedError;
|
||||||
|
String get title => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
$AlbumModelCopyWith<AlbumModel> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $AlbumModelCopyWith<$Res> {
|
||||||
|
factory $AlbumModelCopyWith(
|
||||||
|
AlbumModel value, $Res Function(AlbumModel) then) =
|
||||||
|
_$AlbumModelCopyWithImpl<$Res, AlbumModel>;
|
||||||
|
@useResult
|
||||||
|
$Res call({int userId, int id, String title});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$AlbumModelCopyWithImpl<$Res, $Val extends AlbumModel>
|
||||||
|
implements $AlbumModelCopyWith<$Res> {
|
||||||
|
_$AlbumModelCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? userId = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? title = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
userId: null == userId
|
||||||
|
? _value.userId
|
||||||
|
: userId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
title: null == title
|
||||||
|
? _value.title
|
||||||
|
: title // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$_AlbumModelCopyWith<$Res>
|
||||||
|
implements $AlbumModelCopyWith<$Res> {
|
||||||
|
factory _$$_AlbumModelCopyWith(
|
||||||
|
_$_AlbumModel value, $Res Function(_$_AlbumModel) then) =
|
||||||
|
__$$_AlbumModelCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({int userId, int id, String title});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$_AlbumModelCopyWithImpl<$Res>
|
||||||
|
extends _$AlbumModelCopyWithImpl<$Res, _$_AlbumModel>
|
||||||
|
implements _$$_AlbumModelCopyWith<$Res> {
|
||||||
|
__$$_AlbumModelCopyWithImpl(
|
||||||
|
_$_AlbumModel _value, $Res Function(_$_AlbumModel) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? userId = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? title = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$_AlbumModel(
|
||||||
|
userId: null == userId
|
||||||
|
? _value.userId
|
||||||
|
: userId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
title: null == title
|
||||||
|
? _value.title
|
||||||
|
: title // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$_AlbumModel implements _AlbumModel {
|
||||||
|
const _$_AlbumModel(
|
||||||
|
{required this.userId, required this.id, required this.title});
|
||||||
|
|
||||||
|
factory _$_AlbumModel.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$_AlbumModelFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final int userId;
|
||||||
|
@override
|
||||||
|
final int id;
|
||||||
|
@override
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AlbumModel(userId: $userId, id: $id, title: $title)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$_AlbumModelCopyWith<_$_AlbumModel> get copyWith =>
|
||||||
|
__$$_AlbumModelCopyWithImpl<_$_AlbumModel>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$_AlbumModelToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _AlbumModel implements AlbumModel {
|
||||||
|
const factory _AlbumModel(
|
||||||
|
{required final int userId,
|
||||||
|
required final int id,
|
||||||
|
required final String title}) = _$_AlbumModel;
|
||||||
|
|
||||||
|
factory _AlbumModel.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$_AlbumModel.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get userId;
|
||||||
|
@override
|
||||||
|
int get id;
|
||||||
|
@override
|
||||||
|
String get title;
|
||||||
|
@override
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$$_AlbumModelCopyWith<_$_AlbumModel> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'album_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$_AlbumModel _$$_AlbumModelFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$_AlbumModel(
|
||||||
|
userId: json['userId'] as int,
|
||||||
|
id: json['id'] as int,
|
||||||
|
title: json['title'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$_AlbumModelToJson(_$_AlbumModel instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'userId': instance.userId,
|
||||||
|
'id': instance.id,
|
||||||
|
'title': instance.title,
|
||||||
|
};
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:architecture_example/data/models/album_model.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'list_album_model.freezed.dart';
|
||||||
|
part 'list_album_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ListAlbumModel with _$ListAlbumModel {
|
||||||
|
const factory ListAlbumModel({
|
||||||
|
required List<AlbumModel> albums,
|
||||||
|
}) = _ListAlbumModel;
|
||||||
|
|
||||||
|
factory ListAlbumModel.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$ListAlbumModelFromJson(json);
|
||||||
|
}
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
|
||||||
|
|
||||||
|
part of 'list_album_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||||
|
|
||||||
|
ListAlbumModel _$ListAlbumModelFromJson(Map<String, dynamic> json) {
|
||||||
|
return _ListAlbumModel.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ListAlbumModel {
|
||||||
|
List<AlbumModel> get albums => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
$ListAlbumModelCopyWith<ListAlbumModel> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $ListAlbumModelCopyWith<$Res> {
|
||||||
|
factory $ListAlbumModelCopyWith(
|
||||||
|
ListAlbumModel value, $Res Function(ListAlbumModel) then) =
|
||||||
|
_$ListAlbumModelCopyWithImpl<$Res, ListAlbumModel>;
|
||||||
|
@useResult
|
||||||
|
$Res call({List<AlbumModel> albums});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$ListAlbumModelCopyWithImpl<$Res, $Val extends ListAlbumModel>
|
||||||
|
implements $ListAlbumModelCopyWith<$Res> {
|
||||||
|
_$ListAlbumModelCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? albums = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
albums: null == albums
|
||||||
|
? _value.albums
|
||||||
|
: albums // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<AlbumModel>,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$_ListAlbumModelCopyWith<$Res>
|
||||||
|
implements $ListAlbumModelCopyWith<$Res> {
|
||||||
|
factory _$$_ListAlbumModelCopyWith(
|
||||||
|
_$_ListAlbumModel value, $Res Function(_$_ListAlbumModel) then) =
|
||||||
|
__$$_ListAlbumModelCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({List<AlbumModel> albums});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$_ListAlbumModelCopyWithImpl<$Res>
|
||||||
|
extends _$ListAlbumModelCopyWithImpl<$Res, _$_ListAlbumModel>
|
||||||
|
implements _$$_ListAlbumModelCopyWith<$Res> {
|
||||||
|
__$$_ListAlbumModelCopyWithImpl(
|
||||||
|
_$_ListAlbumModel _value, $Res Function(_$_ListAlbumModel) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? albums = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$_ListAlbumModel(
|
||||||
|
albums: null == albums
|
||||||
|
? _value._albums
|
||||||
|
: albums // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<AlbumModel>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$_ListAlbumModel implements _ListAlbumModel {
|
||||||
|
const _$_ListAlbumModel({required final List<AlbumModel> albums})
|
||||||
|
: _albums = albums;
|
||||||
|
|
||||||
|
factory _$_ListAlbumModel.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$_ListAlbumModelFromJson(json);
|
||||||
|
|
||||||
|
final List<AlbumModel> _albums;
|
||||||
|
@override
|
||||||
|
List<AlbumModel> get albums {
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_albums);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ListAlbumModel(albums: $albums)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(dynamic other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$_ListAlbumModel &&
|
||||||
|
const DeepCollectionEquality().equals(other._albums, _albums));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
Object.hash(runtimeType, const DeepCollectionEquality().hash(_albums));
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$_ListAlbumModelCopyWith<_$_ListAlbumModel> get copyWith =>
|
||||||
|
__$$_ListAlbumModelCopyWithImpl<_$_ListAlbumModel>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$_ListAlbumModelToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _ListAlbumModel implements ListAlbumModel {
|
||||||
|
const factory _ListAlbumModel({required final List<AlbumModel> albums}) =
|
||||||
|
_$_ListAlbumModel;
|
||||||
|
|
||||||
|
factory _ListAlbumModel.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$_ListAlbumModel.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<AlbumModel> get albums;
|
||||||
|
@override
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$$_ListAlbumModelCopyWith<_$_ListAlbumModel> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'list_album_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$_ListAlbumModel _$$_ListAlbumModelFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$_ListAlbumModel(
|
||||||
|
albums: (json['albums'] as List<dynamic>)
|
||||||
|
.map((e) => AlbumModel.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$_ListAlbumModelToJson(_$_ListAlbumModel instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'albums': instance.albums,
|
||||||
|
};
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import 'package:architecture_example/data/models/photo_model.dart';
|
||||||
|
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'list_photo_model.freezed.dart';
|
||||||
|
part 'list_photo_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ListPhotoModel with _$ListPhotoModel {
|
||||||
|
const factory ListPhotoModel({
|
||||||
|
required List<PhotoModel> photos,
|
||||||
|
}) = _ListPhotoModel;
|
||||||
|
|
||||||
|
factory ListPhotoModel.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$ListPhotoModelFromJson(json);
|
||||||
|
}
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
|
||||||
|
|
||||||
|
part of 'list_photo_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||||
|
|
||||||
|
ListPhotoModel _$ListPhotoModelFromJson(Map<String, dynamic> json) {
|
||||||
|
return _ListPhotoModel.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ListPhotoModel {
|
||||||
|
List<PhotoModel> get photos => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
$ListPhotoModelCopyWith<ListPhotoModel> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $ListPhotoModelCopyWith<$Res> {
|
||||||
|
factory $ListPhotoModelCopyWith(
|
||||||
|
ListPhotoModel value, $Res Function(ListPhotoModel) then) =
|
||||||
|
_$ListPhotoModelCopyWithImpl<$Res, ListPhotoModel>;
|
||||||
|
@useResult
|
||||||
|
$Res call({List<PhotoModel> photos});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$ListPhotoModelCopyWithImpl<$Res, $Val extends ListPhotoModel>
|
||||||
|
implements $ListPhotoModelCopyWith<$Res> {
|
||||||
|
_$ListPhotoModelCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? photos = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
photos: null == photos
|
||||||
|
? _value.photos
|
||||||
|
: photos // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<PhotoModel>,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$_ListPhotoModelCopyWith<$Res>
|
||||||
|
implements $ListPhotoModelCopyWith<$Res> {
|
||||||
|
factory _$$_ListPhotoModelCopyWith(
|
||||||
|
_$_ListPhotoModel value, $Res Function(_$_ListPhotoModel) then) =
|
||||||
|
__$$_ListPhotoModelCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({List<PhotoModel> photos});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$_ListPhotoModelCopyWithImpl<$Res>
|
||||||
|
extends _$ListPhotoModelCopyWithImpl<$Res, _$_ListPhotoModel>
|
||||||
|
implements _$$_ListPhotoModelCopyWith<$Res> {
|
||||||
|
__$$_ListPhotoModelCopyWithImpl(
|
||||||
|
_$_ListPhotoModel _value, $Res Function(_$_ListPhotoModel) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? photos = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$_ListPhotoModel(
|
||||||
|
photos: null == photos
|
||||||
|
? _value._photos
|
||||||
|
: photos // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<PhotoModel>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$_ListPhotoModel implements _ListPhotoModel {
|
||||||
|
const _$_ListPhotoModel({required final List<PhotoModel> photos})
|
||||||
|
: _photos = photos;
|
||||||
|
|
||||||
|
factory _$_ListPhotoModel.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$_ListPhotoModelFromJson(json);
|
||||||
|
|
||||||
|
final List<PhotoModel> _photos;
|
||||||
|
@override
|
||||||
|
List<PhotoModel> get photos {
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_photos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ListPhotoModel(photos: $photos)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(dynamic other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$_ListPhotoModel &&
|
||||||
|
const DeepCollectionEquality().equals(other._photos, _photos));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
Object.hash(runtimeType, const DeepCollectionEquality().hash(_photos));
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$_ListPhotoModelCopyWith<_$_ListPhotoModel> get copyWith =>
|
||||||
|
__$$_ListPhotoModelCopyWithImpl<_$_ListPhotoModel>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$_ListPhotoModelToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _ListPhotoModel implements ListPhotoModel {
|
||||||
|
const factory _ListPhotoModel({required final List<PhotoModel> photos}) =
|
||||||
|
_$_ListPhotoModel;
|
||||||
|
|
||||||
|
factory _ListPhotoModel.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$_ListPhotoModel.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<PhotoModel> get photos;
|
||||||
|
@override
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$$_ListPhotoModelCopyWith<_$_ListPhotoModel> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'list_photo_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$_ListPhotoModel _$$_ListPhotoModelFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$_ListPhotoModel(
|
||||||
|
photos: (json['photos'] as List<dynamic>)
|
||||||
|
.map((e) => PhotoModel.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$_ListPhotoModelToJson(_$_ListPhotoModel instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'photos': instance.photos,
|
||||||
|
};
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// 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:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'photo_model.freezed.dart';
|
||||||
|
part 'photo_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class PhotoModel extends Photo with _$PhotoModel {
|
||||||
|
const factory PhotoModel({
|
||||||
|
required int albumId,
|
||||||
|
required int id,
|
||||||
|
required String title,
|
||||||
|
required String url,
|
||||||
|
required String thumbnailUrl,
|
||||||
|
}) = _PhotoModel;
|
||||||
|
|
||||||
|
factory PhotoModel.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$PhotoModelFromJson(json);
|
||||||
|
}
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
|
||||||
|
|
||||||
|
part of 'photo_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||||
|
|
||||||
|
PhotoModel _$PhotoModelFromJson(Map<String, dynamic> json) {
|
||||||
|
return _PhotoModel.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$PhotoModel {
|
||||||
|
int get albumId => throw _privateConstructorUsedError;
|
||||||
|
int get id => throw _privateConstructorUsedError;
|
||||||
|
String get title => throw _privateConstructorUsedError;
|
||||||
|
String get url => throw _privateConstructorUsedError;
|
||||||
|
String get thumbnailUrl => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
$PhotoModelCopyWith<PhotoModel> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $PhotoModelCopyWith<$Res> {
|
||||||
|
factory $PhotoModelCopyWith(
|
||||||
|
PhotoModel value, $Res Function(PhotoModel) then) =
|
||||||
|
_$PhotoModelCopyWithImpl<$Res, PhotoModel>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{int albumId, int id, String title, String url, String thumbnailUrl});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$PhotoModelCopyWithImpl<$Res, $Val extends PhotoModel>
|
||||||
|
implements $PhotoModelCopyWith<$Res> {
|
||||||
|
_$PhotoModelCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? albumId = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? title = null,
|
||||||
|
Object? url = null,
|
||||||
|
Object? thumbnailUrl = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
albumId: null == albumId
|
||||||
|
? _value.albumId
|
||||||
|
: albumId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
title: null == title
|
||||||
|
? _value.title
|
||||||
|
: title // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
url: null == url
|
||||||
|
? _value.url
|
||||||
|
: url // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
thumbnailUrl: null == thumbnailUrl
|
||||||
|
? _value.thumbnailUrl
|
||||||
|
: thumbnailUrl // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$_PhotoModelCopyWith<$Res>
|
||||||
|
implements $PhotoModelCopyWith<$Res> {
|
||||||
|
factory _$$_PhotoModelCopyWith(
|
||||||
|
_$_PhotoModel value, $Res Function(_$_PhotoModel) then) =
|
||||||
|
__$$_PhotoModelCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{int albumId, int id, String title, String url, String thumbnailUrl});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$_PhotoModelCopyWithImpl<$Res>
|
||||||
|
extends _$PhotoModelCopyWithImpl<$Res, _$_PhotoModel>
|
||||||
|
implements _$$_PhotoModelCopyWith<$Res> {
|
||||||
|
__$$_PhotoModelCopyWithImpl(
|
||||||
|
_$_PhotoModel _value, $Res Function(_$_PhotoModel) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? albumId = null,
|
||||||
|
Object? id = null,
|
||||||
|
Object? title = null,
|
||||||
|
Object? url = null,
|
||||||
|
Object? thumbnailUrl = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$_PhotoModel(
|
||||||
|
albumId: null == albumId
|
||||||
|
? _value.albumId
|
||||||
|
: albumId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
title: null == title
|
||||||
|
? _value.title
|
||||||
|
: title // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
url: null == url
|
||||||
|
? _value.url
|
||||||
|
: url // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
thumbnailUrl: null == thumbnailUrl
|
||||||
|
? _value.thumbnailUrl
|
||||||
|
: thumbnailUrl // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$_PhotoModel implements _PhotoModel {
|
||||||
|
const _$_PhotoModel(
|
||||||
|
{required this.albumId,
|
||||||
|
required this.id,
|
||||||
|
required this.title,
|
||||||
|
required this.url,
|
||||||
|
required this.thumbnailUrl});
|
||||||
|
|
||||||
|
factory _$_PhotoModel.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$_PhotoModelFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final int albumId;
|
||||||
|
@override
|
||||||
|
final int id;
|
||||||
|
@override
|
||||||
|
final String title;
|
||||||
|
@override
|
||||||
|
final String url;
|
||||||
|
@override
|
||||||
|
final String thumbnailUrl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'PhotoModel(albumId: $albumId, id: $id, title: $title, url: $url, thumbnailUrl: $thumbnailUrl)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$_PhotoModelCopyWith<_$_PhotoModel> get copyWith =>
|
||||||
|
__$$_PhotoModelCopyWithImpl<_$_PhotoModel>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$_PhotoModelToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _PhotoModel implements PhotoModel {
|
||||||
|
const factory _PhotoModel(
|
||||||
|
{required final int albumId,
|
||||||
|
required final int id,
|
||||||
|
required final String title,
|
||||||
|
required final String url,
|
||||||
|
required final String thumbnailUrl}) = _$_PhotoModel;
|
||||||
|
|
||||||
|
factory _PhotoModel.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$_PhotoModel.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get albumId;
|
||||||
|
@override
|
||||||
|
int get id;
|
||||||
|
@override
|
||||||
|
String get title;
|
||||||
|
@override
|
||||||
|
String get url;
|
||||||
|
@override
|
||||||
|
String get thumbnailUrl;
|
||||||
|
@override
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$$_PhotoModelCopyWith<_$_PhotoModel> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'photo_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$_PhotoModel _$$_PhotoModelFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$_PhotoModel(
|
||||||
|
albumId: json['albumId'] as int,
|
||||||
|
id: json['id'] as int,
|
||||||
|
title: json['title'] as String,
|
||||||
|
url: json['url'] as String,
|
||||||
|
thumbnailUrl: json['thumbnailUrl'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$_PhotoModelToJson(_$_PhotoModel instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'albumId': instance.albumId,
|
||||||
|
'id': instance.id,
|
||||||
|
'title': instance.title,
|
||||||
|
'url': instance.url,
|
||||||
|
'thumbnailUrl': instance.thumbnailUrl,
|
||||||
|
};
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
// 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:architecture_example/domain/data_sources/local/favorite_local_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/album_remote_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/photo_remote_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||||
|
|
||||||
|
class PhotoRepositoryImpl extends PhotoRepository {
|
||||||
|
final PhotoRemoteDataSource _photoRemoteDataSource;
|
||||||
|
final AlbumRemoteDataSource _albumRemoteDataSource;
|
||||||
|
final FavoriteLocalDataSource _favoriteLocalDataSource;
|
||||||
|
|
||||||
|
PhotoRepositoryImpl(
|
||||||
|
this._photoRemoteDataSource,
|
||||||
|
this._albumRemoteDataSource,
|
||||||
|
this._favoriteLocalDataSource,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> addPhotoToFavorites(Photo photo) => Result.tryCatchAsync(
|
||||||
|
() => _favoriteLocalDataSource.addPhotoToFavorites(photo),
|
||||||
|
(error) => ClientException('Cannot add photo to favorites.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<bool> checkIfPhotoIsInFavorites(int id) => Result.tryCatchAsync(
|
||||||
|
() => _favoriteLocalDataSource.checkIfPhotoIsInFavorites(id),
|
||||||
|
(error) =>
|
||||||
|
ClientException('Cannot check if photo `$id` is in favorites.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<void> deletePhotoFromFavorites(int id) => Result.tryCatchAsync(
|
||||||
|
() => _favoriteLocalDataSource.deletePhotoFromFavorites(id),
|
||||||
|
(error) => ClientException('Cannot delete photo `$id` from favorites.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<Album> getAlbum(int id) => Result.tryCatchAsync(
|
||||||
|
() => _albumRemoteDataSource.getAlbum(id),
|
||||||
|
(error) => ServerException('Cannot retrieve album $id.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Album>> getAllAlbums({int? start, int? limit}) =>
|
||||||
|
Result.tryCatchAsync(
|
||||||
|
() => _albumRemoteDataSource.getAllAlbums(start: start, limit: limit),
|
||||||
|
(error) => ServerException('Cannot retrieve all albums.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> getAllPhotos({int? start, int? limit}) async =>
|
||||||
|
Result.tryCatchAsync(
|
||||||
|
() => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit),
|
||||||
|
(error) => ServerException('Cannot retrieve all photos.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> getAllPhotosFromFavorites() async {
|
||||||
|
try {
|
||||||
|
final response = <Photo>[];
|
||||||
|
final favorites =
|
||||||
|
await _favoriteLocalDataSource.getAllPhotosFromFavorites();
|
||||||
|
final photos = await _photoRemoteDataSource.getAllPhotos();
|
||||||
|
|
||||||
|
for (final photo in photos) {
|
||||||
|
if (favorites.any((favId) => photo.id == favId)) {
|
||||||
|
response.add(photo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(response);
|
||||||
|
} catch (_) {
|
||||||
|
return Err(
|
||||||
|
ClientException('Cannot retrieve all photos from favorites.'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<Photo> getPhoto(int id) => Result.tryCatchAsync(
|
||||||
|
() => _photoRemoteDataSource.getPhoto(id),
|
||||||
|
(error) => ServerException('Cannot retrieve photo $id.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> getPhotosFromAlbum(
|
||||||
|
int albumId, {
|
||||||
|
int? start,
|
||||||
|
int? limit,
|
||||||
|
}) async =>
|
||||||
|
Result.tryCatchAsync(
|
||||||
|
() => _photoRemoteDataSource.getPhotosFromAlbum(
|
||||||
|
albumId,
|
||||||
|
start: start,
|
||||||
|
limit: limit,
|
||||||
|
),
|
||||||
|
(error) =>
|
||||||
|
ServerException('Cannot retrieve all photos from album $albumId'),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// 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:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
abstract class FavoriteLocalDataSource extends BaseLocalDataSource {
|
||||||
|
Future<void> addPhotoToFavorites(Photo photo);
|
||||||
|
Future<void> deletePhotoFromFavorites(int id);
|
||||||
|
Future<List<int>> getAllPhotosFromFavorites();
|
||||||
|
Future<bool> checkIfPhotoIsInFavorites(int id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// 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:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
abstract class AlbumRemoteDataSource extends BaseRemoteDataSource {
|
||||||
|
Future<Album> getAlbum(int id);
|
||||||
|
Future<List<Album>> getAllAlbums({int? start, int? limit});
|
||||||
|
}
|
||||||
@@ -14,11 +14,11 @@
|
|||||||
// 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/>.
|
||||||
|
|
||||||
const String formFieldName = 'name';
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
const String formFieldPhone = 'phone';
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
const String formFieldPro = 'isPro';
|
|
||||||
const String formFieldConfirmedPassword = 'confirmedPassword';
|
|
||||||
const String formFieldSiren = 'siren';
|
|
||||||
const String formFieldIban = 'iban';
|
|
||||||
|
|
||||||
const String firestoreCollectionUsers = 'authentication_bloc_users';
|
abstract class PhotoRemoteDataSource extends BaseRemoteDataSource {
|
||||||
|
Future<Photo> getPhoto(int id);
|
||||||
|
Future<List<Photo>> getAllPhotos({int? start, int? limit});
|
||||||
|
Future<List<Photo>> getPhotosFromAlbum(int albumId, {int? start, int? limit});
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class Album extends Entity {
|
||||||
|
final int userId;
|
||||||
|
final int id;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
const Album({
|
||||||
|
required this.userId,
|
||||||
|
required this.id,
|
||||||
|
required this.title,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant Album other) {
|
||||||
|
if (identical(this, other)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return other.userId == userId && other.id == id && other.title == title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => userId.hashCode ^ id.hashCode ^ title.hashCode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class Photo extends Entity {
|
||||||
|
final int albumId;
|
||||||
|
final int id;
|
||||||
|
final String title;
|
||||||
|
final String url;
|
||||||
|
final String thumbnailUrl;
|
||||||
|
|
||||||
|
const Photo({
|
||||||
|
required this.albumId,
|
||||||
|
required this.id,
|
||||||
|
required this.title,
|
||||||
|
required this.url,
|
||||||
|
required this.thumbnailUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant Photo other) {
|
||||||
|
if (identical(this, other)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return other.albumId == albumId &&
|
||||||
|
other.id == id &&
|
||||||
|
other.title == title &&
|
||||||
|
other.url == url &&
|
||||||
|
other.thumbnailUrl == thumbnailUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
albumId.hashCode ^
|
||||||
|
id.hashCode ^
|
||||||
|
title.hashCode ^
|
||||||
|
url.hashCode ^
|
||||||
|
thumbnailUrl.hashCode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// 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:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
abstract class PhotoRepository extends BaseRepository {
|
||||||
|
FutureResult<Album> getAlbum(int id);
|
||||||
|
FutureResult<List<Album>> getAllAlbums({int? start, int? limit});
|
||||||
|
FutureResult<Photo> getPhoto(int id);
|
||||||
|
FutureResult<List<Photo>> getAllPhotos({int? start, int? limit});
|
||||||
|
FutureResult<List<Photo>> getPhotosFromAlbum(
|
||||||
|
int albumId, {
|
||||||
|
int? start,
|
||||||
|
int? limit,
|
||||||
|
});
|
||||||
|
FutureResult<void> addPhotoToFavorites(Photo photo);
|
||||||
|
FutureResult<void> deletePhotoFromFavorites(int id);
|
||||||
|
FutureResult<List<Photo>> getAllPhotosFromFavorites();
|
||||||
|
FutureResult<bool> checkIfPhotoIsInFavorites(int id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// 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:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
class AddPhotoToFavorites extends UseCase<Photo, List<Photo>> {
|
||||||
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
|
AddPhotoToFavorites(this._photoRepository);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> call(Photo params) async {
|
||||||
|
await _photoRepository.addPhotoToFavorites(params);
|
||||||
|
return _photoRepository.getAllPhotosFromFavorites();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// 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:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
class CheckIfPhotoIsInFavorites extends UseCase<int, bool> {
|
||||||
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
|
CheckIfPhotoIsInFavorites(this._photoRepository);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<bool> call(int params) async =>
|
||||||
|
_photoRepository.checkIfPhotoIsInFavorites(params);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// 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:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
class DisplayFavorites extends UseCase<void, List<Photo>> {
|
||||||
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
|
DisplayFavorites(this._photoRepository);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> call(void params) {
|
||||||
|
final photos = _photoRepository.getAllPhotosFromFavorites();
|
||||||
|
return photos;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// 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:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
class DisplayPhoto extends UseCase<int, Photo> {
|
||||||
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
|
DisplayPhoto(this._photoRepository);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<Photo> call(int params) {
|
||||||
|
final photo = _photoRepository.getPhoto(params);
|
||||||
|
return photo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,39 +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/>.
|
||||||
|
|
||||||
class UserFirestore {
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
final String email;
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
final String name;
|
import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart';
|
||||||
final String phone;
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
final String uid;
|
|
||||||
|
|
||||||
UserFirestore({
|
class OpenAlbum extends UseCase<QueryParameters, List<Photo>> {
|
||||||
required this.email,
|
final PhotoRepository _photoRepository;
|
||||||
required this.name,
|
|
||||||
required this.phone,
|
|
||||||
required this.uid,
|
|
||||||
});
|
|
||||||
|
|
||||||
factory UserFirestore.fromMap(Map<String, dynamic> map) {
|
OpenAlbum(this._photoRepository);
|
||||||
return UserFirestore(
|
|
||||||
uid: map['uid'],
|
|
||||||
email: map['email'],
|
|
||||||
name: map['name'],
|
|
||||||
phone: map['phone'],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
|
||||||
return {
|
|
||||||
'uid': uid,
|
|
||||||
'email': email,
|
|
||||||
'name': name,
|
|
||||||
'phone': phone,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
FutureResult<List<Photo>> call(QueryParameters params) {
|
||||||
return 'UserFirestore(email: $email, name: $name, phone: $phone, uid: $uid)';
|
final photos = _photoRepository.getPhotosFromAlbum(
|
||||||
|
params.albumId,
|
||||||
|
start: params.start,
|
||||||
|
limit: params.limit,
|
||||||
|
);
|
||||||
|
|
||||||
|
return photos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
class QueryParameters {
|
||||||
|
final int albumId;
|
||||||
|
final int? start;
|
||||||
|
final int? limit;
|
||||||
|
|
||||||
|
QueryParameters(this.start, this.limit, {this.albumId = -1});
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// 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:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
class RemovePhotoFromFavorites extends UseCase<int, List<Photo>> {
|
||||||
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
|
RemovePhotoFromFavorites(this._photoRepository);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Photo>> call(int params) async {
|
||||||
|
await _photoRepository.deletePhotoFromFavorites(params);
|
||||||
|
return _photoRepository.getAllPhotosFromFavorites();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// 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:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart';
|
||||||
|
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||||
|
|
||||||
|
class RetrieveAllAlbums extends UseCase<QueryParameters, List<Album>> {
|
||||||
|
final PhotoRepository _photoRepository;
|
||||||
|
|
||||||
|
RetrieveAllAlbums(this._photoRepository);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureResult<List<Album>> call(QueryParameters params) {
|
||||||
|
final albums = _photoRepository.getAllAlbums(
|
||||||
|
start: params.start,
|
||||||
|
limit: params.limit,
|
||||||
|
);
|
||||||
|
return albums;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,34 +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 'package:architecture_example/bootstrap.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:architecture_example/presentation/features/app/app.dart';
|
||||||
|
|
||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
|
||||||
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MyApp());
|
bootstrap(() => const App());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
|
||||||
const MyApp({super.key});
|
|
||||||
|
|
||||||
// This widget is the root of your application.
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return MaterialApp(
|
|
||||||
title: 'Architecture Example',
|
|
||||||
theme: ThemeData(
|
|
||||||
primarySwatch: Colors.blue,
|
|
||||||
),
|
|
||||||
home: Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text('Architecture Example'),
|
|
||||||
),
|
|
||||||
body: Center(child: Text(wyatt())),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// 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:architecture_example/presentation/features/albums/state_management/albums_screen.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Albums extends StatelessWidget {
|
||||||
|
const Albums({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => const AlbumsScreen();
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
// 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:architecture_example/core/enums/fetch_status.dart';
|
||||||
|
import 'package:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/retrieve_all_albums.dart';
|
||||||
|
import 'package:bloc_concurrency/bloc_concurrency.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:stream_transform/stream_transform.dart';
|
||||||
|
|
||||||
|
part 'album_event.dart';
|
||||||
|
part 'album_state.dart';
|
||||||
|
|
||||||
|
const _albumLimit = 20;
|
||||||
|
const throttleDuration = Duration(milliseconds: 100);
|
||||||
|
|
||||||
|
EventTransformer<E> throttleDroppable<E>(Duration duration) =>
|
||||||
|
(events, mapper) => droppable<E>().call(events.throttle(duration), mapper);
|
||||||
|
|
||||||
|
class AlbumBloc extends Bloc<AlbumEvent, AlbumState> {
|
||||||
|
final RetrieveAllAlbums _retrieveAllAlbums;
|
||||||
|
|
||||||
|
AlbumBloc(this._retrieveAllAlbums) : super(const AlbumState()) {
|
||||||
|
on<AlbumFetched>(
|
||||||
|
_onAlbumFetched,
|
||||||
|
transformer: throttleDroppable(throttleDuration),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onAlbumFetched(
|
||||||
|
AlbumFetched event,
|
||||||
|
Emitter<AlbumState> emit,
|
||||||
|
) async {
|
||||||
|
if (state.hasReachedMax) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (state.status == FetchStatus.initial) {
|
||||||
|
final albums =
|
||||||
|
await _retrieveAllAlbums.call(QueryParameters(0, _albumLimit));
|
||||||
|
return emit(
|
||||||
|
albums.fold(
|
||||||
|
(value) => state.copyWith(
|
||||||
|
status: FetchStatus.success,
|
||||||
|
albums: value,
|
||||||
|
hasReachedMax: false,
|
||||||
|
),
|
||||||
|
(error) => state.copyWith(
|
||||||
|
status: FetchStatus.failure,
|
||||||
|
albums: [],
|
||||||
|
hasReachedMax: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final albums = await _retrieveAllAlbums
|
||||||
|
.call(QueryParameters(state.albums.length, _albumLimit));
|
||||||
|
return emit(
|
||||||
|
albums.fold(
|
||||||
|
(value) {
|
||||||
|
if (value.isEmpty) {
|
||||||
|
return state.copyWith(
|
||||||
|
hasReachedMax: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return state.copyWith(
|
||||||
|
status: FetchStatus.success,
|
||||||
|
albums: List.of(state.albums)..addAll(value),
|
||||||
|
hasReachedMax: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error) => state.copyWith(
|
||||||
|
status: FetchStatus.failure,
|
||||||
|
albums: List.of(state.albums),
|
||||||
|
hasReachedMax: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
part of 'album_bloc.dart';
|
||||||
|
|
||||||
|
abstract class AlbumEvent extends Equatable {
|
||||||
|
const AlbumEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlbumFetched extends AlbumEvent {}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
part of 'album_bloc.dart';
|
||||||
|
|
||||||
|
class AlbumState extends Equatable {
|
||||||
|
const AlbumState({
|
||||||
|
this.status = FetchStatus.initial,
|
||||||
|
this.albums = const <Album>[],
|
||||||
|
this.hasReachedMax = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
final FetchStatus status;
|
||||||
|
final List<Album> albums;
|
||||||
|
final bool hasReachedMax;
|
||||||
|
|
||||||
|
AlbumState copyWith({
|
||||||
|
FetchStatus? status,
|
||||||
|
List<Album>? albums,
|
||||||
|
bool? hasReachedMax,
|
||||||
|
}) =>
|
||||||
|
AlbumState(
|
||||||
|
status: status ?? this.status,
|
||||||
|
albums: albums ?? this.albums,
|
||||||
|
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [status, albums, hasReachedMax];
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// 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:architecture_example/core/enums/fetch_status.dart';
|
||||||
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/retrieve_all_albums.dart';
|
||||||
|
import 'package:architecture_example/presentation/features/albums/blocs/album/album_bloc.dart';
|
||||||
|
import 'package:architecture_example/presentation/features/albums/state_management/albums_wrapper_widget.dart';
|
||||||
|
import 'package:architecture_example/presentation/features/albums/state_management/widgets/albums_list.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
||||||
|
|
||||||
|
class AlbumsScreen extends BlocScreen<AlbumBloc, AlbumEvent, AlbumState> {
|
||||||
|
const AlbumsScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
AlbumBloc create(BuildContext context) =>
|
||||||
|
AlbumBloc(RetrieveAllAlbums(repo<PhotoRepository>(context)));
|
||||||
|
|
||||||
|
@override
|
||||||
|
AlbumBloc init(BuildContext context, AlbumBloc bloc) =>
|
||||||
|
bloc..add(AlbumFetched());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget onWrap(BuildContext context, Widget child) => AlbumsWrapperWidget(
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget onBuild(BuildContext context, AlbumState state) {
|
||||||
|
switch (state.status) {
|
||||||
|
case FetchStatus.initial:
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
case FetchStatus.failure:
|
||||||
|
return const Center(
|
||||||
|
child: Text('failed to fetch albums'),
|
||||||
|
);
|
||||||
|
case FetchStatus.success:
|
||||||
|
return AlbumsList(
|
||||||
|
albums: state.albums,
|
||||||
|
hasReachedMax: state.hasReachedMax,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// 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:flutter/material.dart';
|
||||||
|
|
||||||
|
class AlbumsWrapperWidget extends StatelessWidget {
|
||||||
|
const AlbumsWrapperWidget({required this.child, super.key});
|
||||||
|
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Albums'),
|
||||||
|
),
|
||||||
|
body: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// 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:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:architecture_example/presentation/features/albums/blocs/album/album_bloc.dart';
|
||||||
|
import 'package:architecture_example/presentation/features/albums/state_management/widgets/albums_list_item.dart';
|
||||||
|
import 'package:architecture_example/presentation/shared/widgets/bottom_loader.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class AlbumsList extends StatefulWidget {
|
||||||
|
const AlbumsList(
|
||||||
|
{required this.albums, required this.hasReachedMax, super.key,});
|
||||||
|
|
||||||
|
final List<Album> albums;
|
||||||
|
final bool hasReachedMax;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AlbumsList> createState() => _AlbumsListState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AlbumsListState extends State<AlbumsList> {
|
||||||
|
final _scrollController = ScrollController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_scrollController.addListener(_onScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_scrollController
|
||||||
|
..removeListener(_onScroll)
|
||||||
|
..dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onScroll() {
|
||||||
|
if (_isBottom) {
|
||||||
|
context.read<AlbumBloc>().add(AlbumFetched());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get _isBottom {
|
||||||
|
if (!_scrollController.hasClients) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final maxScroll = _scrollController.position.maxScrollExtent;
|
||||||
|
final currentScroll = _scrollController.offset;
|
||||||
|
return currentScroll >= (maxScroll * 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => ListView.builder(
|
||||||
|
itemBuilder: (context, index) => index >= widget.albums.length
|
||||||
|
? const BottomLoader()
|
||||||
|
: AlbumsListItem(album: widget.albums[index]),
|
||||||
|
itemCount: widget.hasReachedMax
|
||||||
|
? widget.albums.length
|
||||||
|
: widget.albums.length + 1,
|
||||||
|
controller: _scrollController,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -14,26 +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 'package:authentication_bloc_example/sign_up/widgets/sign_up_form.dart';
|
import 'package:architecture_example/domain/entities/album.dart';
|
||||||
|
import 'package:architecture_example/presentation/features/photos/photos.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class SignUpPage extends StatelessWidget {
|
class AlbumsListItem extends StatelessWidget {
|
||||||
const SignUpPage({Key? key}) : super(key: key);
|
const AlbumsListItem({required this.album, super.key});
|
||||||
|
|
||||||
static Route route() {
|
final Album album;
|
||||||
return MaterialPageRoute<void>(builder: (_) => const SignUpPage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => ListTile(
|
||||||
return Scaffold(
|
leading: Text('${album.id}'),
|
||||||
appBar: AppBar(title: const Text('Sign Up')),
|
title: Text(album.title),
|
||||||
body: const Padding(
|
dense: true,
|
||||||
padding: EdgeInsets.all(8),
|
onTap: () => Navigator.of(context).push(
|
||||||
child: SingleChildScrollView(
|
MaterialPageRoute<void>(
|
||||||
child: SignUpForm(),
|
builder: (context) => Photos(albumId: album.id),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// 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:architecture_example/core/dependency_injection/get_it.dart';
|
||||||
|
import 'package:architecture_example/data/repositories/photo_repository_impl.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/local/favorite_local_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/album_remote_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/data_sources/remote/photo_remote_data_source.dart';
|
||||||
|
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:architecture_example/presentation/features/albums/albums.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class App extends StatelessWidget {
|
||||||
|
const App({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => MultiRepositoryProvider(
|
||||||
|
providers: [
|
||||||
|
RepositoryProvider<PhotoRepository>(
|
||||||
|
create: (_) => PhotoRepositoryImpl(
|
||||||
|
getIt<PhotoRemoteDataSource>(),
|
||||||
|
getIt<AlbumRemoteDataSource>(),
|
||||||
|
getIt<FavoriteLocalDataSource>(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: const MaterialApp(
|
||||||
|
title: 'Demo',
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
home: Albums(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:architecture_example/domain/entities/photo.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/add_photo_to_favorites.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/check_if_photo_is_in_favorites.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/display_photo.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/remove_photo_from_favorites.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
part 'photo_details_state.dart';
|
||||||
|
|
||||||
|
class PhotoDetailsCubit extends Cubit<PhotoDetailsState> {
|
||||||
|
final DisplayPhoto _displayPhoto;
|
||||||
|
final CheckIfPhotoIsInFavorites _checkIfPhotoIsInFavorites;
|
||||||
|
final AddPhotoToFavorites _addPhotoToFavorites;
|
||||||
|
final RemovePhotoFromFavorites _removePhotoFromFavorites;
|
||||||
|
|
||||||
|
PhotoDetailsCubit(
|
||||||
|
this._displayPhoto,
|
||||||
|
this._checkIfPhotoIsInFavorites,
|
||||||
|
this._addPhotoToFavorites,
|
||||||
|
this._removePhotoFromFavorites,
|
||||||
|
) : super(PhotoDetailsInitial());
|
||||||
|
|
||||||
|
FutureOr<void> load(int photoId) async {
|
||||||
|
final photo = await _displayPhoto.call(photoId);
|
||||||
|
final isFavorite = await _checkIfPhotoIsInFavorites.call(photoId);
|
||||||
|
|
||||||
|
emit(
|
||||||
|
photo.fold(
|
||||||
|
(value) => PhotoDetailsSuccess(
|
||||||
|
value,
|
||||||
|
isFavorite: isFavorite.fold((value) => value, (error) => false),
|
||||||
|
),
|
||||||
|
(error) => PhotoDetailsFailure(error.toString()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureOr<void> addToFavorites() async {
|
||||||
|
if (state is! PhotoDetailsSuccess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final actualState = state as PhotoDetailsSuccess;
|
||||||
|
final response = await _addPhotoToFavorites.call(actualState.photo);
|
||||||
|
if (response.isOk) {
|
||||||
|
emit(PhotoDetailsSuccess(actualState.photo, isFavorite: true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureOr<void> removeFromFavorites() async {
|
||||||
|
if (state is! PhotoDetailsSuccess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final actualState = state as PhotoDetailsSuccess;
|
||||||
|
final response = await _removePhotoFromFavorites.call(actualState.photo.id);
|
||||||
|
if (response.isOk) {
|
||||||
|
emit(PhotoDetailsSuccess(actualState.photo, isFavorite: false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,24 +14,32 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
part of 'photo_details_cubit.dart';
|
||||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart';
|
|
||||||
|
|
||||||
/// {@template siren}
|
abstract class PhotoDetailsState extends Equatable {
|
||||||
/// Form input for a SIREN input.
|
const PhotoDetailsState();
|
||||||
/// {@endtemplate}
|
|
||||||
class Siren extends RegexValidator<ValidationStandardError> {
|
|
||||||
/// {@macro siren}
|
|
||||||
const Siren.pure() : super.pure();
|
|
||||||
|
|
||||||
/// {@macro siren}
|
|
||||||
const Siren.dirty([super.value = '']) : super.dirty();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValidationStandardError get onEmpty => ValidationStandardError.empty;
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PhotoDetailsInitial extends PhotoDetailsState {}
|
||||||
|
|
||||||
|
class PhotoDetailsSuccess extends PhotoDetailsState {
|
||||||
|
final Photo photo;
|
||||||
|
final bool isFavorite;
|
||||||
|
|
||||||
|
const PhotoDetailsSuccess(this.photo, {required this.isFavorite});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValidationStandardError get onError => ValidationStandardError.invalid;
|
List<Object> get props => [photo, isFavorite];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PhotoDetailsFailure extends PhotoDetailsState {
|
||||||
|
final String error;
|
||||||
|
|
||||||
|
const PhotoDetailsFailure(this.error);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
RegExp get regex => RegExp(r'(\d{9}|\d{3}[ ]\d{3}[ ]\d{3})$');
|
List<Object> get props => [error];
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// 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:architecture_example/presentation/features/photo_details/state_management/photo_details_screen.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class PhotoDetails extends StatelessWidget {
|
||||||
|
const PhotoDetails({required this.photoId, super.key});
|
||||||
|
|
||||||
|
final int photoId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => PhotoDetailsScreen(photoId: photoId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
// 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:architecture_example/domain/repositories/photo_repository.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/add_photo_to_favorites.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/check_if_photo_is_in_favorites.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/display_photo.dart';
|
||||||
|
import 'package:architecture_example/domain/usecases/photos/remove_photo_from_favorites.dart';
|
||||||
|
import 'package:architecture_example/presentation/features/photo_details/blocs/photo_details/photo_details_cubit.dart';
|
||||||
|
import 'package:architecture_example/presentation/features/photo_details/state_management/photo_details_wrapper_widget.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
||||||
|
|
||||||
|
class PhotoDetailsScreen
|
||||||
|
extends CubitScreen<PhotoDetailsCubit, PhotoDetailsState> {
|
||||||
|
const PhotoDetailsScreen({required this.photoId, super.key});
|
||||||
|
|
||||||
|
final int photoId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
PhotoDetailsCubit create(BuildContext context) => PhotoDetailsCubit(
|
||||||
|
DisplayPhoto(repo<PhotoRepository>(context)),
|
||||||
|
CheckIfPhotoIsInFavorites(repo<PhotoRepository>(context)),
|
||||||
|
AddPhotoToFavorites(repo<PhotoRepository>(context)),
|
||||||
|
RemovePhotoFromFavorites(repo<PhotoRepository>(context)),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
PhotoDetailsCubit init(BuildContext context, PhotoDetailsCubit bloc) =>
|
||||||
|
bloc..load(photoId);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget onWrap(BuildContext context, Widget child) =>
|
||||||
|
PhotoDetailsWrapperWidget(child: child);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget onBuild(BuildContext context, PhotoDetailsState state) {
|
||||||
|
if (state is PhotoDetailsFailure) {
|
||||||
|
return const Center(
|
||||||
|
child: Text('failed to fetch photo details'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (state is PhotoDetailsSuccess) {
|
||||||
|
return CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverAppBar(
|
||||||
|
expandedHeight: 400,
|
||||||
|
stretch: true,
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
background: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(
|
||||||
|
child: Image.network(
|
||||||
|
state.photo.thumbnailUrl,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned.fill(
|
||||||
|
child: Image.network(
|
||||||
|
state.photo.url,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverList(
|
||||||
|
delegate: SliverChildListDelegate([
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
state.photo.title,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
state.isFavorite
|
||||||
|
? bloc(context).removeFromFavorites()
|
||||||
|
: bloc(context).addToFavorites();
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
state.isFavorite
|
||||||
|
? Icons.favorite
|
||||||
|
: Icons.favorite_outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||