doc(arch): add fully featured example
This commit is contained in:
+40
@@ -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()),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+29
@@ -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];
|
||||
}
|
||||
+104
@@ -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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+30
@@ -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);
|
||||
}
|
||||
+43
@@ -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];
|
||||
}
|
||||
Reference in New Issue
Block a user