relatica/lib/friendica_client/paged_response.dart

98 wiersze
2.8 KiB
Dart

import 'package:logging/logging.dart';
import 'package:result_monad/result_monad.dart';
import '../models/exec_error.dart';
import 'paging_data.dart';
final _logger = Logger('PagedResponse');
class PagedResponse<T> {
PagingData? previous;
PagingData? next;
T data;
PagedResponse(this.data, {this.previous, this.next});
bool get hasMorePages => previous != null || next != null;
static Result<PagedResponse<T>, ExecError> fromLinkHeader<T>(
String? linkHeader, T data) {
if (linkHeader == null || linkHeader.isEmpty) {
return Result.ok(PagedResponse(data));
}
String? previousPage;
String? nextPage;
for (String linkTerms in linkHeader.trim().split(',')) {
if (linkHeader.isEmpty) {
return buildErrorResult(
type: ErrorType.parsingError,
message: 'Link header element is blank',
);
}
final paging = linkTerms.split(';');
if (paging.length != 2) {
return buildErrorResult(
type: ErrorType.parsingError,
message:
'Incorrect number of elements, ${paging.length} != 2, for: $linkTerms',
);
}
final urlPieceString = paging.first.trim();
if (!urlPieceString.startsWith('<') && !urlPieceString.endsWith('>')) {
return buildErrorResult(
type: ErrorType.parsingError,
message:
'Link URL is malformed (no leading trailing <>): $urlPieceString',
);
}
final url = urlPieceString.substring(1, urlPieceString.length - 1);
final directionString = paging.last.trim();
if (directionString == 'rel="prev"') {
previousPage = url;
} else if (directionString == 'rel="next"') {
nextPage = url;
} else {
_logger.info('Unknown paging data: $directionString for url: $url');
}
}
return Result.ok(PagedResponse(
data,
previous: previousPage == null
? null
: PagingData.fromQueryParameters(
Uri.parse(previousPage),
),
next: nextPage == null
? null
: PagingData.fromQueryParameters(
Uri.parse(nextPage),
),
));
}
PagedResponse<T2> map<T2>(T2 Function(T data) func) => PagedResponse(
func(data),
previous: previous,
next: next,
);
@override
String toString() {
return 'PagedResponse{previous: $previous, next: $next, data: $data}';
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is PagedResponse &&
runtimeType == other.runtimeType &&
previous == other.previous &&
next == other.next &&
data == other.data;
@override
int get hashCode => previous.hashCode ^ next.hashCode ^ data.hashCode;
}