import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:smooth_app/generic_lib/buttons/smooth_action_button.dart'; import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; /// Dialog with a stop button, while a future is running. /// /// Typical use-case: wait during download. class LoadingDialog { LoadingDialog._(); /// Is the dialog already pop'ed? bool _popEd = false; /// Runs a future while displaying a stoppable dialog. static Future run({ required final BuildContext context, required final Future future, final String? title, }) async => LoadingDialog._()._run( context: context, future: future, title: title ?? 'Downloading data', // TODO(monsieurtanuki): localize ); /// Shows an loading error dialog. /// /// Typical use-case: when the [run] call failed. static Future error({ required final BuildContext context, final String? title, }) async => showDialog( context: context, builder: (BuildContext context) => SmoothAlertDialog( close: false, body: ListTile( leading: const Icon(Icons.error), title: Text(title ?? 'Could not download data'), // TODO(monsieurtanuki): localize ), actions: [ SmoothActionButton( text: AppLocalizations.of(context)!.close, onPressed: () => Navigator.pop(context), ), ], ), ); /// Displays "downloading" dialog while actually downloading Future _run({ required final BuildContext context, required final Future future, required final String title, }) async => showDialog( context: context, builder: (BuildContext context) { future.then( (final T value) => _popDialog(context, value), ); // TODO(monsieurtanuki): is that safe? If the future finishes before the "return" call? return _getDialog(context, title); }, ); /// Closes the dialog if relevant, pop'ing the [value] void _popDialog(final BuildContext context, final T? value) { if (_popEd) { return; } _popEd = true; // Here we use the root navigator so that we can pop dialog while using multiple navigators. Navigator.of(context, rootNavigator: true).pop(value); } /// Displayed dialog during future. Widget _getDialog( final BuildContext context, final String title, ) => SmoothAlertDialog( close: false, body: ListTile( leading: const CircularProgressIndicator(), title: Text(title), ), actions: [ SmoothActionButton( text: AppLocalizations.of(context)!.stop, onPressed: () => _popDialog(context, null), ), ], ); }