Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat:[공통] Pagination 마지막 페이지 체크 로직 보완 #85 #88

Merged
merged 2 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 14 additions & 15 deletions lib/core/pagination/pagination_response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class PaginationResponse<T> {
required this.page,
required this.size,
required this.items,
required this.isLastPage,
});

PaginationResponse.fromJson(
Expand All @@ -13,27 +14,25 @@ class PaginationResponse<T> {
size = json['size'] as int,
items = (json['items'] as List<dynamic>)
.map((e) => fromJson.call(e))
.toList();
.toList(),
isLastPage = json['is_last_page'] as bool;

final int page;
final int size;
final List<T> items;
final bool isLastPage;

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is PaginationResponse &&
other.items == items &&
other.page == page &&
other.size == size;
}
bool operator ==(Object other) =>
identical(this, other) ||
other is PaginationResponse<T> &&
runtimeType == other.runtimeType &&
page == other.page &&
size == other.size &&
items == other.items &&
isLastPage == other.isLastPage;

@override
int get hashCode => items.hashCode ^ page.hashCode ^ size.hashCode;

Map<String, dynamic> toJson() => {
'page': page,
'size': size,
};
int get hashCode =>
page.hashCode ^ size.hashCode ^ items.hashCode ^ isLastPage.hashCode;
}
42 changes: 6 additions & 36 deletions lib/features/pet/domain/breeds_pagination_response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,15 @@ import 'package:pets_next_door_flutter/core/pagination/pagination_response.dart'
import 'package:pets_next_door_flutter/features/pet/domain/breed.dart';

/// Metadata used when fetching movies with the paginated search API.
class BreedsPaginationResponse implements PaginationResponse<Breed> {
class BreedsPaginationResponse extends PaginationResponse<Breed> {
BreedsPaginationResponse({
required this.page,
required this.size,
required this.items,
required super.page,
required super.size,
required super.items,
required super.isLastPage,
});

BreedsPaginationResponse.fromJson(
Map<String, dynamic> json,
) : page = json['page'] as int,
size = json['size'] as int,
items = (json['items'] as List<dynamic>)
.map((e) => Breed.fromJson(e))
.toList();

@override
final int page;

@override
final int size;

@override
final List<Breed> items;

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is BreedsPaginationResponse &&
other.page == page &&
other.size == size;
}

@override
int get hashCode => page.hashCode ^ size.hashCode;

@override
Map<String, dynamic> toJson() {
// TODO: implement toJson
throw UnimplementedError();
}
) : super.fromJson(json, (e) => Breed.fromJson(e));
Comment on lines +5 to +15
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개별 PaginationResponse들이 기본 PaginationResponse들을 기존에 implements 하던 것을 extends 하도록 변경해 불필요하게 반복되는 로직들을 제거했습니다.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PaginationResponse가 다른 클래스들의 순수한 is-a 관계인 것 같아 상속으로 바꿔도 좋을 것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

불필요하게 반복되는 코드를 줄여보자는 관점으로 접근 했었는데 is-ahas-aextendsimplements를 판단할 수 있군요.

}
4 changes: 2 additions & 2 deletions lib/features/pet/repository/pet_repository.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'package:pets_next_door_flutter/core/utils/result.dart';
import 'package:pets_next_door_flutter/features/pet/domain/breed.dart';
import 'package:pets_next_door_flutter/features/pet/domain/breeds_pagination_request.dart';
import 'package:pets_next_door_flutter/features/pet/domain/breeds_pagination_response.dart';
import 'package:pets_next_door_flutter/features/pet/entities/pet_data_entity.dart';

