Compare commits

...

2 Commits

77 changed files with 381 additions and 603 deletions

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -17,14 +17,14 @@
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_local_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/album_remote_data_source.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:architecture_example/data/data_sources/remote/photo_remote_data_source.dart';
import 'package:get_it/get_it.dart';
import 'package:wyatt_http_client/wyatt_http_client.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -15,11 +15,11 @@
// 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/data/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 {
class FavoriteHiveDataSource implements FavoriteLocalDataSource {
@override
Future<void> addPhotoToFavorites(Photo photo) async {
final box = await Hive.openBox<bool>(HiveBoxes.favorites);

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -17,7 +17,7 @@
import 'package:architecture_example/domain/entities/photo.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
abstract class FavoriteLocalDataSource extends BaseLocalDataSource {
abstract interface class FavoriteLocalDataSource extends BaseLocalDataSource {
Future<void> addPhotoToFavorites(Photo photo);
Future<void> deletePhotoFromFavorites(int id);
Future<List<int>> getAllPhotosFromFavorites();

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,11 +14,11 @@
// 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/data_sources/local/favorite_local_data_source.dart';
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 {
class FavoriteMockDataSource implements FavoriteLocalDataSource {
final Map<int, Photo> _mock = {
2: const PhotoModel(
albumId: 1,

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -16,14 +16,13 @@
import 'dart:convert';
import 'package:architecture_example/data/data_sources/remote/album_remote_data_source.dart';
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 {
class AlbumApiDataSourceImpl implements AlbumRemoteDataSource {
AlbumApiDataSourceImpl(this._client);
final MiddlewareClient _client;
@ -37,8 +36,8 @@ class AlbumApiDataSourceImpl extends AlbumRemoteDataSource {
@override
Future<List<Album>> getAllAlbums({int? start, int? limit}) async {
final startQuery = start.isNotNull ? '_start=$start' : '';
final limitQuery = limit.isNotNull ? '_limit=$limit' : '';
final startQuery = (start != null) ? '_start=$start' : '';
final limitQuery = (limit != null) ? '_limit=$limit' : '';
final delimiter1 =
(startQuery.isNotEmpty || limitQuery.isNotEmpty) ? '?' : '';
final delimiter2 =

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,12 +14,11 @@
// 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/data_sources/remote/album_remote_data_source.dart';
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 {
class AlbumMockDataSourceImpl implements AlbumRemoteDataSource {
final Map<int, Album> _mock = {
1: const AlbumModel(
id: 1,
@ -31,10 +30,10 @@ class AlbumMockDataSourceImpl extends AlbumRemoteDataSource {
@override
Future<Album> getAlbum(int id) async {
final response = _mock[id];
if (response.isNull) {
if (response == null) {
throw Exception('Unknown album');
}
return response!;
return response;
}
@override

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -17,7 +17,7 @@
import 'package:architecture_example/domain/entities/album.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
abstract class AlbumRemoteDataSource extends BaseRemoteDataSource {
abstract interface class AlbumRemoteDataSource extends BaseRemoteDataSource {
Future<Album> getAlbum(int id);
Future<List<Album>> getAllAlbums({int? start, int? limit});
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -16,14 +16,13 @@
import 'dart:convert';
import 'package:architecture_example/data/data_sources/remote/photo_remote_data_source.dart';
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 {
class PhotoApiDataSourceImpl implements PhotoRemoteDataSource {
PhotoApiDataSourceImpl(this._client);
final MiddlewareClient _client;
@ -37,8 +36,8 @@ class PhotoApiDataSourceImpl extends PhotoRemoteDataSource {
@override
Future<List<Photo>> getAllPhotos({int? start, int? limit}) async {
final startQuery = start.isNotNull ? '_start=$start' : '';
final limitQuery = limit.isNotNull ? '_limit=$limit' : '';
final startQuery = (start != null) ? '_start=$start' : '';
final limitQuery = (limit != null) ? '_limit=$limit' : '';
final delimiter1 =
(startQuery.isNotEmpty || limitQuery.isNotEmpty) ? '?' : '';
final delimiter2 =
@ -56,8 +55,8 @@ class PhotoApiDataSourceImpl extends PhotoRemoteDataSource {
int? start,
int? limit,
}) async {
final startQuery = start.isNotNull ? '_start=$start' : '';
final limitQuery = limit.isNotNull ? '_limit=$limit' : '';
final startQuery = (start != null) ? '_start=$start' : '';
final limitQuery = (limit != null) ? '_limit=$limit' : '';
final delimiter =
(startQuery.isNotEmpty && limitQuery.isNotEmpty) ? '&' : '';
final url = '/photos?albumId=$albumId&$startQuery$delimiter$limitQuery';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,12 +14,11 @@
// 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/data_sources/remote/photo_remote_data_source.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_type_utils/wyatt_type_utils.dart';
class PhotoMockDataSourceImpl extends PhotoRemoteDataSource {
class PhotoMockDataSourceImpl implements PhotoRemoteDataSource {
final Map<int, Photo> _mock = {
1: const PhotoModel(
albumId: 1,
@ -40,10 +39,10 @@ class PhotoMockDataSourceImpl extends PhotoRemoteDataSource {
@override
Future<Photo> getPhoto(int id) async {
final response = _mock[id];
if (response.isNull) {
if (response == null) {
throw Exception('Unknown photo');
}
return response!;
return response;
}
@override

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -17,7 +17,7 @@
import 'package:architecture_example/domain/entities/photo.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
abstract class PhotoRemoteDataSource extends BaseRemoteDataSource {
abstract interface 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});

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,14 +14,14 @@
// 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/data/data_sources/local/favorite_local_data_source.dart';
import 'package:architecture_example/data/data_sources/remote/album_remote_data_source.dart';
import 'package:architecture_example/data/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:sealed_result/sealed_result.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
class PhotoRepositoryImpl extends PhotoRepository {
PhotoRepositoryImpl(
@ -34,43 +34,35 @@ class PhotoRepositoryImpl extends PhotoRepository {
final FavoriteLocalDataSource _favoriteLocalDataSource;
@override
FutureOrResult<void> addPhotoToFavorites(Photo photo) => Result.tryCatchAsync(
FutureOrResult<void> addPhotoToFavorites(Photo photo) => Result.fromAsync(
() => _favoriteLocalDataSource.addPhotoToFavorites(photo),
(error) => const ClientException('Cannot add photo to favorites.'),
);
@override
FutureOrResult<bool> checkIfPhotoIsInFavorites(int id) =>
Result.tryCatchAsync(
FutureOrResult<bool> checkIfPhotoIsInFavorites(int id) => Result.fromAsync(
() => _favoriteLocalDataSource.checkIfPhotoIsInFavorites(id),
(error) =>
ClientException('Cannot check if photo `$id` is in favorites.'),
);
@override
FutureOrResult<void> deletePhotoFromFavorites(int id) => Result.tryCatchAsync(
FutureOrResult<void> deletePhotoFromFavorites(int id) => Result.fromAsync(
() => _favoriteLocalDataSource.deletePhotoFromFavorites(id),
(error) => ClientException('Cannot delete photo `$id` from favorites.'),
);
@override
FutureOrResult<Album> getAlbum(int id) => Result.tryCatchAsync(
FutureOrResult<Album> getAlbum(int id) => Result.fromAsync(
() => _albumRemoteDataSource.getAlbum(id),
(error) => ServerException('Cannot retrieve album $id.'),
);
@override
FutureOrResult<List<Album>> getAllAlbums({int? start, int? limit}) =>
Result.tryCatchAsync(
Result.fromAsync(
() => _albumRemoteDataSource.getAllAlbums(start: start, limit: limit),
(error) => const ServerException('Cannot retrieve all albums.'),
);
@override
FutureOrResult<List<Photo>> getAllPhotos({int? start, int? limit}) async =>
Result.tryCatchAsync(
Result.fromAsync(
() => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit),
(error) => const ServerException('Cannot retrieve all photos.'),
);
@override
@ -89,15 +81,14 @@ class PhotoRepositoryImpl extends PhotoRepository {
return Ok(response);
} catch (_) {
return const Err(
ClientException('Cannot retrieve all photos from favorites.'),
ClientException(message: 'Cannot retrieve all photos from favorites.'),
);
}
}
@override
FutureOrResult<Photo> getPhoto(int id) => Result.tryCatchAsync(
FutureOrResult<Photo> getPhoto(int id) => Result.fromAsync(
() => _photoRemoteDataSource.getPhoto(id),
(error) => ServerException('Cannot retrieve photo $id.'),
);
@override
@ -106,13 +97,11 @@ class PhotoRepositoryImpl extends PhotoRepository {
int? start,
int? limit,
}) async =>
Result.tryCatchAsync(
Result.fromAsync(
() => _photoRemoteDataSource.getPhotosFromAlbum(
albumId,
start: start,
limit: limit,
),
(error) =>
ServerException('Cannot retrieve all photos from album $albumId'),
);
}

View File

@ -1,5 +1,5 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,8 +14,13 @@
// 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 {
QueryParameters(this.start, this.limit, {this.albumId = -1});
import 'package:flutter/foundation.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
@immutable
class QueryParameters extends Entity {
const QueryParameters(this.start, this.limit, {this.albumId = -1});
final int albumId;
final int? start;
final int? limit;

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,14 +14,13 @@
// 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/repositories/photo_repository.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
class AddPhotoToFavorites extends AsyncUseCase<Photo, List<Photo>> {
AddPhotoToFavorites(this._photoRepository);
class AddPhotoToFavorites extends Usecase<Photo, List<Photo>> {
const AddPhotoToFavorites(this._photoRepository);
final PhotoRepository _photoRepository;
@override
@ -29,11 +28,4 @@ class AddPhotoToFavorites extends AsyncUseCase<Photo, List<Photo>> {
await _photoRepository.addPhotoToFavorites(params!);
return _photoRepository.getAllPhotosFromFavorites();
}
@override
FutureOr<void> onStart(Photo? params) {
if (params == null) {
throw const ClientException('Photo cannot be null');
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,23 +14,15 @@
// 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/repositories/photo_repository.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
class CheckIfPhotoIsInFavorites extends AsyncUseCase<int, bool> {
CheckIfPhotoIsInFavorites(this._photoRepository);
class CheckIfPhotoIsInFavorites extends Usecase<int, bool> {
const CheckIfPhotoIsInFavorites(this._photoRepository);
final PhotoRepository _photoRepository;
@override
FutureOrResult<bool> execute(int? params) async =>
_photoRepository.checkIfPhotoIsInFavorites(params!);
@override
FutureOr<void> onStart(int? params) {
if (params == null) {
throw const ClientException('id cannot be null');
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -18,12 +18,13 @@ 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 AsyncUseCase<NoParam, List<Photo>> {
DisplayFavorites(this._photoRepository);
class DisplayFavorites extends NoParamsUsecase<List<Photo>> {
const DisplayFavorites(this._photoRepository);
final PhotoRepository _photoRepository;
@override
FutureOrResult<List<Photo>> execute(void params) {
FutureOrResult<List<Photo>> execute() {
final photos = _photoRepository.getAllPhotosFromFavorites();
return photos;
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,14 +14,13 @@
// 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/repositories/photo_repository.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
class DisplayPhoto extends AsyncUseCase<int, Photo> {
DisplayPhoto(this._photoRepository);
class DisplayPhoto extends Usecase<int, Photo> {
const DisplayPhoto(this._photoRepository);
final PhotoRepository _photoRepository;
@override
@ -29,11 +28,4 @@ class DisplayPhoto extends AsyncUseCase<int, Photo> {
final photo = _photoRepository.getPhoto(params!);
return photo;
}
@override
FutureOr<void> onStart(int? params) {
if (params == null) {
throw const ClientException('id cannot be null');
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,15 +14,14 @@
// 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/entities/query_parameters.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 OpenAlbum extends AsyncUseCase<QueryParameters, List<Photo>> {
OpenAlbum(this._photoRepository);
class OpenAlbum extends Usecase<QueryParameters, List<Photo>> {
const OpenAlbum(this._photoRepository);
final PhotoRepository _photoRepository;
@override
@ -35,11 +34,4 @@ class OpenAlbum extends AsyncUseCase<QueryParameters, List<Photo>> {
return photos;
}
@override
FutureOr<void> onStart(QueryParameters? params) {
if (params == null) {
throw const ClientException('params cannot be null');
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,14 +14,13 @@
// 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/repositories/photo_repository.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
class RemovePhotoFromFavorites extends AsyncUseCase<int, List<Photo>> {
RemovePhotoFromFavorites(this._photoRepository);
class RemovePhotoFromFavorites extends Usecase<int, List<Photo>> {
const RemovePhotoFromFavorites(this._photoRepository);
final PhotoRepository _photoRepository;
@override
@ -29,11 +28,4 @@ class RemovePhotoFromFavorites extends AsyncUseCase<int, List<Photo>> {
await _photoRepository.deletePhotoFromFavorites(params!);
return _photoRepository.getAllPhotosFromFavorites();
}
@override
FutureOr<void> onStart(int? params) {
if (params == null) {
throw const ClientException('id cannot be null');
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,15 +14,14 @@
// 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/album.dart';
import 'package:architecture_example/domain/entities/query_parameters.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 AsyncUseCase<QueryParameters, List<Album>> {
RetrieveAllAlbums(this._photoRepository);
class RetrieveAllAlbums extends Usecase<QueryParameters, List<Album>> {
const RetrieveAllAlbums(this._photoRepository);
final PhotoRepository _photoRepository;
@override
@ -33,11 +32,4 @@ class RetrieveAllAlbums extends AsyncUseCase<QueryParameters, List<Album>> {
);
return albums;
}
@override
FutureOr<void> onStart(QueryParameters? params) {
if (params == null) {
throw const ClientException('params cannot be null');
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,25 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package: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();
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -16,7 +16,8 @@
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/entities/query_parameters.dart';
import 'package:architecture_example/domain/repositories/photo_repository.dart';
import 'package:architecture_example/domain/usecases/photos/retrieve_all_albums.dart';
import 'package:bloc_concurrency/bloc_concurrency.dart';
import 'package:equatable/equatable.dart';
@ -39,6 +40,11 @@ class AlbumBloc extends Bloc<AlbumEvent, AlbumState> {
transformer: throttleDroppable(throttleDuration),
);
}
factory AlbumBloc.create(PhotoRepository photoRepository) => AlbumBloc(
RetrieveAllAlbums(photoRepository),
);
final RetrieveAllAlbums _retrieveAllAlbums;
Future<void> _onAlbumFetched(
@ -50,7 +56,7 @@ class AlbumBloc extends Bloc<AlbumEvent, AlbumState> {
}
if (state.status == FetchStatus.initial) {
final albums =
await _retrieveAllAlbums.call(QueryParameters(0, _albumLimit));
await _retrieveAllAlbums.call(const QueryParameters(0, _albumLimit));
return emit(
albums.fold(
(value) => state.copyWith(

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -15,11 +15,8 @@
// 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:architecture_example/presentation/features/albums/stateful/albums_list.dart';
import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
@ -27,18 +24,12 @@ class AlbumsScreen extends BlocScreen<AlbumBloc, AlbumEvent, AlbumState> {
const AlbumsScreen({super.key});
@override
AlbumBloc create(BuildContext context) =>
AlbumBloc(RetrieveAllAlbums(repo<PhotoRepository>(context)));
AlbumBloc create(BuildContext context) => AlbumBloc.create(repo(context));
@override
AlbumBloc init(BuildContext context, AlbumBloc bloc) =>
bloc..add(AlbumFetched());
@override
Widget parent(BuildContext context, Widget child) => AlbumsWrapperWidget(
child: child,
);
@override
Widget onBuild(BuildContext context, AlbumState state) {
switch (state.status) {

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -16,8 +16,9 @@
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/features/albums/stateless/albums_list_item.dart';
import 'package:architecture_example/presentation/shared/widgets/bottom_loader.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -33,6 +34,14 @@ class AlbumsList extends StatefulWidget {
@override
State<AlbumsList> createState() => _AlbumsListState();
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(IterableProperty<Album>('albums', albums))
..add(DiagnosticsProperty<bool>('hasReachedMax', hasReachedMax));
}
}
class _AlbumsListState extends State<AlbumsList> {

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -15,7 +15,8 @@
// 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/photos/photos.dart';
import 'package:architecture_example/presentation/pages/photos_page.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class AlbumsListItem extends StatelessWidget {
@ -30,8 +31,14 @@ class AlbumsListItem extends StatelessWidget {
dense: true,
onTap: () => Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) => Photos(albumId: album.id),
builder: (context) => PhotosPage(albumId: album.id),
),
),
);
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Album>('album', album));
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -15,12 +15,12 @@
// 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/data_sources/local/favorite_local_data_source.dart';
import 'package:architecture_example/data/data_sources/remote/album_remote_data_source.dart';
import 'package:architecture_example/data/data_sources/remote/photo_remote_data_source.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:architecture_example/presentation/pages/albums_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -41,7 +41,7 @@ class App extends StatelessWidget {
child: const MaterialApp(
title: 'Demo',
debugShowCheckedModeBanner: false,
home: Albums(),
home: AlbumsPage(),
),
);
}

View File

@ -1,5 +1,5 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -18,6 +18,7 @@
import 'dart:async';
import 'package:architecture_example/domain/entities/photo.dart';
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';
@ -28,11 +29,6 @@ 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,
@ -40,6 +36,21 @@ class PhotoDetailsCubit extends Cubit<PhotoDetailsState> {
this._removePhotoFromFavorites,
) : super(PhotoDetailsInitial());
factory PhotoDetailsCubit.create(
PhotoRepository photoRepository,
) =>
PhotoDetailsCubit(
DisplayPhoto(photoRepository),
CheckIfPhotoIsInFavorites(photoRepository),
AddPhotoToFavorites(photoRepository),
RemovePhotoFromFavorites(photoRepository),
);
final DisplayPhoto _displayPhoto;
final CheckIfPhotoIsInFavorites _checkIfPhotoIsInFavorites;
final AddPhotoToFavorites _addPhotoToFavorites;
final RemovePhotoFromFavorites _removePhotoFromFavorites;
FutureOr<void> load(int photoId) async {
final photo = await _displayPhoto.call(photoId);
final isFavorite = await _checkIfPhotoIsInFavorites.call(photoId);

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,13 +14,8 @@
// 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/foundation.dart';
import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
@ -31,21 +26,13 @@ class PhotoDetailsScreen
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)),
);
PhotoDetailsCubit create(BuildContext context) =>
PhotoDetailsCubit.create(repo(context));
@override
PhotoDetailsCubit init(BuildContext context, PhotoDetailsCubit bloc) =>
bloc..load(photoId);
@override
Widget parent(BuildContext context, Widget child) =>
PhotoDetailsWrapperWidget(child: child);
@override
Widget onBuild(BuildContext context, PhotoDetailsState state) {
if (state is PhotoDetailsFailure) {
@ -116,4 +103,10 @@ class PhotoDetailsScreen
child: CircularProgressIndicator(),
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(IntProperty('photoId', photoId));
}
}

View File

@ -1,28 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
class PhotoDetailsWrapperWidget extends StatelessWidget {
const PhotoDetailsWrapperWidget({required this.child, super.key});
final Widget child;
@override
Widget build(BuildContext context) => Scaffold(
body: child,
);
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -16,6 +16,7 @@
import 'dart:async';
import 'package:architecture_example/domain/repositories/photo_repository.dart';
import 'package:architecture_example/domain/usecases/photos/check_if_photo_is_in_favorites.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -25,6 +26,14 @@ part 'favorite_checker_state.dart';
class FavoriteCheckerCubit extends Cubit<FavoriteCheckerState> {
FavoriteCheckerCubit(this._checkIfPhotoIsInFavorites)
: super(FavoriteCheckerInitial());
factory FavoriteCheckerCubit.create(
PhotoRepository photoRepository,
) =>
FavoriteCheckerCubit(
CheckIfPhotoIsInFavorites(photoRepository),
);
final CheckIfPhotoIsInFavorites _checkIfPhotoIsInFavorites;
FutureOr<void> checkIfPhotoIsInFavorites(int photoId) async {

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -16,8 +16,9 @@
import 'package:architecture_example/core/enums/fetch_status.dart';
import 'package:architecture_example/domain/entities/photo.dart';
import 'package:architecture_example/domain/entities/query_parameters.dart';
import 'package:architecture_example/domain/repositories/photo_repository.dart';
import 'package:architecture_example/domain/usecases/photos/open_album.dart';
import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart';
import 'package:bloc_concurrency/bloc_concurrency.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -39,6 +40,11 @@ class PhotoBloc extends Bloc<PhotoEvent, PhotoState> {
transformer: throttleDroppable(throttleDuration),
);
}
factory PhotoBloc.create(PhotoRepository photoRepository) => PhotoBloc(
OpenAlbum(photoRepository),
);
final OpenAlbum _openAlbum;
Future<void> _onPhotoFetched(

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,27 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:architecture_example/presentation/features/photos/state_management/photos_screen.dart';
import 'package:flutter/material.dart';
class Photos extends StatelessWidget {
const Photos({required this.albumId, super.key});
final int albumId;
@override
Widget build(BuildContext context) => PhotosScreen(albumId: albumId);
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -15,10 +15,9 @@
// 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:architecture_example/domain/usecases/photos/check_if_photo_is_in_favorites.dart';
import 'package:architecture_example/presentation/features/photo_details/photo_details.dart';
import 'package:architecture_example/presentation/features/photos/blocs/favorite_checker/favorite_checker_cubit.dart';
import 'package:architecture_example/presentation/pages/photo_details_page.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
@ -29,9 +28,8 @@ class PhotosGridThumbnail
final Photo photo;
@override
FavoriteCheckerCubit create(BuildContext context) => FavoriteCheckerCubit(
CheckIfPhotoIsInFavorites(repo<PhotoRepository>(context)),
);
FavoriteCheckerCubit create(BuildContext context) =>
FavoriteCheckerCubit.create(repo(context));
@override
FavoriteCheckerCubit init(BuildContext context, FavoriteCheckerCubit bloc) =>
@ -42,7 +40,7 @@ class PhotosGridThumbnail
GestureDetector(
onTap: () => Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) => PhotoDetails(photoId: photo.id),
builder: (context) => PhotoDetailsPage(photoId: photo.id),
),
),
child: Stack(
@ -63,4 +61,10 @@ class PhotosGridThumbnail
],
),
);
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Photo>('photo', photo));
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -15,11 +15,9 @@
// 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/open_album.dart';
import 'package:architecture_example/presentation/features/photos/blocs/photo/photo_bloc.dart';
import 'package:architecture_example/presentation/features/photos/state_management/photos_wrapper_widget.dart';
import 'package:architecture_example/presentation/features/photos/state_management/widgets/photos_grid.dart';
import 'package:architecture_example/presentation/features/photos/stateful/photos_grid.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
@ -29,18 +27,12 @@ class PhotosScreen extends BlocScreen<PhotoBloc, PhotoEvent, PhotoState> {
final int albumId;
@override
PhotoBloc create(BuildContext context) =>
PhotoBloc(OpenAlbum(repo<PhotoRepository>(context)));
PhotoBloc create(BuildContext context) => PhotoBloc.create(repo(context));
@override
PhotoBloc init(BuildContext context, PhotoBloc bloc) =>
bloc..add(PhotoFetched(albumId));
@override
Widget parent(BuildContext context, Widget child) => PhotosWrapperWidget(
child: child,
);
@override
Widget onBuild(BuildContext context, PhotoState state) {
switch (state.status) {
@ -58,4 +50,10 @@ class PhotosScreen extends BlocScreen<PhotoBloc, PhotoEvent, PhotoState> {
);
}
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(IntProperty('albumId', albumId));
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -16,8 +16,9 @@
import 'package:architecture_example/domain/entities/photo.dart';
import 'package:architecture_example/presentation/features/photos/blocs/photo/photo_bloc.dart';
import 'package:architecture_example/presentation/features/photos/state_management/widgets/photos_grid_thumbnail.dart';
import 'package:architecture_example/presentation/features/photos/screens/photos_grid_thumbnail.dart';
import 'package:architecture_example/presentation/shared/widgets/bottom_loader.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -35,6 +36,15 @@ class PhotosGrid extends StatefulWidget {
@override
State<PhotosGrid> createState() => _PhotosGridState();
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(IterableProperty<Photo>('photos', photos))
..add(IntProperty('albumId', albumId))
..add(DiagnosticsProperty<bool>('hasReachedMax', hasReachedMax));
}
}
class _PhotosGridState extends State<PhotosGrid> {

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,18 +14,17 @@
// 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/screens/albums_screen.dart';
import 'package:flutter/material.dart';
class AlbumsWrapperWidget extends StatelessWidget {
const AlbumsWrapperWidget({required this.child, super.key});
final Widget child;
class AlbumsPage extends StatelessWidget {
const AlbumsPage({super.key});
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Albums'),
),
body: child,
body: const AlbumsScreen(),
);
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,14 +14,23 @@
// 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:architecture_example/presentation/features/photo_details/screens/photo_details_screen.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class PhotoDetails extends StatelessWidget {
const PhotoDetails({required this.photoId, super.key});
class PhotoDetailsPage extends StatelessWidget {
const PhotoDetailsPage({required this.photoId, super.key});
final int photoId;
@override
Widget build(BuildContext context) => PhotoDetailsScreen(photoId: photoId);
Widget build(BuildContext context) => Scaffold(
body: PhotoDetailsScreen(photoId: photoId),
);
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(IntProperty('photoId', photoId));
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,18 +14,26 @@
// 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/photos/screens/photos_screen.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class PhotosWrapperWidget extends StatelessWidget {
const PhotosWrapperWidget({required this.child, super.key});
class PhotosPage extends StatelessWidget {
const PhotosPage({required this.albumId, super.key});
final Widget child;
final int albumId;
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Photos'),
),
body: child,
body: PhotosScreen(albumId: albumId),
);
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(IntProperty('albumId', albumId));
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.17.0 <3.0.0"
sdk: ^3.0.0
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
@ -41,6 +41,7 @@ dependencies:
bloc_concurrency: ^0.2.0
freezed_annotation: ^2.2.0
json_annotation: ^4.7.0
sealed_result: ^3.0.0
wyatt_bloc_helper:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
@ -48,9 +49,6 @@ dependencies:
wyatt_http_client:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
version: ^2.0.1
wyatt_type_utils:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
version: ^0.0.5
dev_dependencies:
build_runner: ^2.3.2

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,24 +14,43 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
/// {@template app_exception}
/// [AppException] is a base class for all exceptions in the wyatt architecture.
/// {@endtemplate}
abstract class AppException implements Exception {
/// {@macro app_exception}
const AppException([this.message]);
const AppException({this.message, this.underlyingException});
/// {@macro app_exception}
///
/// Constructs an [AppException] from an [Exception].
factory AppException.from(Object e) {
if (e is AppException) {
return e;
} else {
return ClientException(underlyingException: e);
}
}
/// The message of the exception.
final String? message;
/// The exception which triggered this exception being thrown.
final Object? underlyingException;
@override
String toString() {
if (message.isNotNullOrEmpty) {
return '$runtimeType: $message';
final str = StringBuffer(runtimeType.toString());
if (message != null && message!.isNotEmpty) {
str.write(': $message');
} else {
return '$runtimeType: An exception occured';
str.write(': An exception occured');
}
if (underlyingException != null) {
str.write('\n$underlyingException');
}
return str.toString();
}
}
@ -41,7 +60,7 @@ abstract class AppException implements Exception {
/// {@endtemplate}
class ClientException extends AppException {
/// {@macro client_exception}
const ClientException([super.message]);
const ClientException({super.message, super.underlyingException});
}
/// {@template server_exception}
@ -50,5 +69,5 @@ class ClientException extends AppException {
/// {@endtemplate}
class ServerException extends AppException {
/// {@macro server_exception}
const ServerException([super.message]);
const ServerException({super.message, super.underlyingException});
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,4 +14,4 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'base_repository.dart';
export 'data_sources/data_sources.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -15,5 +15,5 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'base_data_source.dart';
export 'local/local.dart';
export 'remote/remote.dart';
export 'local/base_local_data_source.dart';
export 'remote/base_remote_data_source.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart';
import 'package:wyatt_architecture/src/data/data_sources/base_data_source.dart';
/// {@template base_local_data_source}
/// [BaseLocalDataSource] is a base class for all local data sources in the

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/src/domain/data_sources/base_data_source.dart';
import 'package:wyatt_architecture/src/data/data_sources/base_data_source.dart';
/// {@template base_remote_data_source}
/// [BaseRemoteDataSource] is a base class for all remote data sources in the

View File

@ -1,17 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'base_local_data_source.dart';

View File

@ -1,17 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'base_remote_data_source.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'data_sources/data_sources.dart';
export 'entities/entities.dart';
export 'repositories/repositories.dart';
export 'entities/entity.dart';
export 'repositories/base_repository.dart';
export 'usecases/usecases.dart';

View File

@ -1,17 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'entity.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -1,26 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/src/domain/entities/entity.dart';
/// {@template no_param}
/// [NoParam] is a class that is used when a use case does not require any
/// parameters.
/// {@endtemplate}
class NoParam extends Entity {
/// {@macro no_param}
const NoParam();
}

View File

@ -1,45 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:async';
import 'package:wyatt_architecture/wyatt_architecture.dart';
/// Usecase observers
mixin Observer<Parameters, ReturnType> {
/// Called before usecase is runned.
/// Useful to check the preconditions
FutureOr<void> onStart(Parameters? params) {}
/// Called when error occures during main scenario
/// Useful to run alternative scenario
FutureOr<void> onError(AppException? error) {}
}
/// Specific observer for classic usecase
mixin AsyncObserver<ReturnType> {
/// Called when usecase is completed
FutureOr<void> onComplete(ReturnType? data) {}
}
/// Specific observer for stream case usecase
mixin StreamObserver<ReturnType> {
/// Replaces the data event handler of this subscription.
void onDone() {}
/// Replaces the done event handler of this subscription.
void onData(ReturnType? data) {}
}

View File

@ -1,100 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:async';
import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart';
import 'package:wyatt_architecture/src/domain/usecases/observers.dart';
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
typedef FutureOrResult<T> = FutureOr<Result<T, AppException>>;
typedef StreamResult<T> = Stream<Result<T, AppException>>;
/// {@template base_usecase}
/// Abstract class of any use case.
/// {@endtemplate}
abstract class BaseUseCase<Parameters, ReturnType> {
/// {@macro base_usecase}
const BaseUseCase();
/// Run use case scenarios
ReturnType call(Parameters parameters);
/// Private function to implement main scenario
/// of your usecase.
ReturnType execute(Parameters params);
}
/// {@template usecase}
/// Abstract class of a use case that deals specifically
/// with the response and its state.
/// {@endtemplate}
abstract class UseCase<Parameters, ReturnType>
extends BaseUseCase<Parameters?, FutureOrResult<ReturnType>>
with Observer<Parameters, ReturnType> {
/// {@macro usecase}
const UseCase();
FutureOr<void> _onSuccess(ReturnType data);
/// Supports the result of the main scenario and integrates
/// some alternative scenarios if necessary.
@override
FutureOrResult<ReturnType> call(Parameters? parameters) async {
try {
await onStart(parameters);
final response = await execute(parameters);
if (response.isErr) {
await onError(response.err);
} else if (response.isOk && response.ok != null) {
await _onSuccess(response.ok as ReturnType);
}
return response;
} catch (e) {
return Err(ClientException(e.toString()));
}
}
}
/// {@template async_usecase}
/// Abtstract classic usecase bases on futures
/// {@endtemplate}
abstract class AsyncUseCase<Parameters, ReturnType>
extends UseCase<Parameters?, ReturnType> with AsyncObserver<ReturnType> {
/// {@macro async_usecase}
const AsyncUseCase();
@override
FutureOr<void> _onSuccess(ReturnType data) => onComplete(data);
}
/// {@template stream_usecase}
/// Abstract specific usecase bases on streams
/// {@endtemplate}
abstract class StreamUseCase<Parameters, ReturnType>
extends UseCase<Parameters?, Stream<ReturnType>>
with StreamObserver<ReturnType> {
/// {@macro stream_usecase}
const StreamUseCase();
@override
FutureOr<void> _onSuccess(Stream<ReturnType> data) {
data.listen(
onData,
onDone: onDone,
);
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -14,6 +14,67 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'no_param.dart';
export 'observers.dart';
export 'usecase.dart';
import 'dart:async';
import 'package:generic_usecase/generic_usecase.dart' as uc;
import 'package:sealed_result/sealed_result.dart';
import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart';
typedef FutureOrResult<T> = FutureOr<Result<T, AppException>>;
typedef StreamResult<T> = Stream<Result<T, AppException>>;
/// {@template result_usecase}
/// A usecase that requires params of type [Input] and returns a result of type
/// [Output] or an error of type [AppException].
/// {@endtemplate}
abstract class Usecase<Input, Output>
extends uc.Usecase<Input, Result<Output, AppException>> {
/// {@macro result_usecase}
const Usecase() : super();
@override
FutureOrResult<Output> onException(Object e) =>
Result.err(AppException.from(e));
}
/// {@template no_params_result_usecase}
/// A usecase that does not require any params, but returns a result of type
/// [Output] or an error of type [AppException].
/// {@endtemplate}
abstract class NoParamsUsecase<Output>
extends uc.NoParamsUsecase<Result<Output, AppException>> {
/// {@macro no_params_result_usecase}
const NoParamsUsecase() : super();
@override
FutureOrResult<Output> onException(Object e) =>
Result.err(AppException.from(e));
}
/// {@template result_stream_usecase}
/// A stream usecase that requires params of type [Input] and returns a
/// stream of [Output] or [AppException].
/// {@endtemplate}
abstract class StreamUsecase<Input, Output>
extends uc.StreamUsecase<Input, Result<Output, AppException>> {
/// {@macro result_stream_usecase}
const StreamUsecase() : super();
@override
FutureOrResult<Output> onException(Object e) =>
Result.err(AppException.from(e));
}
/// {@template no_params_result_stream_usecase}
/// A stream usecase that does not require any params, but returns a
/// stream of [Output] or [AppException].
/// {@endtemplate}
abstract class NoParamsStreamUsecase<Output>
extends uc.NoParamsStreamUsecase<Result<Output, AppException>> {
/// {@macro no_params_result_stream_usecase}
const NoParamsStreamUsecase() : super();
@override
FutureOrResult<Output> onException(Object e) =>
Result.err(AppException.from(e));
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
@ -15,4 +15,5 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
export 'core/core.dart';
export 'data/data.dart';
export 'domain/domain.dart';

View File

@ -1,4 +1,4 @@
// Copyright (C) 2022 WYATT GROUP
// Copyright (C) WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify

View File

@ -22,14 +22,13 @@ version: 0.2.0+1
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
environment:
sdk: ">=2.17.0 <3.0.0"
sdk: ^3.0.0
dependencies:
wyatt_type_utils:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
version: ^0.0.5
sealed_result: ^3.0.0
generic_usecase: ^3.0.0
dev_dependencies:
wyatt_analysis:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
version: ^2.5.0
version: ^2.6.0