diff --git a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart index 546fbe408d..3c943f0501 100644 --- a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart @@ -1,15 +1,34 @@ import 'dart:io'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; +class _SharePreparingDialog extends StatelessWidget { + const _SharePreparingDialog(); + + @override + Widget build(BuildContext context) { + return AlertDialog( + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const CircularProgressIndicator(), + Container(margin: const EdgeInsets.only(top: 12), child: const Text('share_dialog_preparing').tr()), + ], + ), + ); + } +} + class ShareActionButton extends ConsumerWidget { final ActionSource source; @@ -20,28 +39,34 @@ class ShareActionButton extends ConsumerWidget { return; } - final result = await ref.read(actionProvider.notifier).shareAssets(source); - ref.read(multiSelectProvider.notifier).reset(); + showDialog( + context: context, + builder: (BuildContext buildContext) { + ref.read(actionProvider.notifier).shareAssets(source).then((ActionResult result) { + ref.read(multiSelectProvider.notifier).reset(); - if (!context.mounted) { - return; - } + if (!context.mounted) { + return; + } - if (!result.success) { - ImmichToast.show( - context: context, - msg: 'scaffold_body_error_occurred'.t(context: context), - gravity: ToastGravity.BOTTOM, - toastType: ToastType.error, - ); - } else if (result.count > 0) { - ImmichToast.show( - context: context, - msg: 'share_action_prompt'.t(context: context, args: {'count': result.count.toString()}), - gravity: ToastGravity.BOTTOM, - toastType: ToastType.success, - ); - } + if (!result.success) { + ImmichToast.show( + context: context, + msg: 'scaffold_body_error_occurred'.t(context: context), + gravity: ToastGravity.BOTTOM, + toastType: ToastType.error, + ); + } + + buildContext.pop(); + }); + + // show a loading spinner with a "Preparing" message + return const _SharePreparingDialog(); + }, + barrierDismissible: false, + useRootNavigator: false, + ); } @override diff --git a/mobile/lib/providers/infrastructure/action.provider.dart b/mobile/lib/providers/infrastructure/action.provider.dart index 21a22e7e5f..65b4327b7a 100644 --- a/mobile/lib/providers/infrastructure/action.provider.dart +++ b/mobile/lib/providers/infrastructure/action.provider.dart @@ -334,8 +334,8 @@ class ActionNotifier extends Notifier { final ids = _getAssets(source).toList(growable: false); try { - final count = await _service.shareAssets(ids); - return ActionResult(count: count, success: true); + await _service.shareAssets(ids); + return ActionResult(count: ids.length, success: true); } catch (error, stack) { _logger.severe('Failed to share assets', error, stack); return ActionResult(count: ids.length, success: false, error: error.toString()); diff --git a/mobile/lib/repositories/asset_media.repository.dart b/mobile/lib/repositories/asset_media.repository.dart index a0af217f0c..83b5dfb9fd 100644 --- a/mobile/lib/repositories/asset_media.repository.dart +++ b/mobile/lib/repositories/asset_media.repository.dart @@ -104,15 +104,18 @@ class AssetMediaRepository { return 0; } - final result = await Share.shareXFiles(downloadedXFiles); - - for (var file in downloadedXFiles) { - try { - await File(file.path).delete(); - } catch (e) { - _log.warning("Failed to delete temporary file: ${file.path}", e); + // we dont want to await the share result since the + // "preparing" dialog will not disappear unti + Share.shareXFiles(downloadedXFiles).then((result) async { + for (var file in downloadedXFiles) { + try { + await File(file.path).delete(); + } catch (e) { + _log.warning("Failed to delete temporary file: ${file.path}", e); + } } - } - return result.status == ShareResultStatus.success ? downloadedXFiles.length : 0; + }); + + return downloadedXFiles.length; } }