forked from eatvio/eatvio_app
feat(feed): add lazy loading
This commit is contained in:
@@ -7,7 +7,7 @@ class DietsCubit extends Cubit<DietsState> {
|
||||
int currentPage = 1;
|
||||
late int lastPage;
|
||||
bool isLoading = false;
|
||||
// String? _query;
|
||||
String? _query;
|
||||
|
||||
DietsCubit({required this.feedRepository}) : super(const DietsState.loading());
|
||||
|
||||
@@ -15,14 +15,49 @@ class DietsCubit extends Cubit<DietsState> {
|
||||
String? query,
|
||||
}) async {
|
||||
try {
|
||||
// _query = query;
|
||||
final diets = await feedRepository.getDiets(
|
||||
_query = query;
|
||||
final dietsPagination = await feedRepository.getDiets(
|
||||
query: query,
|
||||
);
|
||||
lastPage = diets.meta.lastPage;
|
||||
emit(DietsState.loaded(diets: diets));
|
||||
lastPage = dietsPagination.meta.lastPage;
|
||||
emit(DietsState.loaded(
|
||||
dietsList: dietsPagination.data,
|
||||
isLoading: isLoading,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(DietsState.error(errorMessage: e.toString()));
|
||||
emit(DietsState.error(
|
||||
errorMessage: e.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
loadNextPage() async {
|
||||
if (currentPage < lastPage && !isLoading) {
|
||||
isLoading = true;
|
||||
|
||||
emit((state as DietsStateLoaded).copyWith(isLoading: isLoading));
|
||||
|
||||
try {
|
||||
if (currentPage < lastPage) {
|
||||
currentPage++;
|
||||
final dietPagination = await feedRepository.getDiets(
|
||||
page: currentPage,
|
||||
query: _query,
|
||||
);
|
||||
isLoading = false;
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...(state as DietsStateLoaded).dietsList,
|
||||
...dietPagination.data,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
emit(DietsState.error(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ abstract class DietsState with _$DietsState {
|
||||
const factory DietsState.loading() = DietsStateLoading;
|
||||
|
||||
const factory DietsState.loaded({
|
||||
required DietsPagination diets,
|
||||
required List<Diet> dietsList,
|
||||
required bool isLoading,
|
||||
}) = DietsStateLoaded;
|
||||
|
||||
const factory DietsState.error({
|
||||
|
||||
@@ -20,7 +20,7 @@ mixin _$DietsState {
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(DietsPagination diets) loaded,
|
||||
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@@ -28,7 +28,7 @@ mixin _$DietsState {
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(DietsPagination diets)? loaded,
|
||||
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@@ -36,7 +36,7 @@ mixin _$DietsState {
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(DietsPagination diets)? loaded,
|
||||
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
@@ -132,7 +132,7 @@ class _$DietsStateImpl implements _DietsState {
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(DietsPagination diets) loaded,
|
||||
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return $default();
|
||||
@@ -143,7 +143,7 @@ class _$DietsStateImpl implements _DietsState {
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(DietsPagination diets)? loaded,
|
||||
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return $default?.call();
|
||||
@@ -154,7 +154,7 @@ class _$DietsStateImpl implements _DietsState {
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(DietsPagination diets)? loaded,
|
||||
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
@@ -249,7 +249,7 @@ class _$DietsStateLoadingImpl implements DietsStateLoading {
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(DietsPagination diets) loaded,
|
||||
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return loading();
|
||||
@@ -260,7 +260,7 @@ class _$DietsStateLoadingImpl implements DietsStateLoading {
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(DietsPagination diets)? loaded,
|
||||
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return loading?.call();
|
||||
@@ -271,7 +271,7 @@ class _$DietsStateLoadingImpl implements DietsStateLoading {
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(DietsPagination diets)? loaded,
|
||||
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
@@ -329,9 +329,7 @@ abstract class _$$DietsStateLoadedImplCopyWith<$Res> {
|
||||
$Res Function(_$DietsStateLoadedImpl) then) =
|
||||
__$$DietsStateLoadedImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({DietsPagination diets});
|
||||
|
||||
$DietsPaginationCopyWith<$Res> get diets;
|
||||
$Res call({List<Diet> dietsList, bool isLoading});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -347,38 +345,43 @@ class __$$DietsStateLoadedImplCopyWithImpl<$Res>
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? diets = null,
|
||||
Object? dietsList = null,
|
||||
Object? isLoading = null,
|
||||
}) {
|
||||
return _then(_$DietsStateLoadedImpl(
|
||||
diets: null == diets
|
||||
? _value.diets
|
||||
: diets // ignore: cast_nullable_to_non_nullable
|
||||
as DietsPagination,
|
||||
dietsList: null == dietsList
|
||||
? _value._dietsList
|
||||
: dietsList // ignore: cast_nullable_to_non_nullable
|
||||
as List<Diet>,
|
||||
isLoading: null == isLoading
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of DietsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$DietsPaginationCopyWith<$Res> get diets {
|
||||
return $DietsPaginationCopyWith<$Res>(_value.diets, (value) {
|
||||
return _then(_value.copyWith(diets: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$DietsStateLoadedImpl implements DietsStateLoaded {
|
||||
const _$DietsStateLoadedImpl({required this.diets});
|
||||
const _$DietsStateLoadedImpl(
|
||||
{required final List<Diet> dietsList, required this.isLoading})
|
||||
: _dietsList = dietsList;
|
||||
|
||||
final List<Diet> _dietsList;
|
||||
@override
|
||||
List<Diet> get dietsList {
|
||||
if (_dietsList is EqualUnmodifiableListView) return _dietsList;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_dietsList);
|
||||
}
|
||||
|
||||
@override
|
||||
final DietsPagination diets;
|
||||
final bool isLoading;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DietsState.loaded(diets: $diets)';
|
||||
return 'DietsState.loaded(dietsList: $dietsList, isLoading: $isLoading)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -386,11 +389,15 @@ class _$DietsStateLoadedImpl implements DietsStateLoaded {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$DietsStateLoadedImpl &&
|
||||
(identical(other.diets, diets) || other.diets == diets));
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._dietsList, _dietsList) &&
|
||||
(identical(other.isLoading, isLoading) ||
|
||||
other.isLoading == isLoading));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, diets);
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, const DeepCollectionEquality().hash(_dietsList), isLoading);
|
||||
|
||||
/// Create a copy of DietsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -406,10 +413,10 @@ class _$DietsStateLoadedImpl implements DietsStateLoaded {
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(DietsPagination diets) loaded,
|
||||
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return loaded(diets);
|
||||
return loaded(dietsList, isLoading);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -417,10 +424,10 @@ class _$DietsStateLoadedImpl implements DietsStateLoaded {
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(DietsPagination diets)? loaded,
|
||||
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return loaded?.call(diets);
|
||||
return loaded?.call(dietsList, isLoading);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -428,12 +435,12 @@ class _$DietsStateLoadedImpl implements DietsStateLoaded {
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(DietsPagination diets)? loaded,
|
||||
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(diets);
|
||||
return loaded(dietsList, isLoading);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
@@ -477,10 +484,12 @@ class _$DietsStateLoadedImpl implements DietsStateLoaded {
|
||||
}
|
||||
|
||||
abstract class DietsStateLoaded implements DietsState {
|
||||
const factory DietsStateLoaded({required final DietsPagination diets}) =
|
||||
_$DietsStateLoadedImpl;
|
||||
const factory DietsStateLoaded(
|
||||
{required final List<Diet> dietsList,
|
||||
required final bool isLoading}) = _$DietsStateLoadedImpl;
|
||||
|
||||
DietsPagination get diets;
|
||||
List<Diet> get dietsList;
|
||||
bool get isLoading;
|
||||
|
||||
/// Create a copy of DietsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -561,7 +570,7 @@ class _$DietsStateErrorImpl implements DietsStateError {
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(DietsPagination diets) loaded,
|
||||
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return error(errorMessage);
|
||||
@@ -572,7 +581,7 @@ class _$DietsStateErrorImpl implements DietsStateError {
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(DietsPagination diets)? loaded,
|
||||
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return error?.call(errorMessage);
|
||||
@@ -583,7 +592,7 @@ class _$DietsStateErrorImpl implements DietsStateError {
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(DietsPagination diets)? loaded,
|
||||
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
|
||||
@@ -13,6 +13,11 @@ class RecipesCubit extends Cubit<RecipesState> {
|
||||
bool isLoading = false;
|
||||
String? _query;
|
||||
|
||||
RecipesCubit({
|
||||
required this.feedRepository,
|
||||
required this.recipeRepository,
|
||||
}) : super(const RecipesState.loading());
|
||||
|
||||
loadRecipesList({
|
||||
String? query,
|
||||
}) async {
|
||||
@@ -35,11 +40,6 @@ class RecipesCubit extends Cubit<RecipesState> {
|
||||
}
|
||||
}
|
||||
|
||||
RecipesCubit({
|
||||
required this.feedRepository,
|
||||
required this.recipeRepository,
|
||||
}) : super(const RecipesState.loading());
|
||||
|
||||
loadNextPage() async {
|
||||
if (currentPage < lastPage && !isLoading) {
|
||||
isLoading = true;
|
||||
|
||||
@@ -57,11 +57,23 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
_onScrollRecipes() {}
|
||||
_onScrollRecipes() {
|
||||
if (recipesScrollController.offset >= recipesScrollController.position.maxScrollExtent && !recipesScrollController.position.outOfRange) {
|
||||
recipesCubit.loadNextPage();
|
||||
}
|
||||
}
|
||||
|
||||
_onScrollDiets() {}
|
||||
_onScrollDiets() {
|
||||
if (dietsScrollController.offset >= dietsScrollController.position.maxScrollExtent && !dietsScrollController.position.outOfRange) {
|
||||
dietsCubit.loadNextPage();
|
||||
}
|
||||
}
|
||||
|
||||
_onScrollPlans() {}
|
||||
_onScrollPlans() {
|
||||
if (plansScrollController.offset >= plansScrollController.position.maxScrollExtent && !plansScrollController.position.outOfRange) {
|
||||
// plansCubit.loadNextPage();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@@ -133,16 +145,17 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
},
|
||||
body: Builder(
|
||||
builder: (BuildContext context) {
|
||||
if (_selectedChipIndex == 0)
|
||||
if (_selectedChipIndex == 0) {
|
||||
return _buildAllBlogPosts();
|
||||
else if (_selectedChipIndex == 1)
|
||||
} else if (_selectedChipIndex == 1) {
|
||||
return _buildAllRecipes();
|
||||
else if (_selectedChipIndex == 2)
|
||||
} else if (_selectedChipIndex == 2) {
|
||||
return _buildDiets();
|
||||
else if (_selectedChipIndex == 3)
|
||||
} else if (_selectedChipIndex == 3) {
|
||||
return _buildPlans();
|
||||
else
|
||||
} else {
|
||||
return Center(child: Text(chipsLabelList[_selectedChipIndex]));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -274,12 +287,12 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
shrinkWrap: true,
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return DietsWidget(diet: state.diets.data[index]);
|
||||
return DietsWidget(diet: state.dietsList[index]);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(height: 8);
|
||||
},
|
||||
itemCount: state.diets.data.length,
|
||||
itemCount: state.dietsList.length,
|
||||
);
|
||||
} else if (state is DietsStateError) {
|
||||
return Scaffold(
|
||||
|
||||
Reference in New Issue
Block a user