doc(arch): add fully featured example

This commit is contained in:
2022-11-08 20:09:18 -05:00
parent db67491876
commit 6602db215f
109 changed files with 4499 additions and 29 deletions
@@ -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();
}
}