abstract interface class PetRepository {
Future<Result<List<Breed>>> getBreeds({
Future<Result<BreedsPaginationResponse>> getBreeds({
required BreedsPaginationRequest breedsPaginationRequest,
});

Expand Down
6 changes: 3 additions & 3 deletions lib/features/pet/repository/pet_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:pets_next_door_flutter/core/utils/result.dart';
import 'package:pets_next_door_flutter/features/pet/data/remote/pet_remote_data_source.dart';
import 'package:pets_next_door_flutter/features/pet/domain/breed.dart';
import 'package:pets_next_door_flutter/features/pet/domain/breeds_pagination_request.dart';
import 'package:pets_next_door_flutter/features/pet/domain/breeds_pagination_response.dart';
import 'package:pets_next_door_flutter/features/pet/entities/pet_data_entity.dart';
import 'package:pets_next_door_flutter/features/pet/repository/pet_repository.dart';

Expand All @@ -13,12 +13,12 @@ final class PetRepositoryImpl implements PetRepository {
final PetRemoteDataSource _petRemoteDataSource;

@override
Future<Result<List<Breed>>> getBreeds(
Future<Result<BreedsPaginationResponse>> getBreeds(
{required BreedsPaginationRequest breedsPaginationRequest}) async {
try {
final breedsData = await _petRemoteDataSource.getBreeds(
breedsPaginationRequest: breedsPaginationRequest);
return Result.success(breedsData.items);
return Result.success(breedsData);
} on Exception catch (e) {
return Result.failure(e);
}
Expand Down
9 changes: 5 additions & 4 deletions lib/features/pet/usecases/get_breeds_use_case.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:pets_next_door_flutter/core/utils/result.dart';
import 'package:pets_next_door_flutter/features/pet/domain/breed.dart';
import 'package:pets_next_door_flutter/features/pet/domain/breeds_pagination_request.dart';
import 'package:pets_next_door_flutter/features/pet/domain/breeds_pagination_response.dart';
import 'package:pets_next_door_flutter/features/pet/repository/pet_repository.dart';

final class GetBreedsUseCase {
Expand All @@ -10,9 +10,10 @@ final class GetBreedsUseCase {

final PetRepository _petRepository;

Future<Result<List<Breed>>> call({
Future<Result<BreedsPaginationResponse>> call({
required BreedsPaginationRequest breedsPaginationRequest,
}) async {
return _petRepository.getBreeds(breedsPaginationRequest: breedsPaginationRequest);
return _petRepository.getBreeds(
breedsPaginationRequest: breedsPaginationRequest);
}
}
}
41 changes: 6 additions & 35 deletions lib/features/sos/data/dto/sos_pagination_response_dto.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,15 @@ import 'package:pets_next_door_flutter/core/pagination/pagination_response.dart'
import 'package:pets_next_door_flutter/features/sos/data/dto/sos_post_dto.dart';

/// Metadata used when fetching movies with the paginated search API.
class SosPostPaginationResponseDto implements PaginationResponse<SosPostDto> {
class SosPostPaginationResponseDto extends PaginationResponse<SosPostDto> {
SosPostPaginationResponseDto({
required this.page,
required this.size,
required this.items,
required super.page,
required super.size,
required super.items,
required super.isLastPage,
});

SosPostPaginationResponseDto.fromJson(
Map<String, dynamic> json,
) : page = json['page'] as int,
size = json['size'] as int,
items = (json['items'] as List<dynamic>)
.map((e) => SosPostDto.fromJson(e))
.toList();

@override
final int page;

@override
final int size;

@override
final List<SosPostDto> items;

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is SosPostPaginationResponseDto &&
other.page == page &&
other.size == size;
}

@override
int get hashCode => page.hashCode ^ size.hashCode;

@override
Map<String, dynamic> toJson() {
throw UnimplementedError();
}
) : super.fromJson(json, (e) => SosPostDto.fromJson(e));
}
4 changes: 2 additions & 2 deletions lib/features/sos/repositories/sos_post_repository.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:pets_next_door_flutter/core/utils/result.dart';
import 'package:pets_next_door_flutter/features/sos/data/dto/sos_pagination_request_dto.dart';
import 'package:pets_next_door_flutter/features/sos/entities/sos_post_entity.dart';
import 'package:pets_next_door_flutter/features/sos/data/dto/sos_pagination_response_dto.dart';

abstract interface class SosPostRepository {
Future<Result<List<SosPostEntity>>> getSosPosts(
Future<Result<SosPostPaginationResponseDto>> getSosPosts(
SosPostPaginationRequestDto request);
}
10 changes: 3 additions & 7 deletions lib/features/sos/repositories/sos_post_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:pets_next_door_flutter/core/utils/result.dart';
import 'package:pets_next_door_flutter/features/sos/data/dto/sos_pagination_request_dto.dart';
import 'package:pets_next_door_flutter/features/sos/data/dto/sos_pagination_response_dto.dart';
import 'package:pets_next_door_flutter/features/sos/data/remote/sos_post_remote_data_source.dart';
import 'package:pets_next_door_flutter/features/sos/entities/sos_post_entity.dart';
import 'package:pets_next_door_flutter/features/sos/repositories/sos_post_repository.dart';

final class SosPostRepositoryImpl implements SosPostRepository {
Expand All @@ -12,17 +12,13 @@ final class SosPostRepositoryImpl implements SosPostRepository {
final SosPostRemoteDataSource _sosPostRemoteDataSource;

@override
Future<Result<List<SosPostEntity>>> getSosPosts(
Future<Result<SosPostPaginationResponseDto>> getSosPosts(
SosPostPaginationRequestDto request) async {
try {
final sosPostResponse =
await _sosPostRemoteDataSource.getSosPosts(request);

return Result.success(
sosPostResponse.items
.map((postDto) => SosPostEntity.fromDto(postDto))
.toList(),
);
return Result.success(sosPostResponse);
} on Exception catch (e) {
return Result.failure(e);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/features/sos/usecases/get_sos_post_use_case.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:pets_next_door_flutter/core/enums/sort_type_filter.enum.dart';
import 'package:pets_next_door_flutter/core/utils/result.dart';
import 'package:pets_next_door_flutter/features/sos/data/dto/sos_pagination_request_dto.dart';
import 'package:pets_next_door_flutter/features/sos/entities/sos_post_entity.dart';
import 'package:pets_next_door_flutter/features/sos/data/dto/sos_pagination_response_dto.dart';
import 'package:pets_next_door_flutter/features/sos/repositories/sos_post_repository.dart';

final class GetSosPostsUseCase {
Expand All @@ -11,7 +11,7 @@ final class GetSosPostsUseCase {

final SosPostRepository _sosPostRepository;

Future<Result<List<SosPostEntity>>> call({
Future<Result<SosPostPaginationResponseDto>> call({
required int size,
required int page,
required SortTypeFilter sortType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'breeds_paging_controller_provider.g.dart';

const breedsPagingSize = 20;
const pagingSize = 20;

@riverpod
class BreedsPagingController extends _$BreedsPagingController {
Expand All @@ -24,22 +24,20 @@ class BreedsPagingController extends _$BreedsPagingController {

Future<void> fetchPage(int pageKey) async {
try {
final newBreeds = await getBreedsUseCase.call(
final newPage = await getBreedsUseCase.call(
breedsPaginationRequest: new BreedsPaginationRequest(
page: pageKey,
size: breedsPagingSize,
size: pagingSize,
petType: ref.read(petStateProvider.notifier).state.petType!,
),
);

newBreeds.fold(
onSuccess: (breeds) {
final isLastPage = breeds.length < breedsPagingSize;

if (isLastPage) {
state.appendLastPage(breeds);
newPage.fold(
onSuccess: (page) {
if (page.isLastPage) {
state.appendLastPage(page.items);
} else {
state.appendPage(breeds, pageKey + 1);
state.appendPage(page.items, pageKey + 1);
}
},
onFailure: (e) => print('::: Fold Error ::: $e'),
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,21 @@ class SosPagingController extends _$SosPagingController {

Future<void> fetchPage(int pageKey) async {
try {
final newPosts = await getSosPostUseCase.call(
final newPage = await getSosPostUseCase.call(
size: _pagingSize,
page: pageKey,
sortType: ref.read(sosPostFilterProvider).sortFilter,
);

newPosts.fold(
onSuccess: (breeds) {
final isLastPage = breeds.length < _pagingSize;

if (isLastPage) {
state.appendLastPage(breeds);
newPage.fold(
onSuccess: (page) {
final sosPostList = page.items
.map((sosPost) => SosPostEntity.fromDto(sosPost))
.toList();
if (page.isLastPage) {
state.appendLastPage(sosPostList);
} else {
state.appendPage(breeds, pageKey + 1);
state.appendPage(sosPostList, pageKey + 1);
}
},
onFailure: (e) => print('::: Fold Error ::: $e'),
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.