diff --git a/lib/pages/archive/archive.dart b/lib/pages/archive/archive.dart index c9ab71c10..a39840a3c 100644 --- a/lib/pages/archive/archive.dart +++ b/lib/pages/archive/archive.dart @@ -52,8 +52,10 @@ class ArchiveController extends State { } await showFutureLoadingDialog( context: context, - future: () async { + futureWithProgress: (onProgress) async { + final count = archive.length; while (archive.isNotEmpty) { + onProgress(1 - (archive.length / count)); Logs().v('Forget room ${archive.last.getLocalizedDisplayname()}'); await archive.last.forget(); archive.removeLast(); diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index e0925f9f5..988a69809 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -852,10 +852,12 @@ class ChatController extends State : null; if (reasonInput == null) return; final reason = reasonInput.isEmpty ? null : reasonInput; - for (final event in selectedEvents) { - await showFutureLoadingDialog( - context: context, - future: () async { + await showFutureLoadingDialog( + context: context, + futureWithProgress: (onProgress) async { + final count = selectedEvents.length; + for (final (i, event) in selectedEvents.indexed) { + onProgress(i / count); if (event.status.isSent) { if (event.canRedact) { await event.redactEvent(reason: reason); @@ -875,9 +877,9 @@ class ChatController extends State } else { await event.cancelSend(); } - }, - ); - } + } + }, + ); setState(() { showEmojiPicker = false; selectedEvents.clear(); diff --git a/lib/widgets/future_loading_dialog.dart b/lib/widgets/future_loading_dialog.dart index 055a67205..7fde990f8 100644 --- a/lib/widgets/future_loading_dialog.dart +++ b/lib/widgets/future_loading_dialog.dart @@ -14,7 +14,8 @@ import 'package:fluffychat/widgets/adaptive_dialogs/adaptive_dialog_action.dart' /// null. Future> showFutureLoadingDialog({ required BuildContext context, - required Future Function() future, + Future Function()? future, + Future Function(void Function(double?) setProgress)? futureWithProgress, String? title, String? backLabel, bool barrierDismissible = false, @@ -22,7 +23,10 @@ Future> showFutureLoadingDialog({ ExceptionContext? exceptionContext, bool ignoreError = false, }) async { - final futureExec = future(); + assert(future != null || futureWithProgress != null); + final onProgressStream = StreamController(); + final futureExec = + futureWithProgress?.call(onProgressStream.add) ?? future!(); final resultFuture = ResultFuture(futureExec); if (delay) { @@ -46,6 +50,7 @@ Future> showFutureLoadingDialog({ title: title, backLabel: backLabel, exceptionContext: exceptionContext, + onProgressStream: onProgressStream.stream, ), ); return result ?? @@ -60,6 +65,7 @@ class LoadingDialog extends StatefulWidget { final String? backLabel; final Future future; final ExceptionContext? exceptionContext; + final Stream onProgressStream; const LoadingDialog({ super.key, @@ -67,6 +73,7 @@ class LoadingDialog extends StatefulWidget { this.title, this.backLabel, this.exceptionContext, + required this.onProgressStream, }); @override @@ -110,7 +117,13 @@ class LoadingDialogState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ if (exception == null) ...[ - const CircularProgressIndicator.adaptive(), + StreamBuilder( + stream: widget.onProgressStream, + builder: (context, snapshot) => + CircularProgressIndicator.adaptive( + value: snapshot.data, + ), + ), const SizedBox(width: 20), ], Expanded(