added support for simultan downloads in files and talk, support for background downloads, enhanced loading in files with retry

This commit is contained in:
2026-07-06 15:43:17 +02:00
parent 614ab159af
commit 124b1a5177
34 changed files with 1866 additions and 409 deletions
+38
View File
@@ -0,0 +1,38 @@
import 'package:nextcloud/nextcloud.dart';
/// True for errors worth a short automatic retry: HTTP 5xx thrown by the
/// nextcloud/dynamite clients. Our instance intermittently answers the slow
/// root PROPFIND with a quick empty 500 via nginx that succeeds on retry.
/// Timeouts are deliberately not transient — the root listing already has a
/// multi-minute ceiling, so repeating it would multiply the wait.
bool isTransientServerError(Object error) =>
error is DynamiteApiException &&
error.statusCode >= 500 &&
error.statusCode <= 599;
Duration _defaultRetryDelay(int retry) =>
retry == 1 ? const Duration(seconds: 1) : const Duration(seconds: 3);
/// Runs [attempt] up to [maxAttempts] times, waiting [delayFor] between
/// tries. Errors that don't match [shouldRetry] and the final failure are
/// rethrown unchanged. [onRetry] fires before each wait with the 1-based
/// number of the upcoming attempt, e.g. `(2, 3)` — used to surface retry
/// progress in the UI. [delayFor] receives the 1-based index of the retry
/// being scheduled and is injectable so tests run instantly.
Future<T> retryOnTransientError<T>(
Future<T> Function() attempt, {
int maxAttempts = 3,
Duration Function(int retry) delayFor = _defaultRetryDelay,
bool Function(Object error) shouldRetry = isTransientServerError,
void Function(int nextAttempt, int maxAttempts)? onRetry,
}) async {
for (var attemptNo = 1; ; attemptNo++) {
try {
return await attempt();
} catch (e) {
if (attemptNo >= maxAttempts || !shouldRetry(e)) rethrow;
onRetry?.call(attemptNo + 1, maxAttempts);
await Future<void>.delayed(delayFor(attemptNo));
}
}
}