계정 정보 다이얼로그 추가 및 전체 목록 페치 개선

This commit is contained in:
JiWoong Sul
2025-10-22 01:05:47 +09:00
parent 6b58effc83
commit f4dc83d441
44 changed files with 1636 additions and 362 deletions

View File

@@ -0,0 +1,65 @@
import '../models/paginated_result.dart';
/// 페이지네이션 API에서 모든 항목을 수집하는 도우미.
///
/// - 백엔드가 기본적으로 페이지 크기 제한을 두는 경우, 반복 호출로 전체 목록을 확보한다.
/// - `maxPages`는 안전장치로 사용하며, 비정상 응답으로 무한 루프에 빠지는 것을 막는다.
typedef PaginatedRequest<T> =
Future<PaginatedResult<T>> Function(int page, int pageSize);
/// 페이지 단위로 제공되는 데이터를 모두 불러온다.
///
/// - [request]는 페이지 번호와 페이지 크기를 받아 `PaginatedResult`를 반환해야 한다.
/// - [pageSize]는 첫 호출에 사용할 기본 페이지 크기이며, 서버가 다른 값을 돌려주면
/// 이후 호출에서는 응답 값을 따른다.
/// - [maxPages]는 허용할 최대 페이지 수로, 비정상 응답을 대비한 제한값이다.
Future<List<T>> fetchAllPaginatedItems<T>({
required PaginatedRequest<T> request,
int pageSize = 100,
int maxPages = 50,
}) async {
final results = <T>[];
var currentPage = 1;
var pagesFetched = 0;
var effectivePageSize = pageSize > 0 ? pageSize : 100;
while (pagesFetched < maxPages) {
final previousLength = results.length;
final response = await request(currentPage, effectivePageSize);
pagesFetched += 1;
final items = response.items;
if (items.isEmpty) {
break;
}
results.addAll(items);
final added = results.length - previousLength;
if (added <= 0) {
// 새 항목을 받지 못했다면 더 이상 진행하지 않는다.
break;
}
final receivedPageSize = () {
if (response.pageSize > 0) {
return response.pageSize;
}
if (items.isNotEmpty) {
return items.length;
}
return effectivePageSize;
}();
if (items.length < receivedPageSize) {
// 마지막 페이지에 도달한 경우 즉시 종료한다.
break;
}
effectivePageSize = receivedPageSize;
final nextPage = response.page > 0 ? response.page + 1 : currentPage + 1;
currentPage = nextPage > currentPage ? nextPage : currentPage + 1;
}
return results;
}