previous method
Fetches a previous page of the items.
Implementation
Future<void> previous() async {
if (_disposed) {
return Future.value();
}
final bool locked = _previousGuard.isLocked;
return _previousGuard.protect(() async {
if (locked || _disposed) {
return;
}
await _repeatUntilFulfilled(() async {
Log.debug('previous()...', '$runtimeType');
if (hasPrevious.isTrue && previousLoading.isFalse) {
previousLoading.value = true;
try {
if (items.isNotEmpty) {
try {
final Page<T, C>? page = await Backoff.run(
() =>
provider.before(onKey(items.first), startCursor, perPage),
_cancelToken,
);
Log.debug(
'previous()... fetched ${page?.edges.length} items',
'$runtimeType',
);
final int before = items.length;
for (var e in page?.edges ?? []) {
items[onKey(e)] = e;
}
startCursor = page?.info.startCursor ?? startCursor;
hasPrevious.value = page?.info.hasPrevious ?? hasPrevious.value;
Log.debug('previous()... done', '$runtimeType');
return page?.edges.take(max(0, items.length - before));
} catch (e) {
if (e is! OperationCanceledException) {
rethrow;
}
}
} else {
Log.debug(
'previous()... propagated to `around` due to items being empty',
'$runtimeType',
);
await around();
}
} finally {
previousLoading.value = false;
}
} else {
Log.debug(
'previous()... canceled due to `hasPrevious` being `true` ($hasPrevious) or `previousLoading` being false ($previousLoading)',
'$runtimeType',
);
}
return null;
});
});
}