68 lines
1.8 KiB
Dart
68 lines
1.8 KiB
Dart
part of '../async_action_button.dart';
|
|
|
|
typedef AsyncActionCallback = Future<void> Function();
|
|
typedef AsyncErrorBuilder = String Function(Object error);
|
|
|
|
/// Wraps [action] with a try/catch that pops up an [InfoDialog] on failure
|
|
/// (using [errorBuilder] or the default error mapper). Returns `true` on
|
|
/// success, `false` on caught failure.
|
|
Future<bool> runWithErrorDialog(
|
|
BuildContext context,
|
|
AsyncActionCallback action, {
|
|
AsyncErrorBuilder? errorBuilder,
|
|
}) async {
|
|
try {
|
|
await action();
|
|
return true;
|
|
} catch (e) {
|
|
if (!context.mounted) return false;
|
|
final message = errorBuilder != null
|
|
? errorBuilder(e)
|
|
: errorToUserMessage(e);
|
|
final details = errorToTechnicalDetails(e);
|
|
final body = details != null && details != message
|
|
? '$message\n\n$details'
|
|
: message;
|
|
InfoDialog.show(context, body, copyable: true, title: 'Fehler');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Reusable busy/error state for the async-button family. Multiple buttons
|
|
/// can share the same controller (e.g. a parent toolbar wanting to disable
|
|
/// while any one child is running).
|
|
class AsyncActionController extends ChangeNotifier {
|
|
bool _busy = false;
|
|
String? _error;
|
|
|
|
bool get busy => _busy;
|
|
String? get error => _error;
|
|
|
|
Future<bool> run(
|
|
AsyncActionCallback action, {
|
|
AsyncErrorBuilder? errorBuilder,
|
|
}) async {
|
|
if (_busy) return false;
|
|
_busy = true;
|
|
_error = null;
|
|
notifyListeners();
|
|
try {
|
|
await action();
|
|
_busy = false;
|
|
notifyListeners();
|
|
return true;
|
|
} catch (e) {
|
|
_busy = false;
|
|
_error = errorBuilder != null ? errorBuilder(e) : errorToUserMessage(e);
|
|
notifyListeners();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void clearError() {
|
|
if (_error == null) return;
|
|
_error = null;
|
|
notifyListeners();
|
|
}
|
|
}
|