diff --git a/lib/components/loading_dialog.dart b/lib/components/loading_dialog.dart new file mode 100644 index 0000000..c1e7d94 --- /dev/null +++ b/lib/components/loading_dialog.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; + +/// A reusable loading dialog component with a spinner and message. +/// +/// Use the static [show] method to display the dialog and [hide] to dismiss it. +/// +/// Example: +/// ```dart +/// // Show loading dialog +/// LoadingDialog.show(context, message: 'Loading...'); +/// +/// // Perform async operation +/// await someAsyncOperation(); +/// +/// // Hide loading dialog +/// LoadingDialog.hide(context); +/// ``` +class LoadingDialog extends StatelessWidget { + final String message; + + const LoadingDialog({ + super.key, + required this.message, + }); + + /// Shows a loading dialog with the specified [message]. + /// + /// The dialog is non-dismissible by tapping outside. + /// Use [hide] to dismiss the dialog when the operation completes. + static Future show( + BuildContext context, { + required String message, + }) { + return showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext dialogContext) { + return LoadingDialog(message: message); + }, + ); + } + + /// Hides the currently displayed loading dialog. + /// + /// Should be called after showing a dialog with [show]. + static void hide(BuildContext context) { + Navigator.of(context).pop(); + } + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + final textTheme = Theme.of(context).textTheme; + + return Center( + child: Card( + elevation: 4, + color: colorScheme.surface, + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + CircularProgressIndicator( + color: colorScheme.primary, + ), + const SizedBox(height: 16), + Text( + message, + style: textTheme.bodyMedium?.copyWith( + color: colorScheme.onSurface, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ), + ); + } +}