doc(arch): add fully featured example
This commit is contained in:
+79
@@ -0,0 +1,79 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:architecture_example/domain/entities/photo.dart';
|
||||
import 'package:architecture_example/domain/usecases/photos/add_photo_to_favorites.dart';
|
||||
import 'package:architecture_example/domain/usecases/photos/check_if_photo_is_in_favorites.dart';
|
||||
import 'package:architecture_example/domain/usecases/photos/display_photo.dart';
|
||||
import 'package:architecture_example/domain/usecases/photos/remove_photo_from_favorites.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
part 'photo_details_state.dart';
|
||||
|
||||
class PhotoDetailsCubit extends Cubit<PhotoDetailsState> {
|
||||
final DisplayPhoto _displayPhoto;
|
||||
final CheckIfPhotoIsInFavorites _checkIfPhotoIsInFavorites;
|
||||
final AddPhotoToFavorites _addPhotoToFavorites;
|
||||
final RemovePhotoFromFavorites _removePhotoFromFavorites;
|
||||
|
||||
PhotoDetailsCubit(
|
||||
this._displayPhoto,
|
||||
this._checkIfPhotoIsInFavorites,
|
||||
this._addPhotoToFavorites,
|
||||
this._removePhotoFromFavorites,
|
||||
) : super(PhotoDetailsInitial());
|
||||
|
||||
FutureOr<void> load(int photoId) async {
|
||||
final photo = await _displayPhoto.call(photoId);
|
||||
final isFavorite = await _checkIfPhotoIsInFavorites.call(photoId);
|
||||
|
||||
emit(
|
||||
photo.fold(
|
||||
(value) => PhotoDetailsSuccess(
|
||||
value,
|
||||
isFavorite: isFavorite.fold((value) => value, (error) => false),
|
||||
),
|
||||
(error) => PhotoDetailsFailure(error.toString()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
FutureOr<void> addToFavorites() async {
|
||||
if (state is! PhotoDetailsSuccess) {
|
||||
return;
|
||||
}
|
||||
final actualState = state as PhotoDetailsSuccess;
|
||||
final response = await _addPhotoToFavorites.call(actualState.photo);
|
||||
if (response.isOk) {
|
||||
emit(PhotoDetailsSuccess(actualState.photo, isFavorite: true));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> removeFromFavorites() async {
|
||||
if (state is! PhotoDetailsSuccess) {
|
||||
return;
|
||||
}
|
||||
final actualState = state as PhotoDetailsSuccess;
|
||||
final response = await _removePhotoFromFavorites.call(actualState.photo.id);
|
||||
if (response.isOk) {
|
||||
emit(PhotoDetailsSuccess(actualState.photo, isFavorite: false));
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// 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_details_cubit.dart';
|
||||
|
||||
abstract class PhotoDetailsState extends Equatable {
|
||||
const PhotoDetailsState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class PhotoDetailsInitial extends PhotoDetailsState {}
|
||||
|
||||
class PhotoDetailsSuccess extends PhotoDetailsState {
|
||||
final Photo photo;
|
||||
final bool isFavorite;
|
||||
|
||||
const PhotoDetailsSuccess(this.photo, {required this.isFavorite});
|
||||
|
||||
@override
|
||||
List<Object> get props => [photo, isFavorite];
|
||||
}
|
||||
|
||||
class PhotoDetailsFailure extends PhotoDetailsState {
|
||||
final String error;
|
||||
|
||||
const PhotoDetailsFailure(this.error);
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:architecture_example/presentation/features/photo_details/state_management/photo_details_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PhotoDetails extends StatelessWidget {
|
||||
const PhotoDetails({required this.photoId, super.key});
|
||||
|
||||
final int photoId;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => PhotoDetailsScreen(photoId: photoId);
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||
import 'package:architecture_example/domain/usecases/photos/add_photo_to_favorites.dart';
|
||||
import 'package:architecture_example/domain/usecases/photos/check_if_photo_is_in_favorites.dart';
|
||||
import 'package:architecture_example/domain/usecases/photos/display_photo.dart';
|
||||
import 'package:architecture_example/domain/usecases/photos/remove_photo_from_favorites.dart';
|
||||
import 'package:architecture_example/presentation/features/photo_details/blocs/photo_details/photo_details_cubit.dart';
|
||||
import 'package:architecture_example/presentation/features/photo_details/state_management/photo_details_wrapper_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
||||
|
||||
class PhotoDetailsScreen
|
||||
extends CubitScreen<PhotoDetailsCubit, PhotoDetailsState> {
|
||||
const PhotoDetailsScreen({required this.photoId, super.key});
|
||||
|
||||
final int photoId;
|
||||
|
||||
@override
|
||||
PhotoDetailsCubit create(BuildContext context) => PhotoDetailsCubit(
|
||||
DisplayPhoto(repo<PhotoRepository>(context)),
|
||||
CheckIfPhotoIsInFavorites(repo<PhotoRepository>(context)),
|
||||
AddPhotoToFavorites(repo<PhotoRepository>(context)),
|
||||
RemovePhotoFromFavorites(repo<PhotoRepository>(context)),
|
||||
);
|
||||
|
||||
@override
|
||||
PhotoDetailsCubit init(BuildContext context, PhotoDetailsCubit bloc) =>
|
||||
bloc..load(photoId);
|
||||
|
||||
@override
|
||||
Widget onWrap(BuildContext context, Widget child) =>
|
||||
PhotoDetailsWrapperWidget(child: child);
|
||||
|
||||
@override
|
||||
Widget onBuild(BuildContext context, PhotoDetailsState state) {
|
||||
if (state is PhotoDetailsFailure) {
|
||||
return const Center(
|
||||
child: Text('failed to fetch photo details'),
|
||||
);
|
||||
}
|
||||
if (state is PhotoDetailsSuccess) {
|
||||
return CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
expandedHeight: 400,
|
||||
stretch: true,
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
background: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Image.network(
|
||||
state.photo.thumbnailUrl,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: Image.network(
|
||||
state.photo.url,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
state.photo.title,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
state.isFavorite
|
||||
? bloc(context).removeFromFavorites()
|
||||
: bloc(context).addToFavorites();
|
||||
},
|
||||
icon: Icon(
|
||||
state.isFavorite
|
||||
? Icons.favorite
|
||||
: Icons.favorite_outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package: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,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user