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,40 @@
// 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/usecases/photos/check_if_photo_is_in_favorites.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
part 'favorite_checker_state.dart';
class FavoriteCheckerCubit extends Cubit<FavoriteCheckerState> {
final CheckIfPhotoIsInFavorites _checkIfPhotoIsInFavorites;
FavoriteCheckerCubit(this._checkIfPhotoIsInFavorites)
: super(FavoriteCheckerInitial());
FutureOr<void> checkIfPhotoIsInFavorites(int photoId) async {
final response = await _checkIfPhotoIsInFavorites.call(photoId);
emit(
response.fold(
(value) => FavoriteCheckerSuccess(photoId, isFavorite: value),
(error) => FavoriteCheckerFailure(error.toString()),
),
);
}
}
@@ -0,0 +1,29 @@
part of 'favorite_checker_cubit.dart';
abstract class FavoriteCheckerState extends Equatable {
const FavoriteCheckerState();
@override
List<Object> get props => [];
}
class FavoriteCheckerInitial extends FavoriteCheckerState {}
class FavoriteCheckerSuccess extends FavoriteCheckerState {
final int photoId;
final bool isFavorite;
const FavoriteCheckerSuccess(this.photoId, {required this.isFavorite});
@override
List<Object> get props => [photoId, isFavorite];
}
class FavoriteCheckerFailure extends FavoriteCheckerState {
final String error;
const FavoriteCheckerFailure(this.error);
@override
List<Object> get props => [error];
}
@@ -0,0 +1,104 @@
// 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/photo.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';
import 'package:stream_transform/stream_transform.dart';
part 'photo_event.dart';
part 'photo_state.dart';
const _photoLimit = 40;
const throttleDuration = Duration(milliseconds: 100);
EventTransformer<E> throttleDroppable<E>(Duration duration) =>
(events, mapper) => droppable<E>().call(events.throttle(duration), mapper);
class PhotoBloc extends Bloc<PhotoEvent, PhotoState> {
final OpenAlbum _openAlbum;
PhotoBloc(this._openAlbum) : super(const PhotoState()) {
on<PhotoFetched>(
_onPhotoFetched,
transformer: throttleDroppable(throttleDuration),
);
}
Future<void> _onPhotoFetched(
PhotoFetched event,
Emitter<PhotoState> emit,
) async {
if (state.hasReachedMax) {
return;
}
if (state.status == FetchStatus.initial) {
final photos = await _openAlbum.call(
QueryParameters(
0,
_photoLimit,
albumId: event.albumId,
),
);
return emit(
photos.fold(
(value) => state.copyWith(
status: FetchStatus.success,
photos: value,
hasReachedMax: false,
),
(error) => state.copyWith(
status: FetchStatus.failure,
photos: [],
hasReachedMax: false,
),
),
);
}
final photos = await _openAlbum.call(
QueryParameters(
state.photos.length,
_photoLimit,
albumId: event.albumId,
),
);
return emit(
photos.fold(
(value) {
if (value.isEmpty) {
return state.copyWith(
hasReachedMax: true,
);
}
return state.copyWith(
status: FetchStatus.success,
photos: List.of(state.photos)..addAll(value),
hasReachedMax: false,
);
},
(error) => state.copyWith(
status: FetchStatus.failure,
photos: List.of(state.photos),
hasReachedMax: false,
),
),
);
}
}
@@ -0,0 +1,30 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
part of 'photo_bloc.dart';
abstract class PhotoEvent extends Equatable {
const PhotoEvent();
@override
List<Object> get props => [];
}
class PhotoFetched extends PhotoEvent {
final int albumId;
const PhotoFetched(this.albumId);
}
@@ -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 'photo_bloc.dart';
class PhotoState extends Equatable {
const PhotoState({
this.status = FetchStatus.initial,
this.photos = const <Photo>[],
this.hasReachedMax = false,
});
final FetchStatus status;
final List<Photo> photos;
final bool hasReachedMax;
PhotoState copyWith({
FetchStatus? status,
List<Photo>? photos,
bool? hasReachedMax,
}) =>
PhotoState(
status: status ?? this.status,
photos: photos ?? this.photos,
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
);
@override
List<Object> get props => [status, photos, hasReachedMax];
}