nc-photos/app/lib/notified_action.dart
2022-07-28 17:47:59 +08:00

119 lines
3.2 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:nc_photos/exception_util.dart' as exception_util;
import 'package:nc_photos/k.dart' as k;
import 'package:nc_photos/snack_bar_manager.dart';
class NotifiedAction {
NotifiedAction(
this.action,
this.processingText,
this.successText, {
this.failureText,
});
Future<void> call() async {
if (processingText != null) {
SnackBarManager().showSnackBar(
SnackBar(
content: Text(processingText!),
duration: k.snackBarDurationShort,
),
canBeReplaced: true,
);
}
try {
await action();
SnackBarManager().showSnackBar(SnackBar(
content: Text(successText),
duration: k.snackBarDurationNormal,
));
} catch (e) {
SnackBarManager().showSnackBar(SnackBar(
content: Text(
(failureText?.isNotEmpty == true ? "$failureText: " : "") +
exception_util.toUserString(e)),
duration: k.snackBarDurationNormal,
));
rethrow;
}
}
final FutureOr<void> Function() action;
/// Message to be shown before performing [action]
final String? processingText;
/// Message to be shown after [action] finished without throwing
final String successText;
/// Message to be shown if [action] threw, prepending the exception
final String? failureText;
}
class NotifiedListAction<T> {
NotifiedListAction({
required this.list,
required this.action,
this.processingText,
required this.successText,
this.getFailureText,
this.onActionError,
});
/// Perform the action and return the success count
Future<int> call() async {
if (processingText != null) {
SnackBarManager().showSnackBar(
SnackBar(
content: Text(processingText!),
duration: k.snackBarDurationShort,
),
canBeReplaced: true,
);
}
final failedItems = <T>[];
for (final item in list) {
try {
await action(item);
} catch (e, stackTrace) {
onActionError?.call(item, e, stackTrace);
failedItems.add(item);
}
}
if (failedItems.isEmpty) {
SnackBarManager().showSnackBar(SnackBar(
content: Text(successText),
duration: k.snackBarDurationNormal,
));
} else {
final failureText = getFailureText?.call(failedItems);
if (failureText?.isNotEmpty == true) {
SnackBarManager().showSnackBar(SnackBar(
content: Text(failureText!),
duration: k.snackBarDurationNormal,
));
}
}
return list.length - failedItems.length;
}
final List<T> list;
/// Action to be applied to every items in [list]
final FutureOr<void> Function(T item) action;
/// Message to be shown before performing [action]
final String? processingText;
/// Message to be shown after [action] finished for each elements in [list]
/// without throwing
final String successText;
/// Message to be shown if one or more [action] threw
final String Function(List<T> failedItems)? getFailureText;
/// Called when [action] threw when processing [item]
final void Function(T item, Object e, StackTrace stackTrace)? onActionError;
}