diff --git a/README.md b/README.md index ac263f7..6390958 100644 --- a/README.md +++ b/README.md @@ -1,112 +1,129 @@ -## flutter_future_progress_dialog +# flutter_future_progress_dialog [![Pub Version](https://img.shields.io/pub/v/flutter_future_progress_dialog)](https://pub.dev/packages/flutter_future_progress_dialog) -![GitHub](https://img.shields.io/github/license/nerdy-pro/flutter-progress-dialog) +![GitHub License](https://img.shields.io/github/license/nerdy-pro/flutter-progress-dialog) -Show progress dialog with animation while waiting for Future completion and then return the result of that Future. +A Flutter package that displays a progress dialog while an asynchronous task is running and returns the result when complete. Supports Material, Cupertino, and platform-adaptive dialog styles with built-in error handling. -## Features +Developed and maintained by [Nerdy Pro](https://nerdy.pro). -- Show progress dialog while Future is running -- Material and Cupertino style dialogs -- Adaptive dialog that matches platform style -- Custom dialog builder support -- Type-safe result handling -- Error handling with stack traces +![Flutter progress dialog demo on iPhone](https://raw.githubusercontent.com/nerdy-pro/flutter-progress-dialog/main/img/flutter_progress_dialog_1_4_0.gif) -![Iphone 15](https://raw.githubusercontent.com/nerdy-pro/flutter-progress-dialog/main/img/flutter_progress_dialog_1_4_0.gif) +## Features -## Getting started +- Show a non-dismissible progress dialog while a Future is running +- Material and Cupertino dialog styles +- Adaptive dialog that automatically matches the host platform +- Custom dialog UI via a builder parameter +- Type-safe `ProgressDialogResult` with `Success` and `Failure` variants +- Error handling with stack traces -- install the library +## Installation ```shell flutter pub add flutter_future_progress_dialog ``` -- import the library - ```dart import 'package:flutter_future_progress_dialog/flutter_future_progress_dialog.dart'; ``` - ## Usage -A complete working example can be found in -the [example directory](https://github.com/nerdy-pro/flutter-progress-dialog/tree/develop/example). - -The dialog returns a `ProgressDialogResult` type that can be either: - -- `Success` containing the successful result value -- `Failure` containing the error and stack trace - -You can handle both cases using pattern matching: - -Here is a short example of `showProgressDialog` usage. +### Basic example -Call the `showProgressDialog` inside your function. Pass `context` and `future` arguments. Then handle -result. - -Alternatively you can use `showCupertinoProgressDialog` to show cupertino-styled dialog and `showAdaptiveProgressDialog` to show dialog matching host OS. +Pass a `context` and a `future` callback to `showProgressDialog`. The dialog stays visible until the task completes, then returns a `ProgressDialogResult`. ```dart - -Future myFuture() async { +Future fetchData() async { await Future.delayed(const Duration(seconds: 2)); - return 'my string'; + return 'Hello'; } -Future yourFunction(BuildContext context) async { +Future onButtonPressed(BuildContext context) async { final result = await showProgressDialog( context: context, - future: () => myFuture(), + future: () => fetchData(), ); - if (!mounted) { - return; - } + switch (result) { + case Success(:final value): + print('Got: $value'); case Failure(:final error): - await showDialog( - context: context, - builder: (context) { - return AlertDialog( - content: Text( - '$error', - textAlign: TextAlign.center, - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text( - 'OK', - ), - ), - ], - ); - }, - ); - case Success(:final value): - // value variable would hold the 'my string' value here - break; - } + print('Error: $error'); + } } ``` -Optionally you can pass a `builder` to have a custom progress dialog +### Cupertino and adaptive dialogs + +Use `showCupertinoProgressDialog` for an iOS-styled dialog, or `showAdaptiveProgressDialog` to automatically pick the right style for the current platform. ```dart -Future> buttonCallback({ - required BuildContext context, -}) async { - return await showProgressDialog( - future: () => myLongRunningTask(), - context: context, - builder: (context) => AlertDialog( - content: Text('I am loading now'), - ), - ); +// iOS style +final result = await showCupertinoProgressDialog( + context: context, + future: () => fetchData(), +); + +// Automatic: Cupertino on iOS/macOS, Material elsewhere +final result = await showAdaptiveProgressDialog( + context: context, + future: () => fetchData(), +); +``` + +### Custom dialog UI + +Pass a `builder` to replace the default progress indicator with your own widget. + +```dart +final result = await showProgressDialog( + context: context, + future: () => fetchData(), + builder: (context) => const AlertDialog( + content: Text('Loading, please wait...'), + ), +); +``` + +### Handling results + +`ProgressDialogResult` is a sealed class with two variants: + +- `Success` — contains the `value` returned by the task +- `Failure` — contains the `error` and optional `stackTrace` + +```dart +switch (result) { + case Success(:final value): + // Use the value + break; + case Failure(:final error, :final stackTrace): + // Handle the error + break; } -``` \ No newline at end of file +``` + +You can also use convenience methods: + +```dart +result.isSuccess; // true if Success +result.isError; // true if Failure +result.unwrap(); // returns value or throws error +result.map((v) => v.toString()); // transforms Success value +``` + +## API reference + +| Function | Description | +|---|---| +| `showProgressDialog` | Material-styled progress dialog | +| `showCupertinoProgressDialog` | Cupertino-styled progress dialog | +| `showAdaptiveProgressDialog` | Platform-adaptive progress dialog | + +A complete working example is available in the [example directory](https://github.com/nerdy-pro/flutter-progress-dialog/tree/main/example). + +## License + +MIT License. See [LICENSE](LICENSE) for details. diff --git a/lib/dialog/progress_bar_dialog.dart b/lib/dialog/progress_bar_dialog.dart deleted file mode 100644 index 4b9447f..0000000 --- a/lib/dialog/progress_bar_dialog.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:flutter/material.dart'; - -/// A widget that displays a circular progress indicator inside a [Dialog]. -/// -/// This widget is used internally by [showProgressDialog], [showCupertinoProgressDialog], -/// and [showAdaptiveProgressDialog] to show a loading state while a future task is being executed. -/// -/// The dialog contains a centered [CircularProgressIndicator] with fixed dimensions -/// and padding. The generic type [T] corresponds to the type of data being processed. -class ProgressBarDialog extends StatefulWidget { - /// Creates a progress bar dialog. - /// - /// The [key] parameter is optional and is used to control how one widget replaces - /// another widget in the tree. - const ProgressBarDialog({super.key}); - - @override - State createState() => _ProgressBarDialogState(); -} - -/// State class for [ProgressBarDialog] that manages the dialog's visual representation. -/// -/// This class builds a simple dialog containing a centered circular progress indicator -/// with fixed dimensions and padding. -class _ProgressBarDialogState extends State { - /// Builds the dialog widget with a centered circular progress indicator. - /// - /// @param context The build context for this widget. - /// @return A [Dialog] widget containing a padded circular progress indicator. - @override - Widget build(BuildContext context) { - return const Dialog( - child: Padding( - padding: EdgeInsets.all(16), - child: SizedBox( - height: 40, - width: 40, - child: Center( - child: CircularProgressIndicator(), - ), - ), - ), - ); - } -} diff --git a/lib/flutter_future_progress_dialog.dart b/lib/flutter_future_progress_dialog.dart index c052f43..ae4ca7c 100644 --- a/lib/flutter_future_progress_dialog.dart +++ b/lib/flutter_future_progress_dialog.dart @@ -1,4 +1,4 @@ library flutter_future_progress_dialog; -export 'dialog/result.dart'; -export 'dialog/show_progress_dialog.dart'; +export 'src/result.dart'; +export 'src/show_progress_dialog.dart'; diff --git a/lib/dialog/cupertino_progress_bar_dialog.dart b/lib/src/cupertino_progress_bar_dialog.dart similarity index 100% rename from lib/dialog/cupertino_progress_bar_dialog.dart rename to lib/src/cupertino_progress_bar_dialog.dart diff --git a/lib/dialog/exactly_once.dart b/lib/src/exactly_once.dart similarity index 100% rename from lib/dialog/exactly_once.dart rename to lib/src/exactly_once.dart diff --git a/lib/src/progress_bar_dialog.dart b/lib/src/progress_bar_dialog.dart new file mode 100644 index 0000000..128b188 --- /dev/null +++ b/lib/src/progress_bar_dialog.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +/// A Material-styled dialog that displays a centered [CircularProgressIndicator]. +/// +/// Used as the default UI for [showProgressDialog] and [showAdaptiveProgressDialog] +/// on non-Apple platforms. +class ProgressBarDialog extends StatefulWidget { + const ProgressBarDialog({super.key}); + + @override + State createState() => _ProgressBarDialogState(); +} + +class _ProgressBarDialogState extends State { + @override + Widget build(BuildContext context) { + return const Dialog( + child: Padding( + padding: EdgeInsets.all(16), + child: SizedBox( + height: 40, + width: 40, + child: Center( + child: CircularProgressIndicator(), + ), + ), + ), + ); + } +} diff --git a/lib/dialog/result.dart b/lib/src/result.dart similarity index 80% rename from lib/dialog/result.dart rename to lib/src/result.dart index c777e0f..fbf6803 100644 --- a/lib/dialog/result.dart +++ b/lib/src/result.dart @@ -1,8 +1,6 @@ -/// This class is used to wrap the result of asynchronous operations shown in progress dialogs. -/// It can either be a [Success] containing the operation's result value, or a [Failure] -/// containing error details if the operation failed. +/// The result of an asynchronous operation shown in a progress dialog. /// -/// The type parameter [T] represents the type of value that will be returned in case of success. +/// Either a [Success] containing the value, or a [Failure] containing the error. /// /// Example usage: /// ```dart @@ -54,9 +52,8 @@ sealed class ProgressDialogResult { } } -/// Creates the Result object with [value] containing some value. +/// A successful result containing the [value] returned by the task. class Success extends ProgressDialogResult { - /// [value] property holds the value returned by the Future. final T value; @override @@ -72,12 +69,9 @@ class Success extends ProgressDialogResult { int get hashCode => value.hashCode; } -/// Creates the Result object with [error] and [stackTrace] containing error object and stackTrace object respectively. +/// A failed result containing the [error] and optional [stackTrace]. class Failure extends ProgressDialogResult { - /// [error] holds the error value final Object error; - - /// [stackTrace] holds the stackTrace final StackTrace? stackTrace; @override diff --git a/lib/dialog/show_progress_dialog.dart b/lib/src/show_progress_dialog.dart similarity index 88% rename from lib/dialog/show_progress_dialog.dart rename to lib/src/show_progress_dialog.dart index f05cec7..d73201c 100644 --- a/lib/dialog/show_progress_dialog.dart +++ b/lib/src/show_progress_dialog.dart @@ -3,10 +3,10 @@ import 'dart:io'; import 'package:flutter/cupertino.dart' as c; import 'package:flutter/material.dart' as m; import 'package:flutter/widgets.dart' as w; -import 'package:flutter_future_progress_dialog/dialog/cupertino_progress_bar_dialog.dart'; -import 'package:flutter_future_progress_dialog/dialog/exactly_once.dart'; -import 'package:flutter_future_progress_dialog/dialog/progress_bar_dialog.dart'; -import 'package:flutter_future_progress_dialog/dialog/result.dart'; +import 'package:flutter_future_progress_dialog/src/cupertino_progress_bar_dialog.dart'; +import 'package:flutter_future_progress_dialog/src/exactly_once.dart'; +import 'package:flutter_future_progress_dialog/src/progress_bar_dialog.dart'; +import 'package:flutter_future_progress_dialog/src/result.dart'; typedef Task = Future Function(); @@ -22,10 +22,10 @@ Future _callback( navigator.removeRoute(route, result); } -/// Shows a progress dialog while executing a Future task. +/// Shows a progress dialog while executing an asynchronous task. /// -/// This function displays a modal progress dialog that remains visible until the provided -/// [future] completes. The dialog can be customized using the [builder] parameter. +/// Displays a modal progress dialog that remains visible until [future] completes. +/// The dialog UI can be customized using the [builder] parameter. /// /// Parameters: /// * [context] - The build context used to show the dialog @@ -110,10 +110,10 @@ Future> showProgressDialog({ return result!; } -/// Shows a Cupertino-styled progress dialog while executing a Future task. +/// Shows a Cupertino-styled progress dialog while executing an asynchronous task. /// -/// This function displays a modal progress dialog with iOS-style appearance that -/// remains visible until the provided [future] completes. +/// Displays a modal progress dialog with iOS-style appearance that +/// remains visible until [future] completes. /// /// Parameters: /// * [context] - The build context used to show the dialog @@ -174,11 +174,10 @@ Future> showCupertinoProgressDialog({ return result!; } -/// Shows a platform-adaptive progress dialog while executing a Future task. +/// Shows a platform-adaptive progress dialog while executing an asynchronous task. /// -/// This function displays a modal progress dialog that matches the host platform's style. -/// On iOS and macOS it shows a Cupertino-styled dialog, while on other platforms it -/// shows the Material-styled dialog. +/// Displays a Cupertino-styled dialog on iOS and macOS, and a Material-styled +/// dialog on all other platforms. /// /// Parameters: /// * [context] - The build context used to show the dialog