Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 93 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
@@ -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<T>` 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<T>` type that can be either:

- `Success<T>` 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<T>`.

```dart

Future<String> myFuture() async {
Future<String> fetchData() async {
await Future.delayed(const Duration(seconds: 2));
return 'my string';
return 'Hello';
}

Future<void> yourFunction(BuildContext context) async {
Future<void> 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<String>(: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<ProgressDialogResult<LongRunningTaskResult>> 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<T>` is a sealed class with two variants:

- `Success<T>` — contains the `value` returned by the task
- `Failure<T>` — 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;
}
```
```

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.
45 changes: 0 additions & 45 deletions lib/dialog/progress_bar_dialog.dart

This file was deleted.

4 changes: 2 additions & 2 deletions lib/flutter_future_progress_dialog.dart
Original file line number Diff line number Diff line change
@@ -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';
File renamed without changes.
30 changes: 30 additions & 0 deletions lib/src/progress_bar_dialog.dart
Original file line number Diff line number Diff line change
@@ -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<StatefulWidget> createState() => _ProgressBarDialogState();
}

class _ProgressBarDialogState extends State<ProgressBarDialog> {
@override
Widget build(BuildContext context) {
return const Dialog(
child: Padding(
padding: EdgeInsets.all(16),
child: SizedBox(
height: 40,
width: 40,
child: Center(
child: CircularProgressIndicator(),
),
),
),
);
}
}
14 changes: 4 additions & 10 deletions lib/dialog/result.dart → lib/src/result.dart
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -54,9 +52,8 @@ sealed class ProgressDialogResult<T> {
}
}

/// Creates the Result object with [value] containing some value.
/// A successful result containing the [value] returned by the task.
class Success<T> extends ProgressDialogResult<T> {
/// [value] property holds the value returned by the Future.
final T value;

@override
Expand All @@ -72,12 +69,9 @@ class Success<T> extends ProgressDialogResult<T> {
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<T> extends ProgressDialogResult<T> {
/// [error] holds the error value
final Object error;

/// [stackTrace] holds the stackTrace
final StackTrace? stackTrace;

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> = Future<T> Function();

Expand All @@ -22,10 +22,10 @@ Future<void> _callback<T>(
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
Expand Down Expand Up @@ -110,10 +110,10 @@ Future<ProgressDialogResult<T>> showProgressDialog<T>({
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
Expand Down Expand Up @@ -174,11 +174,10 @@ Future<ProgressDialogResult<T>> showCupertinoProgressDialog<T>({
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
Expand Down
Loading